This is an automated email from the ASF dual-hosted git repository.

imbajin pushed a commit to branch goal-test
in repository https://gitbox.apache.org/repos/asf/hugegraph-ai.git

commit d9a6aaaaa2ded01766cb48e2384777d7f2802352
Author: imbajin <[email protected]>
AuthorDate: Sun May 31 02:05:51 2026 +0800

    test(llm): harden hugegraph boundary coverage
    
    - add real HugeGraph boundary tests for schema, write, read, and gremlin 
paths
    - fix primary-key edge endpoint mapping in Commit2Graph
    - record LLM boundary failures and regression evidence
---
 .../quality-program/checkpoints/04-llm-boundary.md |  79 ++++++++
 .workflow/quality-program/quality-state.json       |  41 +++-
 .../reports/production-change-ledger.md            |   1 +
 .../2026-05-31-hugegraph-ai-quality-program.md     |  16 +-
 .../operators/hugegraph_op/commit_to_hugegraph.py  |  16 +-
 hugegraph-llm/src/tests/conftest.py                |   1 +
 .../tests/integration/test_hugegraph_boundary.py   | 225 +++++++++++++++++++++
 .../hugegraph_op/test_commit_to_hugegraph.py       |  23 +++
 .../hugegraph_op/test_fetch_graph_data.py          |   4 +
 .../operators/hugegraph_op/test_schema_manager.py  |   4 +
 10 files changed, 386 insertions(+), 24 deletions(-)

diff --git a/.workflow/quality-program/checkpoints/04-llm-boundary.md 
b/.workflow/quality-program/checkpoints/04-llm-boundary.md
new file mode 100644
index 00000000..6f0ae38b
--- /dev/null
+++ b/.workflow/quality-program/checkpoints/04-llm-boundary.md
@@ -0,0 +1,79 @@
+# G3 LLM HugeGraph Boundary Checkpoint
+
+## Status
+
+Complete.
+
+## Completed Scope
+
+- Added a real HugeGraph boundary test module for `hugegraph-llm`.
+- Covered production `SchemaManager` against live schema readback.
+- Covered production `Commit2Graph` write path against live HugeGraph Server 
`1.7.0`, including vertex count, edge count, edge source, and edge target.
+- Covered production `FetchGraphData` against live graph data and stable 
summary shape.
+- Covered production `GremlinExecuteNode` invalid-query error surface without 
requiring LLM, embedding, reranker, vector DB, or UI credentials.
+- Marked existing `hugegraph_op` unittest files as Layer A `unit` so strict 
marker selection does not silently deselect the suite.
+- Made the `hugegraph-llm` test harness root-command friendly by switching 
test cwd to the module root before production config import.
+
+## Red Tests Observed
+
+```text
+TestCommit2Graph.test_load_into_graph_raises_explicit_error_when_vertex_creation_fails
+  failed with AttributeError: 'NoneType' object has no attribute 'id'
+
+test_commit_to_graph_writes_vertices_and_edges
+  failed with Server Exception: Invalid vertex id 'quality_person:marko'
+```
+
+## Production Fix
+
+| File | Change | Proving test |
+|---|---|---|
+| 
`hugegraph-llm/src/hugegraph_llm/operators/hugegraph_op/commit_to_hugegraph.py` 
| Map primary-key `label:value` edge endpoints to server-created VIDs and raise 
an explicit `ValueError` when vertex creation returns `None`. | `uv run pytest 
hugegraph-llm/src/tests/operators/hugegraph_op/test_commit_to_hugegraph.py::TestCommit2Graph::test_load_into_graph_raises_explicit_error_when_vertex_creation_fails
 -q`; `HUGEGRAPH_REQUIRED=true uv run pytest 
hugegraph-llm/src/tests/integration/test_hu [...]
+
+## Commands Run
+
+```bash
+uv run pytest 
hugegraph-llm/src/tests/operators/hugegraph_op/test_commit_to_hugegraph.py::TestCommit2Graph::test_load_into_graph_raises_explicit_error_when_vertex_creation_fails
 -q
+HUGEGRAPH_REQUIRED=true uv run pytest 
hugegraph-llm/src/tests/integration/test_hugegraph_boundary.py -v --tb=short 
--maxfail=1
+uv run pytest 
hugegraph-llm/src/tests/operators/hugegraph_op/test_commit_to_hugegraph.py::TestCommit2Graph::test_load_into_graph_raises_explicit_error_when_vertex_creation_fails
 
hugegraph-llm/src/tests/operators/hugegraph_op/test_commit_to_hugegraph.py::TestCommit2Graph::test_load_into_graph_maps_llm_vertex_ids_to_created_vertex_ids
 -q
