Skip to content

Latest commit

 

History

History
104 lines (69 loc) · 8.76 KB

File metadata and controls

104 lines (69 loc) · 8.76 KB

sysmledgraph – model examination (error conditions)

Examined: Requirements (R1–R8), deploy (actions, parts), behaviour (state machine, events). Focus: error conditions, failure modes, and how the model addresses them.


1. Error conditions considered

Error condition Where it can occur Model coverage
Invalid or missing path IndexDbGraph, CleanIndex (path param) R8: report to caller. State: indexingFailed / cleaningFailed; graph unchanged.
Parse failure (e.g. malformed .sysml, LSP unavailable) Indexer during IndexDbGraph R8: report; previous graph unchanged. indexing → indexingFailed (IndexFailed).
Graph store failure (Kuzu open/write/read error) Indexer (write), McpServer (read), list/clean R8: report. Index: indexingFailed; Clean: cleaningFailed. Query/context/impact/rename/cypher: MCP tool returns error (no new state; ready remains).
Invalid tool parameters (e.g. empty query, unknown symbol name) Query, Context, Impact, Rename, Cypher, list_indexed, clean_index R8: report to caller. Handled per call; no state change (tool returns error result).
Path not indexed (clean path that isn't in registry) CleanIndex R8: report. cleaning → cleaningFailed; graph unchanged.
Concurrent index/clean (e.g. two index calls overlapping) Indexer, GraphStore Not explicitly modeled. Implementation may serialize or reject; R8 still applies (report, no inconsistent graph).
Read-only tool failure (query/context/impact/rename/cypher when graph empty or symbol missing) McpServer No new state; tool returns error. R8: report to caller.
Kuzu DB lock (second process or second connection opens same DB file) CLI and MCP, or two MCP servers R8: report (e.g. "Could not set lock on file"). See §6 below.

2. Requirements (error-related)

R8 ReqErrorReporting (new):
The tool SHALL report errors to the caller (MCP tool result or CLI exit/stderr) for invalid path, parse failure, graph store failure, or invalid tool parameters. It SHALL NOT leave the graph in an inconsistent state when indexing or clean fails; on index failure the previous graph content (if any) SHALL remain usable.

Satisfy: SysmledgraphDeployment; actions IndexDbGraph, CleanIndex.


3. Behaviour (failure states and transitions)

New events: IndexFailed, CleanFailed.

New states:

  • indexingFailed — Index failed; error reported; previous graph unchanged. Transitions: StartIndex → idle or StartIndex → indexing (retry).
  • cleaningFailed — Clean failed; error reported; graph unchanged. Transitions: StartClean → ready or StartClean → cleaning (retry).

Transitions added:

  • indexing → indexingFailed (accept IndexFailed)
  • indexingFailed → idle (accept StartIndex)
  • indexingFailed → indexing (accept StartIndex)
  • cleaning → cleaningFailed (accept CleanFailed)
  • cleaningFailed → ready (accept StartClean)
  • cleaningFailed → cleaning (accept StartClean)

Read-only tools (query, context, impact, rename, cypher, list_indexed) do not change lifecycle state; they return success or error per call. No separate "queryFailed" state.


4. Consistency check

Aspect Status
R8 satisfied at deployment and at IndexDbGraph, CleanIndex
State machine includes failure states and retry paths
No transition from failure state leaves graph undefined (idle = empty, ready = has content)
indexingFailed → idle allows "give up" and stay empty; → indexing allows retry
cleaningFailed → ready preserves "graph still there"; → cleaning allows retry
visualize.py (bdd) succeeds with R8 and new events/states

5. Summary

The model now addresses error conditions by:

  1. Requirement R8 — Report errors to caller; do not corrupt or leave graph inconsistent on index/clean failure.
  2. State machine — indexingFailed and cleaningFailed with explicit retry (StartIndex / StartClean) back to idle, indexing, ready, or cleaning.
  3. Actions — IndexDbGraph and CleanIndex document "on failure: report; previous graph unchanged" and satisfy R8.

Read-only tools are covered by R8 (report invalid params or missing data) without new states. Concurrency is left to implementation; R8 still constrains outcome (report, no inconsistent graph).


6. Kuzu lock constraint

Observed behaviour: Kuzu uses file locking on the database directory/file. Only one process (or one connection per process in practice) can open the same DB path at a time. If the MCP server (e.g. Cursor) has the graph open and the user runs the CLI in a terminal, or if two MCP server instances use the same storage root, the second open fails with: "Could not set lock on file : …/db/….kuzu" (Kuzu concurrency docs).

Model alignment: GraphStore (deploy) abstracts the backing store; R3 (ReqSameStorageAsGitNexus) allows Kuzu. The model does not mandate multi-process concurrent access. A single deployment has one GraphStore; the implementation runs as either a CLI process or an MCP process, which do not share the same process.

Design constraint: For a given storage root (and thus DB path per indexed root), at most one process should hold the DB open at a time. The implementation uses a per-process cache (getCachedOrOpenGraphStore) so that within one MCP server process all tools reuse the same connection and avoid double-open; the CLI uses openGraphStore and is a separate process.

Implications:

  • CLI and MCP concurrent use: If MCP is running (e.g. Cursor), CLI analyze/list/clean that touch the same DB may hit the lock. Workaround: run CLI when MCP is not using the DB, or use only MCP tools (indexDbGraph, list_indexed, clean_index) when the server is running.
  • Read-only tools (cypher, query, context, impact): When MCP already has the DB open, these tools use the cached connection and succeed. The lock error typically appears when a second process (CLI) opens the same DB.
  • R8: Lock failure is a "graph store failure"; report to caller and do not leave graph inconsistent. The implementation should surface the Kuzu error to the MCP tool result or CLI stderr.

Conclusion: The Kuzu lock is a documented limitation of the backing store (R3). The model's single GraphStore and R8 cover "store unavailable" and reporting. No new requirement is strictly necessary; the development plan and this doc should record the single-process-per-DB constraint and the CLI-vs-MCP concurrency caveat.


7. OOP and execution model (worker threads)

Deploy parts and OOP: The logical parts (Indexer, GraphStore, McpServer, Cli) map to implementation modules or classes. GraphStore is an abstraction (ports GraphWritePort, GraphReadPort, RegistryPort) with a single backing connection per DB path—implemented as interface + closure or single instance. No deep inheritance; ports represent logical interfaces. This keeps connection ownership clear: one GraphStore instance per (process, dbPath), which aligns with Kuzu's single-connection/single-process constraint.

Execution and threads: The current implementation is single-threaded (Node.js event loop). The indexer processes files sequentially (no worker threads, no parallel parse). MCP tool invocations are serialized by the event loop (one tool at a time per server instance). That avoids shared mutable state and keeps GraphStore writes on one logical thread, so the per-process cached Kuzu connection is not used from multiple threads.

Worker threads (future): If parallel indexing were added (e.g. worker threads or a thread pool to parse files concurrently), then:

  • Writes to GraphStore must stay serialized (e.g. only the main thread calls addDocument/addSymbol/addEdge), or the implementation must comply with Kuzu's thread-safety (one connection per thread or documented multi-thread use). Kuzu's docs should be checked before sharing a connection across threads.
  • Read-only tools (query, context, impact, cypher) could in theory run on workers only if Kuzu supports concurrent read from multiple threads; otherwise keep reads on the same thread that holds the connection.
  • Model: The deploy model does not prescribe threads; it describes logical parts and ports. A design decision to introduce worker threads should be documented in the development plan and in code; the constraint "single writer / single connection ownership" (or Kuzu-compliant sharing) still applies.

Summary: OOP structure (parts = modules/classes, ports = interfaces) and single-threaded execution in the current design are consistent with the Kuzu lock and R8. Any future use of worker threads must preserve single-connection semantics or follow Kuzu's concurrency model.