Skip to content

Edgeguard implementation - #477

Open
toderian wants to merge 98 commits into
developfrom
feature/egm-037-sealed-benchmark
Open

Edgeguard implementation#477
toderian wants to merge 98 commits into
developfrom
feature/egm-037-sealed-benchmark

Conversation

@toderian

Copy link
Copy Markdown
Contributor

No description provided.

toderian added 30 commits June 10, 2026 10:18
What changed:
- Added the normalized Worker App Runner EXPOSED_PORTS tunnel config for the playground UI.
- Documented the EDGEGUARD_PLAYGROUND_UI_CF_TOKEN runtime secret placeholder.

Why:
- The UI deployment needs a Cloudflare token wired to port 3010 without committing the real token.
What changed:
- Added API_URL/API_PORT semaphore exports to EdgeGuard API and LLM-agent API plugins.
- Updated the EdgeGuard playground Worker App Runner sketch to resolve EDGEGUARD_API_BASE_URL from the edgeguard_api semaphore.
- Added tests for EdgeGuard semaphore exports and the semaphored UI wiring contract.

Why:
- The playground UI must consume the actual edge-node API URL/port exported at runtime instead of hardcoding 127.0.0.1:5055.
What changed:
- Rename the validation endpoint to /check_cypher to avoid plugin lifecycle/config hook collisions.
- Unwrap local LLM inference result envelopes before extracting generated text.
- Add devcontainer post-start and restart helpers that start DinD and clean orphaned FastAPI servers.

Why:
- The playground needs stable EdgeGuard API ports and a generation path that survives container restarts and live LLM response shapes.
What changed:
- Added an edg3-scoped post-start guard that corrects a stale startup cache pointing at the local comms testbed app config.
- The guard only restores the app-config endpoint and does not write MQTT broker values.

Why:
- edg3 should reuse the normal dAuth-backed node comms path instead of trying to resolve the isolated emqx testbed broker.
Bring the local EdgeGuard API branch up to current develop so edg3 can match testnet dAuth version checks while preserving the local EdgeGuard commits.
What changed:
- Pointed the stable edgeguard_qwen_4b serving profile at the private v0.5 preview GGUF.
- Updated EdgeGuard API and agent model metadata with continuation, checksum, and live-repair metrics.
- Added regression coverage for the v0.5 preview model metadata.

Why:
- The playground should exercise the latest published EdgeGuard continuation artifact while keeping the existing deployment engine name stable.
What changed:
- add the v0.5.10 deterministic empty-result broadening helper to the EdgeGuard Cypher guard
- apply the helper in EDGEGUARD_API Neo4j execution when an accepted query returns no rows
- expose runtime harness metadata and cover the behavior with EdgeGuard tests

Why:
- use the validated EGM-019 approach in the EdgeGuard backend without publishing a new model
What changed:
- add the Neo4j Python driver to runtime requirements for server-side EdgeGuard execution
- prevent driver close/connect failures from escaping as unstructured API errors
- cover Neo4j failure handling with an EdgeGuard regression test

Why:
- the empty-result broadening path needs backend query execution and should degrade cleanly when Neo4j is unreachable
…geguard-api

# Conflicts:
#	.devcontainer/watch.py
What changed:
- Expanded the EdgeGuard guard schema context for v0.9 labels, relationships, temporal properties, and high-probability graph patterns.
- Reconciled temporal prompt behavior so whitelisted temporal properties are supported while hallucinated properties remain rejected.
- Normalized common user IOC/CVE literal forms before LLM prompting.
- Added focused guard/API tests for temporal guidance, CVSS/sector patterns, and literal normalization.

Why:
- EGM-028 Phase 2 needs the runtime guard prompt to match the live graph schema before v0.9 dataset tooling and row validation proceed.