+HUGEGRAPH_REQUIRED=true uv run pytest 
hugegraph-llm/src/tests/integration/test_hugegraph_boundary.py -v --tb=short
+uv run pytest hugegraph-llm/src/tests/operators/hugegraph_op -m "unit or 
contract" -q
+uv run ruff format --check hugegraph-llm/src/tests/conftest.py 
hugegraph-llm/src/tests/integration/test_hugegraph_boundary.py 
hugegraph-llm/src/tests/operators/hugegraph_op/test_schema_manager.py 
hugegraph-llm/src/tests/operators/hugegraph_op/test_commit_to_hugegraph.py 
hugegraph-llm/src/tests/operators/hugegraph_op/test_fetch_graph_data.py 
hugegraph-llm/src/hugegraph_llm/operators/hugegraph_op/commit_to_hugegraph.py
+uv run ruff check hugegraph-llm/src/tests/conftest.py 
hugegraph-llm/src/tests/integration/test_hugegraph_boundary.py 
hugegraph-llm/src/tests/operators/hugegraph_op/test_schema_manager.py 
hugegraph-llm/src/tests/operators/hugegraph_op/test_commit_to_hugegraph.py 
hugegraph-llm/src/tests/operators/hugegraph_op/test_fetch_graph_data.py 
hugegraph-llm/src/hugegraph_llm/operators/hugegraph_op/commit_to_hugegraph.py
+uv run pytest hugegraph-llm/src/tests --collect-only -q
+git diff --check
+```
+
+## Verification Result
+
+| Layer | Command | Result |
+|---|---|---|
+| LLM HugeGraph operator unit/contract | `uv run pytest 
hugegraph-llm/src/tests/operators/hugegraph_op -m "unit or contract" -q` | `43 
passed` |
+| LLM HugeGraph boundary integration | `HUGEGRAPH_REQUIRED=true uv run pytest 
hugegraph-llm/src/tests/integration/test_hugegraph_boundary.py -v --tb=short` | 
`4 passed` |
+| LLM collection from repo root | `uv run pytest hugegraph-llm/src/tests 
--collect-only -q` | `281 tests collected` |
+| Formatting | `uv run ruff format --check ...` | `6 files already formatted` |
+| Lint | `uv run ruff check ...` | `All checks passed` |
+| Whitespace | `git diff --check` | passed |
+
+## Failure Classification
+
+- `Commit2Graph` primary-key endpoint mapping was an LLM conversion boundary 
gap.
+- `Commit2Graph` `NoneType.id` was a failure-surface contract gap.
+- No HugeGraph service setup, server contract, real LLM, embedding, reranker, 
vector DB, or UI credential dependency blocked G3.
+
+## Files Touched
+
+- `.workflow/quality-program/checkpoints/04-llm-boundary.md`
+- `.workflow/quality-program/quality-state.json`
+- `.workflow/quality-program/reports/production-change-ledger.md`
+- `docs/superpowers/plans/2026-05-31-hugegraph-ai-quality-program.md`
+- 
`hugegraph-llm/src/hugegraph_llm/operators/hugegraph_op/commit_to_hugegraph.py`
+- `hugegraph-llm/src/tests/conftest.py`
+- `hugegraph-llm/src/tests/integration/test_hugegraph_boundary.py`
+- `hugegraph-llm/src/tests/operators/hugegraph_op/test_commit_to_hugegraph.py`
+- `hugegraph-llm/src/tests/operators/hugegraph_op/test_fetch_graph_data.py`
+- `hugegraph-llm/src/tests/operators/hugegraph_op/test_schema_manager.py`
+
+## Next Goal Readiness
+
+G4 can begin. The current test harness supports root-level LLM collection, and 
no G3 boundary blocker remains.
diff --git a/.workflow/quality-program/quality-state.json 
b/.workflow/quality-program/quality-state.json
index 5b85a147..fd83550b 100644
--- a/.workflow/quality-program/quality-state.json
+++ b/.workflow/quality-program/quality-state.json
@@ -1,5 +1,5 @@
 {
-  "current_goal": "G3",
+  "current_goal": "G4",
   "repo_sha_start": "d048bc9fa07042833549dd1def5ff3222c47be70",
   "base_branch": "main",
   "open_pr_snapshot_time": "2026-05-30T17:18:30Z",
@@ -7,7 +7,8 @@
     "P0",
     "G0",
     "G1",
-    "G2"
+    "G2",
+    "G3"
   ],
   "files_touched": [
     ".workflow/quality-program/README.md",
@@ -60,10 +61,16 @@
     "docs/quality/hugegraph-integration.md",
     ".workflow/quality-program/checkpoints/02-service-fixture.md",
     ".workflow/quality-program/checkpoints/03-client-contract.md",
+    ".workflow/quality-program/checkpoints/04-llm-boundary.md",
     ".workflow/quality-program/coverage/client-g2.json",
     ".workflow/quality-program/reports/production-change-ledger.md",
     "docs/superpowers/plans/2026-05-31-hugegraph-ai-quality-program.md",
-    "hugegraph-python-client/src/pyhugegraph/utils/util.py"
+    "hugegraph-python-client/src/pyhugegraph/utils/util.py",
+    
"hugegraph-llm/src/hugegraph_llm/operators/hugegraph_op/commit_to_hugegraph.py",
+    "hugegraph-llm/src/tests/integration/test_hugegraph_boundary.py",
+    
"hugegraph-llm/src/tests/operators/hugegraph_op/test_commit_to_hugegraph.py",
+    "hugegraph-llm/src/tests/operators/hugegraph_op/test_fetch_graph_data.py",
+    "hugegraph-llm/src/tests/operators/hugegraph_op/test_schema_manager.py"
   ],
   "production_changes": [
     {
@@ -71,6 +78,12 @@
       "file": "hugegraph-python-client/src/pyhugegraph/utils/util.py",
       "change": "Preserve backend error envelope details for non-404 HTTP 
errors and prefer server message fields.",
       "test": "uv run pytest 
hugegraph-python-client/src/tests/api/test_response_validation.py -q"
+    },
+    {
+      "goal": "G3",
+      "file": 
"hugegraph-llm/src/hugegraph_llm/operators/hugegraph_op/commit_to_hugegraph.py",
+      "change": "Map primary-key label:value edge endpoints to server-created 
VIDs and raise explicit vertex creation errors before accessing id.",
+      "test": "uv run pytest 
hugegraph-llm/src/tests/operators/hugegraph_op/test_commit_to_hugegraph.py::TestCommit2Graph::test_load_into_graph_raises_explicit_error_when_vertex_creation_fails
 -q; HUGEGRAPH_REQUIRED=true uv run pytest 
hugegraph-llm/src/tests/integration/test_hugegraph_boundary.py -v --tb=short"
     }
   ],
   "tests_added_or_changed": [
@@ -78,7 +91,9 @@
     "Added HugeGraph service fixtures and conftest wiring for client and LLM 
test suites.",
     "Added response validation contract tests for backend and malformed error 
envelopes.",
     "Updated client integration harness so hugegraph-marked legacy tests use 
the service fixture gate before unittest setUpClass.",
-    "Added real HugeGraph schema CRUD, graph ID, and Gremlin error-surface 
contract tests for G2."
+    "Added real HugeGraph schema CRUD, graph ID, and Gremlin error-surface 
contract tests for G2.",
+    "Added LLM HugeGraph boundary integration tests for SchemaManager, 
Commit2Graph, FetchGraphData, and GremlinExecuteNode.",
+    "Marked existing hugegraph_op unittest files as unit so strict marker 
selection exercises them."
   ],
   "commands_run": [
     "sed -n '1,220p' AGENTS.md",
@@ -131,13 +146,17 @@
     "HUGEGRAPH_REQUIRED=true uv run pytest hugegraph-python-client/src/tests 
-m 'integration and hugegraph' -v --tb=short",
     "uv run ruff format --check hugegraph-python-client/src/tests/conftest.py 
hugegraph-python-client/src/tests/api/test_schema.py 
hugegraph-python-client/src/tests/api/test_graph.py 
hugegraph-python-client/src/tests/api/test_gremlin.py",
     "uv run ruff check hugegraph-python-client/src/tests/conftest.py 
hugegraph-python-client/src/tests/api/test_schema.py 
hugegraph-python-client/src/tests/api/test_graph.py 
hugegraph-python-client/src/tests/api/test_gremlin.py",
-    "uv run pytest hugegraph-python-client/src/tests -m 'unit or contract' 
--cov=pyhugegraph --cov-report=term 
--cov-report=json:.workflow/quality-program/coverage/client-g2.json"
-  ],
-  "known_failures": [
-    "Root-level LLM collection command fails before collection because 
existing prompt config requires cwd hugegraph-llm.",
-    "Initial coverage command failed before uv sync because pytest-cov was 
missing from the active environment.",
-    "LLM integration and hugegraph collection is empty before G3 adds 
real-boundary tests; pytest returns exit code 5."
+    "uv run pytest hugegraph-python-client/src/tests -m 'unit or contract' 
--cov=pyhugegraph --cov-report=term 
--cov-report=json:.workflow/quality-program/coverage/client-g2.json",
+    "uv run pytest 
hugegraph-llm/src/tests/operators/hugegraph_op/test_commit_to_hugegraph.py::TestCommit2Graph::test_load_into_graph_raises_explicit_error_when_vertex_creation_fails
 -q",
+    "HUGEGRAPH_REQUIRED=true uv run pytest 
hugegraph-llm/src/tests/integration/test_hugegraph_boundary.py -v --tb=short 
--maxfail=1",
+    "uv run pytest 
hugegraph-llm/src/tests/operators/hugegraph_op/test_commit_to_hugegraph.py::TestCommit2Graph::test_load_into_graph_raises_explicit_error_when_vertex_creation_fails
 
hugegraph-llm/src/tests/operators/hugegraph_op/test_commit_to_hugegraph.py::TestCommit2Graph::test_load_into_graph_maps_llm_vertex_ids_to_created_vertex_ids
 -q",
+    "HUGEGRAPH_REQUIRED=true uv run pytest 
hugegraph-llm/src/tests/integration/test_hugegraph_boundary.py -v --tb=short",
+    "uv run pytest hugegraph-llm/src/tests/operators/hugegraph_op -m 'unit or 
contract' -q",
+    "uv run ruff format --check hugegraph-llm/src/tests/conftest.py 
hugegraph-llm/src/tests/integration/test_hugegraph_boundary.py 
hugegraph-llm/src/tests/operators/hugegraph_op/test_schema_manager.py 
hugegraph-llm/src/tests/operators/hugegraph_op/test_commit_to_hugegraph.py 
hugegraph-llm/src/tests/operators/hugegraph_op/test_fetch_graph_data.py 
hugegraph-llm/src/hugegraph_llm/operators/hugegraph_op/commit_to_hugegraph.py",
+    "uv run ruff check hugegraph-llm/src/tests/conftest.py 
hugegraph-llm/src/tests/integration/test_hugegraph_boundary.py 
hugegraph-llm/src/tests/operators/hugegraph_op/test_schema_manager.py 
hugegraph-llm/src/tests/operators/hugegraph_op/test_commit_to_hugegraph.py 
hugegraph-llm/src/tests/operators/hugegraph_op/test_fetch_graph_data.py 
hugegraph-llm/src/hugegraph_llm/operators/hugegraph_op/commit_to_hugegraph.py",
+    "uv run pytest hugegraph-llm/src/tests --collect-only -q"
   ],
+  "known_failures": [],
   "deferred_items": [
     "Avoid #350/#277 YAML config migration files unless tests require a narrow 
compatibility assertion.",
     "Avoid #179 async/streaming API refactor surface.",
@@ -145,5 +164,5 @@
     "Avoid #240 vector/property embedding abstraction surface.",
     "Quarantine client/test fixes overlapping #323/#329/#342 until exact 
changed files are inspected."
   ],
-  "next_recommended_action": "Start G3 hugegraph-llm HugeGraph boundary 
hardening with the local HugeGraph 1.7.0 service"
+  "next_recommended_action": "Start G4 deterministic parser, API, and operator 
coverage"
 }
diff --git a/.workflow/quality-program/reports/production-change-ledger.md 
b/.workflow/quality-program/reports/production-change-ledger.md
index b5f2eb99..1fbe4888 100644
--- a/.workflow/quality-program/reports/production-change-ledger.md
+++ b/.workflow/quality-program/reports/production-change-ledger.md
@@ -3,3 +3,4 @@
 | Goal | File | Change | Test proving it | Reason | Risk |
 |---|---|---|---|---|---|
 | G2 | `hugegraph-python-client/src/pyhugegraph/utils/util.py` | Preserve 
backend error envelope details for non-404 HTTP errors and prefer server 
`message` over `exception`. | `uv run pytest 
hugegraph-python-client/src/tests/api/test_response_validation.py -q` | 
Response validation contract gap for 500 backend envelopes. | Low; narrows 
error wrapping to preserve parsed server details while keeping 404 mapping. |
+| G3 | 
`hugegraph-llm/src/hugegraph_llm/operators/hugegraph_op/commit_to_hugegraph.py` 
| Map primary-key `label:value` edge endpoints to server-created VIDs and raise 
explicit vertex creation errors before accessing `.id`. | `uv run pytest 
hugegraph-llm/src/tests/operators/hugegraph_op/test_commit_to_hugegraph.py::TestCommit2Graph::test_load_into_graph_raises_explicit_error_when_vertex_creation_fails
 -q`; `HUGEGRAPH_REQUIRED=true uv run pytest 
