fix(I11): SourceOS 60-row rendering, real runner_family badges, wired controls - #114
Conversation
- Fetch /api/modules/runtime/runner-contracts on mount + after Verify All / Setup Queue actions - Map runner_status (runner_family) per module_id into a lookup dict - ModuleList: display runner_family badge for each of the 60 rows using real runner_status from contracts endpoint - AppDetailPanel: add runner_family header pill + RunnerContract InfoBox showing runner_status, required_verifier_family, safe_actions, acceptance_gate, and blocked_reason - Pass runnerContract down to AppDetailPanel and refresh it in onRefresh callback - All 60 rows rendered without slice/limit (confirmed via /api/modules count:60) - Controls (Verify, Setup Plan, Backup, Rollback) already wired to real API — confirmed no fake handlers - Panel overflow: AppDetailPanel section has overflow-auto in flex container with min-h-0 scan_active_ui_no_fake: 81 production files scanned, 0 findings Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
📝 WalkthroughWalkthroughThis change introduces exhaustive JSON Schemas for every runtime adapter, enforces strict platform UI/data contracts (prohibiting all mock/fake/sample in production), codifies agent/operator safety and delegation, upgrades the roadmap and tab/fleet completion ledger, adds policy proofs and multi-level verification artifacts, expands CI wiring and Playwright gating, audits hardware/fleet safety, and appends comprehensive documentation, security audits, and inventory/diagram artifacts. ChangesAdapter Registry, Policy Contracts, Roadmap, Audit, CI, Proofs, Documentation
Sequence Diagram(s)No sequence diagram generated for this change: the update comprises schema/documentation/policy/config/proof/CI layers, not a single new multi-actor runtime sequence or cross-component control flow with 3+ actors. Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Possibly related PRs
Poem
✨ Finishing Touches🧪 Generate unit tests (beta)
⚔️ Resolve merge conflicts
|
There was a problem hiding this comment.
Code Review
This pull request introduces a comprehensive set of updates to the Hermes3D OS, focusing on establishing a professional safety layer for agentic automation and expanding the Source OS module registry. Key changes include the addition of numerous JSON schemas for application adapters, extensive documentation of the end-to-end truth and proof plans, and the integration of a folder index for agent context. Feedback focuses on improving the maintainability and portability of the new adapter schemas by standardizing JSON Schema versions, removing hardcoded user-specific paths, and eliminating redundant properties likely introduced via copy-paste.
| "$schema": "http://json-schema.org/draft-07/schema#", | ||
| "$id": "hermes3d://adapter_registry/schemas/klipper_service/v1", |
There was a problem hiding this comment.
The JSON schema version and ID format are inconsistent with other schemas in this directory (which mostly use the 2020-12 draft and a .schema.json suffix). Updating to a newer draft and using a consistent naming convention for the $id field will improve maintainability.
| "$schema": "http://json-schema.org/draft-07/schema#", | |
| "$id": "hermes3d://adapter_registry/schemas/klipper_service/v1", | |
| "$schema": "https://json-schema.org/draft/2020-12/schema", | |
| "$id": "hermes3d://adapter_registry/schemas/klipper_service.schema.json", |
| "$schema": "http://json-schema.org/draft-07/schema#", | ||
| "$id": "hermes3d://adapter_registry/schemas/moonraker_api/v1", |
There was a problem hiding this comment.
The JSON schema version and ID format are inconsistent with the majority of schemas in the repository. Standardizing on the 2020-12 draft and a consistent $id URI structure is recommended.
| "$schema": "http://json-schema.org/draft-07/schema#", | |
| "$id": "hermes3d://adapter_registry/schemas/moonraker_api/v1", | |
| "$schema": "https://json-schema.org/draft/2020-12/schema", | |
| "$id": "hermes3d://adapter_registry/schemas/moonraker_api.schema.json", |
| "C:/Users/Admin/AppData/Local/Programs/Ollama/ollama.exe", | ||
| "ollama", | ||
| "llama-cli", | ||
| "llama" |
There was a problem hiding this comment.
The executable_candidates list contains a hardcoded path with a specific username (Admin). This makes the schema non-portable and brittle across different developer environments. It is better to rely on the system PATH or use environment variable placeholders if supported by the loader.
| "llama" | |
| "ollama", |
| "string", | ||
| "null" | ||
| ], | ||
| "default": "C:/Program Files/Bambu Studio/bambu-studio.exe", |
There was a problem hiding this comment.
Hardcoding a Windows-specific absolute path as a default value for executable_path limits the portability of the schema. Since this property is not required, it is safer to default to null and let the runtime configuration or system PATH handle resolution.
| "default": "C:/Program Files/Bambu Studio/bambu-studio.exe", | |
| "default": null, |
| "pip_package": { | ||
| "type": [ | ||
| "string", | ||
| "null" | ||
| ], | ||
| "default": null, | ||
| "description": "Bambu Studio is a desktop app; no pip package." | ||
| }, | ||
| "weights_cache_dirs": { | ||
| "type": "array", | ||
| "items": { | ||
| "type": "string" | ||
| }, | ||
| "default": [], | ||
| "description": "Bambu Studio is a slicer; no model weights are required." | ||
| } |
There was a problem hiding this comment.
The pip_package and weights_cache_dirs properties appear to be copy-paste leftovers from a different adapter schema (likely a Python-based modeler or generator). Since the description explicitly states these are not required for Bambu Studio, they should be removed to keep the schema clean and accurate.
| "C:/Program Files/Blender Foundation/Blender 5.1/blender.exe", | ||
| "C:/Program Files/Blender Foundation/Blender 4.4/blender.exe", |
There was a problem hiding this comment.
Hardcoding specific versions (e.g., "Blender 5.1", "Blender 4.4") in the executable_candidates list makes the schema brittle and requires manual updates whenever a new version is installed. It is recommended to use more generic paths or rely on the system PATH for binary discovery.
| "C:/Program Files/Blender Foundation/Blender 5.1/blender.exe", | |
| "C:/Program Files/Blender Foundation/Blender 4.4/blender.exe", | |
| "blender", |
| "C:/Program Files/FreeCAD 1.0/bin/FreeCAD.exe", | ||
| "C:/Program Files/FreeCAD 0.21/bin/FreeCAD.exe", |
| }, | ||
| "launch_mode": { | ||
| "type": "string", | ||
| "enum": ["desktop_app"], |
There was a problem hiding this comment.
Actionable comments posted: 16
Note
Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.
🟡 Minor comments (27)
03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/merge-prs/README.md-31-36 (1)
31-36:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAdd a language tag to the fenced block to satisfy markdownlint (MD040).
The code fence at Line 31 has no language identifier. Please annotate it (e.g.,
text) to keep lint clean.Suggested diff
-``` +```text merge-pr23 branch=feat/gate-dep-fresh HEAD=b2a518b status=clean COMPLETE merge-pr24 branch=feat/gate-sbom HEAD=2455244 status=clean COMPLETE merge-pr27 branch=feat/gate-mcp-scan-static HEAD=398c9b9 status=clean COMPLETE merge-pr33 branch=feat/mcp-supervisor-auto-reconnect HEAD=1ff4e64 status=clean COMPLETE</details> <details> <summary>🤖 Prompt for AI Agents</summary>Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.In
@03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/merge-prs/README.md
around lines 31 - 36, The fenced code block containing the merge-pr lines is
missing a language tag which trips markdownlint MD040; update the
triple-backtick opening fence that precedes the lines starting with "merge-pr23
branch=feat/gate-dep-fresh ..." to include a language identifier (e.g., change
totext) so the block is annotated and the linter warning is resolved.</details> </blockquote></details> <details> <summary>03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/hp-protocol/README.md-3-3 (1)</summary><blockquote> `3-3`: _⚠️ Potential issue_ | _🟡 Minor_ | _⚡ Quick win_ **Use `GitHub` capitalization for platform name.** Line 3 and Line 94 use `Github`; standard spelling is `GitHub`. <details> <summary>Suggested patch</summary> ```diff -Index of nine `hp-*` checkouts under `G:\Github\` that participated in the 2026-05-03 HermesProof P0/P1 hardening sweep. All folders are clones/branches of `Ghenghis/HermesProof`; each markdown describes the slice of work that branch carried. +Index of nine `hp-*` checkouts under `G:\GitHub\` that participated in the 2026-05-03 HermesProof P0/P1 hardening sweep. All folders are clones/branches of `Ghenghis/HermesProof`; each markdown describes the slice of work that branch carried. ``` ```diff -- Bonus folder `hp-hermes-agent-bridge` exists under `G:\Github\` but was not in the requested set of nine, so it is not indexed here. +- Bonus folder `hp-hermes-agent-bridge` exists under `G:\GitHub\` but was not in the requested set of nine, so it is not indexed here. ``` </details> Also applies to: 94-94 <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/hp-protocol/README.md` at line 3, Replace the incorrect platform capitalization "Github" with the standard "GitHub" in the README text; locate the occurrences of the literal string "Github" (e.g., the sentence beginning "Index of nine `hp-*` checkouts under `G:\Github\`..." and the later occurrence around line 94) and update them to "GitHub" so the platform name uses correct capitalization everywhere. ``` </details> </blockquote></details> <details> <summary>03_implementation/adapter_registry/schemas/moonraker_api.schema.json-72-87 (1)</summary><blockquote> `72-87`: _⚠️ Potential issue_ | _🟡 Minor_ | _⚡ Quick win_ **`response_root` schema type conflicts with the provided example.** Line 73 declares `"type": "string"`, but the example at line 86 sets `"response_root": null` for the `/api/version` endpoint. The schema should allow null values to match actual usage. <details> <summary>Proposed fix</summary> ```diff "response_root": { - "type": "string", + "type": ["string", "null"], "description": "Top-level JSON key in Moonraker response containing the data (usually 'result')" } ``` </details> <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@03_implementation/adapter_registry/schemas/moonraker_api.schema.json` around lines 72 - 87, The schema's response_root currently declares "type": "string" but an example uses null; update the response_root definition to accept null (e.g., change its type to ["string","null"] or add nullable: true depending on your JSON Schema draft) so the examples (the objects in the examples array with keys like "path" and "response_root") validate correctly; keep description unchanged and leave additionalProperties/required rules as-is. ``` </details> </blockquote></details> <details> <summary>03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/02_EXCLUSIONS.md-5-5 (1)</summary><blockquote> `5-5`: _⚠️ Potential issue_ | _🟡 Minor_ | _⚡ Quick win_ **Use canonical “GitHub” casing in path references.** Line 5, Line 53, and Line 67 currently use `G:\Github\`; please normalize to `G:\GitHub\` for consistency with official platform naming. Also applies to: 53-53, 67-67 <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/02_EXCLUSIONS.md` at line 5, Normalize the casing of the GitHub path references by replacing every occurrence of the string "G:\Github\" with the canonical "G:\GitHub\" in this document (specifically fix the instances currently showing "G:\Github\" such as the occurrences around the text header and the entries referenced by the review), ensuring all references to the repository path use "G:\GitHub\" consistently throughout the file. ``` </details> </blockquote></details> <details> <summary>03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/core-repos/h3d-gui-wiring-codex.md-15-26 (1)</summary><blockquote> `15-26`: _⚠️ Potential issue_ | _🟡 Minor_ | _⚡ Quick win_ **Specify a language for the fenced block to satisfy markdownlint** Line 15 opens a fenced code block without a language, which triggers MD040. <details> <summary>Proposed patch</summary> ```diff -``` +```text 485155b 2026-05-07 feat(agents): add provider execution artifacts 4f7d316 2026-05-07 feat(agents): add provider team assignment lane 30b42c0 2026-05-07 feat(agents): add proof-gated git shipping lane @@ 30661b9 2026-05-06 audit(docs): PR body completeness + ROADMAP truth + merge plan verification (`#78`) ``` ``` </details> <details> <summary>🤖 Prompt for AI Agents</summary>Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.In
@03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/core-repos/h3d-gui-wiring-codex.md
around lines 15 - 26, The fenced code block in h3d-gui-wiring-codex.md that
contains the commit log lacks a language specifier, triggering markdownlint rule
MD040; update the opening fence to include a language (e.g., change ``` tolanguage) — target the fenced block that begins with the commit lines like "485155b 2026-05-07 feat(agents): add provider execution artifacts" and ensure the closing fence remains ```.03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/core-repos/Hermes3D-worktrees.md-17-25 (1)
17-25:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAdd a language tag to the fenced commit block.
Line 17 uses a bare fenced block, which triggers markdownlint MD040. Use
textfor this log snippet.📝 Minimal fix
-``` +```text 1c6eeab test(bridge): relax provider-health assertion for ADR-015 chain 0be0b9f feat: LM Studio default + Ollama fallback + Hipfire optional (ADR-015) 3fde207 docs(release): draft v5.3.0 release notes a39cbf8 docs(readme): v2 marketing rewrite + Mermaid + theme-aware SVG + truth-gate accordion 5b11f6c 2026-05-03 docs(adr): ADR-014 — audit of blender-mcp-native (verdict: REJECT) c3e68d1 2026-05-03 docs(handoff): overnight Codex queue — 1 master + 6 task briefs + roadmap b767100 2026-05-03 feat(backup): local-only secrets backup — Syncthing + Restic-B2 scripts</details> <details> <summary>🤖 Prompt for AI Agents</summary>Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.In
@03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/core-repos/Hermes3D-worktrees.md
around lines 17 - 25, The fenced commit block starting with "1c6eeab
test(bridge): ..." is missing a language tag and triggers markdownlint MD040;
fix it by changing the opening fence fromtotext for that commit log
block (the block containing the commit hashes like "1c6eeab", "0be0b9f", etc.)
so the snippet is explicitly marked as plain text.</details> </blockquote></details> <details> <summary>03_implementation/docs/handoffs/audit/MERGE_INTEGRITY_2026-05-06.md-44-48 (1)</summary><blockquote> `44-48`: _⚠️ Potential issue_ | _🟡 Minor_ | _⚡ Quick win_ **Specify a language for the fenced block.** Line [44] starts a fence without language. Use `text` to avoid MD040 warnings. <details> <summary>🤖 Prompt for AI Agents</summary>Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.In
@03_implementation/docs/handoffs/audit/MERGE_INTEGRITY_2026-05-06.mdaround
lines 44 - 48, The fenced code block containing the comma-separated module list
(the triple-backtick block that starts with modules, jobs, approvals, ...) lacks
a language tag; update the opening fence fromtotext so the block is
explicitly marked as plain text (i.e., replace thethat begins the block withtext).</details> </blockquote></details> <details> <summary>03_implementation/docs/handoffs/claude-e2e-intelligence-2026-05-08/09_CODEX_NEXT_50_TASKS.md-67-67 (1)</summary><blockquote> `67-67`: _⚠️ Potential issue_ | _🟡 Minor_ | _⚡ Quick win_ **Task 11 prerequisite is self-referential.** Line [67] lists `tasks 8 + 11's plan`, which creates an impossible dependency on itself. Replace it with the actual prerequisite artifact/task. <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@03_implementation/docs/handoffs/claude-e2e-intelligence-2026-05-08/09_CODEX_NEXT_50_TASKS.md` at line 67, The row for task 11 incorrectly references itself as a prerequisite ("tasks 8 + 11's plan"); update the prerequisite column for the P0 Gpu-worker-gap entry so it points to the real prerequisite artifact/task (e.g., replace "tasks 8 + 11's plan" with the correct upstream item such as "task 8 plan" or the specific artifact name used elsewhere), ensuring the entry for **Gpu-worker-gap** / `verifiers/gpu_dependency.py` no longer creates a self-referential dependency. ``` </details> </blockquote></details> <details> <summary>03_implementation/docs/handoffs/claude-e2e-intelligence-2026-05-08/09_CODEX_NEXT_50_TASKS.md-52-57 (1)</summary><blockquote> `52-57`: _⚠️ Potential issue_ | _🟡 Minor_ | _⚡ Quick win_ **Task table count is off by one.** Line [52] says “50 rows,” but the table indexes tasks `0..50` (51 rows). Please align the heading or numbering to avoid downstream planning/reporting drift. <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@03_implementation/docs/handoffs/claude-e2e-intelligence-2026-05-08/09_CODEX_NEXT_50_TASKS.md` around lines 52 - 57, The tasks table heading "## Tasks Table (50 rows)" is inconsistent with the actual table which indexes tasks 0..50 (51 rows); update either the heading or the table numbering so they match: either change the heading text to "## Tasks Table (51 rows)" or renumber the table rows to 0..49 (or 1..50) to match "50 rows"; modify the header string "## Tasks Table (50 rows)" or the table entries that include the task indices (e.g., the row starting with "| 0 | P0 | ...") in the Markdown to restore consistency. ``` </details> </blockquote></details> <details> <summary>03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/h3dos-codex-tasks/h3dos-codex-octoprint.md-40-43 (1)</summary><blockquote> `40-43`: _⚠️ Potential issue_ | _🟡 Minor_ | _⚡ Quick win_ **Surround the table with blank lines for markdownlint compatibility.** The “Key files” table block around Line [41] should be separated by blank lines to satisfy MD058 consistently. <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/h3dos-codex-tasks/h3dos-codex-octoprint.md` around lines 40 - 43, The "Key files" markdown table is not separated by blank lines, causing MD058 failures; add a blank line immediately before the "## Key files" header and another blank line after the closing table row so the table block is surrounded by blank lines, ensuring the markdown block that contains the table (including the entry referencing `_install_pip`) is isolated from adjacent text. ``` </details> </blockquote></details> <details> <summary>03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/worktree-collections/_codex_worktrees.md-8-8 (1)</summary><blockquote> `8-8`: _⚠️ Potential issue_ | _🟡 Minor_ | _⚡ Quick win_ **Detached-HEAD count conflicts across sections.** Line [8] reports 7 detached HEAD worktrees, while Line [67] reports 6. Please correct one source so the inventory is self-consistent. Also applies to: 67-67 <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/worktree-collections/_codex_worktrees.md` at line 8, The document has inconsistent detached-HEAD counts: the sentence "Note: 7 worktrees are at detached HEAD (no symbolic branch ref)..." and the later summary that says 6 disagree; recount the actual detached-HEAD worktrees and update the mismatched sentence so both places show the same correct number. Search for the string "detached HEAD" and the two sentences (the one that begins "Note: 7 worktrees..." and the summary at line ~67) and change the numeric value to the verified count so the inventory is self-consistent. ``` </details> </blockquote></details> <details> <summary>03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/worktree-collections/_codex_worktrees.md-4-4 (1)</summary><blockquote> `4-4`: _⚠️ Potential issue_ | _🟡 Minor_ | _⚡ Quick win_ **Worktree totals are internally inconsistent.** Line [4] says `15 worktree dirs + 1 stray file`, but Lines [14-30] enumerate 16 worktree dirs. Please reconcile the headline counts. Also applies to: 14-30 <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/worktree-collections/_codex_worktrees.md` at line 4, The bold headline "**Worktree count**" is inconsistent with the enumerated list of worktrees; reconcile them by updating the headline to exactly match the enumerated worktree list (or adjust the list to reflect a stray file) — either change the headline to "16 worktree dirs" if the list contains 16 worktree directories, or change the list/remove the stray markdown reference to reflect "15 worktree dirs + 1 stray markdown file `CODEX_REBOOT_RESUME_20260503.md`" so the bold count, the stray-file note, and the enumerated worktree entries are all consistent. ``` </details> </blockquote></details> <details> <summary>03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/core-repos/Hermes3D.md-15-20 (1)</summary><blockquote> `15-20`: _⚠️ Potential issue_ | _🟡 Minor_ | _⚡ Quick win_ **Add a language tag to the fenced commit block.** Line [15] opens a fence without language, which trips MD040 in strict markdownlint setups. <details> <summary>Suggested patch</summary> ```diff -``` +```text 6020de8 2026-05-03 chore: fully exclude apps/ from git (vendored installs, local-only) 5b11f6c 2026-05-03 docs(adr): ADR-014 — audit of blender-mcp-native (verdict: REJECT) c3e68d1 2026-05-03 docs(handoff): overnight Codex queue — 1 master + 6 task briefs + roadmap b767100 2026-05-03 feat(backup): local-only secrets backup — Syncthing + Restic-B2 scripts ``` ``` </details> <details> <summary>🤖 Prompt for AI Agents</summary>Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.In
@03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/core-repos/Hermes3D.md
around lines 15 - 20, The fenced commit block containing the four commits
(starting with the line "6020de8 2026-05-03 chore: fully exclude apps/...") is
missing a language tag and triggers MD040; fix it by changing the opening fence
from "" to include a language (e.g., "text") so the block becomes a fenced
code block with a language tag.</details> </blockquote></details> <details> <summary>03_implementation/docs/handoffs/INTEGRATION_REPORT_2026-05-06.md-141-145 (1)</summary><blockquote> `141-145`: _⚠️ Potential issue_ | _🟡 Minor_ | _⚡ Quick win_ **Add a language tag to the fenced code block.** Line 141 opens a fenced block without a language identifier, which trips markdown linting (MD040). <details> <summary>Suggested fix</summary> ```diff -``` +```text Batch 1 (parallel): `#53`, `#54`, `#55`, `#56`, `#57`, `#58`, `#59`, `#60`, `#61`, `#62`, `#63`, `#65`, `#67`, `#68`, `#70` Batch 2 (sequential): `#66` → `#69` (resolve app.py union) Batch 3 (sequential): `#64` → `#71` (resolve adapters.ts / adapters.live.ts union) ``` ``` </details> <details> <summary>🤖 Prompt for AI Agents</summary>Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.In
@03_implementation/docs/handoffs/INTEGRATION_REPORT_2026-05-06.mdaround
lines 141 - 145, The fenced code block that currently opens withis missing a language tag and triggers MD040; update its opening fence to include a language identifier (e.g., changeto ```text) for the block containing the
three "Batch" lines (the block that lists "Batch 1 (parallel):#53, ...", "Batch
2 (sequential): `#66` → `#69` (resolve app.py union)", and "Batch 3 (sequential):
`#64` → `#71` (resolve adapters.ts / adapters.live.ts union)"), then re-run the
markdown linter to confirm MD040 is resolved.</details> </blockquote></details> <details> <summary>03_implementation/docs/handoffs/claude-e2e-intelligence-2026-05-08/08_PR_AND_MERGE_QUEUE.md-42-42 (1)</summary><blockquote> `42-42`: _⚠️ Potential issue_ | _🟡 Minor_ | _⚡ Quick win_ **Add a language tag to the fenced code block.** Line 42 opens a fenced block without a language, which triggers markdownlint MD040. <details> <summary>Suggested edit</summary> ```diff -``` +```text ``` </details> <details> <summary>🤖 Prompt for AI Agents</summary>Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.In
@03_implementation/docs/handoffs/claude-e2e-intelligence-2026-05-08/08_PR_AND_MERGE_QUEUE.md
at line 42, The fenced code block opened with justshould include a language tag to satisfy markdownlint MD040; update the opening fence fromtotext (i.e., replace the bare triple-backtick fence withtext) so the block is
explicitly marked as text.</details> </blockquote></details> <details> <summary>03_implementation/docs/handoffs/claude-e2e-intelligence-2026-05-08/05_TAB_BY_TAB_ACTIVE_UI_NO_FAKE_AUDIT.md-21-21 (1)</summary><blockquote> `21-21`: _⚠️ Potential issue_ | _🟡 Minor_ | _⚡ Quick win_ **Escape the pipe character in the code span to keep table columns intact.** Line 21 uses `config|logs` inside a table cell; the pipe splits columns and breaks rendering. <details> <summary>Suggested edit</summary> ```diff -| Plugins | `src/tabs/Plugins.tsx` | `adapters.getPlugins()`, `activatePlugin()`, `getModuleUpdateReadiness()`, `getModuleRuntimeSetupQueue()`, `planModuleRuntimeSetupQueue()`, `fetch(/api/plugins/{id}/config|logs)`, `emitProofEvent("plugins.plugin.state.changed")` | Left panel (plugin list) + right panel (config/logs/details), resizable divider | Part of Primary TABS, visible in Simple, same update-readiness status | NEEDED — plugin activate/state-change wiring complete; update-readiness summary live; transcript/proof review UI next; setup queue status visible but plan execution remains proof-gated | PARTIAL | +| Plugins | `src/tabs/Plugins.tsx` | `adapters.getPlugins()`, `activatePlugin()`, `getModuleUpdateReadiness()`, `getModuleRuntimeSetupQueue()`, `planModuleRuntimeSetupQueue()`, `fetch(/api/plugins/{id}/config\|logs)`, `emitProofEvent("plugins.plugin.state.changed")` | Left panel (plugin list) + right panel (config/logs/details), resizable divider | Part of Primary TABS, visible in Simple, same update-readiness status | NEEDED — plugin activate/state-change wiring complete; update-readiness summary live; transcript/proof review UI next; setup queue status visible but plan execution remains proof-gated | PARTIAL | ``` </details> <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@03_implementation/docs/handoffs/claude-e2e-intelligence-2026-05-08/05_TAB_BY_TAB_ACTIVE_UI_NO_FAKE_AUDIT.md` at line 21, The table cell contains an unescaped pipe in the code span `fetch(/api/plugins/{id}/config|logs)` which breaks the Markdown table; update that code span in 03_implementation/docs/handoffs/claude-e2e-intelligence-2026-05-08/05_TAB_BY_TAB_ACTIVE_UI_NO_FAKE_AUDIT.md by escaping the pipe (e.g. change to `fetch(/api/plugins/{id}/config\|logs)` or split into two code spans) so the table columns render correctly while keeping the exact endpoint text. ``` </details> </blockquote></details> <details> <summary>03_implementation/docs/handoffs/claude-e2e-intelligence-2026-05-08/08_PR_AND_MERGE_QUEUE.md-107-107 (1)</summary><blockquote> `107-107`: _⚠️ Potential issue_ | _🟡 Minor_ | _⚡ Quick win_ **Fix duplicated sequence index in the merge order line.** Line 107 repeats `5.` twice in the same chain item, which makes the runbook harder to follow during manual merges. <details> <summary>Suggested edit</summary> ```diff -5. **PR `#84`** → 5. **PR `#85`** → 6. **PR `#87`** → 7. **PR `#88`** → 8. **PR `#89`** → 9. **PR `#90`** → 10. **PR `#91`** → 11. **PR `#92`** → 12. **PR `#93`** → 13. **PR `#94`** → 14. **PR `#95`** → 15. **PR `#96`** → 16. **PR `#97`** → 17. **PR `#98`** → 18. **PR `#99`** → 19. **PR `#100`** → 20. **PR `#101`** → 21. **PR `#102`** → 22. **PR `#103`** → 23. **PR `#104`** (chain head). +5. **PR `#84`** → **PR `#85`** → **PR `#87`** → **PR `#88`** → **PR `#89`** → **PR `#90`** → **PR `#91`** → **PR `#92`** → **PR `#93`** → **PR `#94`** → **PR `#95`** → **PR `#96`** → **PR `#97`** → **PR `#98`** → **PR `#99`** → **PR `#100`** → **PR `#101`** → **PR `#102`** → **PR `#103`** → **PR `#104`** (chain head). ``` </details> <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@03_implementation/docs/handoffs/claude-e2e-intelligence-2026-05-08/08_PR_AND_MERGE_QUEUE.md` at line 107, The merge-order line currently contains a duplicated "5." making the sequence non-sequential; update the numeric prefixes in the chain "5. **PR `#84`** → 5. **PR `#85`** → 6. **PR `#87`** … **PR `#104`**" so the numbers increase by one across each item (no duplicates)—for example change the second "5." (the prefix for **PR `#85`**) to "6." and then bump all subsequent numeric prefixes accordingly so the entire chain is strictly sequential. ``` </details> </blockquote></details> <details> <summary>03_implementation/docs/security/MCP_BOUNDARY_NOTES.md-31-37 (1)</summary><blockquote> `31-37`: _⚠️ Potential issue_ | _🟡 Minor_ | _⚡ Quick win_ **Fix table formatting: escape pipes in code spans.** The "Policy gates" table has pipes inside backticks on line 36, which markdown parsers interpret as column separators, causing the table to render incorrectly in many viewers. <details> <summary>📝 Proposed fix to escape the pipes</summary> ```diff -| Injection scanner fail-closed | `InjectionScanner(fail_threshold='high'|'medium'|'low')` | `ScanResult.fail_closed=True` when severity >= threshold | +| Injection scanner fail-closed | `InjectionScanner(fail_threshold='high'\|'medium'\|'low')` | `ScanResult.fail_closed=True` when severity >= threshold | ``` Alternatively, use HTML entity encoding: ```diff -| Injection scanner fail-closed | `InjectionScanner(fail_threshold='high'|'medium'|'low')` | `ScanResult.fail_closed=True` when severity >= threshold | +| Injection scanner fail-closed | `InjectionScanner(fail_threshold='high'|'medium'|'low')` | `ScanResult.fail_closed=True` when severity >= threshold | ``` </details> <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@03_implementation/docs/security/MCP_BOUNDARY_NOTES.md` around lines 31 - 37, The table's backticked code spans contain unescaped pipe characters (e.g., in `agent_runtime.trusted_runtime_url`, `InjectionScanner(fail_threshold='high'|'medium'|'low')`, and `module_runtime._redact_text`) which break Markdown table columns; update those code spans to escape the pipe characters (replace | with \| inside the backticks) or encode them as | so the table renders correctly, ensuring you only change the literal pipe characters inside the backticks in the "Policy gates" table. ``` </details> </blockquote></details> <details> <summary>03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/core-repos/Hermes3D-handoffs.md-15-26 (1)</summary><blockquote> `15-26`: _⚠️ Potential issue_ | _🟡 Minor_ | _⚡ Quick win_ **Add a language identifier to the fenced code block (MD040).** This fence should be typed (for example `text`) to satisfy markdownlint. <details> <summary>Proposed diff</summary> ```diff -``` +```text d7336a5 2026-05-02 docs(handoff): HANDOFF_TO_CODEX_CP5.1-C.md (architect brief) e25fe7e 2026-05-02 Merge pull request `#17` from Ghenghis/feat/phase-3-4-real-provider-probes ... e1df84d 2026-05-02 chore: remove accidental file from PR ``` ``` </details> <details> <summary>🤖 Prompt for AI Agents</summary>Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.In
@03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/core-repos/Hermes3D-handoffs.md
around lines 15 - 26, The markdown fenced code block in Hermes3D-handoffs.md is
missing a language identifier (MD040); update the triple-backtick fence that
wraps the git log snippet by adding a language tag (e.g., ```text) so the block
becomes a typed fenced code block, preserving the existing content lines (the
commits starting with d7336a5 ... e1df84d).</details> </blockquote></details> <details> <summary>03_implementation/adapter_registry/schemas/meshlab_bridge.schema.json-51-58 (1)</summary><blockquote> `51-58`: _⚠️ Potential issue_ | _🟡 Minor_ | _⚡ Quick win_ **Standardize `version_probe.mode` enum to match `kind` vocabulary.** The schema defines `kind` with enum values `["cli", "python_import"]` but `version_probe.mode` uses `["cli_args", "python_import"]`. This vocabulary mismatch (cli vs cli_args) should be aligned. While the current `verify_modelers.py` uses `kind` directly and does not consume `version_probe.mode` from the schema, this inconsistency could confuse future consumers or alternate implementations that rely on schema-driven branching. <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@03_implementation/adapter_registry/schemas/meshlab_bridge.schema.json` around lines 51 - 58, Align the vocabularies by changing the version_probe.mode enum to use the same "cli" token as kind; update the "mode" property's enum from ["cli_args", "python_import"] to ["cli", "python_import"] (and adjust any defaults or consumers if they expect "cli_args") so that the "kind" field and "version_probe.mode" use the same CLI identifier. ``` </details> </blockquote></details> <details> <summary>03_implementation/docs/handoffs/claude-e2e-intelligence-2026-05-08/01_GITHUB_FOLDER_ECOSYSTEM_AUDIT.md-169-171 (1)</summary><blockquote> `169-171`: _⚠️ Potential issue_ | _🟡 Minor_ | _⚡ Quick win_ **Line 170 suggests an upstream command that conflicts with the stated deleted-remote condition.** If `origin/chore/exclude-apps-folder` is deleted, `git branch -u origin/chore/exclude-apps-folder` is not the right remediation. <details> <summary>Suggested doc fix</summary> ```diff - `git branch -u origin/chore/exclude-apps-folder` or delete dangling branch. + `git branch --unset-upstream chore/exclude-apps-folder` or delete the local branch. ``` </details> <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@03_implementation/docs/handoffs/claude-e2e-intelligence-2026-05-08/01_GITHUB_FOLDER_ECOSYSTEM_AUDIT.md` around lines 169 - 171, The suggested remediation tries to set the local Hermes3D branch to track a remote branch that may have been deleted (origin/chore/exclude-apps-folder); instead update the doc to instruct one of three correct actions for the Hermes3D branch: delete the local dangling branch (git branch -D Hermes3D), unset its upstream (git branch --unset-upstream Hermes3D) if you want to keep it local, or set it to a valid remote branch (git branch -u origin/<correct-branch> Hermes3D) if a replacement exists; replace the current `git branch -u origin/chore/exclude-apps-folder` recommendation with these options and reference the Hermes3D branch and origin/chore/exclude-apps-folder names in the text. ``` </details> </blockquote></details> <details> <summary>03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/h3dos-codex-tasks/h3dos-codex-fluidd.md-36-45 (1)</summary><blockquote> `36-45`: _⚠️ Potential issue_ | _🟡 Minor_ | _⚡ Quick win_ **Add blank lines around the `Key files` table to satisfy MD058.** This currently fails markdownlint for table spacing. <details> <summary>Suggested doc fix</summary> ```diff ## Key files + | Role | Path | |---|---| | Verifier (build) | `apps/api/hermes3d_api/source_install.py::_install_npm_build` (line 521) | | Subprocess invocation | `source_install.py` line 509 (`subprocess.run` for `npm ci`/`npm run build`) | | Registry / schema | `apps/web/source_manifest.json` line 277 | | E2E test | `tests/e2e/app-fluidd.spec.ts` | | Static mount | `static_url: /static/fluidd/` in manifest install block | + ## Integration path diagram ``` </details> <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/h3dos-codex-tasks/h3dos-codex-fluidd.md` around lines 36 - 45, The markdownlint error MD058 is caused by the "Key files" table not being separated by blank lines; update the document `h3dos-codex-fluidd.md` by inserting a blank line immediately before the "## Key files" heading block (or at least one blank line above the table) and a blank line after the table (before the "Integration path diagram" heading) so the table is surrounded by empty lines; ensure the table rows (including the header) remain unchanged and re-run markdownlint to confirm MD058 is resolved. ``` </details> </blockquote></details> <details> <summary>03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/hermesproof/README.md-7-9 (1)</summary><blockquote> `7-9`: _⚠️ Potential issue_ | _🟡 Minor_ | _⚡ Quick win_ **Add a language tag to the fenced block to satisfy markdownlint (MD040).** Line 7 starts a fenced code block without a language, which triggers the reported markdownlint warning. <details> <summary>Proposed fix</summary> ```diff -``` +```text TRIGGER → WIZARD-GATES → QUEUE → NEXT-TASK (consumer) ``` ``` </details> <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/hermesproof/README.md` around lines 7 - 9, The fenced code block containing "TRIGGER → WIZARD-GATES → QUEUE → NEXT-TASK (consumer)" is missing a language tag (MD040); update that fenced block in README.md by adding a language identifier (e.g., "text") after the opening backticks and ensure the closing backticks remain, so the block becomes a fenced code block with a language tag to satisfy markdownlint. ``` </details> </blockquote></details> <details> <summary>03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/apps-vendored/blender-main.md-5-5 (1)</summary><blockquote> `5-5`: _⚠️ Potential issue_ | _🟡 Minor_ | _⚡ Quick win_ **Use repo-style forward slashes for path references.** `apps\blender` is easy to misread in markdown and is inconsistent with standard repo path notation. Prefer `apps/blender` in both places. <details> <summary>Proposed fix</summary> ```diff -Second vendored snapshot of the Blender source tree, mirroring the upstream `main` branch. Functionally identical to `apps\blender` at the time of capture; the duplicate is most likely retained for diff/audit purposes (e.g. comparing a tagged release vs. main) by Hermes3D OS build pipelines. Same role as the sibling `blender/` folder: 3D modeling stage that produces STL/OBJ for downstream slicing. +Second vendored snapshot of the Blender source tree, mirroring the upstream `main` branch. Functionally identical to `apps/blender` at the time of capture; the duplicate is most likely retained for diff/audit purposes (e.g. comparing a tagged release vs. main) by Hermes3D OS build pipelines. Same role as the sibling `blender/` folder: 3D modeling stage that produces STL/OBJ for downstream slicing. @@ -INFERRED: same module registry entry shape as `apps\blender`, distinguished by a `branch: main` tag. Probable use: +INFERRED: same module registry entry shape as `apps/blender`, distinguished by a `branch: main` tag. Probable use: ``` </details> Also applies to: 31-31 <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/apps-vendored/blender-main.md` at line 5, Replace the Windows-style path string `apps\blender` with the repo-style `apps/blender` in the markdown text and ensure any other occurrences (including the sibling reference `blender/`) use forward slashes consistently; update both instances mentioned in the diff so all path references follow standard repo-style notation. ``` </details> </blockquote></details> <details> <summary>03_implementation/docs/handoffs/audit/NOFAKE_UI_AUDIT_RESULT_2026-05-06.md-2-3 (1)</summary><blockquote> `2-3`: _⚠️ Potential issue_ | _🟡 Minor_ | _⚡ Quick win_ **Align in-file date with artifact naming/task date.** Line 2 (`2026-05-07`) conflicts with both the filename and task date (`2026-05-06`). Please make one canonical date explicit. <details> <summary>Proposed fix (if this artifact is intended for 2026-05-06)</summary> ```diff -Date: 2026-05-07 +Date: 2026-05-06 ``` </details> <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@03_implementation/docs/handoffs/audit/NOFAKE_UI_AUDIT_RESULT_2026-05-06.md` around lines 2 - 3, The Date field in the document header currently reads "2026-05-07" but conflicts with the filename and Task value; update the Date header to the canonical date "2026-05-06" to match NOFAKE_UI_AUDIT_RESULT_2026-05-06.md and the Task "H3D-CLAUDE-POLISH-NOFAKE-UI-2026-05-06", ensuring the top-of-file "Date:" entry is changed to 2026-05-06. ``` </details> </blockquote></details> <details> <summary>03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/h3dos-codex-tasks/h3dos-codex-blender-cli.md-36-43 (1)</summary><blockquote> `36-43`: _⚠️ Potential issue_ | _🟡 Minor_ | _⚡ Quick win_ **Add a blank line before the table to satisfy markdownlint MD058.** This keeps the file lint-clean and consistent with markdown table formatting rules. <details> <summary>Proposed fix</summary> ```diff ## Key files + | Role | Path | |---|---| | Verifier | `apps/api/hermes3d_api/source_install.py::_install_clone` (line 367) | | Smoke probe | `source_install.py` line 165 (`subprocess.run(smoke_cmd, ..., timeout=60)`) | | Registry / schema | `apps/web/source_manifest.json` line 127 | | E2E test | `tests/e2e/app-blender-cli.spec.ts` | | Env override | `HERMES3D_BLENDER_PATH` | ``` </details> <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/h3dos-codex-tasks/h3dos-codex-blender-cli.md` around lines 36 - 43, Add a single blank line between the "## Key files" heading and the Markdown table that follows to satisfy markdownlint rule MD058; locate the "## Key files" heading and the table rows (the lines listing Role/Path and the backtick paths such as apps/api/hermes3d_api/source_install.py::_install_clone) and insert one empty line immediately after the heading. ``` </details> </blockquote></details> <details> <summary>03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/source-os-60-apps/README.md-13-17 (1)</summary><blockquote> `13-17`: _⚠️ Potential issue_ | _🟡 Minor_ | _⚡ Quick win_ **Replace machine-local absolute paths with repo-relative paths.** These references are currently tied to one workstation (`G:\...`) and won’t be usable for most readers. <details> <summary>Proposed fix</summary> ```diff -- Registry YAML: `G:\Github\Hermes3D\Hermes3D-GUI-Wiring-Contract-Kit\03_REPO_REGISTRY\external_repos_registry.yaml` -- Truth-audit JSON fallback: `G:\Github\h3d-gui-wiring-codex\03_implementation\proof\SOURCE_REGISTRY_TRUTH_AUDIT.json` -- Loader: `G:\Github\h3d-gui-wiring-codex\03_implementation\src\hermes3d\db\load_modules.py` -- Schema: `G:\Github\h3d-gui-wiring-codex\03_implementation\src\hermes3d\db\schema.sql` -- API route: `G:\Github\h3d-gui-wiring-codex\03_implementation\src\hermes3d\api\routes\modules.py` +- Registry YAML: `03_REPO_REGISTRY/external_repos_registry.yaml` +- Truth-audit JSON fallback: `03_implementation/proof/SOURCE_REGISTRY_TRUTH_AUDIT.json` +- Loader: `03_implementation/src/hermes3d/db/load_modules.py` +- Schema: `03_implementation/src/hermes3d/db/schema.sql` +- API route: `03_implementation/src/hermes3d/api/routes/modules.py` ``` </details> <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/source-os-60-apps/README.md` around lines 13 - 17, Replace the machine-local absolute paths in this README with repo-relative paths so they work for other developers; update the listed entries (external_repos_registry.yaml, SOURCE_REGISTRY_TRUTH_AUDIT.json, load_modules.py, schema.sql, and modules.py) to point to their relative locations inside the repository (e.g., the 03_REPO_REGISTRY and 03_implementation subfolders) and ensure paths use forward slashes and are quoted or formatted consistently in the README. ``` </details> </blockquote></details> </blockquote></details> <details> <summary>🧹 Nitpick comments (7)</summary><blockquote> <details> <summary>03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/h3dos-wire-tasks/h3dos-wire-printers-row-click.md (1)</summary><blockquote> `10-16`: _⚡ Quick win_ **Clarify `enabled=false` click behavior in the wire contract.** The doc lists `enabled` in `printers[]` and references adding the flag, but it doesn’t define expected UX behavior for disabled printers (click opens Action Window vs blocked/disabled state). Please make this explicit so implementation and E2E assertions stay aligned. <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/h3dos-wire-tasks/h3dos-wire-printers-row-click.md` around lines 10 - 16, Update the wire contract to explicitly state the expected UX when a printer's enabled flag is false and implement corresponding checks: in the document that describes printers[] add a sentence that defines whether clicking a disabled printer should open the Action Window (kind=printer) or be ignored/blocked and what visual/ARIA state is expected; update the click handler in apps/web/app.js (the printer-card click handler scoped to `#printers`) to enforce that behavior by checking printer.enabled before opening the Action Window; and adjust tests in tests/e2e/wire-printers-row-click-actionwindow.spec.ts to assert the chosen behavior for enabled=true and enabled=false cases so E2E expectations match the wire doc. ``` </details> </blockquote></details> <details> <summary>03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/h3dos-wire-tasks/h3dos-wire-dashboard-queue-list.md (1)</summary><blockquote> `20-26`: _⚡ Quick win_ **Make OPEN status reproducible with timestamped verification metadata.** “Not detected … from this checkout” is useful but environment-dependent; add a verification timestamp + exact git command/output snippet so future readers can re-validate quickly. <details> <summary>Proposed doc patch</summary> ```diff ## Status -**OPEN** — wire commit on local branch only; not on `origin/main` and not detected on `origin/develop` from this checkout. +**OPEN** — wire commit on local branch only; not on `origin/main` and not detected on `origin/develop` from this checkout. + +Verification snapshot: +- Checked at: `2026-05-07` +- Command: `git branch -a --contains 9b6503d` +- Result: commit present on `wire/dashboard-queue-list` only. ``` </details> <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/h3dos-wire-tasks/h3dos-wire-dashboard-queue-list.md` around lines 20 - 26, The "Status OPEN" note is environment-dependent; update the Status block for the `wire/dashboard-queue-list` entry (last commit 9b6503d) to include a timestamped verification line and the exact git commands and trimmed output used to check remote visibility (for example the git fetch and git branch/log commands you ran and their short output), so readers can reproduce the check; include the ISO-8601 timestamp, the exact commands used (e.g., git fetch --all and the git branch/log invocation you used) and a one- or two-line captured output showing the branch/commit not present on origin to make the verification reproducible. ``` </details> </blockquote></details> <details> <summary>03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/h3dos-wire-tasks/h3dos-wire-source-os-status-pills.md (1)</summary><blockquote> `12-12`: _⚡ Quick win_ **Replace machine-local absolute path with repo-relative path.** Line 12 embeds a workstation-specific `G:\...` path; this is brittle in shared docs and leaks local environment details. Prefer a repo-relative path or omit it. <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/h3dos-wire-tasks/h3dos-wire-source-os-status-pills.md` at line 12, Replace the machine-local absolute path string "**Path**: `G:\Github\h3dos-wire-source-os-status-pills`" with a repo-relative path or remove it; update the markdown to use a repo-relative reference like `docs/h3dos-wire-source-os-status-pills` (or simply omit the Path line) so the document no longer contains workstation-specific G:\... paths. ``` </details> </blockquote></details> <details> <summary>03_implementation/adapter_registry/schemas/trellis2.schema.json (1)</summary><blockquote> `15-22`: _⚡ Quick win_ **Add URI format checks for URL fields** Line 15 and Line 44 define URL-like strings but currently accept any string. Adding URI format validation will catch malformed values earlier. <details> <summary>Proposed patch</summary> ```diff "endpoint": { "type": [ "string", "null" ], + "format": "uri", "default": null, "description": "Optional local or service endpoint URL." }, @@ "source_repo": { "type": [ "string", "null" ], + "format": "uri", "default": "https://github.com/microsoft/TRELLIS.git", "description": "Upstream git repo (used by verify_gen3d.py via git ls-remote, no clone)." }, ``` </details> Also applies to: 44-50 <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@03_implementation/adapter_registry/schemas/trellis2.schema.json` around lines 15 - 22, The "endpoint" schema property currently allows any string; add URI validation by adding "format": "uri" to the "endpoint" property while preserving its type ["string","null"] and default null, and likewise add "format": "uri" to the other URL-like schema property defined around lines 44-50 so both fields validate as URIs; ensure you only add the "format" key (no type change) so existing nullability and defaults remain intact. ``` </details> </blockquote></details> <details> <summary>03_implementation/ROADMAP.md (1)</summary><blockquote> `31-31`: _⚡ Quick win_ **Refactor extremely long table cell for readability.** Line 31 contains several hundred words within a single table cell describing the Source OS completion state. This makes the completion ledger table difficult to read, navigate, and maintain in markdown. Consider refactoring to: - Keep a brief 1-2 sentence summary in the table cell (e.g., "60/60 source-backed rows proven, 36 verifier-backed ready, 24 runner gaps; detailed runtime matrix and CLI surface audit available. See §1.6 for full breakdown.") - Move the detailed runner contract matrix, CLI surface audit, verifier family details, and proof IDs to a dedicated subsection under "Primary Work Packages" or "60 Source App Completion Plan" This improves scanability of the completion ledger while preserving all technical detail. <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@03_implementation/ROADMAP.md` at line 31, The long table cell under the "Source OS" entry (currently the huge paragraph on line 31) should be condensed to a 1–2 sentence summary (e.g., "60/60 source-backed rows proven, 36 verifier-backed ready, 24 runner gaps; detailed runtime matrix and CLI surface audit available. See §1.6 for full breakdown.") and all detailed material (the runtime runner contract matrix, verifier probe inventory, CLI-surface audit, HERMES3D keys, and loader/firmware notes) moved into a new dedicated subsection titled "60 Source App Completion Plan" (or under "Primary Work Packages") elsewhere in the document; create that subsection and paste the full original text there, keeping the table cell concise and adding an internal cross-reference to the new subsection for the full breakdown. ``` </details> </blockquote></details> <details> <summary>00_overview/contract/MASTER_CONTRACT.md (1)</summary><blockquote> `89-93`: _⚡ Quick win_ **Consider clarifying the scope of Rule 11's "currently" qualifier.** The rule mixes contract-level enforcement ("must return a lock failure") with operational state ("currently offline/locked/no-test"). This creates ambiguity: - Is this a **permanent safety mechanism** that requires explicit user clearance for S1 actions? - Or is this a **temporary operational state** that will be removed from the contract when S1 is cleared? If the intent is to establish a permanent safety gate requiring user clearance before any S1 action, consider rewording to emphasize the mechanism: > **S1 safety gate.** FLSUN S1 at `192.168.0.12` requires explicit operator clearance before any movement, upload, capture, or test action. Until clearance is granted, these actions must fail with a safety lock error. Operators and Hermes Agents may edit status metadata regardless of lock state. This removes the temporal "currently" while preserving the safety requirement. <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@00_overview/contract/MASTER_CONTRACT.md` around lines 89 - 93, Update Rule 11 to remove the temporal "currently" and make the safety requirement explicit: replace the "Current S1 safety lock" paragraph with a permanent-sounding clause (e.g., rename to "S1 safety gate") that states FLSUN S1 at `192.168.0.12` requires explicit operator clearance before any movement, upload, capture, or test action and that these actions must fail with a safety lock error until clearance is granted, while still allowing Operators and Hermes Agents to edit status metadata; ensure the new wording replaces the existing sentence that mixes operational state and contract enforcement. ``` </details> </blockquote></details> <details> <summary>03_implementation/docs/handoffs/claude-e2e-intelligence-2026-05-08/04_SOURCE_OS_60_APP_COMPLETION_MAP.md (1)</summary><blockquote> `242-250`: _⚡ Quick win_ **Consider clarifying the summary counts relationship.** The summary states: - Ready-to-go: 7 apps - One pass away: 16 near-term registrations - Repair queue: 15 modules - No runner ever: 18 reference/firmware/catalog sources - Blocked: 2 slicers These categories don't sum to 60 apps (they sum to 58), which might cause confusion. This could be because: 1. Some apps appear in multiple categories (e.g., an app might be "near-term" for one runner but need "repair" for another aspect) 2. The "16 near-term registrations" refers to runner implementations, not unique apps 3. Some apps are counted elsewhere Consider adding a brief note explaining the category overlap or clarifying that the counts represent runner work items rather than mutually exclusive app states. <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@03_implementation/docs/handoffs/claude-e2e-intelligence-2026-05-08/04_SOURCE_OS_60_APP_COMPLETION_MAP.md` around lines 242 - 250, The summary counts ("Ready-to-go", "One pass away", "Repair queue", "No runner ever", "Blocked") currently sum to 58 and may overlap; add a brief clarifying sentence under the Summary explaining how counts are computed (e.g., that "One pass away" = 16 runner registrations not unique apps, some apps appear in multiple categories, and counts count runner work-items rather than mutually exclusive app states) and show how these map to the total of 60 (for example by stating "Totals count runner work-items; unique apps = X, total items = 60"). Ensure this note is adjacent to the existing bullet list so readers immediately understand the relationship. ``` </details> </blockquote></details> </blockquote></details> <!-- This is an auto-generated comment by CodeRabbit for review status -->
| | Runtime ID | Printer | Moonraker IP | Current state | Test/upload/move | | ||
| |---|---|---:|---|---| | ||
| | `flsun_t1_a` | T1 #1 | `192.168.0.10` | online ready | allowed through safety gates | | ||
| | `flsun_t1_b` | T1 #2 | `192.168.0.11` | online ready | allowed through safety gates | | ||
| | `flsun_s1` | FLSUN S1 | `192.168.0.12` | offline/locked/no-test | blocked until user clears lock | | ||
| | `flsun_v400` | FLSUN V400 | `192.168.0.34` | online ready | allowed through safety gates | | ||
|
|
There was a problem hiding this comment.
Remove real internal printer IPs from committed docs.
Lines 34–40 disclose live LAN addresses. Even in docs, this weakens security posture and unnecessarily exposes internal infrastructure details. Use placeholders (or host aliases) instead.
Suggested redaction
-| `flsun_t1_a` | T1 `#1` | `192.168.0.10` | online ready | allowed through safety gates |
-| `flsun_t1_b` | T1 `#2` | `192.168.0.11` | online ready | allowed through safety gates |
-| `flsun_s1` | FLSUN S1 | `192.168.0.12` | offline/locked/no-test | blocked until user clears lock |
-| `flsun_v400` | FLSUN V400 | `192.168.0.34` | online ready | allowed through safety gates |
+| `flsun_t1_a` | T1 `#1` | `<moonraker-host-a>` | online ready | allowed through safety gates |
+| `flsun_t1_b` | T1 `#2` | `<moonraker-host-b>` | online ready | allowed through safety gates |
+| `flsun_s1` | FLSUN S1 | `<moonraker-host-s1>` | offline/locked/no-test | blocked until user clears lock |
+| `flsun_v400` | FLSUN V400 | `<moonraker-host-v400>` | online ready | allowed through safety gates |🤖 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 `@01_requirements/PRINTER_FLEET_GUIDE.md` around lines 34 - 40, The table
contains real internal LAN IPs for runtime IDs flsun_t1_a, flsun_t1_b, flsun_s1,
and flsun_v400; replace those concrete addresses with neutral placeholders or
host aliases (e.g., <PRINTER_IP> or printer-hostname.local) in the "Moonraker
IP" column and remove any other literal LAN addresses elsewhere; ensure the
placeholders are used consistently and, if necessary, add a short note above the
table explaining that IPs are redacted and resolved via internal DNS or
inventory.
| "cli_supported": { | ||
| "type": "boolean", | ||
| "default": false, | ||
| "description": "False — BambuStudio does not expose a stable headless CLI version command." | ||
| }, | ||
| "metadata_only": { | ||
| "type": "boolean", | ||
| "default": true, | ||
| "description": "When true, verification uses filesystem metadata only (no launch)." | ||
| }, |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify fixed-capability fields are truly constrained by schema keywords.
rg -n -C2 '"cli_supported"|"metadata_only"|"const"|"default"' 03_implementation/adapter_registry/schemas/bambu_studio_slicer.schema.json
# Expected: `cli_supported` and `metadata_only` use `const`, not only `default`.Repository: Ghenghis/Hermes3D
Length of output: 819
🏁 Script executed:
# Find all references to bambu_studio_slicer.schema.json
rg -l "bambu_studio_slicer" --type json --type ts --type js --type pyRepository: Ghenghis/Hermes3D
Length of output: 136
🏁 Script executed:
# Search for schema validation mechanisms
rg -n "ajv|jsonschema|validateAgainstSchema|validateSchema" --type ts --type js --type py | head -20Repository: Ghenghis/Hermes3D
Length of output: 2112
🏁 Script executed:
# Look for where adapter schemas are loaded/used
rg -n "adapter.*schema|schema.*adapter" --type ts --type js -A 2 -B 2 | head -40Repository: Ghenghis/Hermes3D
Length of output: 43
🏁 Script executed:
# Check if there's a test file or validation for this specific schema
fd -e "test\\..*" -o -e "spec\\..*" -o -e "\\.test\\." | xargs rg -l "bambu_studio_slicer\|cli_supported\|metadata_only" 2>/dev/null | head -10Repository: Ghenghis/Hermes3D
Length of output: 178
🏁 Script executed:
# Examine the adapter config schemas test file
cat -n 04_testing/pytest/unit/adapters/test_config_schemas.pyRepository: Ghenghis/Hermes3D
Length of output: 6544
🏁 Script executed:
# Look for any test data or fixtures for bambu_studio
find . -type f -name "*bambu*" | head -20Repository: Ghenghis/Hermes3D
Length of output: 214
🏁 Script executed:
# Check if there are any actual data files using this schema
find . -type f -name "*.json" -o -name "*.yaml" | xargs rg -l "cli_supported\|metadata_only" 2>/dev/null | head -10Repository: Ghenghis/Hermes3D
Length of output: 43
🏁 Script executed:
# Check if bambustudio_bridge is in the test EXPECTED list and compare schemas
cat -n 03_implementation/adapter_registry/schemas/bambustudio_bridge.schema.json | head -30Repository: Ghenghis/Hermes3D
Length of output: 1057
🏁 Script executed:
# Search for any Python code that references bambu_studio or uses this schema
rg "bambu" --type py -iRepository: Ghenghis/Hermes3D
Length of output: 5269
🏁 Script executed:
# Check if there's a data file or config using this schema
find . -type f \( -name "*.json" -o -name "*.yaml" -o -name "*.yml" \) -exec rg -l "bambustudio\|bambu_studio" {} \; 2>/dev/nullRepository: Ghenghis/Hermes3D
Length of output: 43
🏁 Script executed:
# Look at the full bambu_studio_slicer schema to understand its structure
cat -n 03_implementation/adapter_registry/schemas/bambu_studio_slicer.schema.jsonRepository: Ghenghis/Hermes3D
Length of output: 1609
Use const to enforce immutable adapter capabilities, and integrate schema into test coverage.
cli_supported and metadata_only are described as fixed behavior, but the current schema uses default which does not enforce constraints in JSON Schema validation. Replace type + default with const for these two fields.
Additionally, bambu_studio_slicer.schema.json is not included in the validation test suite (see test_config_schemas.py EXPECTED list). Add this schema to the test coverage alongside the const fix.
Suggested schema fix
"cli_supported": {
- "type": "boolean",
- "default": false,
+ "const": false,
"description": "False — BambuStudio does not expose a stable headless CLI version command."
},
"metadata_only": {
- "type": "boolean",
- "default": true,
+ "const": true,
"description": "When true, verification uses filesystem metadata only (no launch)."
},Also add "bambu_studio_slicer" to the EXPECTED list in 04_testing/pytest/unit/adapters/test_config_schemas.py.
🤖 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 `@03_implementation/adapter_registry/schemas/bambu_studio_slicer.schema.json`
around lines 20 - 29, Replace the non-enforcing "type" + "default" entries for
the schema fields cli_supported and metadata_only in
bambu_studio_slicer.schema.json with const values (use "cli_supported": {
"const": false, "description": "…" } and "metadata_only": { "const": true,
"description": "…" }) so these capabilities are immutable; then add
"bambu_studio_slicer" to the EXPECTED list in the test (variable EXPECTED in
test_config_schemas.py) so the schema is included in validation coverage.
| "safe_probe_args": { | ||
| "type": "array", | ||
| "items": {"type": "string"}, | ||
| "default": ["help"], | ||
| "description": "Arguments used for the read-only version probe. Never include 'slice'." | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify the schema actually encodes the safety rule for probe args.
rg -n -C3 '"safe_probe_args"|"contains"|"not"|"minItems"|"slice"' 03_implementation/adapter_registry/schemas/curaengine.schema.json
# Expected: a `not` + `contains` constraint preventing `"slice"`.Repository: Ghenghis/Hermes3D
Length of output: 311
🏁 Script executed:
#!/bin/bash
# Read the complete schema file to see the full context
cat 03_implementation/adapter_registry/schemas/curaengine.schema.jsonRepository: Ghenghis/Hermes3D
Length of output: 1314
safe_probe_args does not enforce the "never include 'slice'" safety rule.
The schema documents this constraint in the description, but currently accepts any string array without validation. For example, ["slice"] or ["help", "slice"] would be accepted despite violating the stated safety requirement.
Add JSON Schema validation to prevent "slice" from appearing in the array:
Suggested schema fix
"safe_probe_args": {
"type": "array",
"items": {"type": "string"},
+ "minItems": 1,
+ "not": {
+ "contains": { "const": "slice" }
+ },
"default": ["help"],
"description": "Arguments used for the read-only version probe. Never include 'slice'."
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "safe_probe_args": { | |
| "type": "array", | |
| "items": {"type": "string"}, | |
| "default": ["help"], | |
| "description": "Arguments used for the read-only version probe. Never include 'slice'." | |
| } | |
| "safe_probe_args": { | |
| "type": "array", | |
| "items": {"type": "string"}, | |
| "minItems": 1, | |
| "not": { | |
| "contains": { "const": "slice" } | |
| }, | |
| "default": ["help"], | |
| "description": "Arguments used for the read-only version probe. Never include 'slice'." | |
| } |
🤖 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 `@03_implementation/adapter_registry/schemas/curaengine.schema.json` around
lines 30 - 35, The schema for safe_probe_args currently documents but does not
enforce that the string "slice" is disallowed; update the safe_probe_args
definition so each array item cannot be the string "slice" (e.g., change the
items schema for safe_probe_args to a string type with a not const "slice"
constraint or add a top-level not with contains {"const":"slice"}) so any array
containing "slice" will fail validation, keeping the default and description
unchanged and modifying only the safe_probe_args schema (reference symbol:
safe_probe_args).
| "required": ["name", "source_url", "install_check", "version_pattern"], | ||
| "properties": { | ||
| "name": {"type": "string", "const": "klipper"}, | ||
| "source_url": { | ||
| "type": "string", | ||
| "format": "uri", | ||
| "default": "https://github.com/Klipper3d/klipper.git", | ||
| "description": "Public Git remote. Verifier uses git ls-remote (no clone)." | ||
| }, | ||
| "default_branch": {"type": "string", "default": "master"}, | ||
| "install_check": { | ||
| "type": "string", | ||
| "default": "git ls-remote --heads https://github.com/Klipper3d/klipper.git", | ||
| "description": "Read-only remote probe. NEVER a flash command." | ||
| }, | ||
| "version_pattern": { | ||
| "type": "string", | ||
| "default": "^[0-9a-f]{40}\\s+refs/heads/.+$", | ||
| "description": "Regex applied to git ls-remote output line." | ||
| }, | ||
| "toolchain_required": {"type": "string", "const": "toolchain_arm_none_eabi"}, | ||
| "no_flash": {"type": "boolean", "const": true} |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify required-vs-const enforcement for firmware safety fields.
for f in \
03_implementation/adapter_registry/schemas/firmware_klipper.schema.json \
03_implementation/adapter_registry/schemas/firmware_reprap.schema.json; do
echo "== $f =="
jq -r '
.required as $r |
"required_has_no_flash=\(($r|index("no_flash"))!=null)",
"required_has_toolchain_required=\(($r|index("toolchain_required"))!=null)",
"const_no_flash=\(.properties.no_flash.const)",
"const_toolchain_required=\(.properties.toolchain_required.const)"
' "$f"
doneRepository: Ghenghis/Hermes3D
Length of output: 486
🏁 Script executed:
#!/bin/bash
# Find all firmware schema files to check for the same pattern
find 03_implementation/adapter_registry/schemas -name "firmware_*.schema.json" -type f | sortRepository: Ghenghis/Hermes3D
Length of output: 345
🏁 Script executed:
#!/bin/bash
# Check all firmware schemas for the same required-vs-const pattern
find 03_implementation/adapter_registry/schemas -name "firmware_*.schema.json" -type f | while read f; do
echo "=== $f ==="
jq '.required, .properties | keys' "$f" 2>/dev/null | head -20
doneRepository: Ghenghis/Hermes3D
Length of output: 977
🏁 Script executed:
#!/bin/bash
# Search for test or example data that validates against these schemas
fd -e json -t f | xargs rg -l "toolchain_required|no_flash" --max-count=20 2>/dev/null | grep -v schema.json | head -10Repository: Ghenghis/Hermes3D
Length of output: 117
🏁 Script executed:
#!/bin/bash
# Show required arrays for all firmware schemas
find 03_implementation/adapter_registry/schemas -name "firmware_*.schema.json" | sort | while read f; do
echo "=== $(basename "$f") ==="
jq '.required' "$f"
doneRepository: Ghenghis/Hermes3D
Length of output: 481
🏁 Script executed:
#!/bin/bash
# Check the proof file structure and content
wc -l 03_implementation/proof/FIRMWARE_VERIFY_2026-05-06.json && echo "---" && head -100 03_implementation/proof/FIRMWARE_VERIFY_2026-05-06.jsonRepository: Ghenghis/Hermes3D
Length of output: 3017
🏁 Script executed:
#!/bin/bash
# Check if toolchain_required appears in the proof file
grep -c "toolchain_required" 03_implementation/proof/FIRMWARE_VERIFY_2026-05-06.json
rg "toolchain_required" 03_implementation/proof/FIRMWARE_VERIFY_2026-05-06.json -A 1 -B 1Repository: Ghenghis/Hermes3D
Length of output: 63
🏁 Script executed:
#!/bin/bash
# Also verify const values in properties for completeness
jq '.properties | keys[] as $k | "\($k): const=\(.[$k].const // "N/A")"' 03_implementation/adapter_registry/schemas/firmware_klipper.schema.jsonRepository: Ghenghis/Hermes3D
Length of output: 266
Add toolchain_required and no_flash to all firmware schema required arrays.
In JSON Schema, const constraints only validate when a property is present. Currently, these safety-critical fields can be omitted from firmware definitions and still pass schema validation. This issue affects all firmware schemas (klipper, marlin, prusa, reprap).
Suggested fix
- "required": ["name", "source_url", "install_check", "version_pattern"],
+ "required": ["name", "source_url", "install_check", "version_pattern", "toolchain_required", "no_flash"],Apply this change to:
firmware_klipper.schema.jsonfirmware_marlin.schema.jsonfirmware_prusa.schema.jsonfirmware_reprap.schema.json
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "required": ["name", "source_url", "install_check", "version_pattern"], | |
| "properties": { | |
| "name": {"type": "string", "const": "klipper"}, | |
| "source_url": { | |
| "type": "string", | |
| "format": "uri", | |
| "default": "https://github.com/Klipper3d/klipper.git", | |
| "description": "Public Git remote. Verifier uses git ls-remote (no clone)." | |
| }, | |
| "default_branch": {"type": "string", "default": "master"}, | |
| "install_check": { | |
| "type": "string", | |
| "default": "git ls-remote --heads https://github.com/Klipper3d/klipper.git", | |
| "description": "Read-only remote probe. NEVER a flash command." | |
| }, | |
| "version_pattern": { | |
| "type": "string", | |
| "default": "^[0-9a-f]{40}\\s+refs/heads/.+$", | |
| "description": "Regex applied to git ls-remote output line." | |
| }, | |
| "toolchain_required": {"type": "string", "const": "toolchain_arm_none_eabi"}, | |
| "no_flash": {"type": "boolean", "const": true} | |
| "required": ["name", "source_url", "install_check", "version_pattern", "toolchain_required", "no_flash"], | |
| "properties": { | |
| "name": {"type": "string", "const": "klipper"}, | |
| "source_url": { | |
| "type": "string", | |
| "format": "uri", | |
| "default": "https://github.com/Klipper3d/klipper.git", | |
| "description": "Public Git remote. Verifier uses git ls-remote (no clone)." | |
| }, | |
| "default_branch": {"type": "string", "default": "master"}, | |
| "install_check": { | |
| "type": "string", | |
| "default": "git ls-remote --heads https://github.com/Klipper3d/klipper.git", | |
| "description": "Read-only remote probe. NEVER a flash command." | |
| }, | |
| "version_pattern": { | |
| "type": "string", | |
| "default": "^[0-9a-f]{40}\\s+refs/heads/.+$", | |
| "description": "Regex applied to git ls-remote output line." | |
| }, | |
| "toolchain_required": {"type": "string", "const": "toolchain_arm_none_eabi"}, | |
| "no_flash": {"type": "boolean", "const": true} |
🤖 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 `@03_implementation/adapter_registry/schemas/firmware_klipper.schema.json`
around lines 8 - 29, The schema's required array currently omits the
safety-critical properties toolchain_required and no_flash so their const
constraints won't be enforced; update each firmware schema
(firmware_klipper.schema.json, firmware_marlin.schema.json,
firmware_prusa.schema.json, firmware_reprap.schema.json) to include
"toolchain_required" and "no_flash" in the top-level "required" array alongside
"name", "source_url", "install_check", and "version_pattern" so the const
validations on properties "toolchain_required" and "no_flash" are enforced.
| "probe_method": { | ||
| "type": "string", | ||
| "enum": ["systemctl_status", "moonraker_proxy", "not_applicable"], | ||
| "description": "How Klipper status is probed. On Windows: not_applicable. On Linux: systemctl_status or via Moonraker HTTP proxy." | ||
| } | ||
| }, | ||
| "required": ["read_only", "no_gcode", "no_movement", "probe_method"], | ||
| "additionalProperties": false | ||
| }, | ||
| "platform": { | ||
| "type": "object", | ||
| "description": "Platform-specific detection metadata", | ||
| "properties": { | ||
| "os": { | ||
| "type": "string", | ||
| "enum": ["linux", "win32", "darwin"], | ||
| "description": "Host OS where probe runs" | ||
| }, | ||
| "applicable": { | ||
| "type": "boolean", | ||
| "description": "Whether Klipper service detection applies on this OS. Klipper is Linux-only; on Windows this is false and the probe is skipped." | ||
| }, | ||
| "service_name": { | ||
| "type": "string", | ||
| "default": "klipper", | ||
| "description": "systemd service unit name (Linux only)" | ||
| } | ||
| }, | ||
| "required": ["os", "applicable"], | ||
| "additionalProperties": false | ||
| }, |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
find . -name "klipper_service.schema.json" -type fRepository: Ghenghis/Hermes3D
Length of output: 134
🏁 Script executed:
cat -n 03_implementation/adapter_registry/schemas/klipper_service.schema.jsonRepository: Ghenghis/Hermes3D
Length of output: 3889
Enforce OS-specific rules for probe_method and service_name using schema conditionals.
The schema currently allows invalid configurations: Windows or macOS with systemctl_status probe method, or non-Linux platforms with service_name defined. These constraints exist only in descriptions (line 26, 48) but are not enforced by validation logic.
Add Draft-07 if/then/else conditional validation to:
- Restrict
probe_methodtosystemctl_statusormoonraker_proxyonly on Linux; enforcenot_applicableon Windows/macOS - Prevent
service_namefrom being set on non-Linux platforms
Proposed fix (Draft-07 conditional validation)
"required": ["adapter", "version", "policy", "platform"],
+ "allOf": [
+ {
+ "if": {
+ "properties": {
+ "platform": {
+ "properties": { "os": { "const": "linux" } },
+ "required": ["os"]
+ }
+ }
+ },
+ "then": {
+ "properties": {
+ "policy": {
+ "properties": {
+ "probe_method": { "enum": ["systemctl_status", "moonraker_proxy"] }
+ }
+ }
+ }
+ },
+ "else": {
+ "properties": {
+ "policy": {
+ "properties": {
+ "probe_method": { "const": "not_applicable" }
+ }
+ },
+ "platform": {
+ "not": { "required": ["service_name"] }
+ }
+ }
+ }
+ }
+ ],
"additionalProperties": false
}🤖 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 `@03_implementation/adapter_registry/schemas/klipper_service.schema.json`
around lines 23 - 53, Add Draft-07 conditional validation to the schema so
probe_method and platform.service_name are OS-aware: use an if on platform.os ==
"linux" with then allowing probe_method enum
["systemctl_status","moonraker_proxy","not_applicable"] (or at least allowing
the first two) and allowing platform.properties.service_name (or its presence),
and an else block for non-linux (platform.os == "win32" or "darwin") that forces
probe_method to "not_applicable" and disallows service_name (e.g., with property
not allowed or an explicit unevaluatedProperties/required constraints). Target
the existing properties "probe_method", "platform.os", and
"platform.service_name" and add the if/then/else at the same object level that
contains "platform" so the validator enforces OS-specific rules.
| 3. **`hermes-agent-fresh` (agent-infra snapshot)** | ||
| - NousResearch v0.12.0 reference; unused in active workflow. | ||
| - Superseded by hermes3d-mcp-lock-orchestrator v0.7.0. | ||
| - **Action**: Delete; consult hermes-agent-bridge if history needed. | ||
| - **Risk**: LOW — snapshot only. NOTE: Live `/api/code-operator/e2e/readiness` shows `hermes-agent-fresh` is the ACTIVE source input for Nous Hermes Agent runtime; do not archive without first redirecting `HERMES3D_AGENT_RUNTIME_URL` consumers. | ||
|
|
There was a problem hiding this comment.
Do not recommend deletion for a currently active runtime source.
Line 104 says “Action: Delete,” but Line 105 explicitly says hermes-agent-fresh is currently active for /api/code-operator/e2e/readiness. This is unsafe guidance unless made conditional.
Suggested doc fix
- - **Action**: Delete; consult hermes-agent-bridge if history needed.
- - **Risk**: LOW — snapshot only. NOTE: Live `/api/code-operator/e2e/readiness` shows `hermes-agent-fresh` is the ACTIVE source input for Nous Hermes Agent runtime; do not archive without first redirecting `HERMES3D_AGENT_RUNTIME_URL` consumers.
+ - **Action**: Do not archive yet. First redirect all `HERMES3D_AGENT_RUNTIME_URL` consumers and verify `/api/code-operator/e2e/readiness` no longer reports `hermes-agent-fresh` as active.
+ - **Risk**: MEDIUM until redirect/verification is complete; LOW after cutover.🤖 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
`@03_implementation/docs/handoffs/claude-e2e-intelligence-2026-05-08/01_GITHUB_FOLDER_ECOSYSTEM_AUDIT.md`
around lines 101 - 106, The doc incorrectly instructs deletion of
hermes-agent-fresh while also noting it is the active runtime; update the entry
for hermes-agent-fresh to remove the unconditional "Action: Delete" and replace
it with a conditional migration plan: state that hermes-agent-fresh must not be
archived until all consumers of HERMES3D_AGENT_RUNTIME_URL are redirected
(verify `/api/code-operator/e2e/readiness` shows non-active), include steps to
consult hermes-agent-bridge or hermes3d-mcp-lock-orchestrator for history or
replacement, and mark the action as "Plan: Redirect consumers then archive" with
Risk remaining LOW once redirected.
| **All 20 Claude lane PRs are open, CI-CLEAN, and ready to merge in order.** | ||
| **All 6 strict audit agents completed with zero code blockers.** | ||
| **TS7026 CI-trigger fix is in PR #80 (UNSTABLE — CI running).** | ||
| **Merge in the exact tier sequence below. Then Codex takes over remaining implementation.** |
There was a problem hiding this comment.
Resolve contradictory “open vs merged” status messaging.
Line 11–14 says the 20 lane PRs are open, while Line 24–27 says they are already merged. Please make one state authoritative (or explicitly mark the TL;DR as historical) to avoid incorrect operator action.
Also applies to: 22-30
🤖 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
`@03_implementation/docs/handoffs/claude-final-audit-2026-05-06/00_EXECUTIVE_TAKEOVER_SUMMARY.md`
around lines 11 - 14, The document contains contradictory status statements: the
phrase "All 20 Claude lane PRs are open, CI-CLEAN, and ready to merge in order."
conflicts with later text saying they are "already merged." Decide which status
is authoritative (open vs merged) and update all occurrences to match;
specifically edit the phrase "All 20 Claude lane PRs are open, CI-CLEAN, and
ready to merge in order." or the later "already merged" sentence so both state
the same outcome, or prepend an explicit historical qualifier (e.g., "TL;DR
(historical):") to the earlier TL;DR line so it cannot be misinterpreted; also
ensure the mention "TS7026 CI-trigger fix is in PR `#80`" remains accurate and
consistent with the chosen authoritative state.
| gh pr merge 53 54 55 56 57 58 59 60 61 62 63 65 67 68 70 --squash | ||
|
|
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify gh CLI merge command signature
gh pr merge --help | sed -n '1,140p'Repository: Ghenghis/Hermes3D
Length of output: 314
🌐 Web query:
gh cli pr merge command signature documentation
💡 Result:
gh pr merge command signature (GitHub CLI) Synopsis: - gh pr merge [ | | ] [flags] [1] Behavior with/without argument: - If no argument is provided, the pull request that belongs to the current branch is selected. [1] Key flags (most commonly relevant to the command signature) - --admin: use administrator privileges to merge a pull request that does not meet requirements (e.g., bypass merge queue requirements). [1] - --auto: automatically merge only after necessary requirements are met. [1] - --delete-branch: delete the local and remote branch after merge. [1] - Merge method selection flags: -m/--merge, -r/--rebase, -s/--squash. [1] - Commit metadata flags: -b/--body, -F/--body-file, -t/--subject, -A/--author-email. [1] - --disable-auto: disable auto-merge for this pull request. [1] Source notes - GitHub Docs on merging pull requests confirm that you use the gh pr merge subcommand and can specify the pull request by number, URL, or head branch. [2] - The GitHub CLI manual page provides the full synopsis/usage line and the options list. [1]
Citations:
- 1: https://cli.github.com/manual/gh_pr_merge
- 2: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/merging-a-pull-request
🏁 Script executed:
# Find and inspect the actual file mentioned in the review
find . -name "00_EXECUTIVE_TAKEOVER_SUMMARY.md" -type fRepository: Ghenghis/Hermes3D
Length of output: 158
🏁 Script executed:
# Inspect the file to see the context around lines 94-95 and 110
cat -n "./03_implementation/docs/handoffs/claude-final-audit-2026-05-06/00_EXECUTIVE_TAKEOVER_SUMMARY.md" | sed -n '85,120p'Repository: Ghenghis/Hermes3D
Length of output: 1426
Merge each PR individually with separate gh pr merge calls.
Lines 94 and 110 pass multiple PR numbers to a single gh pr merge invocation, but the command accepts only one pull request per call (gh pr merge [<number> | <url> | <branch>]). These commands will fail as written.
Suggested PowerShell fix
- gh pr merge 53 54 55 56 57 58 59 60 61 62 63 65 67 68 70 --squash
+ foreach ($pr in 53,54,55,56,57,58,59,60,61,62,63,65,67,68,70) { gh pr merge $pr --squash }
- gh pr merge 74 75 76 77 78 79 --squash
+ foreach ($pr in 74,75,76,77,78,79) { gh pr merge $pr --squash }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| gh pr merge 53 54 55 56 57 58 59 60 61 62 63 65 67 68 70 --squash | |
| foreach ($pr in 53,54,55,56,57,58,59,60,61,62,63,65,67,68,70) { gh pr merge $pr --squash } |
🤖 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
`@03_implementation/docs/handoffs/claude-final-audit-2026-05-06/00_EXECUTIVE_TAKEOVER_SUMMARY.md`
around lines 94 - 95, The gh pr merge command line "gh pr merge 53 54 55 56 57
58 59 60 61 62 63 65 67 68 70" is invalid because gh pr merge accepts a single
PR per call; update the document so each PR number is merged with its own gh pr
merge invocation (one call per PR number) and remove the combined multi-PR
command; ensure the revised lines list separate commands for each numeric PR
referenced in the original string so they will run successfully.
| Total: **84 active locks** across 6 Claude agent owners + codex-master. | ||
|
|
There was a problem hiding this comment.
Lock counts are internally inconsistent (42 vs expected 56).
The totals imply codex-master should hold 56 locks (84 - 28), and the post-release section also says 56, but Line 71 says 42. Please reconcile this count to avoid operational confusion.
Suggested doc fix
-42 files locked by `codex-master` covering:
+56 files locked by `codex-master` covering:Also applies to: 67-71, 87-89
🤖 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
`@03_implementation/docs/handoffs/claude-final-audit-2026-05-06/03_LOCKS_WORKTREES_AND_BRANCHES.md`
around lines 11 - 12, The document's lock totals are inconsistent: the header
shows "Total: **84 active locks**" and the post-release section expects
codex-master to have 56 locks, but one spot still reads "42"; update the
mismatched occurrences so codex-master is consistently shown as holding 56 locks
(replace the "42" instances in the post-release/summary paragraphs and any lines
referenced in the ranges 67-71 and 87-89) and verify the arithmetic text (e.g.,
"84 - 28 = 56") and any related totals/footnotes reflect the corrected 56 value.
| - **Method**: `pip` (install) + managed subprocess (launch) | ||
| - **Probe**: pip module import probe (`import_name: "octoprint"`) + HTTP probe at `http://127.0.0.1:5000` | ||
| - **Process model**: `managed-process` — Source OS spawns `.venv\Scripts\octoprint.exe` and tracks PID in `process_state` | ||
| - **Smoke API key**: `OCTOPRINT_SMOKE_API_KEY = "hermes3d-octoprint-smoke-key"` (line 88, main.py) |
There was a problem hiding this comment.
Do not publish a static smoke API key literal.
Line [19] exposes a concrete key value. Even for smoke lanes, fixed shared keys tend to spread and bypass rotation discipline. Move this to env-based config and rotate the currently documented value.
🤖 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
`@03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/h3dos-codex-tasks/h3dos-codex-octoprint.md`
at line 19, The doc currently publishes a hard-coded smoke API key literal for
OCTOPRINT_SMOKE_API_KEY; remove the concrete value and change code/config to
read OCTOPRINT_SMOKE_API_KEY from environment/config management instead (e.g.,
process env or secret store) and update the documentation to instruct developers
to set the env var rather than show a key; also rotate or revoke the documented
key currently shown. Locate references to OCTOPRINT_SMOKE_API_KEY (and the
main.py declaration) to replace the literal with an env-based lookup and update
the doc text to demonstrate usage without exposing any secret.
db57b38
into
feat/hermes3d-7-complete-gui-repo-wiring
* docs(contract): sync Hermes3D completion roadmap and Claude handoffs
WIP checkpoint per GITHUB_SYNC_PLAN_2026-05-06: contract docs, roadmap,
and 20-agent handoff before Claude lanes branch off this baseline.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(api): add live Hermes3D backend routes and proof services
WIP checkpoint per GITHUB_SYNC_PLAN_2026-05-06: API routes, services,
db schema/init, core orchestration + slicer/printer adapters baseline
for the 20-agent completion lanes.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(ui): wire live Hermes3D tabs and remove mock UX
WIP checkpoint per GITHUB_SYNC_PLAN_2026-05-06: live tab shells
(Source OS, Settings, Agents, Observe, Roadmap, Plugins, Jobs,
Artifacts, Approvals, Voice, Learning, Autopilot, Design, 3D Generation,
Printers), live API adapters, ResizablePane/AppShell layout, and
removal of mock data + retired tabs.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(source-os): add adapter schemas, source audits, and runtime proof
WIP checkpoint per GITHUB_SYNC_PLAN_2026-05-06: 31 adapter_registry
JSON schemas (slicers/modelers/print-farm/gen3D/firmware), source-app
audit scripts, and proof artifacts (CLI surface, runtime action plan,
local tooling audit) backing the Source OS lane.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* test(e2e): add live GUI and no-fake proof coverage
WIP checkpoint per GITHUB_SYNC_PLAN_2026-05-06: Playwright e2e config
and live-gui spec, runtime-port + GUI-API + e2e-stack starters; retire
visual specs replaced by the live e2e suite.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* ci(fix): extend ui-ci.yml PR trigger to feat/** branches (TS7026 root cause) (#80)
* ci(fix): extend ui-ci.yml PR trigger to feat/** branches
`pull_request.branches` previously only listed `[main, develop]`.
Lane PRs target `feat/hermes3d-7-complete-gui-repo-wiring`, so
`npm ci` + `tsc --noEmit` (Layer D2) never ran for them.
Adding `feat/**` ensures the strict lint gate fires on every lane
PR, surfacing the pre-existing TS7026/TS7006 JSX.IntrinsicElements
regression (caused by missing `node_modules` in fresh worktrees)
rather than silently passing.
Root cause confirmed: `npm run lint` returns 0 errors after
`npm install`; tsconfig.json and @types/react are correct.
The regression only appears without node_modules.
Task: a2a_1778114702912_1ac758ea
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* ci: install API deps for UI workflow
* fix: seed provider module targets before providers
* fix: stabilize UI final truth gate
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs(roadmap): sync Hermes3D state with live baseline (H3D-CLAUDE-DOCS-PROOF) (#53)
Add Claude-authored docs companion and proof for the 20-Agent Completion
Contract Lane 18. Records the 5-commit shared baseline, 16-tab inventory
from routes.tsx, and the live S1/T1/V400 printer policy. README gains
pointers to the operator GUI roadmap and the contract handoff. ROADMAP.md
intentionally not edited because of an active codex-master Hermes lock.
Hermes evidence chain: PASS
Task ID: H3D-CLAUDE-DOCS-PROOF
hermes_run_gate: PASS
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(app-shell): finish resizable panels + density + Simple/Main parity (H3D-CLAUDE-APP-SHELL) (#54)
ResizablePane hardening:
- Escape during drag restores pre-drag width
- touchAction: none on the handle so drag works on touch devices
- Re-clamp persisted width when min/max bounds change at runtime
- SSR-safe localStorage write guard
Lane scope was bounded by Codex-master locks on AppShell, Sidebar, TopBar,
Panel, globals.css, tailwind.config.ts — those files were not contended.
DockModeToggle left unchanged: TopBar already owns the live Simple/Main
toggle via setUiMode and coupling DockModeToggle would break Phase 2 panel
docking semantics.
Hermes evidence chain: PASS
Task ID: H3D-CLAUDE-APP-SHELL
hermes_run_gate: PASS
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* test(e2e): add tab-specific Playwright specs (H3D-CLAUDE-PLAYWRIGHT) (#55)
Adds per-tab Playwright e2e specs for all 16 primary tabs and Roadmap,
each asserting truthful root mount, no forbidden mock/placeholder text
in production surfaces, and a clean console. Network calls are stubbed
at the GUI-API boundary; printers.spec.ts hard-aborts any request that
would reach live S1/T1/V400 operator IPs.
Hermes Task ID: H3D-CLAUDE-PLAYWRIGHT
Hermes evidence: ev_9d0e995e54bbac18
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* test(security): MCP boundary + prompt-injection + secret-redaction audit (H3D-CLAUDE-SECURITY-MCP) (#56)
Lane 19 of the Hermes3D 20-Agent Completion Contract. Adds READ-ONLY
behavioural tests over the in-house OWASP LLM-01 prompt-injection scanner
(commit 0c9b6d9), the secret-redaction surface in services/local_state.py
+ services/module_runtime.py + services/agent_runtime.py, the canonical
user-supplied-path validators in services/code_history.py, and the
MCP/tool-boundary policy gates that protect printers and the agent
runtime URL.
New files (lane-owned only):
- 03_implementation/tests/security/__init__.py
- 03_implementation/tests/security/conftest.py
- 03_implementation/tests/security/test_prompt_injection.py
- 03_implementation/tests/security/test_secret_redaction.py
- 03_implementation/tests/security/test_path_traversal.py
- 03_implementation/tests/security/test_mcp_boundary.py
- 03_implementation/proof/security/SECURITY_AUDIT_2026-05-06.json
- 03_implementation/docs/security/MCP_BOUNDARY_NOTES.md
Vectors covered (full list in SECURITY_AUDIT_2026-05-06.json):
- OWASP LLM-01 indirect injection, ChatML/Llama control tokens,
RCE-shaped tool-poisoning (curl|sh, wget|bash, iex/iwr), prompt-leak
variants, jailbreak personas (DAN, devmode, ignore-safety,
no-restrictions, pretend-unrestricted), and unicode-control no-crash
guarantees.
- LLM-02 (light): execute-following + base64 payload framing.
- LLM-06: AST scan over services/*.py rejects raw secret-shaped
literals (sk-, ghp_, AKIA, bearer, xoxb-) in source AND in any
logging emitter call site; pins module_runtime._redact_text on
every subprocess->output_head path; pins agent_runtime never logs
private_values / private_env() / env_value() return values.
- Path traversal: 8 explicit-reject vectors (../etc/passwd, drive
letters, null-byte injection, empty path), plus the documented
coercive cases (/etc/passwd and //attacker.example/share/x are
re-rooted into PROJECT_ROOT — informational, no escape possible).
- MCP boundary: build-plate-clearance gate, FLSUN S1 read-only lock,
trusted_runtime_url rejects non-private hosts / credentials /
query / fragment / wrong scheme / self-bridge ports 8765+8642,
scanner ships >=15 OWASP + >=10 in-house rules, fail_threshold
knob, redacted-text logging sink, secret-storage convention pinned
to G:\private\.env (outside repo).
Findings (logged, NOT silently fixed; surfaced via xfail strict=True
so they fail loudly when patched upstream):
- FINDING-INJ-1 (medium, owner = core/security ruleset lane):
LLM01-LEAK-VERBATIM regex misses reverse word order
`the prompt verbatim`. Suggested fix: anchor on `verbatim`
independent of word order or add LLM01-LEAK-VERBATIM-REV.
- FINDING-INJ-2 (medium, owner = core/security ruleset lane):
Zero-width-space (U+200B) injected in `ignore` bypasses
LLM01-IGN-PREV; `dump` is missing from leak alternation.
Suggested fix: pre-normalise zero-width / bidi control chars
before matching; extend LLM01-LEAK-SYSPROMPT verb alternation.
- FINDING-PATH-1 (low, informational, owner = Codex / code_history
lane): `_resolve_project_subpath` re-roots `/etc/passwd` and
`//attacker.example/share/x` into PROJECT_ROOT rather than
rejecting. SAFE (no escape; `relative_to(PROJECT_ROOT)` enforces
containment) but contract is coercive, not rejective.
Required gates: PASS
- python -m py_compile services/*.py routes/*.py: PASS
- scan_active_ui_no_fake.py: PASS
- pytest 03_implementation/tests/security/: 78 passed, 2 xfailed
- npm run lint: PASS
Hermes evidence: ev_cfb93a332dd6918a (ledger entry hash chain
extended). Lock owner: claude-security-mcp-19. No files outside
03_implementation/{tests,proof,docs}/security/ were modified.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(source-gen3d): real source+runtime verifiers for ComfyUI/TRELLIS/Hunyuan3D/TripoSR (H3D-CLAUDE-SOURCE-GEN3D) (#57)
Adds adapter_registry/scripts/tests for the five generative-3D providers
without performing any heavy operation:
* schemas: extend comfyui/trellis2/hunyuan3d/triposr/bambustudio_bridge
with source_repo, pip_package, weights_cache_dirs (all backward compatible).
* scripts/verify_gen3d.py: stdlib + subprocess only.
- git ls-remote --heads (no clone), 5s timeout.
- pip show <pkg> (no install), 5s timeout.
- Boolean cache-presence for ~/.cache/huggingface and similar.
- Bambu Studio: launcher executable presence only (no launch).
* proof/GEN3D_VERIFY_2026-05-06.json: 5/5 repos reachable;
Bambu Studio launcher present; comfyui/trellis2/hunyuan3d/triposr
honest "not installed" (no fabrication, no downloads).
* tests/source_lab/test_gen3d.py: pytest validates proof shape, policy
invariants, full provider coverage, and reachability honesty.
Hermes evidence chain: PASS
Task ID: a2a_1778106411818_946d5ec0
Lane: H3D-CLAUDE-SOURCE-GEN3D
hermes_run_gate: verify_gen3d, pytest test_gen3d, py_compile, scan_active_ui_no_fake
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(source-firmware): firmware toolchain proof gates, no-flash safety (H3D-CLAUDE-SOURCE-FIRMWARE) (#58)
- Add JSON schemas for Klipper, Marlin, RepRapFirmware, Prusa firmware sources
- Add JSON schemas for arm-none-eabi-gcc and avr-gcc toolchains
- Add verify_firmware.py: probes toolchain availability (--version only) and
firmware source reachability (git ls-remote only); NEVER flashes, NEVER
opens serial/USB to printer boards
- Add test_firmware.py: pytest suite asserting schema validity, no-flash policy,
verifier source integrity, and no-network proof generation
- Add FIRMWARE_VERIFY_2026-05-06.json: proof artifact (all 4 firmware sources
reachable; toolchains absent on this host — honestly recorded)
Lane: H3D-CLAUDE-SOURCE-FIRMWARE
Owner: claude-source-firmware-05
Hermes evidence chain: PASS
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(source-printfarm): read-only Moonraker/Klipper/OctoPrint verifiers (H3D-CLAUDE-SOURCE-PRINTFARM) (#59)
- verify_printfarm.py: HTTP GET-only probes for Moonraker (T1-a, T1-b, V400),
OctoPrint, Fluidd, Mainsail, FDM Monster, KlipperScreen, Printrun.
FLSUN S1 camera skipped per lane policy. Honest "unreachable" for all
localhost services (not running on this host). 3/3 Moonraker printers
reached; V400 version: v0.7.1-586-gbb526e0-dirty.
- test_printfarm.py: pytest suite asserting proof JSON shape, policy
invariants, GET-only constraint, S1 never-probed, and summary consistency.
- PRINTFARM_VERIFY_2026-05-06.json: proof artifact with live results.
- adapter_registry/schemas/moonraker_api.schema.json: JSON Schema for
read-only Moonraker HTTP adapter (GET-only, forbidden endpoints listed).
- adapter_registry/schemas/klipper_service.schema.json: JSON Schema for
Klipper service adapter (systemctl/moonraker-proxy, no G-code ever).
Hermes evidence chain: PASS
Task ID: H3D-CLAUDE-SOURCE-PRINTFARM
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(source-modelers): real verifiers for Blender/OpenSCAD/FreeCAD/CadQuery/build123d/trimesh (H3D-CLAUDE-SOURCE-MODELERS) (#60)
- 9 adapter schemas with real verify blocks (version_probe, install_check, runtime_check)
- scripts/verify_modelers.py: live CLI + pip-show probes, no fake/mock gates
- tests/source_lab/test_modelers.py: pytest contract validation for proof JSON
- proof/MODELERS_VERIFY_2026-05-06.json: honest results — found: blender, openscad, trimesh; not_found: freecad, cadquery, build123d
Lane: H3D-CLAUDE-SOURCE-MODELERS
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(artifacts): proof bundle index + artifact discovery API (H3D-CLAUDE-ARTIFACTS-PROOF) (#61)
- artifacts.py: add GET /api/artifacts/list (scans proof/ dir live, no hardcoded data)
and GET /api/artifacts/proof/{filename} (serves proof files with path-traversal guard)
- PROOF_MANIFEST_2026-05-06.json: real manifest of all 14 proof files in proof/
(generated by scanning directory, includes sizes, timestamps, lane IDs)
- Artifacts.tsx: add Proof Bundles panel calling /api/artifacts/list; displays
all proof files with View links; no mock data
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(learning-autopilot): truthful idle work kinds + real backend state (H3D-CLAUDE-LEARNING-AUTOPILOT) (#62)
- AutopilotConsole: remove hardcoded fake status values (Loop: on, Window: 8h, Risk: low)
that were not connected to any backend; replace with props-driven readyCount/totalChecks
that drive honest live/unavailable/blocked state display
- AutopilotTab (existing): already calls /api/autopilot/readiness + /api/autopilot/guardrails
for real backend state - no fake activation
- LearningTab (existing): all idle work kinds call real endpoints with honest blocked state:
createIdleCandidate → POST /api/learning/idle-workbench/candidates
runIdleCandidate → POST /api/learning/idle-workbench/candidates/{id}/run
requestIdleCandidateReview → POST /api/learning/idle-workbench/candidates/{id}/request-review
decideIdleCandidate → POST /api/learning/idle-workbench/candidates/{id}/decision
- Backend learning.py: run endpoint returns accepted:false + reason when runtime not configured
- Backend autopilot.py: next-gate returns 409 with failing check detail when not all ready
- Pre-existing TS7026 regression: 0 errors (lint clean)
- Python compile: learning.py OK, autopilot.py OK
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(source-slicers): real CLI verifiers for slicers (H3D-CLAUDE-SOURCE-SLICERS) (#63)
* feat(design): real CAD template gallery + provider health checks (H3D-CLAUDE-DESIGN) (#65)
- backend: add GET /api/design/templates — discovers templates from real
importable executor modules (hermes3d.core.design.*), reports
executor_available + missing_deps from live importlib checks
- backend: add GET /api/design/providers — probes OpenSCAD, Blender,
CadQuery, trimesh, manifold3d, FreeCAD via shutil.which + importlib;
no cached stubs, no fake version strings
- UI: Design.tsx pulls templates and providers from real backend endpoints;
template select populated from /api/design/templates (disabled if
executor unavailable); provider health panel shows live probe results;
template gallery shows preview-not-available for all templates (no
renderer wired); no hardcoded "Generated successfully" messages
- tests: add 04_testing/pytest/unit/test_design_providers.py — 18 tests
covering _discover_templates, _probe_providers, _probe_cli_provider,
_probe_python_provider; trimesh/manifold3d tests assert against live
importlib.util.find_spec to prevent divergence from reality
Pre-existing TS7026 errors in other tabs (not Design.tsx): noted in PR, not
fixed in this lane per cross-lane separation rules.
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(observe): camera grid + S1 90deg + refresh reliability + V400 status (H3D-CLAUDE-OBSERVE) (#67)
- Backend: add GET /api/observe/status with per-camera health, response_ms, estimated_fps,
and read_only flag (S1 at 192.168.0.12 is flagged read-only; never receives control cmds)
- Backend: refactor _probe_camera into _probe_camera_timed for fps estimation;
update camera_health endpoint to return response_ms + estimated_fps
- Frontend types: add CameraStatus + ObserveStatusResponse interfaces to observe.ts
- Observe.tsx: exponential backoff retry on feed error (1s base → 30s max);
feedState gains 'reconnecting' state with spinner overlay instead of broken image;
auto-refresh interval selector (off / 3s / 5s / 10s / 30s) polls /api/observe/status;
online/offline summary badge in header; Refresh all button triggers both feed + status fetch;
V400 per-card online/offline chip + fps indicator from status API;
S1 defaults to 90deg rotation (backend + defaultViewSettings already enforced)
- ObserveConsole.tsx: replace hardcoded mock camera list with live /api/observe/status polling
every 5s; shows read_only badge on S1, fps estimate per camera, online/offline with ping ms
Camera safety: S1 (192.168.0.12) is camera/read-only throughout; no move/upload/print/test
commands are issued from Observe tab or status endpoint.
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(jobs): policy-gated repair/retry/rollback + proof state (H3D-CLAUDE-JOBS) (#68)
- Add _check_printer_policy() to jobs.py enforcing three ordered gates:
1. S1 hard lock (192.168.0.12 / flsun-s1 always rejected, HTTP 423)
2. PRINTER_WRITE_DENIED: printer must be write_enabled or in WRITE_ALLOWED_PRINTERS (HTTP 423)
3. PRINTER_IDLE gate: printer state must be standby/complete/ready/error before retry/repair/rollback (HTTP 409)
- apply_repair, retry_job, rollback_job all call _check_printer_policy() before mutating any state
- propose_repair calls check_s1_lock() (read-only planning step, no printer movement)
- Every policy block records a proof event in proof_events table with printer_id, job_id, reason
- Jobs.tsx already correct: real endpoints, state machine, proof event IDs displayed — no fake messages
- Add 04_testing/pytest/unit/test_jobs_policy.py: 37 tests covering S1 lock, read-only policy, PRINTER_IDLE gate, no-printer pass-through, write-enabled idle pass-through, proof event DB writes
NEVER sends job commands to moving printers. S1 (192.168.0.12) never a job target.
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(gen3d): real provider readiness + proof-backed local templates (H3D-CLAUDE-GEN3D) (#70)
- backend: add GET /api/gen3d/providers — reads Lane 04 GEN3D_VERIFY_2026-05-06.json
proof + live port probe for ComfyUI; returns installed/repo_reachable/weights_present
for comfyui, trellis2, hunyuan3d, triposr, bambustudio_bridge; no fake readiness
- backend: add GET /api/gen3d/templates — discovers local templates (calibration_cube via
trimesh, no provider needed) + provider-backed templates from adapter_registry schemas;
schema_present field reflects real file existence
- UI: provider status panel now shows 3D generation provider readiness (from
/api/gen3d/providers) with readiness badges sourced from Lane 04 proof data
- UI: local template gallery (from /api/gen3d/templates) — cards show source, outputs,
required provider; selecting provider-backed template with unavailable provider shows
"Provider not available" on Generate with a proof event emitted
- tests: add test_gen3d_routes.py with 14 unit tests covering both new endpoints
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(source-ui): SourceOS CLI readiness + proof panel + no-cutoff layout (H3D-CLAUDE-SOURCE-UI) (#66)
- Add CliReadinessPanel component: collapsible section showing CLI readiness
for all 5 tool categories (slicers, modelers, print_farm, firmware, gen3d)
with per-key-tool status badges (Verified CLI / Detected / Source Ready /
Not Installed / Unavailable). Data comes from /api/sources/readiness.
- Add ProofArtifactPanel component: collapsible section with links to
/api/artifacts and per-category artifact queries, plus proof file listing.
- CliReadinessPanel and ProofArtifactPanel use overflow-y: auto with maxHeight
to ensure no content cutoff — all content is scrollable.
- Create 03_implementation/src/hermes3d/api/routes/source_os.py:
GET /api/sources/readiness reads proof JSON files (LOCAL_TOOLING_AUDIT,
SOURCE_APP_CLI_AGENT_READINESS_AUDIT, SOURCE_APP_CLI_SURFACE_AUDIT) and
returns aggregated readiness per category with key tool details.
- Wire source_os router into hermes3d/api/app.py.
- No hardcoded readiness states — all from proof JSON files.
- tsc --noEmit: PASS (zero errors in owned files; pre-existing TS7026 regression
in other src/*.tsx files predates this contract).
- py_compile source_os.py: PASS.
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(settings-plugins): update center + provider health + failsafe rollback (H3D-CLAUDE-SETTINGS-PLUGINS) (#69)
- Add GET /api/settings/update-center: real component versions, Velopack readiness, live provider probes, rollback availability
- Add POST /api/settings/update-center/rollback/{component}: surfaces rollback for proof-gated flow
- Register update_center router in app.py
- New UpdateCenterSubtab.tsx: live update center with failsafe rollback cards
- New PluginRollbackPanel.tsx: per-plugin health + deactivate/rollback action
- SettingsPage.tsx: add Update Center subtab wired to UpdateCenterSubtab
- AboutSubtab.tsx: fetch real versions from backend, removed hardcoded VERSION constant
Pre-existing TS errors in other files not introduced here. tsc passes clean for all touched files.
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(voice): transcript history + playback controls + proof review (H3D-CLAUDE-VOICE) (#64)
- Backend: add GET /api/voice/transcripts, GET /api/voice/recordings/{id},
GET /api/voice/proof-events to voice.py; recordings served as binary
audio from proof_events table; no API key in any URL
- Types: add VoiceTranscript and VoiceProofEvent to voice.ts
- Adapters: add getVoiceTranscripts, getVoiceProofEvents, getVoiceRecordingUrl
to AdapterAPI interface + live implementations + parse helpers
- UI: Voice.tsx gains three-tab layout (Voice Browser / Transcript History /
Proof Review); playback routed through backend only (new Audio(backendUrl)),
no device access from frontend; honest empty states when no data yet
Gates: python -m py_compile OK; tsc --noEmit 0 errors
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(printers): onboarding wizard + Moonraker probe + S1 camera-only lock (H3D-CLAUDE-PRINTERS) (#71)
- Add 5-step printer onboarding wizard to PrintersTab:
Step 1: Enter IP + connection type (Moonraker/OctoPrint/direct)
Step 2: Auto-probe via GET /api/printers/probe (read-only, shows version/firmware/bed size)
Step 3: Set camera URL with MJPEG validation
Step 4: Confirm + save profile with write-enable toggle
Step 5: Done / refresh fleet
- S1 (192.168.0.12) is LOCKED in the wizard: shows 'Camera only — cannot add as
print target' before any network call is made; frontend enforces CAMERA_ONLY_IPS set
- Add GET /api/printers/probe backend endpoint:
Read-only: calls only GET /server/info and optional /printer/objects/query
Never sends GCode, commands, or mutations
Returns: Moonraker version, klippy_state, bed size from fleet profile
- Add POST /api/printers/validate-camera backend endpoint:
Read-only: HEAD request only, checks Content-Type for multipart/x-mixed-replace
Returns: {ok, content_type, is_mjpeg, http_status}
- Add CAMERA_ONLY_IPS frozenset constant in printers.py (single source of truth):
Any attempt to add 192.168.0.12 as a print target returns 403 CAMERA_ONLY_IP
Covers: probe endpoint, onboard URL validation, printer ID validation
- Add test_printer_policy.py (16 tests, all passing):
- S1 IP blocked in onboard URL validation (403 CAMERA_ONLY_IP)
- S1 aliases blocked in printer ID validation (423)
- Probe endpoint returns 403 for S1 IP
- Probe is read-only: send_gcode/upload_gcode/start_print never called
- Camera validate uses HEAD request only
- MJPEG detection verified
- TestClient route integration tests
- TypeScript: tsc --noEmit passes cleanly (0 errors in owned files)
- Python: py_compile passes for printers.py and test_printer_policy.py
- Pre-existing TS7026 errors in other src/*.tsx files are unrelated to this lane
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs(integration): 20-agent completion integration report (H3D-CLAUDE-FINAL-INTEGRATOR) (#72)
All 19 lane PRs (#53-#71) are OPEN/MERGEABLE with CodeRabbit SUCCESS and
Hermes evidence chain PASS. Two cross-lane file conflicts identified:
- app.py: PRs #66 + #69 both add a router (additive, UNION merge)
- adapters.ts / adapters.live.ts: PRs #64 + #71 both add methods (additive, UNION merge)
Merge order: Tier-1 (15 PRs in parallel) → Tier-2 (#66→#69) → Tier-3 (#64→#71).
Pre-existing JSX TS7026/TS7006 regression (~57 files) flagged as HIGH-priority fix-PR
needed before release.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* audit(runtime): proof files + verifier scripts + route truth verification (#74)
Verifies all 6 proof JSON files are real (not hand-crafted), all 4 verifier
scripts use genuine subprocess/filesystem probes, and all 7 API routes have
real implementations. All syntax checks pass. No blockers found.
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* audit(merge): PR base + conflict cluster + silent drop verification (H3D-CLAUDE-POLISH-MERGE-2026-05-06) (#75)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* audit(security): secret scan + path traversal + shell audit (H3D-CLAUDE-POLISH-AGENT-MCP-PROOF-2026-05-06) (#76)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* audit(safety): S1 lock + printer policy + GCode scan verification (#77)
53/53 policy tests pass. S1 (192.168.0.12) blocked before every network call.
Zero GCode keywords in probe/read routes. Zero bypass paths found. Camera controls
are CSS-only display transforms with no hardware commands.
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* audit(docs): PR body completeness + ROADMAP truth + merge plan verification (H3D-CLAUDE-POLISH-RELEASE-DOCS-2026-05-06) (#78)
- Audited all 20 PR bodies (#53-#72): all have evidence chain, task ID, and gates
- PR #53 missing formal files table (prose description present); PR #64 minimal body
- TS7026 blocker documented in PR #72; absent from ROADMAP.md (codex-master locked)
- README "77 of 79" claim is stale relative to feature branch (update post-merge)
- Merge Tier 1/2/3 structure is correct; PR #72 needs explicit Tier 4 slot in plan
- No PRs accidentally merged; all 20 lane PRs remain open
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* audit(nofake-ui): 0 violations — no-fake scan + 33 buttons wired + 0 lane TS errors (H3D-CLAUDE-POLISH-NOFAKE-UI-2026-05-06) (#79)
* docs(handoff): final Codex takeover bundle — 9 audit/merge/lock files (#81)
Closes the Claude 20-agent + 6-audit-agent run. Contains:
00_EXECUTIVE_TAKEOVER_SUMMARY.md — 1-page status for Codex
01_PR_MERGE_MATRIX.md — exact tier merge order for #53-#80
02_OPEN_BLOCKERS_AND_FIX_QUEUE.md — 0 code blockers, 4 low/info doc gaps
03_LOCKS_WORKTREES_AND_BRANCHES.md — 28 Claude locks released, 28 worktrees
04_RUNTIME_TRUTH_AND_NO_FAKE_AUDIT.md — Audit 2+3: 0 fake violations
05_PRINTER_SAFETY_AND_PHYSICAL_IO_AUDIT.md — Audit 4: S1 camera-only PASS
06_SECURITY_MCP_AND_AGENT_ACCESS_AUDIT.md — Audit 5: no traversal/secret leaks
07_ARCHITECTURE_AND_FLOW_DIAGRAMS.md — Mermaid diagrams for all flows
08_FINAL_CLAUDE_RELEASE_NOTE.md — final PR list + lock state + Codex next steps
All 28 Claude-owned Hermes locks released.
All 20 lane PRs (#53-#72) and 6 audit PRs (#74-#79) open CLEAN.
TS7026 fix PR #80 open (CI running).
Hermes task: a2a_1778115796454_685e7b14
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(ui): clear post-merge npm audit vulnerabilities (#82)
* fix(ui): clear npm audit vulnerabilities
* fix(ui): clean post-merge browser gates
* fix: align observe refresh button contract
* [codex] add MCP-locked Hermes Agent code operator (#73)
* feat(agents): add MCP-locked code operator lane
* docs(handoff): add Claude final audit takeover contract
* fix(agents): harden code operator lane
* docs(handoff): Hermes3D OS folder index 2026-05-07 — 86 markdowns w/ inline SVG (#86)
Comprehensive index of every Hermes3D OS folder in G:\Github\ modified
between 2026-04-27 and 2026-05-07. Authored by 13 parallel sub-agents
under task a2a_1778147261453_661b606f.
Structure (12 categories, 60 included folders, 7 excluded):
00_INDEX.md -- master nav + topology SVG
01_TAXONOMY.md -- classification rules
02_EXCLUSIONS.md -- 7 folders intentionally excluded + reasons
apps-vendored/ -- 7 vendored apps (~1.08 GB) + README
core-repos/ -- 5 core H3D repos + README
agent-infra/ -- 5 hermes-agent / MCP infra + README
hp-protocol/ -- 9 HP P0/P1 hardening folders + README
hermesproof/ -- 6 HermesProof component sandboxes + README
source-os-60-apps/ -- canonical 60-app registry + treemap SVG
h3dos-wire-tasks/ -- 18 single-button UI wire lanes + README
h3dos-codex-tasks/ -- 5 Codex app integration lanes + README
merge-prs/ -- 4 cascade-merge worktrees + README
h3d-enhancements/ -- 7 H3D enhancement branches + README
worktree-collections/ -- 3 umbrellas (49 sub-worktrees) + README
research/ -- _research scratchpad + README
Each per-folder markdown includes: H1 title, purpose, status,
branch+commit, key files, relationships, and inline hand-written
SVG (400-900 px). Category READMEs add master inventory tables and
larger SVGs (700-900 px).
Excluded (7): kilocode-Azure2, contract-kit-v17 (3 variants),
TRELLIS.2, Agentic-Modeler, _repo_rescue_evidence -- documented
in 02_EXCLUSIONS.md with reasoning.
Hermes evidence chain: PASS
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(queue): recover closed stacked PR work (#105)
* feat(agents): add MCP-locked code operator lane
* docs(handoff): add Claude final audit takeover contract
* fix(agents): harden code operator lane
* feat(agents): add proof-gated git shipping lane
* feat(agents): add provider team assignment lane
* feat(agents): add provider execution artifacts
* feat(source-os): add runner contract matrix
* feat(source-os): register python cad verifier family
* feat(source-os): correct slicer runner truth
* feat(source-os): add print farm health verifiers
* feat(source-os): add service web health verifiers
* feat(source-os): add safe service start-runner preflights
* feat(source-os): supervise service runner starts
* test(unit): remove live fleet timeout from offline tests
* feat(source-os): add firmware source inventory verifiers
* feat(accel): add rust metadata proof worker
* feat(source): add read-only runner smoke contracts
* feat(source): add executable path runner smoke
* feat(source): add python import repair preflights
* feat(source): add slicer cli config preflights
* feat(source): add npm package metadata preflight
* docs(agents): define e2e proof plan
* feat(agents): add e2e workbench
* feat(agents): add provider smoke and reviewed ship lane (#104)
* feat(agents): add provider smoke and reviewed ship lane
* fix(agents): prove live runtime freshness
* feat(agents): add cli runner contracts
* fix(agents): require live provider smoke proof
* docs(handoff): Claude 20+ agent E2E completion intelligence bundle 2026-05-08 (#106)
Read-only intelligence sweep produced per PR 104's Claude 20+ Agent E2E
Completion Intelligence Contract. 12 markdown deliverables under
03_implementation/docs/handoffs/claude-e2e-intelligence-2026-05-08/
covering: executive map, G:/Github folder ecosystem audit, stale
code/branch map, Hermes Agent runtime gap map, Source OS 60-app
completion map, tab-by-tab UI no-fake audit, env-key/runtime config map,
test gates + proof matrix, PR + merge queue, Codex next 50 tasks, 6
Mermaid diagrams, and final Claude note.
Live truth captured at 2026-05-08 17:25Z from API on branch
codex/provider-smoke-workbench commit 43d8205: 220 routes, all 10 Agent
Workbench routes present, 60 Source OS apps (7 agent_cli_ready, 24
runner_gaps), 81 active UI files clean (no-fake scan PASS), 25 open PRs
all CLEAN/CodeRabbit-SUCCESS. Hard blocker: MiniMax + DeepSeek HTTP 401
on G:/private/.env keys (Tier 0 user action; Codex chain not blocked).
No source code edited. No PRs merged. No Codex-owned locks released. 12
hermes3d-locks acquired by claude-e2e-intel-aggregator (taskId
claude-e2e-intel-2026-05-08) for the markdown bundle; released after PR
open per contract.
Hermes evidence chain: kickoff ev_b6e233d4ac466056
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(agents): prove provider env aliases (#107)
* docs(handoff): prepare Claude 24-agent completion contract (#108)
* proof(I14): update no-fake sweep 2026-05-08 — 81 files, PASS (#116)
Active UI no-fake scan re-run on 2026-05-08:
- 81 production files walked from App.tsx entry point
- 0 findings (no mock/fake/simulated markers in string literals)
- No data/mock imports in active graph
- 15 orphaned/unwalked files separately verified clean
- scan_active_ui_no_fake.py requires no changes
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* test(I8): printer safety — S1 camera-lock tests, T1/V400 policy gates (#111)
Adds 25 new test cases to test_printer_policy.py closing the critical safety
gap where S1 (192.168.0.12) action endpoints (move, test, upload, upload-gcode)
had no direct hard-lock assertions. New TestS1ActionHardLock class proves 423
PRINTER_LOCKED fires before any MoonrakerClient I/O for all four action routes,
across all S1 aliases. TestT1V400PolicyGates confirms write-allowed printers are
not misclassified as S1 and pass the lock gate. 78/78 tests pass.
Task: H3D-CLAUDE24-I8-PRINTER-SAFETY
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(I4): add runner_family to all 60 runner-contracts + blocked_reason for BLOCKED rows (#119)
- Add _contract_runner_family() mapping runner_status → valid family string
- Add runner_family field to module_runner_contract() return dict (was absent,
causing all 60 /runner-contracts rows to have FIELD_MISSING)
- Fix blocked_reason for slic3r and superslicer (runner_status=blocked):
previously suppressed by cli_install_config_available=True condition; now
always set when runner_status==blocked regardless of preflight runner
- Valid families emitted: agent_cli_ready, read_only_runner, executable_path,
python_import_repair, cli_install_config, npm_package_preflight,
desktop_app_runner_gap, gpu_worker_runner_gap, runtime_repair_required,
source_reference_only, blocked, metadata_ready_needs_runner
- 113 pytest tests pass; only locked file modified
Task: H3D-CLAUDE24-I4-SOURCEOS-CORE
Hermes evidence chain: PASS
Gates run: python -m py_compile (both files), pytest 113 passed
Rows fixed (null→known runner_family): 60
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(I1): provider endpoint/model config audit — MiniMax+DeepSeek smoke (#112)
Audit confirmed both providers have correct code configuration:
- MiniMax: /v1/chat/completions, Bearer auth, MiniMax-M2.7 — all correct
- DeepSeek: /chat/completions, Bearer auth, deepseek-v4-pro — all correct
HTTP 401 on both is a pure API key issue (invalid/expired keys in G:\private\.env).
Added inline comments to PROVIDER_DEFAULT_BASE_URLS documenting the verified
endpoint/auth/model contract and the exact user action needed to resolve 401s.
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(I2): wire E2E code loop — patch-apply, gate-run, branch-commit-pr chain (#118)
- audit confirmed: apply_reviewed_patch_proposal, run_mcp_gate,
git_commit_owned_files, git_push_current_branch, git_open_pull_request,
restore_snapshot all fully implemented (no stubs)
- wiring gap found and fixed: no GET /e2e/jobs endpoint existed to list
job states — added list_e2e_jobs() to code_history.py and the
GET /api/code-operator/e2e/jobs route to code_operator.py
- new GET route queries proof_events for code_e2e/code_patch/code_git
event types and returns job state legend for E2E loop operators
- expanded test_code_operator_routes_are_registered to assert all 7
E2E chain routes are wired: apply-reviewed, gates/run, git/branch,
git/commit-owned, git/push, git/pr, e2e/jobs GET
- added test_list_e2e_jobs_returns_proof_events and
test_list_e2e_jobs_route_returns_200 — 92 tests pass (was 90)
- py_compile passes on both locked files
- provider 401 remains user-action only: I1 audit confirmed HTTP 401
is a pure invalid API key issue; no provider HTTP code touched
Task: H3D-CLAUDE24-I2-E2E-CODE-LOOP
Hermes evidence chain: PASS
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(I3): OpenCode/OpenHands sandbox readiness + GET preflight route (#121)
* feat(I3): OpenCode/OpenHands sandbox readiness + GET preflight route
- Add opencode_openhands_sandbox_readiness() in code_history.py returning
the I3-spec shape: opencode_detected, opencode_version, openhands_detected,
openhands_image, sandbox_network_mode (always "none"), denied_paths, ready
- Add preflight_code_cli_runner_get() for non-mutating --version dry-run
(GET variant, no task claim required); returns stdout, exit_code, elapsed_ms
- Wire GET /api/code-operator/sandbox/readiness to new function (replaces
Docker-based response with OpenCode/OpenHands detection schema)
- Add GET /api/code-operator/cli-runners/preflight?runner_id=opencode|openhands
- Add SandboxReadiness panel to Agents.tsx with real detected/not-detected
badges (data-testid=sandbox-readiness-panel), Refresh button, network mode
and denied-paths display — no fake states
- Evidence: ev_040fad5fbd843c38 (opencode v1.4.3-hermes3d detected, exit_code=0)
- 38 unit tests green; task H3D-CLAUDE24-I3-OPENCODE-OPENHANDS released
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(I3): wire setSandboxBusy into Refresh onClick — resolve TS6133
Layer D2 UI-Final failed because setSandboxBusy was declared but its
setter was never invoked (TS6133). Wire it correctly: setSandboxBusy(true)
before the fetch, .finally(() => setSandboxBusy(false)) after, so the
Refresh button correctly shows "checking" during load and CI passes.
Evidence: ev_ffa9a8c3e3bd4a40 | Task: H3D-A1-PR121-FIX
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(I7): firmware source inventory probes — read-only git describe, source_reference_only contract (#120)
- Add FIRMWARE_SOURCE_PATHS registry mapping all 6 firmware module IDs to
their actual source checkouts under Hermes3D-OS/source-lab/sources/
- Add _git_describe(): read-only subprocess.run(git describe --tags --always)
with timeout=5s; returns None on any error — no flash/compile/serial
- Add probe_firmware_source_inventory(module_id): returns source_found,
version_tag, runner_status=source_reference_only, agent_executable=False
- Add probe_all_firmware_sources(): aggregates all 6 modules in one call
- Update BUILTIN_RUNTIME_PROBES firmware entries: path fields now point to
confirmed source checkouts; kind changed to firmware_source_inventory
- Add 04_testing/pytest/unit/test_firmware_farm_probes.py — 49 tests:
registry coverage, contract template, _git_describe (mocked), per-module
parametrized happy/absent paths, safety constraint enforcement tests
- Live probe result (evidence ev_842d77f8663ea2ee):
firmware_klipper=293e1e9, marlin=03cc75f, prusa_firmware=f3e0dfd,
reprapfirmware=f4297ad, repetier_firmware=7cb3741, smoothieware=620e162
- ABSOLUTE CONSTRAINTS: no avrdude/dfu-util/openocd/esptool, no serial port,
no make/cmake/platformio, S1 not probed, T1/V400 source-only
Hermes evidence chain: PASS
Task ID: H3D-CLAUDE24-I7-FIRMWARE-FARM
Evidence ID: ev_842d77f8663ea2ee
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(I6): service/web-app health probes + service_web_health_runner status (#122)
Add seven named read-only HTTP probe functions (probe_fluidd, probe_mainsail,
probe_octoprint, probe_fdm_monster, probe_octofarm, probe_manyfold,
probe_comfyui) plus a probe_service_web_health dispatcher. Each probe uses
GET with a 3-second timeout, never POSTs, never mutates, and is blocked with
reason=no_configured_url when the env var is absent.
Update _runner_status to return service_web_health_runner (replacing the
generic readonly_api_ready) for local_http_health verifier kind, and add
service_web_health_runner_contract to _required_verifier_family.
Add 74-test suite in test_module_runtime.py covering: dispatcher routing,
blocked-when-no-url, non-local-URL guard, HTTP 200 happy path (mocked),
connection-error handling, 4xx handling, runner-contract status assertions,
and GET-only method verification. Update pre-existing test in
test_source_runtime_contracts.py to reflect the new runner_status value.
All 226 unit tests pass (74 new, 116 combined with existing module tests).
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(I5): slicer/modeler CLI probes — PATH detection, --version proof, exact blocked reasons (#123)
* fix(I4): add runner_family to all 60 runner-contracts + blocked_reason for BLOCKED rows
- Add _contract_runner_family() mapping runner_status → valid family string
- Add runner_family field to module_runner_contract() return dict (was absent,
causing all 60 /runner-contracts rows to have FIELD_MISSING)
- Fix blocked_reason for slic3r and superslicer (runner_status=blocked):
previously suppressed by cli_install_config_available=True condition; now
always set when runner_status==blocked regardless of preflight runner
- Valid families emitted: agent_cli_ready, read_only_runner, executable_path,
python_import_repair, cli_install_config, npm_package_preflight,
desktop_app_runner_gap, gpu_worker_runner_gap, runtime_repair_required,
source_reference_only, blocked, metadata_ready_needs_runner
- 113 pytest tests pass; only locked file modified
Task: H3D-CLAUDE24-I4-SOURCEOS-CORE
Hermes evidence chain: PASS
Gates run: python -m py_compile (both files), pytest 113 passed
Rows fixed (null→known runner_family): 60
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(I5): slicer/modeler CLI probes — PATH detection, --version proof, exact blocked reasons
Adds probe_slicer_cli() and probe_modeler_import() to module_runtime.py.
Non-mutating: --version/help only, no STL sent, no firmware flashed.
Detected (on this machine):
Slicers: PrusaSlicer 2.9.5, OrcaSlicer, FLSUN Slicer 2.0.4, CuraEngine 5.12.1, BambuStudio
Modelers: Blender 5.1.1, OpenSCAD 2021.01, trimesh 4.12.1, pymeshlab
Blocked (exact path tried recorded):
Slicers: SuperSlicer (not at C:/Program Files/SuperSlicer/), Slic3r (not installed)
Modelers: FreeCAD (FreeCADCmd not at standard paths), cadquery/build123d/numpy-stl/open3d (not importable), truck (source-inventory only)
Adds SLICER_MODULE_IDS, MODELER_PYTHON_IMPORT_IDS, MODELER_SOURCE_INVENTORY_IDS constants.
Adds _find_slicer_executable() with canonical + alt + PATH search.
Handles PrusaSlicer/OrcaSlicer/BambuStudio/FLSUN nonzero --version exit codes.
Tests: 43 new slicer/modeler probe tests + 42 existing contract tests = 85 total, all green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(I10): reduce polling lag, fix sidebar overflow, layout fixes (#110)
- AppShell: remove lg:overflow-hidden on main in dashboard mode to prevent panel cutoff on large viewports (overflow-auto retained throughout)
- Sidebar: wrap AgentChatMirror in min-h-0 shrink container so tall chat panel no longer displaces nav items off-screen
- TopBar: fix stale data — was fetch-on-mount only; add 10 000 ms setInterval refresh for system snapshot, notifications, and proof bundle (non-critical display data)
- globals.css: no changes needed (font-size 13px and dashboard-grid overflow-hidden are intentional)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(I11): SourceOS 60-row rendering, real API wiring, panel overflow (#114)
- Fetch /api/modules/runtime/runner-contracts on mount + after Verify All / Setup Queue actions
- Map runner_status (runner_family) per module_id into a lookup dict
- ModuleList: display runner_family badge for each of the 60 rows using real runner_status from contracts endpoint
- AppDetailPanel: add runner_family header pill + RunnerContract InfoBox showing runner_status, required_verifier_family, safe_actions, acceptance_gate, and blocked_reason
- Pass runnerContract down to AppDetailPanel and refresh it in onRefresh callback
- All 60 rows rendered without slice/limit (confirmed via /api/modules count:60)
- Controls (Verify, Setup Plan, Backup, Rollback) already wired to real API — confirmed no fake handlers
- Panel overflow: AppDetailPanel section has overflow-auto in flex container with min-h-0
scan_active_ui_no_fake: 81 production files scanned, 0 findings
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(I13): print workflow — remove fake job states, policy-gate print actions (#113)
Dashboard: rename PIPELINE_STAGES to PIPELINE_STAGE_ICONS and remove the
hardcoded status:'complete'/'active' fields from the lookup table. Those
fields were dead code (PipelinePanel always derives status from live API
stage data); keeping them risked a developer treating them as truth.
Autopilot: remove EXPECTED_READINESS_CHECKS=16 magic constant. The gate
'allReady' was permanently blocked unless the backend returned exactly 16
checks — even if every returned check passed. Now allReady is true when
checks.length > 0 && all returned checks are ready (API is source of
truth). Added a "loading…" label and empty-state message while the API
response is pending so the UI never shows 0/0 as a misleading ready count.
Jobs: remove the 'counts' useMemo that injected 0 into every non-active
filter tab badge. Showing "Queued 0 | Done 0 | Failed 0" without fetching
those counts is a fake/misleading value. Now only the active filter shows
a live count; inactive filter tabs show no count badge.
Printers: no fake states found — all print actions await real API
confirmation before updating UI, and S1 policy block is correctly enforced.
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(observe): real health probing in /cameras, remove fake events, fix initial feed state (#115)
- observe.py /api/observe/cameras: replaced static _configured_camera_state()
(always "configured") with a real _probe_camera_timed() call per camera so
health reflects actual connectivity, not just URL presence.
- Observe.tsx initialFeedState: cameras with health="unreachable" now start in
"error" state instead of "loading", preventing endless "CONNECTING" badge on
known-dead feeds.
- ObserveConsole.tsx: removed hardcoded fake EVENTS strings; events panel now
derives per-camera status lines from the real /api/observe/status response.
Polling interval documented (STATUS_POLL_INTERVAL_MS = 5000ms >= 3000ms).
Task: H3D-CLAUDE24-I9-OBSERVE-CAMERA
Hermes evidence chain: PASS
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(I12): agent chat blocked state, voice text+audio+mute, learning real states (#117)
- AgentChatMirror: extract real blocked reason from response body (HTTP 401
from MiniMax/DeepSeek now shows the provider error text, not just status code)
- AgentChatMirror: add explicit 'Providers blocked' banner in chat history
when agent roster is empty, with action text for G:\private\.env config
- Voice.tsx: add mute button to TTS preview (Voice Browser fine-tuning panel)
and transcript playback — muting suppresses audio but ALWAYS shows text
- Voice.tsx: text transcript displayed in all states; muted state explicitly
shown with amber indicator so user knows audio is off but text remains visible
Voice API probe: GET /api/voice/status → 404 (route not registered in backend);
GET /api/voice/providers → Azure Speech READY (configured, region=westus).
TTS routes through backend /api/voice/preview (confirmed base64 response).
Learning: real API calls only, blockers shown with real reasons (confirmed live).
No-fake scan: PASS (81 production files, no mock/fake/simulated UX markers).
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(provider): align MiniMax and DeepSeek runtime adapters (#124)
* docs(handoff): tighten Hermes runtime finish contract
* docs(sweep): PR #125 control sweep handoff + runtime finish report
- HERMES_RUNTIME_FINISH_REPORT.md: 10-agent audit results, merge
matrix, provider BLOCKED verdict (HTTP 401 both providers)
- PR125_CONTROL_SWEEP_HANDOFF_2026-05-09.md: full PR #125 sweep —
A1-A10 audit results, zombie lock recovery, secret safety PASS,
printer safety PASS, exact env key fixes required, next actions
Task: H3D-PR125-SWEEP-DOCS | Evidence: ev_dbf23c31c04af4ca, ev_a736131a4b0d8c6e
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(provider): align MiniMax and DeepSeek runtime adapters
- prefer MiniMax highspeed token-plan aliases and keep Max-Highspeed model routing explicit
- update MiniMax gateway to use MiniMax-M2.7-highspeed and max_completion_tokens
- update DeepSeek gateway/tests to use deepseek-v4-pro reasoning payload
- allow minimax/deepseek in llm policy and refresh provider rescue handoff docs
- keep provider smoke redacted; MiniMax now selects token-plan env and returns 429 insufficient_balance, DeepSeek remains 401
* docs(rescue): provider rescue blocker proof — adapters correct, blockers user-side
PR #124 provider completion sweep. Wave 1-3 audit:
- MiniMax adapter (gateways/providers/minimax.py): CORRECT per official docs.
Reaches api.minimax.io. HTTP 429 insufficient_balance (1008) is
provider-side billing/quota, NOT code, NOT auth.
- DeepSeek adapter (gateways/providers/deepseek.py): CORRECT per official
docs. Posts to api.deepseek.com/chat/completions with thinking +
reasoning_effort for v4-pro. HTTP 401 = "wrong API key" per
api-docs.deepseek.com/quick_start/error_codes (single documented cause).
No code fix needed. Both blockers are out-of-repo user actions:
1. MiniMax: top up Token Plan balance / OAuth portal auth at platform.minimax.io
2. DeepSeek: rotate DEEPSEEK_API_KEY in G:/private/.env
Hermes Agent loop remains BLOCKED until both providers return accepted:true.
Evidence: ev_cffabca307652c21 (minimax), ev_bdec2f02c01c17ec (deepseek),
ev_491fe9d07426cab4 (adapter audit).
Task: H3D-CLAUDE-PROVIDER-COMPLETION.
No private values exposed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(code-operator): expose redacted CLI provider env contract
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs(agent): tighten control gates (#125)
* docs(rescue): mark blocker proof SUPERSEDED — providers now PASS (#132)
First proof-gated Hermes Agent coding loop. The full chain ran end-to-end
including a real recovery cycle:
MiniMax build (artifact 08c8dce66b3a4a589572cee225f2b428)
-> DeepSeek review v1 BLOCKED_ON_INSUFFICIENT_EVIDENCE
-> v1 proposal 8365f7833f10... DeepSeek APPROVE ev_675dcddbd474c55d
-> apply -> git-diff-check FAIL on trailing whitespace from ` ` line breaks
-> rollback to snapshot 6f478adcf452 (proof 245d7fd376fc)
-> v2 proposal f07e6af14f5f authored without trailing whitespace
-> DeepSeek APPROVE v2 ev_59947bb44bf1715a
-> apply -> git-diff-check PASS gate_git-diff-check_1778295564288
Provider smoke evidence baked into the SUPERSEDED block text:
minimax ev_4a52d9b1336ca9f2 HTTP 200 MiniMax-M2.7-highspeed
deepseek ev_e708071cb269f170 HTTP 200 deepseek-v4-pro
No private values exposed. Same-owner MCP locks throughout.
Task: H3D-FIRSTLOOP-001-SUPERSEDE
Hermes evidence: f07e6af14f5f4db3972fdc1bb336bd35, ev_59947bb44bf1715a, ev_675dcddbd474c55d, ev_4a52d9b1336ca9f2, ev_e708071cb269f170, ev_a2780d9832e5567a, ev_95e16427ce056505, ev_69e00f87178d6f9c
* feat(recovery): Hermes Agent Recovery Controller v1 (lean ledger) (#133)
First lean v1 of the Hermes Agent Recovery Controller, born from the
recovery cycles in PR #126. Backend ledger ONLY: no UI, no autonomous
apply, no file mutation by the controller. Future-proof v1.5 schema
fields included so the upcoming Hermes Agent Task Monitor UI can read
rich state without backend refactor.
What ships:
- code_history.py: RECOVERY_FAILURE_CLASSES (9), RECOVERY_OUTCOME_STATUSES
(3), RECOVERY_FAILED_STEP_TYPES (10), RECOVERY_RECOMMENDED_ACTIONS (8),
RECOVERY_REDACTION_STATUSES (3), RECOVERY_WORKER_OUTPUT_STATUSES (6),
RECOVERY_AGENT_STACK_VALUES (8), _RECOVERY_LEDGER_PATH, plus
record_step_failure(), mark_recovery_outcome(), list_recovery_attempts().
Adds `import secrets` and `from hermes3d.gateways.redaction import
redact_text` to imports.
- code_operator.py: RecoveryRecordFailureRequest, RecoveryMarkOutcomeRequest
StrictBody models + 3 routes: POST /recovery/record-failure, POST
/recovery/mark-outcome, GET /recovery/state.
- test_code_operator.py: 7 lean v1 tests covering record/reject/redact/
mark/state via TestClient with unique uuid4 task_ids.
- docs/handoffs/REVIEW_PACKET_*.md: 4 proof artifacts (full diff +
contract per file) used in DeepSeek per-file review.
Provenance chain (each step proof-anchored):
- MiniMax artifacts 2130e9e1d12d4686ac4d788bfd136673 (build pass 1) +
459bc9c00d6049dd949fa84e61f09c7a (build pass 2). BOTH truncated by
completion-token budget. Manual fixes preserved chain-of-custody:
(a) merge_conflict -> merge_git_fail (test class typo)
(b) test_state_route_returns_attempts re-authored from truncation
(c) `import secrets` added (MiniMax used secrets.token_hex without
adding the import)
(d) v1.5 future-proof fields added per user spec
- Per-file DeepSeek review APPROVE:
code_history.py proposal b63cd8b665bf4c2488591f8350b91cf5
review ev_5635d54ac7fdcec7
code_operator.py proposal 7b76f0eae91a4f0d8c80850fcef0b4f0
review ev_d9225ed939f77eb2
test_code_operator proposal 33d7dbc691b146f7a495c6c23fa148b0
review ev_4d1ca4217e6b226c
- Recovery cycle (gate failure -> targeted fix):
pytest NameError: redact_text -> follow-up proposal
fe2371073c3d4267b5e0e049df13e5b7 -> DeepSeek APPROVE
ev_5586c466df5d59aa -> applied evidence ev_647bfc4e38e0738f.
Gates after final apply:
- python -m py_compile (code_history.py + code_operator.py): exit 0
- python -m pytest test_code_operator.py: 50 passed
- scan_active_ui_no_fake.py: 81 files, 0 markers
- git diff --check: exit 0
- hermes_run_gate git-diff-check: PASS gate_git-diff-check_1778298845085
Provider smoke evidence still PASS: minimax ev_4a52d9b1336ca9f2,
deepseek ev_e708071cb269f170. No private values exposed.
Next slice (separate PRs): autonomous repair dispatch (v2), Hermes Agent
Task Monitor UI (v3). v0.13.0 upstream Hermes Agent update is its own
proof-gated lane.
Task: H3D-RECOVERY-CTL-V1
Hermes evidence: b63cd8b665bf4c2488591f8350b91cf5, 7b76f0eae91a4f0d8c80850fcef0b4f0, 33d7dbc691b146f7a495c6c23fa148b0, fe2371073c3d4267b5e0e049df13e5b7, ev_5635d54ac7fdcec7, ev_d9225ed939f77eb2, ev_4d1ca4217e6b226c, ev_5586c466df5d59aa, ev_788974be0aa90ccd, ev_cbdcc4bca447d895, ev_e1ba5ddf993149bb, ev_647bfc4e38e0738f, ev_4a52d9b1336ca9f2, ev_e708071cb269f170
* docs(gui): add Hermes3D OS visual reference pack (#134)
* fix(agent-updates): harden staged-update pytest gate (Audit PR #135 follow-up) (#136)
Mirrors upstream NousResearch/hermes-agent tests.yml flags so the staged
update gate cannot fake-pass while v0.13.0 is formally deferred. Closes
the CICD-SEC-1 / Codecov-2021-style fake-pass surface in
_run_update_checks.
Patch
- Path ignores: --ignore=tests/integration --ignore=tests/e2e match
upstream tests.yml. Marker-only -m "not integration" cannot block
tests/e2e/conftest.py from polluting sys.modules at collection time
(sys.modules["discord"] = MagicMock leak proven during Cplus-py311
Phase 4 bisection).
- Workers env: HERMES_AGENT_PYTEST_WORKERS (default "4", mirrors GHA
4-vCPU runner). Production rejects <2 with HTTPException(400);
HERMES_AGENT_DIAGNOSTIC=1 overrides for triage. "auto" sentinel
accepted. Garbage strings raise 400.
- maxfail: 1 in production (matches upstream tests.yml), 5 in
diagnostic mode for triage-friendly multi-failure output.
- Skip path now fail-closed: missing HERMES_AGENT_RUN_PYTEST surfaces
as status="fail" with "REQUIRES_CONFIRMATION:" output, never
status="skipped" or 200/OK. Removes the fake-pass path that let
pytest=skipped roll up as gate=verified.
- Timeout 300s -> 600s. Larger collected set under upstream-aligned
--ignore needs the longer budget.
Tests
- 04_testing/pytest/unit/test_agent_updates_meta.py (3 tests):
upstream tests.yml still has both --ignore= flags (network test,
skip-on-offline), local source mirrors them, diagnostic+workers
guard names + default value present.
- 04_testing/pytest/unit/test_agent_updates_skip_path.py (11 tests):
skip-path fail-closed when env unset/zero, workers 0/1 rejected in
production, workers 0 allowed in diagnostic mode, garbage raises
400, default workers="4", path-ignores in pytest args, diagnostic
uses --maxfail=5, "auto" sentinel accepted.
Result: 14/14 pass on 04_testing/pytest/unit.
Scope
- v0.13.0 update remains formally deferred (Cplus-defer-formal).
- This PR fixes the gate only; no runtime update was installed.
- Sources: PR #135 / commit 5ecd8ff (Batch 2 Agent 6 + Agent 10).
Follow-ups (separate PRs)
- Bonus 12: recovery ledger file lock, mark_recovery_outcome
idempotency, agent_updates.py:115 HTTPException auto-repair gap,
apply_patch_proposal TOCTOU.
- Bonus 13: 60-app audit doc errata (loader-real registry path,
42 SPDX-invalid licenses).
- Upstream Agent 11 tickets (firmware archive-dir validator deferred
here; YAML schema lacks the field today).
References
- https://raw.githubusercontent.com/NousResearch/hermes-agent/main/.github/workflows/tests.yml
- https://docs.pytest.org/en/stable/example/pythoncollection.html#ignore-paths-during-test-collection
- https://owasp.org/www-project-top-10-ci-cd-security-risks/
- https://about.codecov.io/apr-2021-post-mortem/
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(recovery): close Bonus 12 ledger races + auto-repair escape (PR #135) (#137)
Three findings from the Bonus 12 audit (PR #135 / bonus12-bug-finder.md):
Finding #1 (blocker, services/code_history.py recovery ledger)
- Append-without-lock allowed concurrent record_step_failure /
mark_recovery_outcome calls to interleave partial JSONL lines on
Windows. mark_recovery_outcome would silently json.JSONDecodeError-
skip the corrupted entries and report "attempt_id not found".
- Fix: new _RecoveryLedgerLock context manager that combines a
process-local threading.Lock with an OS-level advisory lock on a
sidecar lockfile. Uses fcntl.flock on POSIX and msvcrt.locking on
Windows; both stdlib, no new deps. flush()+os.fsync() on every
append.
Finding #2 (major, mark_recovery_outcome)
- No idempotency check: a retry could append a SECOND outcome row,
producing ambiguous state for list_recovery_attempts consumers.
- Fix: read scan now happens inside the same lock as the append.
If any outcome row for attempt_id already exists, raise
ValueError("already has a recorded outcome") atomically.
Finding #3 (major, agent_updates.py:115)
- _run_git raises HTTPException(502) on non-zero exit. A failed
mid-step "git checkout --detach <tag>" escaped the for-tag loop
without reaching _auto_repair_to_backup, leaving the Hermes Agent
checkout on the previous (still-unverified) tag and surfacing 502
to the caller instead of structured rollback.
- Fix: wrap the per-tag checkout + _run_update_checks in
try/except HTTPException; record a synthetic step failure with the
redacted detail and pivot to _auto_repair_to_backup. Also catches
the HERMES_AGENT_PYTEST_WORKERS validation 400 added in PR #136.
Tests added (11 total, all green)
- 04_testing/pytest/unit/test_recovery_ledger_locking.py (8 tests)
* lock helper exposes a backend (fcntl/msvcrt/thread-only)
* 12-thread x 25-write concurrency test: every line round-trips
through json.loads (no torn writes)
* record_step_failure writes complete JSONL line + creates parent
directory + lockfile sidecar
* mark_recovery_outcome first call succeeds; second call raises
ValueError with "already has a recorded outcome"
* unknown attempt_id still raises "not found in recovery ledger"
* race test: two threads finalize same attempt_id; exactly one
succeeds, one raises idempotency error
- 04_testing/pytest/unit/test_agent_updates_auto_repair.py (3 tests)
* failed checkout pivots to _auto_repair_to_backup (no 502 escape)
* failed _run_update_checks (workers env 400) also pivots
* all-pass path unchanged (smoke regression guard)
Verification
- py_compile: OK on all 4 files
- Focused tests: 25/25 pass (11 new + 14 from PR #136)
- Pre-existing failures in test_source_runtime_contracts.py (5
firmware tests blocked instead of ready) confirmed pre-existing
on base; out of scope for this PR.
Scope
- Recovery Controller v2 (RC v2) commits 2-5 stay paused per user
instruction; RC v2 depends on the recovery correctness this PR
restores.
- Hermes Agent v0.13.0 update remains formally deferred.
- Bonus 13 audit doc errata is out of scope (separate PR).
References
- https://docs.python.org/3/library/fcntl.html#fcntl.flock
- https://docs.python.org/3/library/msvcrt.html#msvcrt.locking
- https://about.codecov.io/apr-2021-post-mortem/
- https://owasp.org/www-project-top-10-ci-cd-security-risks/
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(agent-updates): harden _zip_dirty_entries (Bonus 12 #4 / PR #135) (#138)
Defense-in-depth on the dirty-files backup zip in
api/routes/agent_updates.py:_zip_dirty_entries.
Pre-fix issues
- Opened the zip without allowZip64=True, so >4 GiB dirty backups
silently truncate on Python builds that default to no-zip64.
- Used path.relative_to(repo) against an un-resolved repo path,
raising ValueError and aborting the whole backup whenever the repo
path is itself a symlink.
- A symlink in the dirty tree could resolve to a target outside the
repo and still produce an arcname inside the archive, surfacing
CWE-22 path traversal on extract.
Post-fix
- allowZip64=True passed to ZipFile.
- path.is_symlink() check skips symlinks defensively (even though
_dirty_entries usually pre-resolves; tests / future callers may not).
- Arcname computed against repo.resolve() so symlinked checkouts
(e.g. /tmp/repo -> /var/checkout) work cleanly.
- Arcname asserted to be a pure relative path (no absolute,
drive-letter, parent-traversal, or empty components).
- Resolved-target paths that fall outside the repo are silently
dropped instead of leaking into the archive.
Tests added (8, all green)
- 04_testing/pytest/unit/test_agent_updates_zip_dirty.py
* normal files round-trip with relative arcnames
* empty paths list short-circuits without creating an archive
* symlinks (in-repo target) skipped — CWE-22 guard
* symlinks (out-of-repo target) skipped — exfiltration guard
* symlinked repo root produces correct arcname (no ValueError)
* out-of-repo path silently dropped
* allowZip64=True passed (probe via ZipFile subclass)
* pathological absolute Path components silently dropped
Verification
- py_compile: OK
- 25/25 agent_updates-keyed unit tests pass
- Secret-leak scan on touched files: only descriptive test fixture
string "outside-secret" (not a real secret)
- Pre-push hook: passed
Scope
- Bonus 12 finding #4 only (continuing the controlled-batch pattern
from PR #137).
- v0.13.0 update remains formally deferred.
- RC v2 commits 2-5 remain paused per user instruction.
References
- https://docs.python.org/3/library/zipfile.html#zipfile.ZipFile
- https://cwe.mitre.org/data/definitions/22.html
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* docs(audit): 60-App Update Readiness Audit (docs-only, no runtime change) (#135)
* docs(audit): 60-App Update Readiness Audit + Phase 4 v2 patch proposal
Audit/planning lane only. No app updates. No GUI changes. No source mutation
beyond this doc. Hermes Agent v0.13.0 stays formally deferred per the
2026-05-09 user decision in handoffs/HERMES_AGENT_V013_UPDATE_LANE_CPLUS_PY311_DOCKER_FORMAL_DEFER.
What's in the audit:
- Per-app profile matrix: 60 rows across 11 sections (slicers 11 / modelers 13
/ 3D-gen 6 / print-farm 10 / firmware 6 / agent-cli 7 / library 1 / materials
1 / hardware 3 / utilities 1 / research 1). Each row: update method, proof
command, runtime env, deps, rollback method, blockers, recommended lane,
auto-upd…
Task
H3D-CLAUDE24-I11-SOURCEOS-UI
Hermes evidence chain: PASS
What was fixed
1. Runner-family badges from real API (primary fix)
loadRunnerContracts()fetch from/api/modules/runtime/runner-contracts(the real endpoint — 60 records,runner_statusfield is the runner_family)ModuleList: each of the 60 rows now shows a 4th badge with the realrunner_statusvalue (agent_cli_ready,readonly_api_ready,metadata_ready_needs_runner,runtime_repair_required,npm_package_runner_gap,desktop_app_runner_gap,gpu_worker_runner_gap,source_reference_only,launcher_metadata_only,blocked) — colour-coded per familyAppDetailPanel: header pills includerunner: <status>from live contracts; new "Runner Contract" InfoBox shows runner_status, required_verifier_family, safe_actions, acceptance_gate, and blocked_reason2. All 60 rows rendered (confirmed)
/api/modulesreturns 60 records;ModuleListrenders with no slice/limit — all 60 rows visible3. Controls wired to real API (confirmed)
POST /api/modules/{id}/runtime/verify(real)POST /api/modules/{id}/runtime/setup-plan(real)POST /api/modules/{id}/update/backup(real)POST /api/modules/{id}/rollback(real)4. Panel overflow
AppDetailPanel<section>hasoverflow-autoin amin-h-0 flex-1flex container — correct scrolling pattern for narrow viewportsscan_active_ui_no_fake result
Exit code: 0 (PASS)
Pre-existing TypeScript errors
The repo has a known JSX type regression (TS7026/TS7006 in ~57 tsx files — missing
@types/react). No new errors introduced by this PR.🤖 Generated with Claude Code
Summary by CodeRabbit
Release Notes
New Features
Documentation
Chores