Checks:
- python3 -m unittest extensions.business.cybersec.red_mesh.tests.test_edgeguard_cypher_guard extensions.business.cybersec.red_mesh.tests.test_edgeguard_api: passed
- python3 -m py_compile extensions/business/cybersec/red_mesh/edgeguard_cypher_guard.py extensions/business/cybersec/red_mesh/edgeguard_llm_agent_api.py extensions/business/cybersec/red_mesh/edgeguard_api.py: passed
- git diff --cached --check: passed
Point the EdgeGuard API and LLM-agent API at
ratio1/edgeguard-cypher-qwen3-4b-v0.9-graph-intent-gguf (EGM-028), with
updated artifact/adapter SHA256, display name, harness version, and the
44/45 = 97.78% generated-live gate result. Metadata now reflects that
the v0.9 graph-intent weights are the deployed artifact rather than the
v0.5 preview + live-repair harness. Update model-metadata test to match.
Replace Llama.from_pretrained with an explicit list_repo_files +
hf_hub_download flow so MODEL_FILENAME can be a glob pattern. Fail
closed when zero or multiple repo files match, preserve subfolder paths,
pass the HF token through, and raise a clear ImportError when
huggingface-hub is unavailable.
Increase the EdgeGuard API and LLM-agent timeout budgets to 600 seconds so cold local GGUF generation has enough time to return.\n\nFail pending inference requests when the local LLM path emits an invalid empty response, and propagate that failure envelope through the EdgeGuard agent instead of treating it as empty assistant content.\n\nAdd targeted regression coverage for the timeout defaults, local failure propagation, and invalid-empty inference handling.
Move EdgeGuard API, LLM-agent, guard, playground config, and focused tests from red_mesh into extensions/business/cybersec/edgeguard.\n\nKeep signature-derived plugin filenames so EDGEGUARD_API and EDGEGUARD_LLM_AGENT_API remain discoverable by the business plugin loader, and leave the serving profile in the serving registry path.\n\nSplit EdgeGuard semaphore contract checks into the new package and record the module-boundary change in AGENTS.md.
What changed:
- Add /explain_graph to EDGEGUARD_API with explanation-mode Cypher execution, packet construction, and local-only explanation provider calls.
- Add fail-closed GraphEvidencePacket and CaseExplanation validation for evidence IDs, caveats, redaction, severity, and unsafe pivots.
- Cover accepted, rejected, broadened, truncated, limit-adjusted, malformed/provider-error, redaction, nested-schema, and unsafe-pivot paths.

Why:
- Completes EGM-030 Phase 2 runtime API prototype while preserving the EGM-029 Cypher model path.

Checks:
- python3 -m unittest extensions.business.cybersec.edgeguard.tests.test_api: 31 tests OK
- python3 -m unittest extensions.business.cybersec.edgeguard.tests.test_api extensions.business.cybersec.edgeguard.tests.test_cypher_guard extensions.business.cybersec.edgeguard.tests.test_native_api_semaphore_contract extensions.business.cybersec.red_mesh.test_native_api_semaphore_contract extensions.business.edge_inference_api.test_llm_inference_api: 60 tests OK
- python3 -m unittest discover -s extensions/business/cybersec/edgeguard/tests -p 'test_*.py': 48 tests OK
- temp py_compile, AST parse, and git diff --check passed
What changed:
- Remove the old EdgeGuard LLM-agent generation plugin and EDGEGUARD_API /generate path.
- Add safe /models and /prompt_contract metadata for finetuned and base playground model keys.
- Update EdgeGuard runtime docs and focused tests for direct LLM_INFERENCE_API workers.

Why:
- EGM-032 moves text-to-Cypher generation orchestration into the playground server route while EDGEGUARD_API remains the safety and metadata facade.

Checks:
- python3 -B -m unittest extensions.business.cybersec.edgeguard.tests.test_api extensions.business.cybersec.edgeguard.tests.test_cypher_guard extensions.business.cybersec.edgeguard.tests.test_native_api_semaphore_contract extensions.serving.test_cybersec_qwen_engine: passed
- git diff --check: passed
What changed:
- document separate finetuned/base LLM streams and the semaphore-wired UI runner
- verify plain AI engine aliases with distinct model instance IDs

Why:
- preserve the live-proven routing shape and restore the EGM-032 contract test

Checks:
- python3 -B -m unittest focused EdgeGuard and serving suites: 49 passed
What changed:
- add CyberSecQwen model and prompt-profile metadata behind a default-off runtime gate
- preserve the existing two-model catalog and finetuned default until enabled
- test both default and enabled catalog/profile contracts

Why:
- implement EGM-033 Phase 2 without exposing the experimental model before live validation

Checks:
- focused EdgeGuard/serving suite: 51 passed
Document the isolated 5092 worker, runtime-only Hugging Face download contract, and UI runner endpoint. Ratchet the deployment contract with a focused static test.
What changed:
- removed the CyberSecQwen experimental catalog flag and conditional profile branch
- renamed active catalog/runtime documentation to CyberSecQwen 4B
- require the exact three-model and three-profile contracts without overrides

Why:
- EGM-034 makes model visibility independent of quality and worker availability gates

