Repository navigation
fix(observe): real camera health probing, remove fake events, fix initial feed state - #115
Conversation
…x initial feed state - 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>
📝 WalkthroughWalkthroughThis PR expands Hermes3D documentation with project, folder, research, and audit records, strictly formalizes all adapter and tool schemas, hardens contracts and proof/data quality criteria, synchronizes printer fleet safety, bundles proof/artifact verification runs, and upgrades CI workflows to integrate Python+Playwright+artifact validation. ChangesHermes3D Documentation, Schemas, Contracts, Proofs, and CI
Sequence Diagram(s)sequenceDiagram
participant GitHubActions
participant Python
participant Node
participant Playwright
participant ProofArtifacts
GitHubActions->>Python: Setup Python 3.11 & pip install
Python->>Node: npm ci, deps setup
Node->>Playwright: Run E2E/no-fake/smoke tests
Playwright->>ProofArtifacts: Write/validate all proof/config JSONs
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 project, focusing on the agentic automation ecosystem, printer fleet management, and extensive documentation of the codebase structure. Key changes include the addition of numerous JSON schemas for adapter configurations, updates to the 'Definition of Done' and 'Master Contract' to enforce data integrity and safety rules for agents, and the implementation of a detailed roadmap for end-to-end GUI completion. Feedback highlights several improvement opportunities in the newly added schemas, such as removing machine-specific hardcoded paths in the local modeling LLM schema, resolving type inconsistencies in the Moonraker API schema, and standardizing the JSON Schema draft versions and ID naming conventions across the registry. Additionally, minor typos in the printer configuration file were identified for correction.
| "C:/Users/Admin/AppData/Local/Programs/Ollama/ollama.exe", | ||
| "ollama", | ||
| "llama-cli", | ||
| "llama" | ||
| ] | ||
| }, |
There was a problem hiding this comment.
The default executable_candidates list includes a hardcoded path for a specific user (Admin). This path is machine-specific and will fail for other users. It should be removed from the default candidates list in the schema.
"executable_candidates": {
"type": "array",
"items": {"type": "string"},
"default": [
"ollama",
"llama-cli",
"llama"
]
},| "response_root": { | ||
| "type": "string", | ||
| "description": "Top-level JSON key in Moonraker response containing the data (usually 'result')" | ||
| } |
There was a problem hiding this comment.
The response_root property is defined as a string, but the example on line 86 uses null. This inconsistency will cause validation errors if the example is used as a test case or if the schema is strictly enforced. Consider allowing null in the type definition to support endpoints without a result wrapper.
| "response_root": { | |
| "type": "string", | |
| "description": "Top-level JSON key in Moonraker response containing the data (usually 'result')" | |
| } | |
| "response_root": { | |
| "type": ["string", "null"], | |
| "description": "Top-level JSON key in Moonraker response containing the data (usually 'result')" | |
| } |
| moonraker_url = "http://flsun-t1-a.local" | ||
| api_key = "" | ||
| official_wiki_url = "https://wiki.flsun3d.com/en/FlsunT1" | ||
| official_config_topics = ["Network Connection Guidelines", "Orca import T1 configurationfile", "First Printing with Local Test Models"] |
There was a problem hiding this comment.
Typo in official_config_topics: "configurationfile" should be "configuration file".
| official_config_topics = ["Network Connection Guidelines", "Orca import T1 configurationfile", "First Printing with Local Test Models"] | |
| official_config_topics = ["Network Connection Guidelines", "Orca import T1 configuration file", "First Printing with Local Test Models"] |
| moonraker_url = "http://flsun-t1-b.local" | ||
| api_key = "" | ||
| official_wiki_url = "https://wiki.flsun3d.com/en/FlsunT1" | ||
| official_config_topics = ["Network Connection Guidelines", "Orca import T1 configurationfile", "First Printing with Local Test Models"] |
There was a problem hiding this comment.
Typo in official_config_topics: "configurationfile" should be "configuration file".
| official_config_topics = ["Network Connection Guidelines", "Orca import T1 configurationfile", "First Printing with Local Test Models"] | |
| official_config_topics = ["Network Connection Guidelines", "Orca import T1 configuration file", "First Printing with Local Test Models"] |
| "$schema": "http://json-schema.org/draft-07/schema#", | ||
| "$id": "hermes3d://adapter_registry/schemas/klipper_service/v1", |
There was a problem hiding this comment.
This schema uses an older JSON Schema draft (Draft 7) and an inconsistent $id naming convention compared to other newly added schemas in this directory. For consistency and better compatibility with modern tooling, consider updating to Draft 2020-12 and aligning the $id format.
| "$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.
This schema uses an older JSON Schema draft (Draft 7) and an inconsistent $id naming convention. Consider aligning it with the rest of the schemas in the registry which use Draft 2020-12 and include the filename in the $id.
| "$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", |
There was a problem hiding this comment.
Actionable comments posted: 1
Note
Due to the large number of review comments, Critical severity comments were prioritized as inline comments.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/h3dos-wire-tasks/h3dos-wire-dashboard-events-tail.md (1)
1-51:⚠️ Potential issue | 🟠 Major | ⚖️ Poor tradeoffCritical inconsistency: This file does not match the PR objectives.
The PR is titled "fix(observe): real camera health probing, remove fake events, fix initial feed state" and describes changes to camera connectivity probing (
/api/observe/cameras,_probe_camera_timed()), Observe.tsx feed state, and ObserveConsole event handling.However, this file documents the Dashboard events tail feature (
#dashboardEventspanel,GET /api/workspace, Action Window rendering) - an entirely different subsystem. The PR objectives make no mention of Dashboard events tail documentation, and this file makes no reference to camera observation, health probing, or the Observe feature.This file appears to have been included in the wrong PR.
🤖 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-wire-tasks/h3dos-wire-dashboard-events-tail.md` around lines 1 - 51, The file h3dos-wire-dashboard-events-tail.../h3dos-wire-dashboard-events-tail (which documents `#dashboardEvents` and GET /api/workspace) is unrelated to the PR titled "fix(observe): real camera health probing..." and must be removed or moved out of this branch; update the PR so it only contains Observe-related changes (e.g. _probe_camera_timed(), /api/observe/cameras, Observe.tsx feed state, ObserveConsole event handling) by deleting this documentation file from the branch or moving it to the correct wire/dashboard-events-tail branch, then amend the commit/PR so diffs only include the intended Observe code changes and re-run tests.01_requirements/AGENTIC_AUTOMATION.md (1)
180-182:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winFix internal tool-count mismatch (11 vs 16).
Lines 180-182 conflict with Lines 147-159: the doc enumerates 11 built-in registry tools but then says the registry is exposed as 16 MCP tools. Please reconcile the count or explicitly split “registry tools” vs “additional MCP utilities.”
Suggested doc fix
-The MCP server (`api.mcp_server`) exposes the registry as 16 MCP -tools. Connect any MCP-aware LLM client (Claude Desktop, Cursor, -custom) and the tools appear automatically. +The MCP server (`api.mcp_server`) exposes the tool registry to MCP +clients. Connect any MCP-aware LLM client (Claude Desktop, Cursor, +custom) and the registered tools appear automatically.🤖 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/AGENTIC_AUTOMATION.md` around lines 180 - 182, The document conflict: the registry tools list (Lines ~147-159) enumerates 11 built-ins but later text (Lines ~180-182) claims the MCP server (`api.mcp_server`) exposes 16 tools; reconcile by either updating the later sentence to match 11 or explicitly splitting the items into "11 built-in registry tools" plus "5 additional MCP utilities" and list or reference those extra utilities; update the phrasing around `api.mcp_server` and "registry" to clearly state which set (registry tools vs additional MCP utilities) totals 11 or 16 so the counts and terminology are consistent.03_implementation/docs/handoffs/HERMES_AGENT_E2E_TRUTH_PROOF_PLAN_2026-05-08.md (1)
1-282:⚠️ Potential issue | 🔴 Critical | ⚡ Quick winCRITICAL: Documentation files do not match PR objectives.
The PR title and description state this PR fixes "real camera health probing, remove fake events, fix initial feed state" with changes to
/api/observe/cameras,Observe.tsx, andObserveConsole. However, the files provided for review are:
- A new Hermes Agent E2E Truth/Proof planning document
- A ROADMAP.md update
Neither file contains observe/camera implementation code. This suggests either:
- The wrong files were provided for review
- The PR objectives are incorrect
- These documentation updates belong in a separate PR
If this PR truly addresses camera health probing (as the title states), the implementation files for
/api/observe/cameras,Observe.tsx, andObserveConsoleshould be included in the review.If this PR is actually a documentation update, the PR title and objectives should be corrected to reflect that scope.
🤖 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/HERMES_AGENT_E2E_TRUTH_PROOF_PLAN_2026-05-08.md` around lines 1 - 282, PR mismatch: the changed files (HERMES_AGENT_E2E_TRUTH_PROOF_PLAN_2026-05-08.md and ROADMAP.md) do not include the camera health fixes named in the title; either include the implementation files or correct the PR metadata. Fix it by either (A) add the missing implementation files and commits that modify the camera endpoint and UI components (/api/observe/cameras, Observe.tsx, ObserveConsole) so reviewers can inspect the actual changes, or (B) update the PR title/description to state this is a documentation-only change (reference the new HERMES_AGENT_E2E_TRUTH_PROOF_PLAN_2026-05-08.md and ROADMAP.md) and open a separate PR for the camera fixes; ensure commit messages reference the corresponding symbols (endpoint /api/observe/cameras and component names Observe and ObserveConsole) so CI and reviewers can trace intent.
🟠 Major comments (21)
03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/core-repos/Hermes3D-worktrees.md-1-95 (1)
1-95:⚠️ Potential issue | 🟠 Major | ⚡ Quick winPR scope appears mismatched with stated objective
This file documents worktree structure, but the PR objective is camera health probing and Observe UI/feed-state fixes. Please confirm this file is intentionally part of H3D-CLAUDE24-I9-OBSERVE-CAMERA (or move it to a separate docs PR) to keep traceability and release risk clear.
🤖 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/core-repos/Hermes3D-worktrees.md` around lines 1 - 95, The PR includes a docs file (Hermes3D-worktrees / headings like lm-studio-default, ADR-015) that doesn't match the stated camera-health/Observe UI objective; either confirm this file belongs in H3D-CLAUDE24-I9-OBSERVE-CAMERA by updating the PR description and title to mention the docs addition and rationale, or remove the Hermes3D-worktrees file from this branch and open a separate docs-only PR (or move the commit to a docs branch) so the camera-health and Observe UI changes remain isolated for traceability and release risk management.03_implementation/adapter_registry/schemas/curaengine.schema.json-30-35 (1)
30-35:⚠️ Potential issue | 🟠 Major | ⚡ Quick winEnforce the "never include
slice" safety rule in schema validation, not only description.Line 34 documents a hard requirement, but the schema currently permits
safe_probe_argscontaining"slice". The JSON Schema Draft 2020-12 validator supports the suggested fix and the validation library (jsonschemawithDraft202012Validator) is already in use.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'." }🤖 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 allows "slice" despite the description—update the safe_probe_args definition to forbid the string "slice" at validation time by changing its items schema to disallow that exact value (e.g., replace "items": {"type":"string"} with "items": {"type":"string", "not": {"const": "slice"}}) so any array element equal to "slice" fails validation while keeping the existing default and description.03_implementation/adapter_registry/schemas/printer_connection.schema.json-23-39 (1)
23-39:⚠️ Potential issue | 🟠 Major | ⚡ Quick winTighten network field validation to prevent invalid configs passing schema checks.
ipandmoonraker_urlcurrently accept arbitrary non-empty strings. That permits invalid connection data to validate and fail later at runtime.Suggested fix
"ip": { - "type": "string", - "minLength": 1 + "type": "string", + "anyOf": [ + { "format": "ipv4" }, + { "format": "ipv6" }, + { "format": "hostname" } + ] }, @@ "moonraker_url": { - "type": [ - "string", - "null" - ], + "anyOf": [ + { "type": "string", "format": "uri" }, + { "type": "null" } + ], "default": null },🤖 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/printer_connection.schema.json` around lines 23 - 39, The schema currently allows arbitrary non-empty strings for "ip" and "moonraker_url", so tighten their validators: change the "ip" subschema to validate addresses (for example add "format":"ipv4" or a hostname/IP regex to accept IPv4/IPv6/hostname as needed) and remove the loose minLength-only check; change "moonraker_url" to use "type":["string","null"] with an additional "format":"uri" (or a "pattern" enforcing ^https?://) while keeping null as allowed. Keep the existing "port" constraints as-is. Update only the "ip" and "moonraker_url" subschemas (retain "default": null for moonraker_url).03_implementation/adapter_registry/schemas/cadquery_worker.schema.json-7-9 (1)
7-9:⚠️ Potential issue | 🟠 Major | ⚡ Quick winRequire
verifywhenenabledis true.Line 7-Line 9 currently allows an enabled adapter config without probe metadata, which conflicts with the “real probe metadata” contract on Line 46.
Proposed schema fix
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "hermes3d://adapter_registry/schemas/cadquery_worker.schema.json", "title": "cadquery worker config", "type": "object", "additionalProperties": false, "required": [ "enabled" ], + "allOf": [ + { + "if": { + "properties": { + "enabled": { "const": true } + }, + "required": ["enabled"] + }, + "then": { + "required": ["verify"] + } + } + ], "properties": {Also applies to: 44-48
🤖 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/cadquery_worker.schema.json` around lines 7 - 9, The schema currently allows "enabled": true without the "verify" probe metadata; add a JSON Schema conditional so that when the "enabled" property is true the "verify" property is required (use an "if": {"properties":{"enabled":{"const":true}}}, "then": {"required":["verify"]} block) and apply the same conditional in the second adapter schema occurrence (the other block that defines the adapter config at the later location), ensuring the "enabled" -> "verify" contract is enforced.03_implementation/adapter_registry/schemas/build123d_worker.schema.json-7-9 (1)
7-9:⚠️ Potential issue | 🟠 Major | ⚡ Quick winRequire
verifyat the top level to enforce probe metadata.Line 7 currently requires only
enabled. A config can validate without anyverifyblock, which bypasses the intended probe contract.Suggested fix
"required": [ - "enabled" + "enabled", + "verify" ],Also applies to: 44-48
🤖 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/build123d_worker.schema.json` around lines 7 - 9, The schema's top-level "required" array currently only includes "enabled", allowing configs without a "verify" block; update the top-level required array to include "verify" (so it requires both "enabled" and "verify") and apply the same change to the other required array instance (the one around lines 44-48) so that both schema objects mandate the "verify" property; locate the "required" arrays in build123d_worker.schema.json and add "verify" alongside "enabled" to enforce probe metadata.03_implementation/adapter_registry/schemas/blender_bridge.schema.json-7-9 (1)
7-9:⚠️ Potential issue | 🟠 Major | ⚡ Quick winMake
verifymandatory at the adapter root.Line 7 only enforces
enabled. A config can pass validation with no verification metadata, which weakens adapter readiness checks.Suggested fix
"required": [ - "enabled" + "enabled", + "verify" ],Also applies to: 44-48
🤖 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/blender_bridge.schema.json` around lines 7 - 9, The root JSON schema's required array currently only enforces "enabled" so adapters can validate without verification metadata; update the top-level "required" array in blender_bridge.schema.json to include "verify" alongside "enabled" and make the same change to the second required array around the other schema block (the one at lines ~44-48) so both top-level required arrays contain ["enabled","verify"]; locate the top-level "required" arrays and add "verify" to each to ensure verification metadata is mandatory.03_implementation/adapter_registry/schemas/build123d_worker.schema.json-63-84 (1)
63-84:⚠️ Potential issue | 🟠 Major | ⚡ Quick win
install_checkandruntime_checkcurrently allow empty objects.At Line 63 and Line 75, both objects have no required keys, so
{}passes schema validation and can silently disable meaningful checks.Suggested fix
"install_check": { "type": "object", "additionalProperties": false, + "required": ["import_must_succeed", "required_capabilities"], "properties": { "import_must_succeed": {"type": "boolean", "default": true}, "required_capabilities": { "type": "array", "items": {"type": "string"}, "default": ["python_cad", "boolean_geometry", "step_export"] } } }, "runtime_check": { "type": "object", "additionalProperties": false, + "required": ["smoke_expression", "timeout_s"], "properties": { "smoke_expression": { "type": "string", "default": "from build123d import Box; Box(1,1,1)" }, "timeout_s": {"type": "integer", "minimum": 1, "maximum": 60, "default": 15} } }🤖 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/build123d_worker.schema.json` around lines 63 - 84, The install_check and runtime_check objects currently accept empty objects; add JSON Schema "required" arrays to each to enforce presence of their meaningful keys: for install_check add required: ["import_must_succeed","required_capabilities"] and for runtime_check add required: ["smoke_expression","timeout_s"] so that {} will fail validation and the properties import_must_succeed, required_capabilities, smoke_expression and timeout_s must be provided.03_implementation/adapter_registry/schemas/blender_bridge.schema.json-72-91 (1)
72-91:⚠️ Potential issue | 🟠 Major | ⚡ Quick winPrevent empty
install_check/runtime_checkpayloads.At Line 72 and Line 84 these objects can be
{}and still validate, which undermines enforcement of real install/runtime probes.Suggested fix
"install_check": { "type": "object", "additionalProperties": false, + "required": ["executable_must_exist", "required_capabilities"], "properties": { "executable_must_exist": {"type": "boolean", "default": true}, "required_capabilities": { "type": "array", "items": {"type": "string"}, "default": ["headless_blender_cli", "python_scene_worker"] } } }, "runtime_check": { "type": "object", "additionalProperties": false, + "required": ["help_args", "expected_help_substring", "timeout_s"], "properties": { "help_args": {"type": "array", "items": {"type": "string"}, "default": ["--help"]}, "expected_help_substring": {"type": "string", "default": "Blender"}, "timeout_s": {"type": "integer", "minimum": 1, "maximum": 60, "default": 15} } }🤖 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/blender_bridge.schema.json` around lines 72 - 91, The install_check and runtime_check schema objects currently allow empty objects; update their definitions to require at least one property so empty {} payloads are rejected—either add "minProperties": 1 to the "install_check" and "runtime_check" object schemas or declare specific required properties (e.g., require "executable_must_exist" for install_check and "help_args" or "expected_help_substring" for runtime_check) so that the schema enforces meaningful probe data; locate and modify the "install_check" and "runtime_check" entries in the blender_bridge.schema.json accordingly.03_implementation/proof/GEN3D_VERIFY_2026-05-06.json-57-64 (1)
57-64:⚠️ Potential issue | 🟠 Major | 🏗️ Heavy liftRedact machine-specific home paths from committed proof artifacts.
resolvedvalues inweights_present.checked[]andexecutable_presentinclude absolute paths expanded from user-home templates (e.g.,C:\Users\Admin\comfy\models). These paths leak host identifiers into versioned artifacts and create avoidable privacy/compliance risk.The generator's
probe_weights_cache()(line 207) andprobe_executable_presence()(line 229) expand user paths withos.path.expanduser()and serialize the absolute result directly to JSON. Redact or normalize these resolved paths before serialization—either omit them entirely for committed artifacts, store them relative to a standard base (e.g., user home as~), or hash them.🤖 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/proof/GEN3D_VERIFY_2026-05-06.json` around lines 57 - 64, The proof generator is writing absolute, machine-specific paths into weights_present.checked[] and executable_present via probe_weights_cache() and probe_executable_presence(); update those functions so they do not serialize expanded absolute paths: before writing the "resolved" value, normalize or redact it (e.g., replace os.path.expanduser(...) roots with "~", or drop the "resolved" key, or store a deterministic hash of the path) and ensure the resulting JSON only contains non-identifying values; apply the same normalization logic to any other place that sets "resolved" so committed artifacts no longer contain host-specific home paths.03_implementation/adapter_registry/schemas/klipper_service.schema.json-2-3 (1)
2-3:⚠️ Potential issue | 🟠 Major | ⚡ Quick winStandardize schema draft and protocol versions; add missing schemas to test coverage.
Two adapter schemas use draft-07 with http:// instead of the repo-standard draft-2020-12 with https://:
klipper_service.schema.json(line 2)moonraker_api.schema.jsonAdditionally, both schemas are uncovered by the test harness. The assertion in
test_firmware.py:64explicitly requireshttps://json-schema.org/, which these would fail if tested.Update both files to use
https://json-schema.org/draft/2020-12/schema, and include them in the parametrized test coverage to prevent future drift.🤖 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 2 - 3, Update the two adapter schema files klipper_service.schema.json and moonraker_api.schema.json to use the repo-standard "$schema": "https://json-schema.org/draft/2020-12/schema" (replace the draft-07 http:// value) and ensure their "$id" remains correct; then add both schema filenames into the parametrized list used by the test in test_firmware.py (the parametrized test at the assertion around line 64) so the test harness validates them and prevents drift.01_requirements/PRINTER_FLEET_GUIDE.md-34-39 (1)
34-39:⚠️ Potential issue | 🟠 Major | ⚡ Quick winAvoid committing live internal Moonraker IP addresses.
Documenting exact LAN IPs in repo docs unnecessarily exposes internal topology and tends to drift. Prefer stable runtime IDs/hostnames and keep concrete addresses in operator-local config.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@01_requirements/PRINTER_FLEET_GUIDE.md` around lines 34 - 39, The table currently commits internal Moonraker IPs in the "Moonraker IP" column for runtime IDs `flsun_t1_a`, `flsun_t1_b`, `flsun_s1`, and `flsun_v400`; remove these concrete LAN addresses and replace them with stable runtime IDs/hostnames or a redacted placeholder (e.g., "see operator config" or "<operator-local-ip>") and add a short note pointing readers to operator-local configuration for the actual IPs so live internal addresses are not stored in the repo.03_implementation/docs/handoffs/claude-e2e-intelligence-2026-05-08/06_ENV_KEYS_AND_RUNTIME_CONFIG_MAP.md-80-86 (1)
80-86:⚠️ Potential issue | 🟠 Major | ⚡ Quick winRedact host-specific absolute paths from committed docs.
Lines 80–86 expose machine-local paths (including
C:\Users\Admin\...) and internal filesystem layout. Even without secrets, this leaks operator identifiers and environment topology in versioned artifacts.Use sanitized placeholders (for example,
<workspace>/...,<user_home>/...) in committed docs/proof summaries.🤖 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/06_ENV_KEYS_AND_RUNTIME_CONFIG_MAP.md` around lines 80 - 86, The doc currently embeds machine-local absolute paths for keys like HERMES3D_OPENCODE_BIN, OPENCODE_BIN, HERMES3D_OPENCODE_SOURCE, HERMES3D_OPENHANDS_BIN, OPENHANDS_BIN and HERMES3D_OPENHANDS_SOURCE; replace those concrete paths (e.g. G:\Github…, C:\Users\Admin\…) with sanitized placeholders such as <workspace>/opencode/dist/..., <user_home>/.local/bin/openhands.exe or <repo_root>/OpenHands to avoid leaking host identifiers or topology, update the table cell text and any “Resolves to …” examples accordingly, and ensure required_env_keys notes remain accurate while not exposing real filesystem locations.03_implementation/docs/handoffs/claude-e2e-intelligence-2026-05-08/04_SOURCE_OS_60_APP_COMPLETION_MAP.md-216-219 (1)
216-219:⚠️ Potential issue | 🟠 Major | ⚡ Quick winFix
modelersrollup to match the inventory rows.Line 218 classifies
FreeCAD,Manifold, andMeshLabunderruntime_repair_required, but the inventory table (Lines 52–55) marks them assource_ready/metadata_ready_needs_runner. This creates conflicting operational guidance in the same document.🤖 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/04_SOURCE_OS_60_APP_COMPLETION_MAP.md` around lines 216 - 219, The "modelers (13 apps, 9 gaps)" rollup misclassifies FreeCAD, Manifold, and MeshLab as runtime_repair_required; update the rollup line to match the inventory table by moving FreeCAD, Manifold, and MeshLab into the source_ready / metadata_ready_needs_runner category (or `metadata_ready_needs_runner` if that is the inventory state), adjust the counts (apps and gaps) accordingly, and ensure the accompanying guidance still mentions registering dry-run smoke verifiers for the metadata-ready batch and repair verification only for the true repair-state apps.03_implementation/docs/handoffs/claude-e2e-intelligence-2026-05-08/00_EXECUTIVE_MAP.md-13-20 (1)
13-20:⚠️ Potential issue | 🟠 Major | ⚡ Quick winRedact machine-specific/internal filesystem paths from committed docs.
These lines expose internal workstation/worktree topology (
G:/...,C:/Users/Admin/...). Even without credentials, this is avoidable infrastructure leakage in repository artifacts. Prefer sanitized placeholders (for example,<repo_root>,<workspace_path>,<private_env_path>) and keep exact local paths in non-committed operator notes.🤖 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/00_EXECUTIVE_MAP.md` around lines 13 - 20, The markdown contains committed machine-specific absolute paths (e.g., the "MCP locks" line mentioning G:/Github/hermes3d-mcp-lock-orchestrator/src/server.mjs, the "Sandbox" and other bullets referencing G:/Github/h3d-gui-wiring-codex, G:/private, and any C:/Users/... style paths); replace those exact absolute path strings with sanitized placeholders (for example <repo_root>, <workspace_path>, <private_env_path> or <local_image_sha>) across the document and any bullets referencing those paths, and run a quick grep for drive-letter patterns (like "^[A-Za-z]:/" or "^[A-Za-z]:\\") to catch other occurrences before committing so no local filesystem topology remains in the committed docs.03_implementation/docs/handoffs/claude-final-audit-2026-05-06/03_LOCKS_WORKTREES_AND_BRANCHES.md-11-12 (1)
11-12:⚠️ Potential issue | 🟠 Major | ⚡ Quick winReconcile lock totals; current numbers are internally inconsistent.
Line 11 says 84 active locks, but the detailed breakdown shows 28 (Claude) + 42 (codex-master) = 70. Line 88 then derives 56 remaining from 84−28, which implies codex-master should be 56, not 42. Please fix the breakdown/counts so handoff math is trustworthy.
Also applies to: 67-72, 88-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 total lock counts are inconsistent: the header "Total: **84 active locks**", the breakdown "28 (Claude) + 42 (codex-master)" (which sums to 70), and the derived "56 remaining from 84−28" disagree; reconcile them by updating either the total or the per-owner counts so all arithmetic matches (update "Total: **84 active locks**" or change the codex-master count from 42 to 56), and then fix the dependent lines referenced in the breakdown and calculations (the detailed breakdown lines showing 28 and codex-master, and the derived calculation lines currently yielding 56) so every sum and subtraction is numerically consistent across the document.03_implementation/proof/ACTIVE_UI_NO_FAKE_SWEEP.md-33-43 (1)
33-43:⚠️ Potential issue | 🟠 Major | ⚡ Quick winRedact environment and LAN topology details from committed proof text.
The document exposes internal deployment specifics (
G:/private/.env, explicit LAN printer IPs, and runtime endpoint details). Even in docs, this unnecessarily increases reconnaissance surface and should be generalized.Proposed doc redaction pattern
-- `/api/settings` rejects camera/Moonraker URLs whose hosts are not configured printer IPs... +- `/api/settings` rejects camera/Moonraker URLs whose hosts are not configured allowlisted printer hosts... ... -- ...on T1 `#1` (`192.168.0.10`) and T1 `#2` (`192.168.0.11`). S1 (`192.168.0.12`)... +- ...on T1 `#1` (`<lan-printer-1>`) and T1 `#2` (`<lan-printer-2>`). S1 (`<lan-printer-3>`)... ... -- GUI API launchers now load `G:/private/.env`... +- GUI API launchers now load the private runtime env file from a non-repo path...Also applies to: 64-69
🤖 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/proof/ACTIVE_UI_NO_FAKE_SWEEP.md` around lines 33 - 43, The proof document exposes sensitive environment and LAN topology details (e.g., literal path "G:/private/.env", specific runtime endpoints and printer IP/topology, and evidence id "ev_13689248a20f86bf"); redact or generalize those values throughout the text (including occurrences around `/api/system/snapshot`, `/api/desktop/compat`, `/api/system/runtime-readiness`, and the Hermes evidence ledger entry) by replacing concrete paths, IPs, ports and secret-bearing URLs with generic placeholders (e.g., "<private env>", "<lan-printer-ip>", "<runtime-url>") and remove or anonymize any exact SHA/IDs where not required for verification; ensure the same redaction pattern is applied to lines referenced in the comment (and also lines 64-69) so no private file paths, explicit LAN addresses, or secret tokens remain in the committed proof.03_implementation/docs/handoffs/claude-e2e-intelligence-2026-05-08/01_GITHUB_FOLDER_ECOSYSTEM_AUDIT.md-101-106 (1)
101-106:⚠️ Potential issue | 🟠 Major | ⚡ Quick winResolve contradictory archive guidance for
hermes-agent-fresh.This section marks
hermes-agent-freshas an archive candidate, but Line 105 states it is currently ACTIVE runtime input. That conflict is operationally risky if someone executes cleanup from this list.Proposed doc fix
-3. **`hermes-agent-fresh` (agent-infra snapshot)** +3. **`hermes-agent-fresh` (agent-infra snapshot, conditional)** ... - - **Action**: Delete; consult hermes-agent-bridge if history needed. + - **Action**: Do not archive until runtime input is migrated and validated.🤖 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 document currently lists hermes-agent-fresh as an archive candidate while noting it is the ACTIVE runtime input in /api/code-operator/e2e/readiness; resolve this contradiction by updating the Action and Risk lines: change the Action from "Delete" to a conditional workflow (e.g., "Do not delete; first redirect HERMES3D_AGENT_RUNTIME_URL consumers to hermes3d-mcp-lock-orchestrator and verify via /api/code-operator/e2e/readiness"), and update Risk to HIGH until the redirect is validated; mention hermes-agent-bridge only as an archival fallback after the redirect completes and readiness checks pass.03_implementation/ROADMAP.md-29-29 (1)
29-29:⚠️ Potential issue | 🟠 Major | ⚡ Quick winInconsistency: Observe marked DONE but PR claims to fix camera probing.
Line 29 states: "Observe | DONE | Live camera cards for T1
#1, T1#2, S1, and V400; Refresh visibly reconnects 4/4 configured feeds without leaving#observe"However, the PR objectives claim this PR "Replaces the prior static camera state with real connectivity probing" and "fixes initial feed state." If Observe was already DONE, why is this PR fixing camera health probing?
Either:
- This ROADMAP update is premature and should mark Observe as DONE only after this PR merges
- The PR objectives are incorrect about what this PR changes
- This documentation belongs in a different PR
🤖 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/ROADMAP.md` at line 29, The ROADMAP entry shows "Observe | DONE" while the PR description claims it "Replaces the prior static camera state with real connectivity probing" and "fixes initial feed state", so update one of them to be consistent: either move the camera-probing changes out of this PR description or change the ROADMAP row to a non-DONE status (e.g., "In Progress" or remove the camera probing claim) until the PR merges; specifically edit the "Observe | DONE" line in ROADMAP.md or the PR title/body strings "Replaces the prior static camera state with real connectivity probing" and "fixes initial feed state" so both the ROADMAP row labeled Observe and the PR objectives refer to the same state of completion.03_implementation/adapter_registry/schemas/toolchain_arm_none_eabi.schema.json-8-8 (1)
8-8:⚠️ Potential issue | 🟠 Major | ⚡ Quick win
compile_onlyandno_flashmust be added to therequiredarray.Lines 27-28 define
const: trueconstraints for these fields, but line 8 omits them fromrequired. In JSON Schema Draft 2020-12,constconstrains values only when properties are present—it does not enforce presence. This allows instances to omit both fields and still validate, breaking the safety contract stated in the schema description: "NEVER used for flashing."Suggested fix
- "required": ["name", "source_url", "install_check", "version_pattern"], + "required": ["name", "source_url", "install_check", "version_pattern", "compile_only", "no_flash"],🤖 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/toolchain_arm_none_eabi.schema.json` at line 8, The schema's required array is missing the boolean flags compile_only and no_flash so instances can omit them; update the "required" array in toolchain_arm_none_eabi.schema.json to include "compile_only" and "no_flash" alongside "name", "source_url", "install_check", and "version_pattern" so the const: true constraints (for compile_only and no_flash) are enforced as required properties.03_implementation/adapter_registry/schemas/firmware_klipper.schema.json-8-8 (1)
8-8:⚠️ Potential issue | 🟠 Major | ⚡ Quick winSafety metadata must be required in schema validation.
Lines 28-29 define
toolchain_requiredandno_flashwithconstvalues, but line 8 does not include them in therequiredarray. This allows instances to omit these properties and still pass validation, despite the const declaration suggesting they are mandatory metadata for this adapter type.Suggested fix
- "required": ["name", "source_url", "install_check", "version_pattern"], + "required": ["name", "source_url", "install_check", "version_pattern", "toolchain_required", "no_flash"],🤖 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` at line 8, The schema's required array is missing safety metadata keys; update the JSON Schema so that "toolchain_required" and "no_flash" are included in the top-level "required" array (alongside "name", "source_url", "install_check", "version_pattern") to enforce presence of those const-valued properties and prevent instances omitting them; refer to the "required" array and the property definitions "toolchain_required" and "no_flash" in firmware_klipper.schema.json when making the change.03_implementation/adapter_registry/schemas/firmware_klipper.schema.json-17-17 (1)
17-17:⚠️ Potential issue | 🟠 Major | ⚡ Quick winProbe does not verify the declared default branch exists.
The
default_branchfield declares "master" as the branch to use, but theinstall_checkcommand andversion_patternregex do not filter for or validate that branch specifically. Line 20'sgit ls-remote --headsreturns all branches, and line 25's regex patternrefs/heads/.+accepts any branch. This allows the probe to report success even if the "master" branch no longer exists, as long as any other branch is present.To ensure the probe actually validates that "master" exists, add it as an argument to the
git ls-remotecommand on line 20 and update the regex on line 25 to match only that branch:Suggested fix
- "default": "git ls-remote --heads https://github.com/Klipper3d/klipper.git", + "default": "git ls-remote --heads https://github.com/Klipper3d/klipper.git master", @@ - "default": "^[0-9a-f]{40}\\s+refs/heads/.+$", + "default": "^[0-9a-f]{40}\\s+refs/heads/master$",🤖 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` at line 17, The probe currently declares "default_branch" with default "master" but the install_check command (install_check) and version_pattern allow any branch; update the install_check git command to pass the specific default branch as an argument (e.g., add the "${{ default_branch }}"/master ref arg to the git ls-remote --heads invocation) and tighten version_pattern to only match refs/heads/<default_branch> (replace the generic refs/heads/.+ regex with a pattern that interpolates or matches refs/heads/master when default_branch is master) so the probe verifies that the declared default_branch actually exists.
🧹 Nitpick comments (10)
03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/h3dos-wire-tasks/h3dos-wire-action-window-history.md (2)
21-27: ⚡ Quick winTimestamp the status metadata to avoid stale operational context.
OPEN / IN-DEVELOP, branch, and “last commit” fields are time-sensitive. Add an “as of YYYY-MM-DD” marker so readers don’t treat this as current state indefinitely.🤖 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-wire-tasks/h3dos-wire-action-window-history.md` around lines 21 - 27, The status metadata (the “OPEN / IN-DEVELOP” label and the branch/last commit lines: Branch: `wire/action-window-history`, Last commit: `369a0c9`, Wire-feature commit: `404e048`) needs a timestamp to avoid stale context; update the header or immediately below it to append an “as of YYYY-MM-DD” marker (use ISO date) indicating when these fields were accurate so readers know the snapshot time.
10-10: ⚡ Quick winReplace the inferential statement with verifiable wording.
This line mixes fact and inference (
INFERRED), which weakens handoff reliability. Prefer a concrete source reference (commit/diff evidence) or neutral wording like “no endpoint changes observed in commit404e048/4871302.”03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/h3dos-wire-tasks/h3dos-wire-dashboard-events-tail.md (1)
19-20: ⚡ Quick winDocumenting incomplete, in-development features in handoff materials.
This handoff document describes a feature that is "OPEN / IN-DEVELOP" and "not on origin/main," and notes that "the click handler was lost once during a develop merge and had to be restored." Handoff documentation typically covers stable, merged functionality rather than work-in-progress features with known integration fragility.
Consider whether this documentation should be committed now or deferred until the feature is merged to main and stabilized.
🤖 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-wire-tasks/h3dos-wire-dashboard-events-tail.md` around lines 19 - 20, This handoff doc references an in-progress feature (PR `#30`, commit `d9e98ed`) and a fragile click handler that was previously restored in `439699c`; update the document to avoid presenting it as stable by either moving this content to a "DRAFT / WIP" section or removing it until the feature is merged to main, add a clear note about the transient merge fragility and the specific recovered click handler, and include an action item to re-verify and update the doc after PR `#30` is merged to main.03_implementation/adapter_registry/schemas/deepseek_v4.schema.json (1)
39-43: ⚡ Quick winAdd a maximum constraint for
timeout_ms.The
timeout_msfield has a minimum of 100 but no maximum, which could allow extremely large values (e.g., days or weeks) that would cause hangs or poor user experience. Consider adding a reasonable maximum such as300000(5 minutes) or60000(1 minute) depending on the adapter's expected response time.🛡️ Proposed fix to add maximum constraint
"timeout_ms": { "type": "integer", "minimum": 100, + "maximum": 300000, "default": 5000 }🤖 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/deepseek_v4.schema.json` around lines 39 - 43, The JSON schema for the timeout_ms property is missing an upper bound; update the timeout_ms schema entry (the "timeout_ms" object) to include a "maximum" constraint (e.g., "maximum": 60000) so values are capped at a sane limit (1 minute) while keeping the existing "minimum": 100 and "default": 5000 unchanged; ensure the added maximum value is a number and that the default falls within the new min/max range.03_implementation/docs/handoffs/hermes3d-os-folder-index-2026-05-07/core-repos/Hermes3D-handoffs.md (1)
15-26: 💤 Low valueAdd language identifier to fenced code block.
The fenced code block containing git log output should specify a language identifier for proper syntax highlighting and linting compliance.
📝 Suggested fix
-``` +```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 ...🤖 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/core-repos/Hermes3D-handoffs.md` around lines 15 - 26, The fenced code block in Hermes3D-handoffs.md containing the git log is missing a language identifier; update the opening triple-backtick for that block to include a language (e.g., change ``` to ```text) so the git log is properly highlighted and linting passes—look for the fenced block showing the commit lines (the block starting with d7336a5 2026-05-02 ...) and add the identifier to the opening fence.03_implementation/adapter_registry/schemas/moonraker_api.schema.json (1)
2-2: 💤 Low valueConsider aligning JSON Schema draft version with other adapter schemas.
This schema uses
draft-07while other adapter schemas in this PR (triposr.schema.json,hunyuan3d.schema.json,openscad_worker.schema.json) usedraft/2020-12. Using a consistent draft version across all adapter schemas simplifies tooling and validation.♻️ Suggested change
- "$schema": "http://json-schema.org/draft-07/schema#", + "$schema": "https://json-schema.org/draft/2020-12/schema",🤖 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/moonraker_api.schema.json` at line 2, Update the JSON Schema draft used in this adapter by replacing the "$schema" value that currently points to "draft-07" with the same draft used by the other adapter schemas (i.e., the 2020-12 draft URI); locate the "$schema" entry in moonraker_api.schema.json and change it to the 2020-12 schema URI to match triposr.schema.json, hunyuan3d.schema.json and openscad_worker.schema.json so tooling/validation is consistent.03_implementation/docs/security/MCP_BOUNDARY_NOTES.md (1)
31-37: ⚡ Quick winEscape pipe characters within table cell content.
Line 36 contains pipe characters inside a code span (
'high'|'medium'|'low') that confuse markdown parsers, causing a table column-count warning. Consider escaping the pipes or restructuring.📝 Suggested fix
-| 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 |Or use HTML entities:
-| 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 |🤖 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/security/MCP_BOUNDARY_NOTES.md` around lines 31 - 37, The table row for "Injection scanner fail-closed" contains unescaped pipe characters inside the code span InjectionScanner(fail_threshold='high'|'medium'|'low') which breaks Markdown table parsing; update that cell to escape the pipes (e.g., 'high'\|'medium'\|'low') or replace the inline code with an alternative (use HTML entities like | or rephrase to "fail_threshold: high, medium, or low") so the InjectionScanner(...) example and the ScanResult.fail_closed reference render correctly without altering other cells.03_implementation/docs/handoffs/claude-e2e-intelligence-2026-05-08/08_PR_AND_MERGE_QUEUE.md (1)
42-97: ⚡ Quick winAdd language identifier to fenced code block.
The ASCII art diagram should specify a language identifier for better rendering and accessibility. Use
textor leave empty for plain text.📝 Suggested fix
-``` +```text develop🤖 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/08_PR_AND_MERGE_QUEUE.md` around lines 42 - 97, The opened fenced code block containing the ASCII-art PR/merge queue diagram is missing a language identifier; update the opening triple backticks for that block to include a language token (e.g., change ``` to ```text) so the diagram renders as plain text and improves accessibility and syntax highlighting in renderers that rely on a language hint.03_implementation/ROADMAP.md (2)
71-71: 💤 Low valueDuplicate provider blocker documentation.
This line states "MiniMax and DeepSeek chat execution are both blocked by redacted HTTP 401 from their configured private provider values," which duplicates the same blocker documented in
HERMES_AGENT_E2E_TRUTH_PROOF_PLAN_2026-05-08.mdat lines 58-60 and 222-224.Consider centralizing provider status in one authoritative location (likely the handoff plan document) and referencing it from the roadmap, rather than maintaining duplicate status descriptions that can drift.
🤖 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/ROADMAP.md` at line 71, The ROADMAP.md line duplicating the provider-blocker ("MiniMax and DeepSeek chat execution are both blocked by redacted HTTP 401...") should be removed and replaced with a single authoritative reference to the existing status in HERMES_AGENT_E2E_TRUTH_PROOF_PLAN_2026-05-08.md; locate the duplicated sentence in ROADMAP.md and replace it with a short note pointing readers to the handoff plan (HERMES_AGENT_E2E_TRUTH_PROOF_PLAN_2026-05-08.md) for provider status, ensuring the unique blocker details remain only in the HERMES_AGENT_E2E_TRUTH_PROOF_PLAN_2026-05-08.md document (check lines around the previously noted 58-60 and 222-224 areas) so documentation doesn't drift.
32-32: ⚡ Quick winExtremely long line reduces readability.
Line 32 in the completion ledger table is over 2000 characters long, containing dense technical details about Source OS runtime readiness, verifiers, runners, and proof IDs.
For maintainability, consider breaking this into:
- A summary status in the ledger table
- Detailed implementation notes in a dedicated subsection below the table
This would make the ledger scannable while preserving technical detail.
🤖 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/ROADMAP.md` at line 32, The single-line ledger entry beginning "Agents rail/chat | UI_DONE_RUNTIME_PARTIAL ..." is far too long; replace that table cell with a brief summary status (e.g., "UI_DONE_RUNTIME_PARTIAL — core UX features present; provider smokes failing (401)") and move the verbose technical details (the rest of the sentence mentioning OpenCode detection `1.4.3-hermes3d`, OpenHands CLI `1.16.0`, Docker sandbox checks, backend env alias acceptance `MINIMAX_*`/`DEEPSEEK_*`, redacted provenance, provider 401s, and Agent Workbench runtime/route guards) into a new subsection below the table titled something like "Agents rail/chat — Implementation notes" so the ledger stays scannable while keeping full details accessible.
| api_key = "" | ||
| official_wiki_url = "https://wiki.flsun3d.com/en/S1" | ||
| official_config_topics = ["Network Connection Guidelines", "Orca import S1 configuration file", "calibration precautions"] | ||
| safety_policy = "offline_locked_no_test_move_upload_until_user_clears" |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Confirm the new token exists where config is parsed/enforced
rg -n -C3 'offline_locked_no_test_move_upload_until_user_clears|safety_policy' 03_implementation
# Locate policy enums/literals and HTTP 423 lock paths for printer safety
rg -n -C3 'Enum|Literal|blocked_by_backend_http_423|http_423|lock' 03_implementation/src 03_implementation/ui/srcRepository: Ghenghis/Hermes3D
Length of output: 50374
Remove the safety_policy token from printers.toml or refactor S1 lock enforcement.
The new token "offline_locked_no_test_move_upload_until_user_clears" at line 50 will have no effect. Backend enforcement bypasses this config value entirely: local_state.py line 404 hardcodes locked = printer_id == "flsun_s1", forcing the S1 to always be locked regardless of the config policy. Either delete the unused token or refactor the S1 lock logic to respect the config-driven policy instead of the printer_id check.
🤖 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/config/printers.toml` at line 50, The safety_policy entry
in printers.toml is unused because local_state.py hardcodes S1 locking with
locked = printer_id == "flsun_s1"; either remove the token from printers.toml or
update local_state.py to respect the config-driven policy by reading the
printer's safety_policy and using that to set locked (e.g., replace the
hardcoded printer_id check in local_state.py with a check against the printer
config's safety_policy value and implement the same semantics as
"offline_locked_no_test_move_upload_until_user_clears").
3c100ff
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-I9-OBSERVE-CAMERA. Hermes evidence chain: PASS. Fixed: (1) /cameras endpoint now probes real connectivity via _probe_camera_timed() instead of always returning health=configured. (2) initialFeedState in Observe.tsx starts cameras with health=unreachable in error state not loading. (3) ObserveConsole hardcoded EVENTS array replaced with real data from /api/observe/status. Camera probe: 4/4 online, T1#1 24ms, T1#2 35ms, S1 27ms read_only, V400 208ms 4.8fps. Python compile PASS. 39/39 tests pass. Diff: 3 locked files only.
Summary by CodeRabbit
New Features
Documentation
Tests & Gates