hugegraph-llm/src/tests/integration/test_hug [...]
diff --git a/docs/superpowers/plans/2026-05-31-hugegraph-ai-quality-program.md 
b/docs/superpowers/plans/2026-05-31-hugegraph-ai-quality-program.md
index f27af976..0e9ecce8 100644
--- a/docs/superpowers/plans/2026-05-31-hugegraph-ai-quality-program.md
+++ b/docs/superpowers/plans/2026-05-31-hugegraph-ai-quality-program.md
@@ -850,7 +850,7 @@ git commit -m "test(client): harden hugegraph contract 
coverage" -m "- add real
 - Update: `.workflow/quality-program/reports/production-change-ledger.md`
 - Create/Update: `.workflow/quality-program/checkpoints/04-llm-boundary.md`
 
-- [ ] **Step G3.1: Add real-boundary fixture data**
+- [x] **Step G3.1: Add real-boundary fixture data**
 
 Create helper functions inside 
`hugegraph-llm/src/tests/integration/test_hugegraph_boundary.py`:
 
@@ -893,7 +893,7 @@ QUALITY_GRAPH = {
 
 Use this fixture as a source for `Commit2Graph.run({"schema": schema, 
"vertices": vertices, "edges": edges})`. Convert the compact fixture into the 
schema format already consumed by `Commit2Graph`: `propertykeys`, 
`vertexlabels`, and `edgelabels`.
 
-- [ ] **Step G3.2: Add schema manager real-service test**
+- [x] **Step G3.2: Add schema manager real-service test**
 
 Add a test that imports production `SchemaManager` and asserts real schema 
readback:
 
@@ -914,7 +914,7 @@ def 
test_schema_manager_reads_real_schema(hugegraph_service):
     assert isinstance(context["schema"]["vertexlabels"], list)
 ```
 
-- [ ] **Step G3.3: Add Commit2Graph write/read integration test**
+- [x] **Step G3.3: Add Commit2Graph write/read integration test**
 
 Add a failing integration test that writes fixture data through production 
`Commit2Graph`, then reads it using pyhugegraph or production fetch code.
 
@@ -973,7 +973,7 @@ The test must assert:
 - creation failures raise explicit errors, not secondary NoneType.id errors
 ```
 
-- [ ] **Step G3.4: Add FetchGraphData integration test**
+- [x] **Step G3.4: Add FetchGraphData integration test**
 
 Add a test that imports `FetchGraphData`, reads known graph data, and asserts 
stable shape:
 
@@ -995,7 +995,7 @@ def 
test_fetch_graph_data_returns_counts_and_samples(hugegraph_service):
     assert isinstance(result["edges"], list)
 ```
 
-- [ ] **Step G3.5: Add Gremlin failure-surface test**
+- [x] **Step G3.5: Add Gremlin failure-surface test**
 
 Add a test for the production Gremlin execution boundary:
 
@@ -1012,7 +1012,7 @@ def 
test_gremlin_execute_surfaces_invalid_query(hugegraph_service):
 
 This documents the current node contract: the node surfaces execution errors 
as result strings instead of raising. If the task changes that production 
contract, add a regression test and ledger row.
 
-- [ ] **Step G3.6: Run LLM boundary suites**
+- [x] **Step G3.6: Run LLM boundary suites**
 
 Run:
 
@@ -1023,7 +1023,7 @@ HUGEGRAPH_REQUIRED=true uv run pytest 
hugegraph-llm/src/tests/integration/test_h
 
 Expected: boundary failures classify as service setup, pyhugegraph contract, 
server contract, or LLM conversion.
 
-- [ ] **Step G3.7: Apply minimal LLM boundary fixes**
+- [x] **Step G3.7: Apply minimal LLM boundary fixes**
 
 Allowed fixes include:
 
@@ -1036,7 +1036,7 @@ Allowed fixes include:
 
 For each production edit, add a production ledger row.
 
-- [ ] **Step G3.8: Write checkpoint and commit**
+- [x] **Step G3.8: Write checkpoint and commit**
 
 Run:
 
diff --git 
a/hugegraph-llm/src/hugegraph_llm/operators/hugegraph_op/commit_to_hugegraph.py 
b/hugegraph-llm/src/hugegraph_llm/operators/hugegraph_op/commit_to_hugegraph.py
index daade304..caa33b9a 100644
--- 
a/hugegraph-llm/src/hugegraph_llm/operators/hugegraph_op/commit_to_hugegraph.py
+++ 
b/hugegraph-llm/src/hugegraph_llm/operators/hugegraph_op/commit_to_hugegraph.py
@@ -147,20 +147,26 @@ class Commit2Graph:
                 continue
 
             # TODO: we could try batch add vertices first, setback to 
single-mode if failed
-            original_id = vertex.get("id")
-            if vertex_label.get("id_strategy") == "CUSTOMIZE_STRING" and 
original_id:
+            explicit_id = vertex.get("id")
+            mapping_id = explicit_id
+            if not mapping_id and len(primary_keys) == 1:
+                mapping_id = 
f"{input_label}:{input_properties[primary_keys[0]]}"
+
+            if vertex_label.get("id_strategy") == "CUSTOMIZE_STRING" and 
explicit_id:
                 result = self._handle_graph_creation(
                     self.client.graph().addVertex,
                     input_label,
                     input_properties,
-                    id=original_id,
+                    id=explicit_id,
                 )
             else:
                 result = 
self._handle_graph_creation(self.client.graph().addVertex, input_label, 
input_properties)
+            if result is None:
+                raise ValueError(f"Failed to create vertex '{input_label}' 
with properties {input_properties}")
             vid = result.id
             vertex["id"] = vid
-            if original_id:
-                vid_mapping[original_id] = vid
+            if mapping_id:
+                vid_mapping[mapping_id] = vid
 
         for edge in edges:
             start = vid_mapping.get(edge.get("outV"), edge.get("outV"))
diff --git a/hugegraph-llm/src/tests/conftest.py 
b/hugegraph-llm/src/tests/conftest.py
index 42033626..ec14a6e3 100644
--- a/hugegraph-llm/src/tests/conftest.py
+++ b/hugegraph-llm/src/tests/conftest.py
@@ -23,6 +23,7 @@ import nltk
 
 # Get project root directory
 project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), 
"../.."))
+os.chdir(project_root)
 # Add to Python path
 sys.path.insert(0, project_root)
 # Add src directory to Python path
diff --git a/hugegraph-llm/src/tests/integration/test_hugegraph_boundary.py 
b/hugegraph-llm/src/tests/integration/test_hugegraph_boundary.py
new file mode 100644
index 00000000..6184a023
--- /dev/null
+++ b/hugegraph-llm/src/tests/integration/test_hugegraph_boundary.py
@@ -0,0 +1,225 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from copy import deepcopy
+
+import pytest
+from pyhugegraph.client import PyHugeClient
+
+pytestmark = [pytest.mark.integration, pytest.mark.hugegraph]
+
+QUALITY_SCHEMA = {
+    "vertices": [
+        {"vertex_label": "quality_person", "properties": ["name", "age"], 
"primary_keys": ["name"]},
+        {"vertex_label": "quality_software", "properties": ["name", "lang"], 
"primary_keys": ["name"]},
+    ],
+    "edges": [
+        {
+            "edge_label": "quality_created",
+            "source_vertex_label": "quality_person",
+            "target_vertex_label": "quality_software",
+            "properties": ["date"],
+        }
+    ],
+}
+
+QUALITY_GRAPH = {
+    "vertices": [
+        {"label": "quality_person", "properties": {"name": "marko", "age": 
29}},
+        {"label": "quality_software", "properties": {"name": "lop", "lang": 
"java"}},
+    ],
+    "edges": [
+        {
+            "label": "quality_created",
+            "source": "marko",
+            "target": "lop",
+            "properties": {"date": "2026-05-31"},
+        }
+    ],
+}
+
+QUALITY_COMMIT_SCHEMA = {
+    "propertykeys": [
+        {"name": "name", "data_type": "TEXT", "cardinality": "SINGLE"},
+        {"name": "age", "data_type": "INT", "cardinality": "SINGLE"},
+        {"name": "lang", "data_type": "TEXT", "cardinality": "SINGLE"},
+        {"name": "date", "data_type": "TEXT", "cardinality": "SINGLE"},
+    ],
+    "vertexlabels": [
+        {
+            "name": "quality_person",
+            "properties": ["name", "age"],
+            "primary_keys": ["name"],
+            "nullable_keys": [],
+        },
+        {
+            "name": "quality_software",
+            "properties": ["name", "lang"],
+            "primary_keys": ["name"],
+            "nullable_keys": [],
+        },
+    ],
+    "edgelabels": [
+        {
+            "name": "quality_created",
+            "source_label": "quality_person",
+            "target_label": "quality_software",
+            "properties": ["date"],
+        }
+    ],
+}
+
+QUALITY_COMMIT_DATA = {
+    "schema": QUALITY_COMMIT_SCHEMA,
+    "vertices": [
+        {"label": "quality_person", "properties": {"name": "marko", "age": 
29}},
+        {"label": "quality_software", "properties": {"name": "lop", "lang": 
"java"}},
+    ],
+    "edges": [
+        {
+            "label": "quality_created",
+            "outV": "quality_person:marko",
+            "inV": "quality_software:lop",
+            "properties": {"date": "2026-05-31"},
+        }
+    ],
+}
+
+
+def _make_client(service):
+    return PyHugeClient(
+        url=service.url,
+        graph=service.graph,
+        user=service.user,
+        pwd=service.password,
+        graphspace=service.graphspace,
+    )
+
+
[email protected]()
+def configured_hugegraph(hugegraph_service):
+    from hugegraph_llm.config import huge_settings
+
+    original = {
+        "graph_url": huge_settings.graph_url,
+        "graph_name": huge_settings.graph_name,
+        "graph_user": huge_settings.graph_user,
+        "graph_pwd": huge_settings.graph_pwd,
+        "graph_space": huge_settings.graph_space,
+    }
+    huge_settings.graph_url = hugegraph_service.url
+    huge_settings.graph_name = hugegraph_service.graph
+    huge_settings.graph_user = hugegraph_service.user
+    huge_settings.graph_pwd = hugegraph_service.password
+    huge_settings.graph_space = hugegraph_service.graphspace
+
+    client = _make_client(hugegraph_service)
+    client.graphs().clear_graph_all_data()
+    yield hugegraph_service
+    client.graphs().clear_graph_all_data()
+    for key, value in original.items():
+        setattr(huge_settings, key, value)
+
+
+def _create_quality_schema(client):
+    schema = client.schema()
+    schema.propertyKey("name").asText().ifNotExist().create()
+    schema.propertyKey("age").asInt().ifNotExist().create()
+    schema.propertyKey("lang").asText().ifNotExist().create()
+    schema.propertyKey("date").asText().ifNotExist().create()
+    schema.vertexLabel("quality_person").properties("name", 
"age").primaryKeys("name").ifNotExist().create()
+    schema.vertexLabel("quality_software").properties("name", 
"lang").primaryKeys("name").ifNotExist().create()
+    
schema.edgeLabel("quality_created").sourceLabel("quality_person").targetLabel("quality_software").properties(
+        "date"
+    ).ifNotExist().create()
+
+
+def _commit_quality_graph():
+    from hugegraph_llm.operators.hugegraph_op.commit_to_hugegraph import 
Commit2Graph
+
+    commit = Commit2Graph()
+    data = deepcopy(QUALITY_COMMIT_DATA)
+    return commit.run(data)
+
+
+def test_schema_manager_reads_real_schema(configured_hugegraph):
+    from hugegraph_llm.operators.hugegraph_op.schema_manager import 
SchemaManager
+
+    client = _make_client(configured_hugegraph)
+    _create_quality_schema(client)
+
+    manager = SchemaManager(graph_name=configured_hugegraph.graph)
+    context = manager.run({})
+
+    assert "schema" in context
+    assert "simple_schema" in context
+    assert isinstance(context["schema"]["vertexlabels"], list)
+    assert any(label["name"] == "quality_person" for label in 
context["schema"]["vertexlabels"])
+
+
+def test_commit_to_graph_writes_vertices_and_edges(configured_hugegraph):
+    _commit_quality_graph()
+
+    client = _make_client(configured_hugegraph)
+    counts = client.gremlin().exec(
+        """
+        g.V().hasLabel('quality_person', 'quality_software').count()
+        """
+    )["data"][0]
+    edges = client.gremlin().exec(
+        """
+        g.E().hasLabel('quality_created').
+          project('out', 'in', 'date').
+          by(outV().values('name')).
+          by(inV().values('name')).
+          by(values('date'))
+        """
+    )["data"]
+
+    assert counts == 2
+    assert len(edges) == 1
+    assert edges[0]["out"] == "marko"
+    assert edges[0]["in"] == "lop"
+    assert edges[0]["date"] == "2026-05-31"
+
+
+def test_fetch_graph_data_returns_counts_and_samples(configured_hugegraph):
+    from hugegraph_llm.operators.hugegraph_op.fetch_graph_data import 
FetchGraphData
+
+    _commit_quality_graph()
+    result = FetchGraphData(_make_client(configured_hugegraph)).run({})
+
+    assert {"vertex_num", "edge_num", "vertices", "edges", 
"note"}.issubset(result)
+    assert result["vertex_num"] == 2
+    assert result["edge_num"] == 1
+    assert isinstance(result["vertices"], list)
+    assert isinstance(result["edges"], list)
+
+
+def test_gremlin_execute_surfaces_invalid_query(configured_hugegraph):
+    from hugegraph_llm.nodes.hugegraph_node.gremlin_execute import 
GremlinExecuteNode
+
+    node = GremlinExecuteNode()
+    node.wk_input = type("Input", (), {"requested_outputs": 
["raw_execution_result"]})()
+    result = node.operator_schedule({"raw_result": "g.V2()"})
+
+    assert result["template_exec_res"] == ""
+    assert (
+        "g.V2" in result["raw_exec_res"]
+        or "No signature" in result["raw_exec_res"]
+        or "NotFound" in result["raw_exec_res"]
+    )
diff --git 
a/hugegraph-llm/src/tests/operators/hugegraph_op/test_commit_to_hugegraph.py 
b/hugegraph-llm/src/tests/operators/hugegraph_op/test_commit_to_hugegraph.py
index b13f9042..d89936d8 100644
--- a/hugegraph-llm/src/tests/operators/hugegraph_op/test_commit_to_hugegraph.py
+++ b/hugegraph-llm/src/tests/operators/hugegraph_op/test_commit_to_hugegraph.py
@@ -19,11 +19,14 @@
 import unittest
 from unittest.mock import MagicMock, patch
 
+import pytest
 from pyhugegraph.utils.exceptions import CreateError, NotFoundError
 
 from hugegraph_llm.operators.hugegraph_op.commit_to_hugegraph import 
Commit2Graph
 from hugegraph_llm.operators.llm_op.property_graph_extract import 
PropertyGraphExtract
 
+pytestmark = [pytest.mark.unit]
+
 
 class TestCommit2Graph(unittest.TestCase):
     def setUp(self):
@@ -521,6 +524,26 @@ class TestCommit2Graph(unittest.TestCase):
             {"role": "Forrest Gump"},
         )
 
+    
@patch("hugegraph_llm.operators.hugegraph_op.commit_to_hugegraph.Commit2Graph._handle_graph_creation")
+    def 
test_load_into_graph_raises_explicit_error_when_vertex_creation_fails(self, 
mock_handle_graph_creation):
+        """Test failed vertex creation is reported before edge creation."""
+        mock_handle_graph_creation.return_value = None
+
+        vertices = [{"label": "person", "properties": {"name": "Tom Hanks", 
"age": 67}}]
+        edges = [
+            {
+                "label": "acted_in",
+                "properties": {"role": "Forrest Gump"},
+                "outV": "person:Tom Hanks",
+                "inV": "movie:Forrest Gump",
+            }
+        ]
+
+        with self.assertRaisesRegex(ValueError, "Failed to create vertex"):
+            self.commit2graph.load_into_graph(vertices, edges, self.schema)
+
+        mock_handle_graph_creation.assert_called_once()
+
     
@patch("hugegraph_llm.operators.hugegraph_op.commit_to_hugegraph.Commit2Graph._handle_graph_creation")
     def test_load_into_graph_with_data_type_validation_failure(self, 
mock_handle_graph_creation):
         """Test load_into_graph method with data type validation failure."""
diff --git 
a/hugegraph-llm/src/tests/operators/hugegraph_op/test_fetch_graph_data.py 
b/hugegraph-llm/src/tests/operators/hugegraph_op/test_fetch_graph_data.py
index 8527502d..44b51f44 100644
--- a/hugegraph-llm/src/tests/operators/hugegraph_op/test_fetch_graph_data.py
+++ b/hugegraph-llm/src/tests/operators/hugegraph_op/test_fetch_graph_data.py
@@ -18,8 +18,12 @@
 import unittest
 from unittest.mock import MagicMock
 
+import pytest
+
 from hugegraph_llm.operators.hugegraph_op.fetch_graph_data import 
FetchGraphData
 
+pytestmark = [pytest.mark.unit]
+
 
 class TestFetchGraphData(unittest.TestCase):
     def setUp(self):
diff --git 
a/hugegraph-llm/src/tests/operators/hugegraph_op/test_schema_manager.py 
b/hugegraph-llm/src/tests/operators/hugegraph_op/test_schema_manager.py
index b77ae01f..05d9659f 100644
--- a/hugegraph-llm/src/tests/operators/hugegraph_op/test_schema_manager.py
+++ b/hugegraph-llm/src/tests/operators/hugegraph_op/test_schema_manager.py
@@ -18,8 +18,12 @@
 import unittest
 from unittest.mock import MagicMock, patch
 
+import pytest
+
 from hugegraph_llm.operators.hugegraph_op.schema_manager import SchemaManager
 
+pytestmark = [pytest.mark.unit]
+
 
 class TestSchemaManager(unittest.TestCase):
     def setUp(self):

Reply via email to