Checks:
- focused EdgeGuard and CyberSecQwen unittest suite: 50 tests passed
- obsolete flag and Experimental metadata search: clear
- git diff --check: passed
toderian added 22 commits July 22, 2026 20:23
What changed:
- Added a frozen graph-first prepare identity envelope.
- Rejected invalid completion accounting before parsing map or synthesis output.
- Made failed traces/transports content-free and logged only bounded provider receipts.

Why:
- Prevent UI/backend version skew and move completion-contract failures to the producer boundary without leaking prompts or evidence.

Checks:
- python3 -m py_compile edgeguard_api.py graph_first_runtime.py: passed
- PYTHONPATH=. python3 -m unittest ...test_graph_first_explanation ...test_api: 106 passed
- git diff --check: passed
What changed:
- add a deterministic three-closure Thorough runtime fixture
- require three map calls, synthesis, and exact coverage accounting

Why:
- live mode caps may fit fewer batches, so the maximum Thorough topology needs deterministic proof

Checks:
- 108 focused graph-first/API tests: pass
Add the five new pure edge-node modules ported from the EGM-047 bake-off
harness (workbooks/egm-047-notation-bakeoff/harness/): explain_notation.py
(numbered_facts + entity_cards renderers with fact/citation -> entity
member maps for CaseExplanation assembly), explain_selection.py
(deterministic Stage A-D relevance selection and token budgeter),
explain_gates.py (five fail-closed semantic gates), explain_profile.py
(analyst prompt profile with the EGM-047 prompt-regime lessons, measured
evidence-budget constants, and the profile manifest + PROFILE_MANIFEST_SHA256
computed at import), and explain_runtime_v2.py (resolve_mode_v2, production
token counter, run_explanation_v2: selection -> render -> one analyst call
+ one validated retry -> gates -> CaseExplanation v1 assembly -> coverage v2
-> trace v2). graph_first_explanation.py/graph_first_runtime.py stay
byte-untouched as the EEL/1 rollback target; only generic pieces
(GraphFirstRuntimeError/GraphFirstContractError, the tokenizer identity
hash, direct_projection_descriptors, sanitized_neo4j_trace) are reused.
Port the EGM-047 offline harness checks (notation determinism, selection
Stage A-D, gates) plus new edge-node-specific coverage: resolve_mode_v2
sampling-drift rejections, retry topology against a scripted provider stub
(fail->pass, fail->fail fail-closed after exactly one retry, deadline-gated
retry), coverage v2 math (cited <= admitted <= returned), the profile
manifest SHA pin, fact->entity mapping correctness for entity_findings, and
sentinel non-leakage across failure traces (no raw_output/parsed/messages,
gate names travel without gate detail). No network, no model calls.
Switch edgeguard_api.py from the EEL/1 + JSON-CB/1 pipeline to EGX/1 at
every touch point: prepare schema bumped to edgeguard.graph_first_prepare.v2,
profile/notation/manifest identity in the prepare contract, prompt_contract,
model, and health endpoints; resolve_mode_v2 replaces resolve_mode in both
graph-explanation endpoints; _run_graph_first now selects/renders from
packet["graph"] (verified byte-for-byte id-space match with evidence_catalog,
so the UI's evidence-ID membership check against neo4j_trace holds) and
calls run_explanation_v2 instead of the map/synthesis pipeline; provider
receipt task-kind classification uses the v2 analyst/retry task vocabulary;
failure transport reports max_tokens=320 and surfaces failed gate NAMES as
validation_codes (never gate detail) recovered from the trace's content-free
per-call gates map.

Update tests/test_api.py: the shared graph-first provider stub now speaks
EGX/1 citations-first JSON; prepare/prompt_contract/model/health identity
assertions updated to EGX/1 + numbered_facts + the pinned manifest SHA;
the three EEL/1 map-output-specific failure tests are repurposed to their
EGX/1 equivalents (extra output keys, fabricated citation, ungrounded
quote), each exercising the one-retry-then-fail-closed contract.
graph_first_explanation.py/graph_first_runtime.py and their existing test
suite remain untouched.
Aligns the EGX/1 trace-v2 gate shape with the client validator and updates
the failure-transport extraction accordingly.
What changed:
- added a dedicated base Qwen3 4B llama.cpp serving profile
- kept CPU, context, and output bounds aligned with the EdgeGuard comparison

Why:
- prevent the base benchmark endpoint from sharing the fine-tuned serving process

Checks:
- python3 -m py_compile extensions/serving/default_inference/nlp/llama_cpp_base_qwen_4b.py
- python3 -m unittest extensions.serving.test_cybersec_qwen_engine
What changed:
- add an EdgeGuard llama.cpp subclass with pinned remote loading and fail-closed SHA-256 verification
- route base and finetuned profiles through it and add a dedicated EdgeGuard CyberSec engine alias
- bind the shared EdgeGuard module into the existing worker identity schema

Why:
- establish the compatibility boundary before generic serving behavior is restored

Checks:
- 73 focused serving/API tests
- python3 -m py_compile for changed serving modules
- git diff --check
What changed:
- restore generic llama_cpp_base.py byte-for-byte to origin/develop
- preserve origin-equivalent generic output logging through an overridable hook
- keep deterministic EdgeGuard generation, failures, telemetry, fingerprints, and content-free logs in its dedicated subclass
- add paired generic/EdgeGuard and API-envelope regressions plus durable boundary guidance

Why:
- prevent EdgeGuard benchmark and privacy requirements from changing unrelated RedMesh llama.cpp consumers

Checks:
- 75 focused serving/API tests
- generic llama_cpp_base.py matches origin/develop
- LLM_INFERENCE_API, queued alignment, and transport constants unchanged from 651906b
- python3 -m py_compile
- git diff --check
What changed:
- removed the EdgeGuard serving base, CyberSec profile, and engine alias
- restored both generic base files to the pinned origin/develop bytes
- made base and finetuned profiles configuration-only generic subclasses
- reconciled tests, operator guidance, and the append-only architecture memory

Why:
- all three EdgeGuard workers must use the existing generic llama.cpp implementation

Checks:
- focused serving/API/operator suite: 71 passed
- generic base comparisons against dc80cab: pass
- all three generic local-path loading cases: pass
@toderian toderian self-assigned this Jul 30, 2026
Keep edg3 startup and restart policy out of the shared Edge Node change set. The RedMesh workspace now supplies these files through read-only devcontainer mounts.
@toderian
toderian force-pushed the feature/egm-037-sealed-benchmark branch from d11a802 to 5394d4a Compare July 30, 2026 15:26
toderian and others added 5 commits July 30, 2026 20:27
…rence_api

The d3114ff drain-loop fix lived in BaseInferenceApiPlugin.process(), a base
class shared by every inference plugin (LLM/SD/CV/text-classifier) and by
non-EdgeGuard LLM consumers. Restore base_inference_api.py to origin/develop
(zero diff) and carry the exact same input<->inference alignment in an
EdgeGuard-owned LLM subclass instead:

- edgeguard_inference_alignment.py: dependency-free align_inputs_to_inferences
  + EdgeGuardAlignmentMixin (overrides handle_inferences, not process()).
- edgeguard_llm_inference_api.py: EDGEGUARD_LLM_INFERENCE_API plugin wiring the
  mixin onto LLMInferenceApiPlugin.
- test_edgeguard_llm_inference_api_alignment.py: 6 tests (backlog attribution,
  multi-model, missing-inference skip, fallback, override delegation).

Only workers pointed at EDGEGUARD_LLM_INFERENCE_API get the fix; the three
EdgeGuard worker stream configs (5090/5091/5092) repoint their SIGNATURE at
deploy time. base_inference_api.py and LLMInferenceApiPlugin are untouched.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Keep only the explicit default-off API guard so benchmark requests fail closed without advertising or forwarding unsupported serving behavior. Remove dormant enablement, attestation, telemetry, seed, and hashing paths while retaining the generic inference compatibility fixes.
What changed:
- remove benchmark parameters and handling from all LLM endpoints
- restore llm_utils exactly to develop and prune cleanup-only tests
- retain and strengthen ordinary inference reliability regressions

Why:
- PR 477 must expose no benchmark API semantics or unrelated cleanup residue

Checks:
- focused 139-test suite passed
- scoped symbol, compile, upstream parity, and whitespace gates passed
What changed:
- rename the clean-base engine and llama.cpp profile to generation-specific Qwen3 identifiers
- add production-loader coverage for the required LlamaCppBaseQwen34B class
- update the operator and native-contract references without changing the public model key

Why:
- keep Qwen3 4B unambiguous before a future Qwen3.5 worker is introduced
- prevent the current base model identity from being repointed across generations

Checks:
- 98 focused serving and EdgeGuard tests passed
- production loader, compilation, stale-name, live health, and serialized worker completion gates passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant