Orchestrata Ultimate / Specs / 021-opencode-integration
021-opencode-integration: OpenCode Integration
A comprehensive TypeScript plugin (3,234 lines) and supporting agents, tools, and commands that integrate OpenCode with the Orchestrata project. The plugin provides session management, code quality enforcement via a 5-gate review pipeline, deception detection, knowledge graph context injection, conversation tracking, and 24 custom tools accessible from within OpenCode sessions.
At a glance
| Item | Value |
|---|---|
| Spec directory | specs/021-opencode-integration/ |
| Status line in the spec | Complete |
| Requirement IDs defined | 295 |
With a @traces citation in src/ |
13 (4.4%) |
With a @traces citation in tests/ |
8 (2.7%) |
| Tracked files | 6 |
| RTM page | 021-opencode-integration |
Reading this spec
The OpenCode Integration connects the OpenCode coding assistant to the Orchestrata project. It is a TypeScript plugin plus supporting agents, tools and commands that provide session management, code quality enforcement through a 5-gate review pipeline, deception detection, knowledge graph context injection, conversation tracking and 24 custom tools available inside OpenCode sessions.
The spec gives these reasons: OpenCode needs project-specific intelligence to work with the monorepo, knowledge graph context is injected automatically, quality standards (no mocking, absolute imports, short functions, snake_case) need enforcement at edit time, session lifecycle must be tracked consistently across Claude Code and OpenCode through the same context.json, and LLMs sometimes claim actions they did not perform.
The scope is a set of actor-driven user stories (labelled US-021-nn, each naming the functional requirements it exercises) and sixteen or more functional requirements: plugin lifecycle hooks, session auto-start and auto-end, knowledge graph context injection, the 5-gate review pipeline, error blocking, deception detection, policy enforcement, custom tool availability, project scoping of knowledge graph queries, Redis queue management, memory search, read throttling, git checkpoints, conversation storage and a knowledge graph sync daemon. Requirement IDs use the REQ-021- prefix.
The design is a single plugin, orchestrata.ts, exporting OrchestrataPlugin and hooking 7 OpenCode lifecycle events. Two OpenCode agents provide automatic and manual context injection, one slash command (/query-kg) runs interactive Cypher queries, and five Python tools query Neo4j with project scoping.
The plugin itself is TypeScript, so the Python trace table covers only supporting code, mostly orchestrata_ultimate/knowledge_graph/conversation_consumer, with orchestrata_ultimate/tools/conversation_tools and orchestrata_ultimate/kernel/cli_main. The per-requirement view is on the RTM page.
The spec's status line reads Complete. It tracks 6 files and defines 295 requirement IDs. The full text follows below.
Measured coverage is 13 of 295 requirements cited by at least one @traces in src/ (4.4%), spread over 5 modules; the module citing the most of them is orchestrata_ultimate/knowledge_graph/conversation_consumer (12 requirements). In tests/, 8 requirements are cited by a test-side @traces.
Coverage gaps: 282 requirements have no citing symbol. The largest untraced groups are REQ-021-* (282). Untraced means no @traces names the ID; the behaviour may still exist in code that was never annotated. Test-side citations are thinner than code-side ones (8 against 13).
Requirements
Checkbox is the state recorded in the requirements checklist; Traced by is the count of src/ symbols whose @traces names the ID.
| ID | Done | Requirement | Traced by |
|---|---|---|---|
REQ-021-001 |
no | KG context lookup triggered on read tool execution for Orchestrata project files |
none |
REQ-021-002 |
no | KG context lookup triggered on grep tool execution for Orchestrata project files |
none |
REQ-021-003 |
no | File path extracted from args.filePath or args.path for KG lookup |
none |
REQ-021-004 |
no | KG context retrieved via KnowledgeGraphContext.get_file_context() Python call |
2 |
REQ-021-005 |
no | Context injected as args._orchestrata_context with kg_context and source: "neo4j" fields |
none |
REQ-021-006 |
no | KG context injection is non-blocking (try/catch with empty catch) | none |
REQ-021-007 |
no | Missing file path gracefully skipped (early return if no filePath) | none |
REQ-021-008 |
no | Empty KG context (whitespace-only) not injected into args | none |
REQ-021-009 |
no | KG context Python subprocess runs with 2>/dev/null error suppression | none |
REQ-021-010 |
no | KG context lookup scoped to ${PROJECT_ROOT} working directory |
none |
REQ-021-011 |
no | Agent activates on direct file path references (/home/mohamed/workspace/orchestrata/...) |
none |
REQ-021-012 |
no | Agent activates on relative path references (packages/orchestrata-core/src/...) |
none |
REQ-021-013 |
no | Agent activates on class name references (TraceabilityModule, Neo4jClient) |
none |
REQ-021-014 |
no | Agent activates on function name references (create_file_node, query_neo4j) |
none |
REQ-021-015 |
no | Agent activates on spec ID references (SPEC-001, 001-kernel) |
none |
REQ-021-016 |
no | Agent activates on requirement ID references (REQ-001, REQ-004-US-001-NNN — placeholder shape; a literal foreign id here would read as this spec claiming another spec's requirement to the cross-spec uniqueness gate) |
none |
REQ-021-017 |
no | Agent activates on user story references (US-001, User Story 001) |
none |
REQ-021-018 |
no | Agent queries file basic info (path, language, line_count, size_bytes) | none |
REQ-021-019 |
no | Agent queries classes defined in file (name, line_start, line_end) | none |
REQ-021-020 |
no | Agent queries functions defined in file (name, line_start, line_end, is_async) | none |
REQ-021-021 |
no | Agent queries traceability links (code type, name, requirement_id, requirement_text) | none |
REQ-021-022 |
no | Agent queries inheritance hierarchy (child to ancestors, depth 3) | none |
REQ-021-023 |
no | Agent queries entity by name with CONTAINS and exact match | none |
REQ-021-024 |
no | Agent queries inbound and outbound relationships (limit 10 each) | none |
REQ-021-025 |
no | Agent connects to the operational KG (Memgraph) at the active env profile's endpoint (test fleet: bolt://10.53.2.10:7687) | none |
REQ-021-026 |
no | Agent uses the orchkg database name | none |
REQ-021-027 |
no | Agent activates on file, class, and function mentions | none |
REQ-021-028 |
no | Agent activates on code structure and relationship questions | none |
REQ-021-029 |
no | Agent activates on refactoring requests | none |
REQ-021-030 |
no | Agent activates on specification and requirement inquiries | none |
REQ-021-031 |
no | Agent uses /query-kg tool internally for Cypher execution | none |
REQ-021-032 |
no | Agent provides file-to-class and file-to-function mappings | none |
REQ-021-033 |
no | Agent provides inheritance hierarchies (depth 2) | none |
REQ-021-034 |
no | Agent provides code-to-requirement traceability links | none |
REQ-021-035 |
no | Agent runs transparently without explicit user invocation | none |
REQ-021-036 |
no | Check existing session via session_cli.py status --json |
none |
REQ-021-037 |
no | Resume existing session if active (log "Resumed existing session N") | none |
REQ-021-038 |
no | Begin new session if none active with purpose "OpenCode session HH:MM" | none |
REQ-021-039 |
no | Update project state to ACTIVE via session_cli.py update-state --status ACTIVE |
none |
REQ-021-040 |
no | Display session banner with seq number (3-digit padded) | none |
REQ-021-041 |
no | Display session focus (purpose) if available | none |
REQ-021-042 |
no | Display project version from state | none |
REQ-021-043 |
no | Display git branch from state | none |
REQ-021-044 |
no | Display test state from state | none |
REQ-021-045 |
no | Display total session count | none |
REQ-021-046 |
no | Display pending work items (top 5 with priority prefix) | none |
REQ-021-047 |
no | Show "... and N more" for pending work beyond 5 items | none |
REQ-021-048 |
no | Inject session context into output.context array |
none |
REQ-021-049 |
no | Log session start/resume to client.app.log with sessionSeq and pendingCount | none |
REQ-021-050 |
no | Trigger background KG sync only for orchestrata project directory | none |
REQ-021-051 |
no | Run sync_monorepo_to_neo4j.py as detached process (nohup, /dev/null redirect) |
none |
REQ-021-052 |
no | KG sync start is non-blocking (catch with empty handler) | none |
REQ-021-053 |
no | Log KG sync start to client.app.log | none |
REQ-021-054 |
no | Check Redis queue size via redis-cli SCARD orchestrata:kg:sync:queue |
none |
REQ-021-055 |
no | Process queue synchronously if pending count > 0 | none |
REQ-021-056 |
no | Pop files from Redis set via SPOP in loop |
none |
REQ-021-057 |
no | Sync each file via FileSynchronizer.sync_file() |
none |
REQ-021-058 |
no | Report synced count to stderr | none |
REQ-021-059 |
no | Queue flush is non-blocking (try/catch) | none |
REQ-021-060 |
no | Check Redis queue depth via redis-cli LLEN orchestrata:conversation:queue |
2 |
REQ-021-061 |
no | Process conversation queue if pending count > 0 | 1 |
REQ-021-062 |
no | Pop turns from Redis list via LPOP in loop |
4 |
REQ-021-063 |
no | Parse JSON turns, skip invalid entries | 4 |
REQ-021-064 |
no | Group turns by session_seq | none |
REQ-021-065 |
no | Create Conversation nodes with session_id opencode-{seq}, platform "opencode" |
3 |
REQ-021-066 |
no | Create ConversationTurn nodes with turn_id, seq, role, content, timestamp, platform | 1 |
REQ-021-067 |
no | Link ConversationTurn to Conversation via HAS_TURN relationship | 1 |
REQ-021-068 |
no | Content truncated to 2000 characters before Neo4j storage | 1 |
REQ-021-069 |
no | Neo4j driver connects to bolt://localhost:7687 (from environment) |
6 |
REQ-021-070 |
no | Conversation flush is non-blocking | 3 |
REQ-021-071 |
no | Extract achievements from git log --oneline --since="2 hours ago" -10 |
none |
REQ-021-072 |
no | Strip commit hash prefix from achievement lines | none |
REQ-021-073 |
no | Take top 5 achievements | none |
REQ-021-074 |
no | End session via session_cli.py end --achievements "..." |
none |
REQ-021-075 |
no | Archive old sessions keeping last 3 via SessionArchiver |
none |
REQ-021-076 |
no | Log session archive with achievement count and deception findings count | none |
REQ-021-077 |
no | Clear toolCallHistory on session end | none |
REQ-021-078 |
no | Reset readCount to 0 on session end | none |
REQ-021-079 |
no | Session auto-end failures logged as warnings (non-blocking) | none |
REQ-021-080 |
no | Run py_compile on edited file with 10-second timeout |
none |
REQ-021-081 |
no | Report syntax errors with first 200 characters of stderr | none |
REQ-021-082 |
no | Run black --check --diff on edited file with 30-second timeout |
none |
REQ-021-083 |
no | Report black formatting diff (first 300 characters) | none |
REQ-021-084 |
no | Run isort --check --diff on edited file with 30-second timeout |
none |
REQ-021-085 |
no | Report isort import ordering diff (first 300 characters) | none |
REQ-021-086 |
no | All Gate 1 tools run via uv run prefix |
none |
REQ-021-087 |
no | Run flake8 with --select=E,F,W,C90 selectors |
none |
REQ-021-088 |
no | Set --max-line-length=88 for black compatibility |
none |
REQ-021-089 |
no | Ignore E203,W503,E501 codes |
none |
REQ-021-090 |
no | Fatal lint codes (E9xx, F63x, F72x) reported as errors | none |
REQ-021-091 |
no | Non-fatal lint codes reported as warnings | none |
REQ-021-092 |
no | Maximum 15 lint lines reported | none |
REQ-021-093 |
no | Flake8 run with 30-second timeout | none |
REQ-021-094 |
no | Run mypy --ignore-missing-imports --no-error-summary with 60-second timeout |
none |
REQ-021-095 |
no | Filter mypy output to lines containing the file path or : error: |
none |
REQ-021-096 |
no | Maximum 10 mypy error lines reported | none |
REQ-021-097 |
no | Module import test: derive module path from packages/ structure | none |
REQ-021-098 |
no | Module import test: run python3 -c "import {module}" with 30-second timeout |
none |
REQ-021-099 |
no | Report import errors with first 300 characters of stderr | none |
REQ-021-100 |
no | Detect hardcoded passwords via regex password\s*=\s*['"][^'"]+['"] |
none |
REQ-021-101 |
no | Detect hardcoded API keys via regex api[_-]?key\s*=\s*['"][^'"]+['"] |
none |
REQ-021-102 |
no | Detect hardcoded secrets via regex secret\s*=\s*['"][^'"]+['"] |
none |
REQ-021-103 |
no | Detect hardcoded tokens via regex token\s*=\s*['"][^'"]+['"] |
none |
REQ-021-104 |
no | Detect debug f-string print statements as warnings | none |
REQ-021-105 |
no | Detect TODO/FIXME/HACK/XXX/BUG comments (max 3 reported) | none |
REQ-021-106 |
no | Detect bare except: with pass body as error |
none |
REQ-021-107 |
no | Detect missing logger in files with except or def blocks |
none |
REQ-021-108 |
no | Detect exceptions not logged via logger.error/exception/critical |
none |
REQ-021-109 |
no | Detect print statements that should use logging | none |
REQ-021-110 |
no | Check mutable default arguments (def func(x=[])) as error |
none |
REQ-021-111 |
no | Check @traces decorator presence for files with 3+ public items | none |
REQ-021-112 |
no | Report spec/requirement references found in code as info | none |
REQ-021-113 |
no | Count branches (if/elif/for/while/except) per function | none |
REQ-021-114 |
no | Branch count > 10 reported as error | none |
REQ-021-115 |
no | Branch count > 7 reported as warning | none |
REQ-021-116 |
no | Calculate max nesting depth (4-space indent units) | none |
REQ-021-117 |
no | Nesting depth > 5 reported as error | none |
REQ-021-118 |
no | Nesting depth > 4 reported as warning | none |
REQ-021-119 |
no | Lines > 100 characters counted and reported as warning | none |
REQ-021-120 |
no | Function body > 40 lines reported as warning with function name | none |
REQ-021-121 |
no | Functions starting with uppercase reported as naming error (must be snake_case) | none |
REQ-021-122 |
no | Classes starting with lowercase reported as naming error (must be PascalCase) | none |
REQ-021-123 |
no | Module-level UPPER_SNAKE constants detected and flagged for review | none |
REQ-021-124 |
no | Singleton pattern detected (__instance = None) and reported as info |
none |
REQ-021-125 |
no | Factory pattern detected (def create/make/build/factory) and reported as info |
none |
REQ-021-126 |
no | Builder pattern detected (def set/with/add/build) and reported as info |
none |
REQ-021-127 |
no | @dataclass usage detected and reported as info | none |
REQ-021-128 |
no | ABC/Protocol usage detected and reported as info | none |
REQ-021-129 |
no | State machine pattern detected and reported as info | none |
REQ-021-130 |
no | God object detection: class with > 20 methods reported as warning | none |
REQ-021-131 |
no | Feature envy detection: function with > 15 self references reported as warning | none |
REQ-021-132 |
no | Only Python files under packages/ trigger the review pipeline |
none |
REQ-021-133 |
no | Review report formatted with box-drawing characters and gate labels | none |
REQ-021-134 |
no | All gates passed: display "ALL GATES PASSED" with gate list | none |
REQ-021-135 |
no | Errors present: display "FAILED" with all error lines | none |
REQ-021-136 |
no | Warnings present: display "WARNINGS" section with all warning lines | none |
REQ-021-137 |
no | Quick-fix commands shown in error output (black, isort) | none |
REQ-021-138 |
no | Errors throw Error to block the edit and force agent to fix | none |
REQ-021-139 |
no | Warnings logged but do not block the edit | none |
REQ-021-140 |
no | Error output maximum: 25 errors, 20 warnings, 8 info items | none |
REQ-021-141 |
no | Passed files queued for KG sync via redis-cli SADD |
none |
REQ-021-142 |
no | Tool calls recorded in toolCallHistory array on tool.execute.after |
none |
REQ-021-143 |
no | Each record includes tool name, args, timestamp (Date.now()), and success boolean | none |
REQ-021-144 |
no | History capped at 100 entries (oldest shifted out) | none |
REQ-021-145 |
no | History cleared on session end (session.idle and session close) | none |
REQ-021-146 |
no | Quoted content removed before analysis (```, `, > blockquotes) | none |
REQ-021-147 |
no | Analysis operates on lowercased narrative text | none |
REQ-021-148 |
no | File creation claims matched against 3 regex patterns | none |
REQ-021-149 |
no | File creation without Write/Edit tool flagged as ACTION_DECEPTION (CRITICAL) | none |
REQ-021-150 |
no | Command execution claims matched against 3 regex patterns | none |
REQ-021-151 |
no | Command execution without Bash tool flagged as ACTION_DECEPTION (CRITICAL) | none |
REQ-021-152 |
no | File reading claims matched against 2 regex patterns | none |
REQ-021-153 |
no | File reading without Read/Grep tool flagged as ACTION_DECEPTION (HIGH) | none |
REQ-021-154 |
no | Unacknowledged tool errors flagged as ERROR_CONCEALMENT (CRITICAL) | none |
REQ-021-155 |
no | Error acknowledgment checked via keywords: error, failed, failure, issue, couldn't, unable, denied | none |
REQ-021-156 |
no | Failed tools listed in evidence field of findings | none |
REQ-021-157 |
no | Deception audit runs on session.idle hook |
none |
REQ-021-158 |
no | Report formatted with severity icons (CRITICAL=red, HIGH=orange, MEDIUM=yellow, LOW=blue) | none |
REQ-021-159 |
no | Each finding shows type, severity, description, and evidence | none |
REQ-021-160 |
no | Total violation count shown at report end | none |
REQ-021-161 |
no | Clean audit displays "No issues detected" message | none |
REQ-021-162 |
no | Findings logged to client.app.log with error level | none |
REQ-021-163 |
no | unittest.mock pattern blocked in test files |
none |
REQ-021-164 |
no | MagicMock pattern blocked in test files |
none |
REQ-021-165 |
no | @patch decorator pattern blocked in test files |
none |
REQ-021-166 |
no | AsyncMock pattern blocked in test files |
none |
REQ-021-167 |
no | Mock() constructor pattern blocked in test files |
none |
REQ-021-168 |
no | patch.object pattern blocked in test files |
none |
REQ-021-169 |
no | Policy only applies to files with "test" in path (case-insensitive) | none |
REQ-021-170 |
no | Violation throws descriptive Error with pattern name | none |
REQ-021-171 |
no | Relative import pattern from . import blocked |
none |
REQ-021-172 |
no | Pattern matches at beginning of line (with optional whitespace) | none |
REQ-021-173 |
no | Violation throws Error with "Use absolute imports" message | none |
REQ-021-174 |
no | pip install blocked with suggestion "uv add" |
none |
REQ-021-175 |
no | pip3 install blocked with suggestion "uv add" |
none |
REQ-021-176 |
no | pip sync blocked with suggestion "uv sync" |
none |
REQ-021-177 |
no | requirements.txt references blocked with suggestion "Use pyproject.toml with uv" |
none |
REQ-021-178 |
no | Violations throw Error with specific suggestion | none |
REQ-021-179 |
no | rm -rf / pattern blocked |
none |
REQ-021-180 |
no | Fork bomb pattern :(){ :|:& }; blocked |
none |
REQ-021-181 |
no | >/dev/null redirect pattern blocked |
none |
REQ-021-182 |
no | Blocked patterns throw Error with command in message | none |
REQ-021-183 |
no | Writes to paths containing .claude/plans blocked |
none |
REQ-021-184 |
no | Redirect message points to ~/workspace/orchestrata/plans/ |
none |
REQ-021-185 |
no | Git checkpoint created before edit and write tool operations |
none |
REQ-021-186 |
no | Checkpoint commits use --no-verify flag |
none |
REQ-021-187 |
no | Checkpoint message format: checkpoint: before {tool} {filePath} |
none |
REQ-021-188 |
no | Git checkpoint failures are non-blocking (|| true) |
none |
REQ-021-189 |
no | Read count incremented on each read tool execution |
none |
REQ-021-190 |
no | Read count > 50 throws Error with guidance to use grep first | none |
REQ-021-191 |
no | Read count reset to 0 on session end | none |
REQ-021-192 |
no | MCP document-reader health checked on read and grep tool execution |
none |
REQ-021-193 |
no | Health check via curl -sf to http://localhost:3456/health |
none |
REQ-021-194 |
no | MCP availability logged as info (does not block native tool) | none |
REQ-021-195 |
no | session-status returns formatted session info with box-drawing characters |
none |
REQ-021-196 |
no | session-status shows session seq, status, purpose, started time, duration |
none |
REQ-021-197 |
no | session-status shows achievements (top 3) and next steps (top 3) |
none |
REQ-021-198 |
no | session-status shows project version, branch, test state, session count, pending count |
none |
REQ-021-199 |
no | session-begin accepts purpose (string) and optional objectives (string[]) |
none |
REQ-021-200 |
no | session-end accepts optional achievements and upcoming (string[]) |
none |
REQ-021-201 |
no | session-log-work accepts desc (string) and optional details (string[]) |
none |
REQ-021-202 |
no | session-log-achievement accepts item (string) |
none |
REQ-021-203 |
no | session-add-work accepts text, optional priority, optional notes |
none |
REQ-021-204 |
no | session-complete-work accepts text (string) |
none |
REQ-021-205 |
no | session-update-state accepts optional version, branch, testState, status |
none |
REQ-021-206 |
no | session-log-choice accepts choice (string) and reason (string) |
none |
REQ-021-207 |
no | kg-query executes Cypher query via neo4j Python driver |
none |
REQ-021-208 |
no | kg-query returns "KG query only available for Orchestrata project" for non-orchestrata dirs |
none |
REQ-021-209 |
no | kg-sync runs sync_monorepo_to_neo4j.py and returns first 2000 chars |
none |
REQ-021-210 |
no | kg-queue-status returns pending count and file list from Redis SET |
none |
REQ-021-211 |
no | kg-flush-queue processes all files in sync queue via FileSynchronizer |
none |
REQ-021-212 |
no | kg-file-context retrieves full KG context for a file path |
none |
REQ-021-213 |
no | kg-find-file searches File nodes by name pattern |
none |
REQ-021-214 |
no | kg-find-entity searches Class and Function nodes by name |
none |
REQ-021-215 |
no | kg-stats returns node and relationship counts by label/type |
none |
REQ-021-216 |
no | conv-status returns conversation queue depth from Redis |
2 |
REQ-021-217 |
no | conv-sync flushes conversation queue to Neo4j |
3 |
REQ-021-218 |
no | "remember when" phrase triggers memory search | none |
REQ-021-219 |
no | "do you remember" phrase triggers memory search | none |
REQ-021-220 |
no | "recall when" phrase triggers memory search | none |
REQ-021-221 |
no | "remember that" phrase triggers memory search | none |
REQ-021-222 |
no | "we discussed" phrase triggers memory search | none |
REQ-021-223 |
no | "we talked about" phrase triggers memory search | none |
REQ-021-224 |
no | "last time we" phrase triggers memory search | none |
REQ-021-225 |
no | "what happened with" phrase triggers memory search | none |
REQ-021-226 |
no | Topic extracted from text after the trigger phrase | none |
REQ-021-227 |
no | Topic cleaned of leading punctuation | none |
REQ-021-228 |
no | Words shorter than 3 characters excluded from search terms | none |
REQ-021-229 |
no | Last 20 sessions searched in reverse order (newest first) | none |
REQ-021-230 |
no | Session purpose matched against topic words | none |
REQ-021-231 |
no | Session achievements matched against topic words | none |
REQ-021-232 |
no | Session work log entries matched against topic words | none |
REQ-021-233 |
no | Maximum 10 results returned | none |
REQ-021-234 |
no | Results include session seq, date, match type (purpose/achievement/log) | none |
REQ-021-235 |
no | Results injected into output.context as formatted block | none |
REQ-021-236 |
no | Memory search logged to client.app.log with topic | none |
REQ-021-237 |
no | Search failure logged as warning (non-blocking) | none |
REQ-021-238 |
no | No-match case prints "No matching sessions found" message | none |
REQ-021-239 |
no | Setup orchestrata paths (workspace, packages, knowledge src, core src) | none |
REQ-021-240 |
no | Async query via Neo4jClient from orchestrata.knowledge |
none |
REQ-021-241 |
no | Connection to the active env profile's KG endpoint (test fleet: bolt://10.53.2.10:7687), database orchkg (auth-less Memgraph) | none |
REQ-021-242 |
no | Return JSON with success, data, and count fields | none |
REQ-021-243 |
no | Return JSON error with type field on failure | none |
REQ-021-244 |
no | Accept Cypher query as argv[1] and optional JSON parameters as argv[2] | none |
REQ-021-245 |
no | Print usage examples to stderr on missing arguments | none |
REQ-021-246 |
no | Auto-detect orchestrata workspace from CWD | none |
REQ-021-247 |
no | Retrieve project ID via (p:Project)-[:HAS_FILE]->(f:File) query |
none |
REQ-021-248 |
no | Rewrite File path queries to anchor through (p:Project)-[:HAS_FILE]-> |
none |
REQ-021-249 |
no | Rewrite Spec ID queries to anchor through (p:Project)-[:HAS_SPEC]-> |
none |
REQ-021-250 |
no | Rewrite Requirement ID queries to anchor through (p:Project)-[:HAS_REQUIREMENT]-> |
none |
REQ-021-251 |
no | General MATCH queries get WHERE EXISTS clause checking 30+ relationship types | none |
REQ-021-252 |
no | Project scoping uses case-insensitive regex pattern matching | none |
REQ-021-253 |
no | Fallback wrapping for unrecognized query patterns | none |
REQ-021-254 |
no | Change to orchestrata workspace directory | none |
REQ-021-255 |
no | Run kg_query_inner.py via uv run python3 |
none |
REQ-021-256 |
no | Pass through all command-line arguments | none |
REQ-021-257 |
no | Fallback mock classes defined if orchestrata imports fail | none |
REQ-021-258 |
no | Import error printed to stderr (not stdout) | none |
REQ-021-259 |
no | Same connection and query interface as kg_query.py | none |
REQ-021-260 |
no | Minimal implementation for connection verification | none |
REQ-021-261 |
no | Same path setup and query interface as kg_query.py | none |
REQ-021-262 |
no | toolCallHistory array initialized empty on plugin load |
none |
REQ-021-263 |
no | readCount counter initialized to 0 on plugin load |
none |
REQ-021-264 |
no | MCP_SERVERS array defines document-reader (3456) and document-writer (3457) |
none |
REQ-021-265 |
no | Plugin activates only for directories under /home/mohamed/workspace |
none |
REQ-021-266 |
no | Plugin returns empty object {} for directories outside workspace |
none |
REQ-021-267 |
no | SESSION_CLI path set to python3 ~/.claude/tools/session_cli.py |
none |
REQ-021-268 |
no | PROJECT_ROOT set to the directory parameter |
none |
REQ-021-269 |
no | All log messages use service name "orchestrata-plugin" | none |
REQ-021-270 |
no | Log levels: info (normal), warn (non-critical failures), error (critical failures), debug (verbose) | none |
REQ-021-271 |
no | Plugin activation logged on startup with project name and directory | none |
REQ-021-272 |
no | "close the session" detected as close request | none |
REQ-021-273 |
no | "cts" detected as close request | none |
REQ-021-274 |
no | "cs" detected as close request | none |
REQ-021-275 |
no | "end session" detected as close request | none |
REQ-021-276 |
no | "finish session" detected as close request | none |
REQ-021-277 |
no | Close validates active session exists | none |
REQ-021-278 |
no | Close extracts achievements from git log (last 2 hours, top 20, filter checkpoints) | none |
REQ-021-279 |
no | Close ends session via session_cli.py | none |
REQ-021-280 |
no | Close pushes branch to origin | none |
REQ-021-281 |
no | Close displays formatted report with session number, achievements, push status | none |
REQ-021-282 |
no | Close clears toolCallHistory and readCount | none |
REQ-021-283 |
no | Close failure displayed as error message | none |
REQ-021-284 |
no | Praise patterns (looks good, great work, well done) logged | none |
REQ-021-285 |
no | Thanks patterns (thanks, thank you, appreciate) logged | none |
REQ-021-286 |
no | Fix confirmation patterns (that works, fixed it, solved it) logged | none |
REQ-021-287 |
no | Completion detection is non-blocking | none |
REQ-021-288 |
no | experimental.session.compacting injects session context | none |
REQ-021-289 |
no | Context includes active session seq, purpose, achievements, carryover tasks | none |
REQ-021-290 |
no | Session status retrieved via session_cli.py status --json (first 1000 chars) | none |
REQ-021-291 |
no | Compacting hook is non-blocking | none |
REQ-021-292 |
no | File operations (edit, write, delete) logged via session_cli.py log-work | none |
REQ-021-293 |
no | Write operations additionally logged via session_cli.py log-artifact | none |
REQ-021-294 |
no | Failed tool operations logged as warnings to client.app.log | none |
REQ-021-295 |
no | Operation logging is non-blocking | none |
Code that traces this spec
Checklists
checklists/README.md
OpenCode Integration Checklists
Project: Orchestrata OpenCode Integration (Spec 021) Component: OrchestrataPlugin, Agents, Tools, Commands, KG Integration Status: Implemented Owner: Mohamed
Overview
The OpenCode Integration is a comprehensive TypeScript plugin and supporting infrastructure that bridges OpenCode with the Orchestrata ecosystem. It provides session management, 5-gate code quality enforcement, deception detection, knowledge graph context injection, conversation tracking, and 24 custom tools.
Checklist Summary
| Checklist | Total Items | Completed | Progress |
|---|---|---|---|
| Requirements | 295 | 0 | 0% |
| Constitutional Compliance | 105 | 0 | 0% |
| Testing Plan | 211 | 0 | 0% |
| TOTAL | 611 | 0 | 0% |
Key Responsibilities
1. Plugin Lifecycle Management
- Hook into 7 OpenCode lifecycle events (session.created, session.idle, tool.execute.before, tool.execute.after, message.updated, file.edited, experimental.session.compacting)
- Activate for any project under /home/mohamed/workspace with context.json
- Manage state (tool call history, read count, MCP health)
2. Session Management
- Auto-start sessions on connection via session_cli.py
- Auto-close sessions on idle with git-extracted achievements
- Display session info, pending work, and project state
- Flush KG sync and conversation queues on session close
3. Code Quality Enforcement (5-Gate Review)
- Gate 1: Syntax validation (py_compile), formatting (black), import ordering (isort)
- Gate 2: Linting (flake8 with E/F/W/C90 selectors)
- Gate 3: Type checking (mypy), security scanning, runtime import verification
- Gate 4: Complexity analysis (branches, nesting, line length, function size)
- Gate 5: Naming conventions and design pattern detection
4. Policy Enforcement
- Testing policy: block mocking patterns (unittest.mock, MagicMock, @patch, AsyncMock)
- Import policy: block relative imports (from . import)
- Development policy: block pip, require uv; block requirements.txt
- Bash safety: block destructive commands (rm -rf /, fork bombs)
5. Deception Detection
- Track tool calls across session for audit
- Detect claimed file creation without Write/Edit tool
- Detect claimed command execution without Bash tool
- Detect claimed file reading without Read/Grep tool
- Detect unacknowledged tool errors
6. Knowledge Graph Integration
- Auto-inject KG context on file reads (classes, functions, specs, traceability)
- 12 KG tools for queries, sync, daemon management, entity search
- 2 agents for automatic and manual KG context injection
- 1 slash command for interactive Cypher queries
- 5 Python tools with project scoping
7. Conversation Tracking
- Queue conversation turns to Redis for batch Neo4j storage
- Flush queue on session close with Conversation and ConversationTurn nodes
- Memory search via "remember when" trigger phrases
8. Custom Tools (24 total)
- 9 session management tools
- 12 KG operation tools
- 3 conversation tracking tools
File References
| Checklist | File |
|---|---|
| Requirements | requirements.md |
| Constitutional | constitutional.md |
| Testing | testing.md |
checklists/constitutional.md
OpenCode Integration Constitutional Checklist
Article I: Security and Access Control
- [ ] CONST-I-001: Neo4j credentials must never be hardcoded in plugin source; environment variables used with local-dev fallbacks only
- [ ] CONST-I-002: Plugin must block destructive bash commands (rm -rf /, fork bombs) before execution
- [ ] CONST-I-003: Gate 3 code review must detect hardcoded passwords, API keys, secrets, and tokens in edited files
- [ ] CONST-I-004: Write operations to sensitive paths (~/.claude/plans/) must be blocked with descriptive redirects
- [ ] CONST-I-005: Read throttling (50/session) must prevent runaway file scanning that could expose sensitive data
- [ ] CONST-I-006: Conversation content must be truncated (2000 chars) before Neo4j storage to limit data exposure
- [ ] CONST-I-007: Tool call history must be capped (100 entries) to bound memory exposure
- [ ] CONST-I-008: KG query tools must not expose credentials in stdout or error messages
- [ ] CONST-I-009: Redis queue data must not contain full file contents, only file paths
- [ ] CONST-I-010: Plugin must not transmit project data to external services beyond configured Neo4j and Redis
Article II: Data Integrity and Consistency
- [ ] CONST-II-001: context.json must remain the single source of truth for session state across Claude Code and OpenCode
- [ ] CONST-II-002: Session CLI operations must be atomic (begin/end do not leave partial state)
- [ ] CONST-II-003: KG sync queue must use Redis SET to prevent duplicate file entries
- [ ] CONST-II-004: Conversation queue must use Redis LIST to preserve turn ordering
- [ ] CONST-II-005: ConversationTurn nodes must have unique turn_id to prevent duplicates
- [ ] CONST-II-006: Git checkpoints must be created before edit/write operations to enable rollback
- [ ] CONST-II-007: KG sync must not corrupt existing Neo4j nodes (MERGE preferred over CREATE)
- [ ] CONST-II-008: Session close must flush both KG and conversation queues before marking session ended
- [ ] CONST-II-009: Tool call history must accurately reflect actual tool invocations (no phantom entries)
- [ ] CONST-II-010: Deception detection must only analyze the actual assistant message, not injected context
Article III: Code Quality and Standards Enforcement
- [ ] CONST-III-001: Testing policy must block all forms of mocking (unittest.mock, MagicMock, @patch, AsyncMock, Mock(), patch.object)
- [ ] CONST-III-002: Import policy must enforce absolute imports only (no relative from . import)
- [ ] CONST-III-003: Development policy must enforce uv over pip for all package operations
- [ ] CONST-III-004: Code review must run all 5 gates in sequence for every Python file edit under packages/
- [ ] CONST-III-005: Errors from code review must block the edit operation (throw Error)
- [ ] CONST-III-006: Warnings from code review must be displayed but not block the operation
- [ ] CONST-III-007: Code review must respect project-specific thresholds (black 88, flake8 ignores)
- [ ] CONST-III-008: Gate 3 must check actual module importability, not just syntax
- [ ] CONST-III-009: Gate 4 complexity thresholds (10 branches error, 5 nesting error) must not be configurable per-file
- [ ] CONST-III-010: Gate 5 naming conventions must match project standards (snake_case functions, PascalCase classes)
Article IV: System Reliability and Resilience
- [ ] CONST-IV-001: All Neo4j operations must be non-blocking (failures must not prevent tool execution)
- [ ] CONST-IV-002: All Redis operations must be non-blocking (failures must not prevent session management)
- [ ] CONST-IV-003: MCP health checks must be non-blocking (unavailable servers must not prevent native tool use)
- [ ] CONST-IV-004: Session CLI failures must be non-blocking (session management errors must not prevent work)
- [ ] CONST-IV-005: KG sync daemon must recover from crashes (queue persists in Redis)
- [ ] CONST-IV-006: Conversation queue must be durable (turns persist in Redis until flushed)
- [ ] CONST-IV-007: Plugin must activate cleanly even if Neo4j, Redis, and MCP are all unavailable
- [ ] CONST-IV-008: Git checkpoint failures must not block edit operations
- [ ] CONST-IV-009: Code review tool failures (except review's own errors) must not block edits
- [ ] CONST-IV-010: Background KG sync process must not impact foreground plugin performance
Article V: Transparency and Auditability
- [ ] CONST-V-001: All plugin operations must be logged to client.app.log with appropriate severity levels
- [ ] CONST-V-002: Deception detection findings must include evidence (tools used) not just claims
- [ ] CONST-V-003: Deception audit report must be generated on every session idle event
- [ ] CONST-V-004: Code review results must clearly distinguish errors (blocking) from warnings (informational)
- [ ] CONST-V-005: Session lifecycle events (start, end, close) must be logged with session seq numbers
- [ ] CONST-V-006: Tool operation logging must record file paths for edit/write/delete operations
- [ ] CONST-V-007: Policy violations must include specific pattern name and suggested alternative
- [ ] CONST-V-008: KG sync progress must be reportable via kg-queue-status tool
- [ ] CONST-V-009: Conversation queue depth must be queryable via conv-status tool
- [ ] CONST-V-010: Plugin activation must be logged with project name and directory
Article VI: Privacy and Data Minimization
- [ ] CONST-VI-001: Conversation turns must be truncated to 2000 characters before storage
- [ ] CONST-VI-002: User messages must not be logged in full to client.app.log (only first 100 chars for close detection)
- [ ] CONST-VI-003: Deception analysis must strip quoted content to avoid analyzing code examples as claims
- [ ] CONST-VI-004: KG context injection must not expose Neo4j credentials in tool args
- [ ] CONST-VI-005: Error messages must not expose stack traces or internal implementation details to the LLM
- [ ] CONST-VI-006: Redis queue data must be processed and cleared on session close (no stale data accumulation)
- [ ] CONST-VI-007: Tool call history must be cleared on session end to prevent cross-session leakage
- [ ] CONST-VI-008: Memory search results must be scoped to the current project's context.json only
- [ ] CONST-VI-009: KG queries must be scoped to the current project via project scoping (kg_query_inner.py)
- [ ] CONST-VI-010: Plugin must not access or modify files outside the workspace directory
Article VII: Ethical AI and Deception Prevention
- [ ] CONST-VII-001: Deception detection must cover file creation, command execution, and file reading claims
- [ ] CONST-VII-002: Error concealment (unacknowledged tool failures) must be flagged as CRITICAL severity
- [ ] CONST-VII-003: Deception analysis must exclude quoted content to prevent false positives from code examples
- [ ] CONST-VII-004: Clean audit results must be explicitly reported ("No issues detected")
- [ ] CONST-VII-005: Deception findings must be visible to the user (stderr output, not suppressed)
- [ ] CONST-VII-006: Tool call tracking must be accurate and complete (no selective recording)
- [ ] CONST-VII-007: Deception severity levels must be appropriate (CRITICAL for action claims, HIGH for reading claims)
- [ ] CONST-VII-008: Deception detection must not produce false positives from legitimate tool-less context (e.g., discussing previous work)
- [ ] CONST-VII-009: Audit report must include all findings, not suppress any for appearance
- [ ] CONST-VII-010: Deception detection logic must be deterministic and reproducible
Article VIII: Interoperability and Compatibility
- [ ] CONST-VIII-001: Plugin must be compatible with @opencode-ai/plugin@1.3.3 API
- [ ] CONST-VIII-002: Session CLI interface must be identical for Claude Code and OpenCode
- [ ] CONST-VIII-003: context.json format must be shared across both platforms
- [ ] CONST-VIII-004: Hook mapping between Claude Code and OpenCode must be documented and maintained
- [ ] CONST-VIII-005: KG query tools must use the same Neo4j schema as orchestrata-knowledge package
- [ ] CONST-VIII-006: Redis queue key naming must not conflict with other orchestrata subsystems
- [ ] CONST-VIII-007: Conversation nodes must use "opencode" platform tag to distinguish from other sources
- [ ] CONST-VIII-008: Git checkpoint commits must use --no-verify to avoid triggering pre-commit hooks
- [ ] CONST-VIII-009: Python tools must be compatible with uv-managed virtual environment
- [ ] CONST-VIII-010: Agent definitions must follow OpenCode agent markdown format
Article IX: Performance and Resource Management
- [ ] CONST-IX-001: Plugin activation must complete within 5 seconds (non-blocking background tasks excluded)
- [ ] CONST-IX-002: KG context injection must not add more than 2 seconds to file read operations
- [ ] CONST-IX-003: Code review pipeline must complete within 2 minutes per file (sum of all gate timeouts)
- [ ] CONST-IX-004: Read throttle must prevent excessive file operations (limit: 50/session)
- [ ] CONST-IX-005: Tool call history must be bounded (100 entries) to prevent memory growth
- [ ] CONST-IX-006: Background KG sync must use nohup/detached process to not block plugin
- [ ] CONST-IX-007: Redis queue operations must use single-command atomics (SADD, SCARD, SPOP, LPUSH, LPOP, LLEN)
- [ ] CONST-IX-008: Neo4j driver connections must be closed after each query operation
- [ ] CONST-IX-009: Subprocess timeouts must be enforced (10s syntax, 30s lint/format, 60s mypy)
- [ ] CONST-IX-010: Plugin must not spawn more than one concurrent background sync process
Article X: Knowledge Graph Integrity
- [ ] CONST-X-001: All Neo4j node creation must include relationship to parent node (no orphans)
- [ ] CONST-X-002: Conversation nodes must be linked to Project via HAS_CONVERSATION relationship
- [ ] CONST-X-003: ConversationTurn nodes must be linked to Conversation via HAS_TURN relationship
- [ ] CONST-X-004: KG sync must use MERGE (not CREATE) to prevent duplicate nodes
- [ ] CONST-X-005: Project scoping must correctly anchor queries to the orchestrata Project node
- [ ] CONST-X-006: File sync must preserve existing node relationships when updating properties
- [ ] CONST-X-007: Conversation platform field must accurately identify the source ("opencode")
- [ ] CONST-X-008: KG statistics reported by kg-stats tool must reflect actual graph state
- [ ] CONST-X-009: Entity search must return results from the correct project scope
- [ ] CONST-X-010: CXP thread queries must correctly follow thread_id chains
Article XI: Deployment and Configuration
- [ ] CONST-XI-001: install.sh must deploy all artifacts (agents, commands, plugins, tools, config) to correct locations
- [ ] CONST-XI-002: Deployed plugin must reference correct session_cli.py path (~/.claude/tools/session_cli.py)
- [ ] CONST-XI-003: Deployed tools must reference correct workspace paths (/home/mohamed/workspace/orchestrata)
- [ ] CONST-XI-004: Plugin must detect and adapt to directory context (orchestrata-specific vs generic workspace)
- [ ] CONST-XI-005: Configuration must support environment variable overrides for Neo4j URI and credentials
checklists/requirements.md
The requirement list above comes from this file; 0 of 295 checkbox items are ticked.
checklists/testing.md
OpenCode Integration Testing Checklist
Unit Tests: Plugin State Management
- [ ] TEST-UNIT-001: Verify toolCallHistory initialized as empty array
- [ ] TEST-UNIT-002: Verify readCount initialized to 0
- [ ] TEST-UNIT-003: Verify MCP_SERVERS contains document-reader (3456) and document-writer (3457)
- [ ] TEST-UNIT-004: Verify toolCallHistory entry contains tool, args, timestamp, success fields
- [ ] TEST-UNIT-005: Verify toolCallHistory caps at 100 entries (oldest removed)
- [ ] TEST-UNIT-006: Verify readCount increments on each read tool execution
- [ ] TEST-UNIT-007: Verify state cleared on session end (toolCallHistory emptied, readCount reset)
Unit Tests: Helper Functions
removeQuotedContent
- [ ] TEST-UNIT-008: Verify triple-backtick code blocks removed
- [ ] TEST-UNIT-009: Verify inline backtick code removed
- [ ] TEST-UNIT-010: Verify blockquote lines (> prefix) removed
- [ ] TEST-UNIT-011: Verify non-quoted text preserved
- [ ] TEST-UNIT-012: Verify nested code blocks handled correctly
detectDeception
- [ ] TEST-UNIT-013: Verify file creation claim with Write tool returns no findings
- [ ] TEST-UNIT-014: Verify file creation claim without Write/Edit tool returns ACTION_DECEPTION (CRITICAL)
- [ ] TEST-UNIT-015: Verify command execution claim with Bash tool returns no findings
- [ ] TEST-UNIT-016: Verify command execution claim without Bash tool returns ACTION_DECEPTION (CRITICAL)
- [ ] TEST-UNIT-017: Verify file reading claim with Read tool returns no findings
- [ ] TEST-UNIT-018: Verify file reading claim without Read/Grep tool returns ACTION_DECEPTION (HIGH)
- [ ] TEST-UNIT-019: Verify tool error without acknowledgment returns ERROR_CONCEALMENT (CRITICAL)
- [ ] TEST-UNIT-020: Verify tool error with acknowledgment returns no findings
- [ ] TEST-UNIT-021: Verify quoted content excluded from deception analysis
- [ ] TEST-UNIT-022: Verify multiple findings can be returned simultaneously
- [ ] TEST-UNIT-023: Verify empty tool history with no claims returns no findings
- [ ] TEST-UNIT-024: Verify evidence field lists tools used
enforceTestingPolicy
- [ ] TEST-UNIT-025: Verify unittest.mock blocked in test files
- [ ] TEST-UNIT-026: Verify MagicMock blocked in test files
- [ ] TEST-UNIT-027: Verify @patch blocked in test files
- [ ] TEST-UNIT-028: Verify AsyncMock blocked in test files
- [ ] TEST-UNIT-029: Verify Mock() blocked in test files
- [ ] TEST-UNIT-030: Verify patch.object blocked in test files
- [ ] TEST-UNIT-031: Verify non-test files not checked (no error thrown)
- [ ] TEST-UNIT-032: Verify error message includes pattern name
enforceImportPolicy
- [ ] TEST-UNIT-033: Verify
from . import xblocked - [ ] TEST-UNIT-034: Verify
from .. import xnot matched (only single dot) - [ ] TEST-UNIT-035: Verify absolute imports allowed
- [ ] TEST-UNIT-036: Verify indented relative imports detected
enforceDevelopmentPolicy
- [ ] TEST-UNIT-037: Verify
pip installblocked with "uv add" suggestion - [ ] TEST-UNIT-038: Verify
pip3 installblocked with "uv add" suggestion - [ ] TEST-UNIT-039: Verify
pip syncblocked with "uv sync" suggestion - [ ] TEST-UNIT-040: Verify
requirements.txtreference blocked - [ ] TEST-UNIT-041: Verify
uv addcommands allowed - [ ] TEST-UNIT-042: Verify
uv synccommands allowed
checkMcpHealth
- [ ] TEST-UNIT-043: Verify returns true when server responds with "ok"
- [ ] TEST-UNIT-044: Verify returns true when server responds with "200"
- [ ] TEST-UNIT-045: Verify returns false when server is down
- [ ] TEST-UNIT-046: Verify returns false on connection error
Unit Tests: 5-Gate Code Review
Gate 1: Syntax & Format
- [ ] TEST-UNIT-047: Verify py_compile detects syntax errors
- [ ] TEST-UNIT-048: Verify black --check detects formatting violations
- [ ] TEST-UNIT-049: Verify isort --check detects import ordering violations
- [ ] TEST-UNIT-050: Verify valid Python file passes Gate 1
- [ ] TEST-UNIT-051: Verify syntax error reported with first 200 chars of stderr
Gate 2: Lint
- [ ] TEST-UNIT-052: Verify flake8 detects E-series errors
- [ ] TEST-UNIT-053: Verify flake8 detects F-series errors
- [ ] TEST-UNIT-054: Verify flake8 detects W-series warnings
- [ ] TEST-UNIT-055: Verify E203, W503, E501 codes ignored
- [ ] TEST-UNIT-056: Verify E9xx/F63x/F72x classified as errors (not warnings)
- [ ] TEST-UNIT-057: Verify max 15 lint lines reported
Gate 3: Runtime & Security
- [ ] TEST-UNIT-058: Verify mypy detects type errors
- [ ] TEST-UNIT-059: Verify module import check derives correct module path
- [ ] TEST-UNIT-060: Verify hardcoded password detection
- [ ] TEST-UNIT-061: Verify hardcoded API key detection
- [ ] TEST-UNIT-062: Verify hardcoded secret detection
- [ ] TEST-UNIT-063: Verify hardcoded token detection
- [ ] TEST-UNIT-064: Verify debug print statement detection
- [ ] TEST-UNIT-065: Verify TODO/FIXME/HACK comment detection (max 3)
- [ ] TEST-UNIT-066: Verify bare except with pass detection
- [ ] TEST-UNIT-067: Verify missing logger warning
- [ ] TEST-UNIT-068: Verify unlogged exception detection
- [ ] TEST-UNIT-069: Verify mutable default argument detection
- [ ] TEST-UNIT-070: Verify @traces decorator presence check (3+ public items)
- [ ] TEST-UNIT-071: Verify spec/requirement reference detection in code
Gate 4: Complexity & Nesting
- [ ] TEST-UNIT-072: Verify branch count > 10 flagged as error
- [ ] TEST-UNIT-073: Verify branch count 8-10 flagged as warning
- [ ] TEST-UNIT-074: Verify branch count <= 7 passes
- [ ] TEST-UNIT-075: Verify nesting depth > 5 flagged as error
- [ ] TEST-UNIT-076: Verify nesting depth 5 flagged as warning
- [ ] TEST-UNIT-077: Verify nesting depth <= 4 passes
- [ ] TEST-UNIT-078: Verify line length > 100 chars counted as warning
- [ ] TEST-UNIT-079: Verify function > 40 lines flagged as warning
Gate 5: Naming & Design
- [ ] TEST-UNIT-080: Verify uppercase function name flagged as naming error
- [ ] TEST-UNIT-081: Verify lowercase class name flagged as naming error
- [ ] TEST-UNIT-082: Verify snake_case function passes
- [ ] TEST-UNIT-083: Verify PascalCase class passes
- [ ] TEST-UNIT-084: Verify god object (> 20 methods) flagged as warning
- [ ] TEST-UNIT-085: Verify feature envy (> 15 self references) flagged as warning
- [ ] TEST-UNIT-086: Verify singleton pattern detected as info
- [ ] TEST-UNIT-087: Verify factory pattern detected as info
- [ ] TEST-UNIT-088: Verify builder pattern detected as info
- [ ] TEST-UNIT-089: Verify @dataclass detected as info
Review Output
- [ ] TEST-UNIT-090: Verify only packages/*.py files trigger review
- [ ] TEST-UNIT-091: Verify non-Python files skip review
- [ ] TEST-UNIT-092: Verify files outside packages/ skip review
- [ ] TEST-UNIT-093: Verify errors cause thrown Error (blocking)
- [ ] TEST-UNIT-094: Verify warnings do not cause thrown Error
- [ ] TEST-UNIT-095: Verify clean file produces "ALL GATES PASSED"
- [ ] TEST-UNIT-096: Verify max 25 errors in output
- [ ] TEST-UNIT-097: Verify max 20 warnings in output
Unit Tests: KG Query Tools (Python)
kg_query.py
- [ ] TEST-UNIT-098: Verify orchestrata paths added to sys.path
- [ ] TEST-UNIT-099: Verify successful Cypher query returns JSON with success=true
- [ ] TEST-UNIT-100: Verify failed connection returns JSON error
- [ ] TEST-UNIT-101: Verify import error returns JSON error with ImportError type
- [ ] TEST-UNIT-102: Verify missing arguments prints usage to stderr
- [ ] TEST-UNIT-103: Verify JSON parameter parsing from argv[2]
- [ ] TEST-UNIT-104: Verify invalid JSON parameter prints error to stderr
kg_query_inner.py (Project Scoping)
- [ ] TEST-UNIT-105: Verify File path query rewritten with Project anchor
- [ ] TEST-UNIT-106: Verify Spec ID query rewritten with Project anchor
- [ ] TEST-UNIT-107: Verify Requirement ID query rewritten with Project anchor
- [ ] TEST-UNIT-108: Verify general MATCH query gets WHERE EXISTS clause
- [ ] TEST-UNIT-109: Verify existing WHERE clause gets AND condition (not replaced)
- [ ] TEST-UNIT-110: Verify MATCH without WHERE gets new WHERE clause
- [ ] TEST-UNIT-111: Verify non-MATCH queries pass through unchanged
- [ ] TEST-UNIT-112: Verify CWD detection for orchestrata workspace
- [ ] TEST-UNIT-113: Verify non-orchestrata CWD skips project scoping
- [ ] TEST-UNIT-114: Verify case-insensitive pattern matching for query rewriting
neo4j_query.py
- [ ] TEST-UNIT-115: Verify fallback mock classes defined on import failure
- [ ] TEST-UNIT-116: Verify import error printed to stderr
- [ ] TEST-UNIT-117: Verify query execution returns JSON result
simple_kg_query.py
- [ ] TEST-UNIT-118: Verify minimal query execution
- [ ] TEST-UNIT-119: Verify connection error returns JSON error
Unit Tests: Memory Search
- [ ] TEST-UNIT-120: Verify "remember when" triggers search
- [ ] TEST-UNIT-121: Verify "do you remember" triggers search
- [ ] TEST-UNIT-122: Verify "recall when" triggers search
- [ ] TEST-UNIT-123: Verify "we discussed" triggers search
- [ ] TEST-UNIT-124: Verify "we talked about" triggers search
- [ ] TEST-UNIT-125: Verify "last time we" triggers search
- [ ] TEST-UNIT-126: Verify "what happened with" triggers search
- [ ] TEST-UNIT-127: Verify topic extracted after trigger phrase
- [ ] TEST-UNIT-128: Verify short words (< 3 chars) excluded
- [ ] TEST-UNIT-129: Verify purpose field searched
- [ ] TEST-UNIT-130: Verify achievements searched
- [ ] TEST-UNIT-131: Verify work log entries searched
- [ ] TEST-UNIT-132: Verify max 10 results returned
- [ ] TEST-UNIT-133: Verify newest sessions searched first
- [ ] TEST-UNIT-134: Verify no-match message displayed
Unit Tests: Session Close Detection
- [ ] TEST-UNIT-135: Verify "close the session" triggers close
- [ ] TEST-UNIT-136: Verify "cts" triggers close
- [ ] TEST-UNIT-137: Verify "cs" triggers close
- [ ] TEST-UNIT-138: Verify "end session" triggers close
- [ ] TEST-UNIT-139: Verify "finish session" triggers close
- [ ] TEST-UNIT-140: Verify no active session displays error
- [ ] TEST-UNIT-141: Verify achievements extracted from git log (filter checkpoints)
- [ ] TEST-UNIT-142: Verify session ended via session_cli.py
- [ ] TEST-UNIT-143: Verify branch pushed to origin
- [ ] TEST-UNIT-144: Verify state cleared after close
Unit Tests: Custom Tools
Session Tools
- [ ] TEST-UNIT-145: Verify session-status returns formatted output
- [ ] TEST-UNIT-146: Verify session-status handles no active session
- [ ] TEST-UNIT-147: Verify session-begin calls session_cli.py begin with purpose
- [ ] TEST-UNIT-148: Verify session-end calls session_cli.py end with achievements
- [ ] TEST-UNIT-149: Verify session-log-work calls session_cli.py log-work with desc
- [ ] TEST-UNIT-150: Verify session-log-achievement calls session_cli.py log-achievement
- [ ] TEST-UNIT-151: Verify session-add-work calls session_cli.py add-work with text and priority
- [ ] TEST-UNIT-152: Verify session-complete-work calls session_cli.py complete-work
- [ ] TEST-UNIT-153: Verify session-update-state passes version, branch, testState, status
- [ ] TEST-UNIT-154: Verify session-log-choice passes choice and reason
KG Tools
- [ ] TEST-UNIT-155: Verify kg-query executes Cypher and returns result
- [ ] TEST-UNIT-156: Verify kg-query rejects non-orchestrata directory
- [ ] TEST-UNIT-157: Verify kg-sync runs sync script and returns output
- [ ] TEST-UNIT-158: Verify kg-queue-status returns pending count from Redis
- [ ] TEST-UNIT-159: Verify kg-flush-queue processes all queued files
- [ ] TEST-UNIT-160: Verify kg-file-context returns KG data for file path
- [ ] TEST-UNIT-161: Verify kg-find-file searches by pattern
- [ ] TEST-UNIT-162: Verify kg-find-entity searches classes and functions by name
- [ ] TEST-UNIT-163: Verify kg-stats returns node/relationship counts
Integration Tests: Plugin Lifecycle
- [ ] TEST-INTEG-001: Verify plugin activates for orchestrata directory
- [ ] TEST-INTEG-002: Verify plugin returns empty object for non-workspace directory
- [ ] TEST-INTEG-003: Verify session.created auto-starts new session when none active
- [ ] TEST-INTEG-004: Verify session.created resumes existing active session
- [ ] TEST-INTEG-005: Verify session.idle runs deception audit and session close
- [ ] TEST-INTEG-006: Verify session.idle clears state after processing
- [ ] TEST-INTEG-007: Verify tool.execute.before injects KG context on file read
- [ ] TEST-INTEG-008: Verify tool.execute.before enforces testing policy on test file edit
- [ ] TEST-INTEG-009: Verify tool.execute.before creates git checkpoint on edit
- [ ] TEST-INTEG-010: Verify tool.execute.before blocks destructive bash commands
- [ ] TEST-INTEG-011: Verify tool.execute.after records tool call in history
- [ ] TEST-INTEG-012: Verify message.updated triggers memory search on "remember when"
- [ ] TEST-INTEG-013: Verify message.updated triggers session close on "close the session"
- [ ] TEST-INTEG-014: Verify message.updated queues conversation turn to Redis
- [ ] TEST-INTEG-015: Verify file.edited runs 5-gate review on packages/*.py
- [ ] TEST-INTEG-016: Verify file.edited skips review for non-Python files
- [ ] TEST-INTEG-017: Verify file.edited queues file for KG sync after passing review
- [ ] TEST-INTEG-018: Verify experimental.session.compacting injects session context
Integration Tests: KG Query Pipeline
- [ ] TEST-INTEG-019: Verify kg_query bash wrapper invokes kg_query_inner.py via uv run
- [ ] TEST-INTEG-020: Verify kg_query_inner.py connects to Neo4j and returns results
- [ ] TEST-INTEG-021: Verify project scoping correctly anchors File queries to Project node
- [ ] TEST-INTEG-022: Verify project scoping correctly anchors Spec queries to Project node
- [ ] TEST-INTEG-023: Verify end-to-end Cypher query execution via plugin kg-query tool
Integration Tests: Session Management End-to-End
- [ ] TEST-INTEG-024: Verify full session lifecycle: create -> log work -> log achievement -> end
- [ ] TEST-INTEG-025: Verify session close via message triggers proper end sequence
- [ ] TEST-INTEG-026: Verify git achievements extracted and stored in session
- [ ] TEST-INTEG-027: Verify context.json updated correctly after session operations
Integration Tests: Code Review End-to-End
- [ ] TEST-INTEG-028: Verify valid Python file passes all 5 gates
- [ ] TEST-INTEG-029: Verify file with syntax error blocked at Gate 1
- [ ] TEST-INTEG-030: Verify file with lint errors blocked at Gate 2
- [ ] TEST-INTEG-031: Verify file with type errors reported at Gate 3
- [ ] TEST-INTEG-032: Verify file with high complexity reported at Gate 4
- [ ] TEST-INTEG-033: Verify file with naming violations reported at Gate 5
- [ ] TEST-INTEG-034: Verify blocked edit throws Error with fix suggestions
Integration Tests: Redis Queue Operations
- [ ] TEST-INTEG-035: Verify KG sync queue accepts file paths via SADD
- [ ] TEST-INTEG-036: Verify KG sync queue reports count via SCARD
- [ ] TEST-INTEG-037: Verify KG sync queue flushed via SPOP loop
- [ ] TEST-INTEG-038: Verify conversation queue accepts turns via LPUSH
- [ ] TEST-INTEG-039: Verify conversation queue reports depth via LLEN
- [ ] TEST-INTEG-040: Verify conversation queue flushed via LPOP loop
Integration Tests: Deployment
- [ ] TEST-INTEG-041: Verify install.sh creates all target directories
- [ ] TEST-INTEG-042: Verify install.sh copies agents to ~/.opencode/agents/
- [ ] TEST-INTEG-043: Verify install.sh copies commands to ~/.opencode/commands/
- [ ] TEST-INTEG-044: Verify install.sh copies plugins to ~/.opencode/plugins/
- [ ] TEST-INTEG-045: Verify install.sh copies tools to ~/.opencode/tools/
- [ ] TEST-INTEG-046: Verify install.sh copies config to ~/.config/opencode/
- [ ] TEST-INTEG-047: Verify deployed kg_query tool is executable
- [ ] TEST-INTEG-048: Verify deployed Python tools have correct shebang lines
Other tracked files
specs/021-opencode-integration/compliance-audit.md
Full spec text
Verbatim from specs/021-opencode-integration/spec.md; headings are pushed down two levels.
SPEC-021: OpenCode Integration
Metadata
- Spec ID: 021-opencode-integration
- Title: OpenCode Integration
- Version: 1.0.0
- Author: Mohamed
- Status: Complete
- Created: 2026-03-29
- Last Updated: 2026-03-29
- Priority: P1
- Components: OrchestrataPlugin, AutoKGContextAgent, KGContextAgent, QueryKGCommand, KGQueryTools
- Dependencies: OpenCode CLI, Bun runtime, Neo4j 5.0+, Redis 7.0+, @opencode-ai/plugin@1.3.3, session_cli.py
Overview
What
A comprehensive TypeScript plugin (3,234 lines) and supporting agents, tools, and commands that integrate OpenCode with the Orchestrata project. The plugin provides session management, code quality enforcement via a 5-gate review pipeline, deception detection, knowledge graph context injection, conversation tracking, and 24 custom tools accessible from within OpenCode sessions.
Why
- OpenCode needs project-specific intelligence to work effectively with Orchestrata's 19-package monorepo architecture
- The knowledge graph (558K+ nodes, 548K+ relationships) contains rich context about files, classes, functions, specs, and requirements that should be injected automatically into the LLM context
- Code quality standards (no mocking, absolute imports, max 40-line functions, snake_case naming) need automated enforcement at edit time to prevent regressions
- Session lifecycle must be tracked consistently across both Claude Code and OpenCode via the same
context.jsonsource of truth - Deception detection is required because LLMs sometimes claim actions (file creation, command execution, file reading) they did not actually perform
- Development policies (use
uvnotpip, no bareexcept, no hardcoded secrets) need automated enforcement before code reaches CI
How
- A single TypeScript plugin (
orchestrata.ts) hooks into 7 OpenCode lifecycle events to provide enforcement, context injection, and session management - The plugin exports
OrchestrataPluginwhich activates for any project under/home/mohamed/workspacethat hascontext.json - 24 custom tools exposed via the
toolexport give the LLM direct access to session operations, KG queries, conversation tracking, and code review - 2 OpenCode agents (auto-kg-context, kg-context-agent) provide automatic and manual knowledge graph context injection
- 1 slash command (
/query-kg) enables interactive Cypher queries against Neo4j - 5 Python tools provide varying levels of Neo4j query capability with project scoping
- Deployment via
install.shcopies artifacts to~/.opencode/and~/.config/opencode/
User Stories
Added 2026-08-02 (spec-consolidation pilot): binds the flat FR list below to actor-driven usage scenarios (SPEC-102 template). Each story names the FRs it exercises, so every requirement has a "who triggers it and why" narrative.
- US-021-01 — Consistent session lifecycle. As a developer, when I open or
close an OpenCode session in a project that has
context.json, the plugin auto-starts and auto-ends session tracking against that samecontext.json, so session state stays consistent across Claude Code and OpenCode. — FR-001, FR-002, FR-003. - US-021-02 — Automatic project context. As the LLM coding agent, when I begin work, the platform injects project-scoped knowledge-graph context (files, classes, functions, specs, requirements) into my prompt automatically, so I reason about the real codebase rather than guessing. — FR-004, FR-010, FR-016.
- US-021-03 — Edit-time quality enforcement. As a developer, when the agent edits
code, a 5-gate review pipeline runs and blocks errors and policy violations before they
reach CI, so regressions (mocking, relative imports, oversized functions, hardcoded
secrets,
pip/bare-except) are prevented at the source. — FR-005, FR-006, FR-008. - US-021-04 — Deception detection. As a developer, when the agent claims an action (file created, command executed, file read), the platform verifies it actually happened, so I am not misled by unperformed actions. — FR-007.
- US-021-05 — In-session tooling. As the LLM coding agent, I have custom tools for session operations, KG queries, conversation tracking, and code review directly inside the session, so I can act on Orchestrata state without leaving OpenCode. — FR-009, FR-011, FR-012.
- US-021-06 — Durable, bounded session record. As the Orchestrata platform, I persist every conversation turn, create git checkpoints, throttle noisy reads, and monitor MCP health across the session, so work is auditable, recoverable, and resource-bounded. — FR-013, FR-014, FR-015, FR-017.
Terminology
| Term | Definition |
|---|---|
| OpenCode | An AI-powered code editor CLI that supports plugins, agents, tools, and commands |
| OrchestrataPlugin | The main TypeScript plugin export that hooks into OpenCode lifecycle events |
| 5-Gate Review | The automated code review pipeline: syntax, lint, runtime/security, complexity, naming/design |
| Deception Detection | Analysis that compares claimed actions in LLM responses against actual tool call history |
| KG Context Injection | Automatic enrichment of file reads with knowledge graph metadata (classes, functions, specs) |
| Session CLI | Python CLI (session_cli.py) that manages session lifecycle in context.json |
| Tool Call History | In-memory array tracking all tool invocations for deception auditing at session end |
| Read Throttle | Per-session limit (50 reads) preventing excessive file reading without search-first patterns |
| KG Sync Queue | Redis set (orchestrata:kg:sync:queue) of file paths pending Neo4j synchronization |
| Conversation Queue | Redis list (orchestrata:conversation:queue) of conversation turns pending Neo4j storage |
| Project Scoping | Automatic Cypher query rewriting to restrict results to the current project's graph subgraph |
| Git Checkpoint | Automatic git commit before edit/write operations to enable rollback |
Data Models
Session Context Model
{
"session_seq": "number",
"purpose": "string",
"version": "string",
"branch": "string",
"testState": "string",
"status": "ACTIVE|IDLE|COMPLETE",
"created_at": "ISO8601",
"updated_at": "ISO8601"
}
KG File Node Model
{
"id": "string (UUID)",
"path": "string",
"language": "string",
"line_count": "number",
"size_bytes": "number",
"package": "string",
"classes": [
{
"name": "string",
"line_start": "number",
"line_end": "number",
"methods": ["string"]
}
],
"functions": [
{
"name": "string",
"line_start": "number",
"line_end": "number",
"is_async": "boolean"
}
]
}
Conversation Turn Model
{
"id": "string (UUID)",
"conversation_id": "string",
"turn_number": "number",
"role": "user|assistant",
"content": "string (max 2000)",
"timestamp": "ISO8601",
"platform": "opencode"
}
Code Review Result Model
{
"file_path": "string",
"gate": "1|2|3|4|5",
"status": "PASS|WARN|ERROR",
"errors": [
{
"line": "number",
"message": "string",
"rule": "string"
}
],
"warnings": [
{
"line": "number",
"message": "string",
"rule": "string"
}
]
}
Deception Detection Result Model
{
"session_id": "string",
"findings": [
{
"type": "ACTION_DECEPTION|ERROR_CONCEALMENT|FILE_READING_DECEPTION",
"severity": "CRITICAL|HIGH|MEDIUM",
"claim": "string",
"evidence": "string",
"tool_calls_required": ["string"],
"tool_calls_found": ["string"]
}
],
"audited_at": "ISO8601"
}
Functional Requirements
FR-001: Plugin Lifecycle Hooks
The OrchestrataPlugin MUST hook into all 7 OpenCode lifecycle events: session.created, session.idle, tool.execute.before, tool.execute.after, message.updated, file.edited, and experimental.session.compacting.
FR-002: Session Auto-Start
On session.created, the plugin MUST automatically start or resume a session via session_cli.py and display session information including seq, purpose, version, branch, and test state.
FR-003: Session Auto-End
On session.idle, the plugin MUST automatically end the session with git-extracted achievements, flush the KG sync queue, flush the conversation queue, and clear session state.
FR-004: KG Context Injection
On file reads within the Orchestrata project directory, the plugin MUST inject knowledge graph context including classes, functions, traceability links, and inheritance hierarchy into tool arguments as _orchestrata_context.
FR-005: 5-Gate Code Review Pipeline
On file.edited for Python files in packages/, the plugin MUST execute a 5-gate code review: Gate 1 (syntax/format), Gate 2 (lint), Gate 3 (runtime/security), Gate 4 (complexity/nesting), Gate 5 (naming/design).
FR-006: Error Blocking
Code review errors MUST block the edit and force the agent to fix issues before proceeding. Warnings MUST be displayed but not block the edit.
FR-007: Deception Detection
On session.idle, the plugin MUST analyze the assistant's final message against tool call history to detect ACTION_DECEPTION, ERROR_CONCEALMENT, and FILE_READING_DECEPTION with appropriate severity levels.
FR-008: Policy Enforcement
The plugin MUST enforce development policies during tool.execute.before: testing policy (block mocking), import policy (block relative imports), development policy (block pip), bash safety (block destructive patterns), write policy (block ~/.claude/plans/).
FR-009: Custom Tools Availability
All 24 custom tools (9 session, 12 KG, 3 conversation) MUST be available and functional within OpenCode sessions when the OrchestrataPlugin is active.
FR-010: KG Query Project Scoping
All KG query tools MUST automatically scope Cypher queries to the current project by anchoring through the Project node relationship chain.
FR-011: Redis Queue Management
The plugin MUST use Redis SET orchestrata:kg:sync:queue for KG sync pending files and LIST orchestrata:conversation:queue for conversation turns pending Neo4j storage.
FR-012: Memory Search Trigger
On message.updated, the plugin MUST detect "remember when" and 7 other trigger patterns, extract the topic, search last 20 sessions, and inject top 10 matches as context.
FR-013: Read Throttling
The plugin MUST enforce a per-session read limit of 50 file reads to prevent excessive file scanning without search-first patterns.
FR-014: Git Checkpoint Creation
Before any edit or write operation, the plugin MUST create a git checkpoint to enable rollback on failure.
FR-015: Conversation Storage
User and assistant messages MUST be queued to Redis and flushed to Neo4j on session close, creating Conversation and ConversationTurn nodes with platform="opencode".
FR-016: KG Sync Daemon
The plugin MUST support background KG synchronization via a daemon process that can be started, stopped, and queried for status.
FR-017: MCP Health Monitoring
The plugin MUST check MCP server health (document-reader at port 3456, document-writer at port 3457) on session start and log availability.
Error Conditions
| ID | Condition | Handling |
|---|---|---|
| ERR-001 | Session CLI process error | Non-blocking, logged to client.app.log, session continues |
| ERR-002 | Neo4j connection timeout | Non-blocking, file read proceeds without KG context |
| ERR-003 | Redis connection refused | Non-blocking, KG sync and conversation storage skipped |
| ERR-004 | MCP health check server down | Non-blocking, logged as info, workflow continues |
| ERR-005 | Git checkpoint dirty worktree | Non-blocking, uses --no-verify with || true fallback |
| ERR-006 | Code review Python tool error | Non-blocking unless it's the review's own thrown error |
| ERR-007 | KG sync daemon process crash | Non-blocking, queue persists in Redis for retry |
| ERR-008 | Conversation Neo4j write failure | Non-blocking, turns remain in Redis queue |
| ERR-009 | Read throttle limit exceeded | Block further reads, prompt to use search tools first |
| ERR-010 | Policy violation detected | Throw descriptive error with suggested alternative |
| ERR-011 | Invalid Cypher query syntax | Return error message, do not execute against Neo4j |
| ERR-012 | KG query project not found | Return no results with "Project not found" message |
| ERR-013 | Session not found on status check | Return "No active session" message |
| ERR-014 | context.json parse error | Log error, treat as no session active |
| ERR-015 | Deception detection tool history unavailable | Skip deception audit, log info message |
| ERR-016 | Conversation queue full (>1000 items) | Drop oldest items, log warning |
| ERR-017 | KG sync queue full (>500 files) | Block new enqueues, log error |
| ERR-018 | Invalid session state transition | Log error, retain current state |
| ERR-019 | Tool argument JSON parse error | Return error to caller, do not execute tool |
| ERR-020 | Network timeout on git push | Retry once, then log failure and continue |
Non-Functional Requirements
Performance
- KG context injection MUST complete within 500ms per file read
- Code review pipeline MUST complete within 5 seconds per file
- Memory search MUST return results within 1 second
- Session start/end operations MUST complete within 2 seconds
Scalability
- Tool call history bounded to 100 entries per session
- Conversation queue bounded to 1000 items before dropping
- KG sync queue bounded to 500 files before blocking
Reliability
- All non-blocking failures logged with context
- Queue operations use Redis atomic commands
- Git checkpoints use
--no-verifyto prevent hook failures
Maintainability
- Plugin code follows TypeScript best practices
- Agent definitions in Markdown for easy editing
- Tool implementations modular with clear separation
Governance
Code Quality Governance
- 5-Gate Review: All Python edits in
packages/MUST pass through the 5-gate review pipeline before commit - Naming Standards: snake_case for functions, PascalCase for classes, UPPER_SNAKE for constants
- Complexity Limits: Max 10 branches, max 5 nesting depth, max 40 lines per function
Policy Governance
- Testing: Mocking patterns blocked in test files
- Imports: Relative imports prohibited
- Package Management: pip prohibited, uv required
- Secrets: Hardcoded secrets, passwords, API keys, tokens detected and flagged
Session Governance
- Lifecycle: All sessions MUST be tracked in
context.json - Achievements: Session end MUST extract achievements from git log
- Tracking: Tool usage history retained for deception auditing
Testing
Unit Tests
- Deception detection regex patterns tested against known cases
- Policy enforcement rules tested with sample code
- Read throttle counter tested with boundary values
Integration Tests
- Session lifecycle: create, update, end flow tested end-to-end
- KG context injection tested with mock Neo4j responses
- Queue operations tested with Redis test instance
E2E Tests
- Full session flow: start, work, remember-when search, close
- Code review pipeline tested with sample Python files
- Tool execution with policy enforcement
Test Coverage Targets
- Deception detection: 90%+ pattern coverage
- Policy enforcement: 100% of documented policies
- Session management: all lifecycle states covered
Integration Points
External Systems
| System | Integration Type | Protocol |
|---|---|---|
| Memgraph KG | Knowledge graph storage (orchkg database) |
Bolt (from active env profile; test fleet: bolt://10.53.2.10:7687) |
| Redis | Queue management | Redis protocol (from active env profile; test fleet: 10.53.2.11:6379) |
| OpenCode | Plugin/agent/command host | OpenCode plugin API |
| Git | Checkpoint/achievement extraction | Git CLI |
| Session CLI | Session management | Python CLI (subprocess) |
Internal Modules
| Module | Purpose | Dependency |
|---|---|---|
| orchestrata.ts | Main plugin | @opencode-ai/plugin@1.3.3 |
| session_cli.py | Context.json management | Python 3.14t |
| kg_query_inner.py | KG queries with scoping | neo4j driver (Bolt, Memgraph) |
| sync_ast_to_graph.py | KG synchronization | Redis, Memgraph KG |
Success Criteria
Core Functionality
- [ ] Plugin loads and hooks into all 7 lifecycle events
- [ ] Session auto-start/end works without manual intervention
- [ ] KG context injected on file reads for Orchestrata files
- [ ] 5-gate code review executes on every Python edit in packages/
- [ ] Policy enforcement blocks prohibited patterns
Tool Availability
- [ ] All 24 custom tools functional and documented
- [ ] KG query tools scope results to current project
- [ ] Session tools work with context.json
Quality Assurance
- [ ] Deception detection identifies all 3 claim types
- [ ] Memory search returns relevant past sessions
- [ ] Read throttle prevents runaway file scanning
Integration
- [ ] Redis queues persist across session states
- [ ] Neo4j stores conversation history correctly
- [ ] Git checkpoints created before edits
Performance
- [ ] KG context injection < 500ms
- [ ] Code review < 5 seconds
- [ ] Session operations < 2 seconds
User Scenarios & Stories
US-001: Automatic KG Context Injection (P0)
As a developer using OpenCode on the Orchestrata project I want file reads and searches to automatically include knowledge graph context So that the LLM understands the file's classes, functions, specs, and relationships without manual queries
Acceptance Criteria:
- [ ] File reads on Orchestrata project files trigger KG context lookup
- [ ] Context includes classes defined in the file with line ranges
- [ ] Context includes functions defined in the file with async flags
- [ ] Context includes traceability links to requirements and specs
- [ ] Context includes inheritance hierarchy for classes in the file
- [ ] KG context is injected as
_orchestrata_contextin tool args - [ ] Context injection is non-blocking (failures do not prevent file reads)
US-002: Session Management (P0)
As a developer using OpenCode
I want sessions to auto-start on connection and auto-close on idle
So that all work is tracked in context.json without manual intervention
Acceptance Criteria:
- [ ]
session.createdhook auto-starts or resumes a session via session CLI - [ ] Session info (seq, purpose, version, branch, tests) displayed on start
- [ ] Pending deferred work items shown on session start (top 5)
- [ ]
session.idlehook auto-ends the session with git-extracted achievements - [ ] Session state cleared (tool history, read count) on session end
- [ ] KG sync queue flushed on session close
- [ ] Conversation queue flushed on session close
- [ ] Project state updated to ACTIVE on session start
US-003: Code Quality Enforcement (P0)
As a developer editing Python files in packages/
I want a 5-gate code review to run automatically on every file edit
So that syntax errors, lint violations, security issues, complexity, and naming problems are caught immediately
Acceptance Criteria:
- [ ] Gate 1 (Syntax & Format):
py_compile,black --check,isort --checkall pass - [ ] Gate 2 (Lint):
flake8with E/F/W/C90 selectors, max-line-length 88, ignoring E203/W503/E501 - [ ] Gate 3 (Runtime & Security):
mypy, module import check, hardcoded secrets/passwords/API keys/tokens detection, debug print detection, temporary comment detection, bareexcept:detection - [ ] Gate 4 (Complexity & Nesting): branch count limit 10 (error) / 7 (warn), nesting depth limit 5 (error) / 4 (warn), line length > 100 chars warning, function size > 40 lines warning
- [ ] Gate 5 (Naming & Design): snake_case for functions, PascalCase for classes, UPPER_SNAKE for constants, god object detection (> 20 methods), feature envy detection (> 15 self references)
- [ ] Errors block the edit and force the agent to fix issues before proceeding
- [ ] Warnings are displayed but do not block the edit
- [ ] Quick-fix suggestions (black, isort commands) shown in error output
- [ ] Only Python files under
packages/trigger the review
US-004: Deception Detection (P1)
As a user reviewing LLM work I want the system to detect when the LLM claims actions it did not perform So that false claims about file creation, command execution, or file reading are flagged
Acceptance Criteria:
- [ ] ACTION_DECEPTION (CRITICAL): Detected when LLM claims file creation without Write/Edit tool usage
- [ ] ACTION_DECEPTION (CRITICAL): Detected when LLM claims command execution without Bash tool usage
- [ ] FILE_READING_DECEPTION (HIGH): Detected when LLM claims file reading without Read/Grep tool usage
- [ ] ERROR_CONCEALMENT (CRITICAL): Detected when tool errors are not acknowledged in the response
- [ ] Quoted content (code blocks, inline code, blockquotes) excluded from deception analysis
- [ ] Deception audit report generated on
session.idlewith severity icons and evidence - [ ] Tool call history tracked across the entire session (last 100 calls)
- [ ] Tool call history cleared on session end
US-005: Policy Enforcement (P0)
As a project maintainer I want development policies automatically enforced during tool execution So that mocking, relative imports, pip usage, and destructive commands are prevented
Acceptance Criteria:
- [ ] Testing policy:
unittest.mock,MagicMock,@patch,AsyncMock,Mock(),patch.objectblocked in test files - [ ] Import policy: relative imports (
from . import) blocked in all Python files - [ ] Development policy:
pip install,pip3 install,pip syncblocked withuvsuggestions - [ ] Development policy:
requirements.txtreferences blocked withpyproject.tomlsuggestion - [ ] Bash safety:
rm -rf /, fork bombs,>/dev/nulldestructive patterns blocked - [ ] Write policy: writes to
~/.claude/plans/blocked with redirect to~/workspace/orchestrata/plans/ - [ ] Policy violations throw descriptive errors with suggested alternatives
US-006: Custom Tools (P1)
As a developer using OpenCode I want 24 custom tools for session management, KG queries, and code review So that the LLM can programmatically interact with Orchestrata infrastructure
Acceptance Criteria:
- [ ] Session tools (9): session-status, session-begin, session-end, session-log-work, session-log-achievement, session-add-work, session-complete-work, session-update-state, session-log-choice
- [ ] KG tools (12): kg-query, kg-sync, kg-queue-status, kg-flush-queue, kg-file-context, kg-daemon-start, kg-daemon-stop, kg-daemon-status, kg-find-file, kg-find-entity, kg-stats, kg-cxp-thread
- [ ] Conversation tools (3): conv-sync, conv-status, conv-query
- [ ] Code review tools (2): code-review, code-fix (if applicable)
- [ ] All tools have description and typed args
- [ ] KG tools only activate for the Orchestrata project directory
- [ ] Session tools work for any project with
context.json
US-007: Conversation Tracking (P2)
As the system I want conversation turns stored in Neo4j via Redis queue So that session interactions are preserved for analysis and memory search
Acceptance Criteria:
- [ ] User messages queued to Redis list
orchestrata:conversation:queueonmessage.updated - [ ] Messages truncated to 2000 characters before queuing
- [ ] Queue flushed to Neo4j on session close, creating Conversation and ConversationTurn nodes
- [ ] ConversationTurn nodes linked to Conversation via HAS_TURN relationship
- [ ] Conversation nodes keyed by
opencode-{session_seq} - [ ] Platform field set to "opencode" on all nodes
- [ ] Queue processing is non-blocking (failures do not interrupt session close)
US-008: Memory Search (P2)
As a developer asking "remember when..." I want the system to search session history for matching context So that previous decisions, achievements, and work logs are recalled automatically
Acceptance Criteria:
- [ ] Trigger phrases: "remember when", "do you remember", "recall when", "remember that", "we discussed", "we talked about", "last time we", "what happened with"
- [ ] Topic extracted from text after the trigger phrase
- [ ] Search covers last 20 sessions in
context.json - [ ] Matches found in session purpose, achievements, and work logs
- [ ] Top 10 results injected as context with session number, date, and match type
- [ ] Short words (< 3 characters) excluded from search terms
- [ ] No-match case returns "No matching sessions found" message
US-009: KG Sync Daemon (P1)
As the system I want modified files queued for background KG synchronization So that the knowledge graph stays current as code evolves during sessions
Acceptance Criteria:
- [ ] Files passing code review are added to Redis set
orchestrata:kg:sync:queue - [ ] KG sync triggered in background on
session.createdviasync_monorepo_to_neo4j.py - [ ] Queue flushed synchronously on session close using
FileSynchronizer - [ ] Queue count available via
kg-queue-statustool - [ ] Queue can be manually flushed via
kg-flush-queuetool - [ ] Daemon start/stop/status tools available for manual control
- [ ] Queue operations are non-blocking (failures do not interrupt workflow)
US-010: Agent Intelligence (P1)
As a developer working with OpenCode I want two agents that automatically detect context triggers and query the KG So that relevant project knowledge is available without manual Cypher queries
Acceptance Criteria:
- [ ] Auto KG Context Agent activates on file paths, class/function names, spec IDs (SPEC-NNN, REQ-NNN)
- [ ] Auto agent queries: file info, classes, functions, traceability links, inheritance hierarchy
- [ ] KG Context Agent provides manual complement for architectural relationship queries
- [ ] Both agents connect to the operational KG (Memgraph,
orchkgdatabase) at the active env profile's endpoint (test fleet:bolt://10.53.2.10:7687) - [ ] Agent results formatted for LLM consumption with clear labels
- [ ] Agents run transparently without requiring explicit user invocation
Architecture
Plugin Architecture (3,234 lines)
opencode/plugins/orchestrata.ts
├── State Management
│ ├── toolCallHistory[]: Tool call tracking for deception detection
│ ├── readCount: File read throttle counter (limit: 50/session)
│ └── MCP_SERVERS[]: Health check endpoints for document-reader/writer
├── Helper Functions
│ ├── checkMcpHealth(): MCP server availability check
│ ├── removeQuotedContent(): Strip code blocks/quotes for deception analysis
│ ├── detectDeception(): Compare claimed actions vs actual tool usage
│ ├── enforceTestingPolicy(): Block mocking patterns in test files
│ ├── enforceImportPolicy(): Block relative imports
│ └── enforceDevelopmentPolicy(): Block pip, require uv
└── Lifecycle Hooks (7)
├── session.created: Auto-start session, inject context, start KG sync
├── session.idle: Deception audit, session close, queue flush
├── tool.execute.before: KG injection, policies, git checkpoint, bash safety
├── tool.execute.after: Operation logging, deception tracking
├── message.updated: Remember-when search, session close, conversation storage
├── file.edited: 5-gate code review, KG sync queue
└── experimental.session.compacting: Custom session context injection
Hook Mapping: Claude Code to OpenCode
| Claude Code Hook | OpenCode Hook | Behavior |
|---|---|---|
| PreToolUse | tool.execute.before | Same concept: intercept before tool execution |
| PostToolUse | tool.execute.after | Same concept: log after tool execution |
| SessionStart | session.created | Different naming, same lifecycle event |
| Stop | session.idle | Different naming, same lifecycle event |
| UserPromptSubmit | message.updated | Broader scope in OpenCode (all message updates) |
| OpenCode-Only | file.edited | OpenCode-specific: triggers on any file edit |
| OpenCode-Only | experimental.session.compacting | OpenCode-specific: context injection during compaction |
Deployment Layout
Source:
open-code/
├── agents/
│ ├── auto-kg-context.md # Auto KG context agent definition
│ └── kg-context-agent.md # Manual KG context agent definition
├── commands/
│ └── query-kg.md # /query-kg slash command definition
├── plugins/
│ └── orchestrata.ts # Main plugin (3,234 lines)
├── tools/
│ ├── kg_query # Bash wrapper for uv environment
│ ├── kg_query.py # Full-featured async query tool
│ ├── kg_query_inner.py # Core implementation with project scoping
│ ├── neo4j_query.py # Standalone direct query tool
│ └── simple_kg_query.py # Simplified connectivity test
├── install.sh # Deployment script
└── config/ # OpenCode configuration
Deployed:
~/.opencode/
├── agents/ # Agent definitions
├── commands/ # Command definitions
├── plugins/ # Plugin (compiled)
└── tools/ # Python query tools
~/.config/opencode/ # OpenCode config
Data Flow
┌──────────────────────┐
│ OpenCode Session │
└──────────┬───────────┘
│
┌──────────▼───────────┐
│ OrchestrataPlugin │
│ (orchestrata.ts) │
└──────────┬───────────┘
│
┌─────────────────────┼─────────────────────┐
│ │ │
┌────────▼────────┐ ┌────────▼────────┐ ┌────────▼────────┐
│ session_cli.py │ │ Memgraph KG │ │ Redis Queue │
│ (context.json) │ │ bolt://10.93. │ │ 10.53.2.11:6379│
│ │ │ 53.10:7687 │ │ │
│ - begin │ │ │ │ - kg:sync: │
│ - end │ │ - File nodes │ │ queue (SET) │
│ - log-work │ │ - Class nodes │ │ - conversation │
│ - status │ │ - Function │ │ :queue (LIST)│
│ - update-state │ │ - Requirement │ │ │
└─────────────────┘ │ - Spec nodes │ └─────────────────┘
│ - Conversation │
│ - Turn nodes │
└─────────────────┘
5-Gate Code Review Pipeline
File Edit (packages/*.py)
│
▼
┌─────────────────────────────────────────────────────┐
│ GATE 1: Syntax & Format │
│ py_compile → black --check → isort --check │
│ Errors: syntax errors, formatting violations │
├─────────────────────────────────────────────────────┤
│ GATE 2: Lint │
│ flake8 --select=E,F,W,C90 --max-line-length=88 │
│ Errors: E9xx, F63x, F72x (fatal) │
│ Warnings: other E/W/C codes │
├─────────────────────────────────────────────────────┤
│ GATE 3: Runtime & Security │
│ mypy (type check) → module import test │
│ Security: hardcoded passwords/keys/secrets/tokens │
│ Quality: debug prints, temporary comments, bare except │
│ Logging: missing logger, unlogged exceptions │
│ Traceability: @traces decorator presence │
├─────────────────────────────────────────────────────┤
│ GATE 4: Complexity & Nesting │
│ Branches: >10 error, >7 warn │
│ Nesting: >5 error, >4 warn │
│ Line length: >100 chars warn │
│ Function size: >40 lines warn │
├─────────────────────────────────────────────────────┤
│ GATE 5: Naming & Design │
│ Functions: must be snake_case │
│ Classes: must be PascalCase │
│ Constants: UPPER_SNAKE_CASE │
│ God objects: >20 methods warn │
│ Feature envy: >15 self references warn │
│ Patterns: singleton, factory, builder, dataclass │
└─────────────────────────────────────────────────────┘
│
▼
Errors? → Block edit, force fix
Warnings? → Display, allow edit
Pass? → Queue file for KG sync
Deception Detection Model
Tool Call History (per session, max 100)
│
▼
On session.idle:
│
├── Extract assistant's final message
├── Remove quoted content (```, `, >)
├── Check file creation claims → require Write/Edit in history
├── Check command execution claims → require Bash in history
├── Check file reading claims → require Read/Grep in history
├── Check for unacknowledged tool errors
│
▼
┌─────────────────────────────────┐
│ Findings (severity levels): │
│ CRITICAL: ACTION_DECEPTION │
│ CRITICAL: ERROR_CONCEALMENT │
│ HIGH: FILE_READING_DECEPTION │
└─────────────────────────────────┘
Examples
Plugin Activation Example
The OrchestrataPlugin automatically activates when OpenCode starts a session in the Orchestrata project:
// orchestrata.ts - Plugin activation check
import { OpenCodePlugin } from '@opencode-ai/plugin';
export const OrchestrataPlugin: OpenCodePlugin = {
name: 'orchestrata',
matches: (context) => {
const workspacePath = context.workspacePath;
return workspacePath.startsWith('/home/mohamed/workspace')
&& context.hasFile('context.json');
}
};
Session Lifecycle Example
# Session auto-starts on OpenCode connection (triggered by session.created hook)
$ opencode
# Session info displayed automatically:
# ┌─────────────────────────────────────────┐
# │ Session #42 | P1 | Active │
# │ Purpose: Implement SPEC-021 │
# │ Branch: feature/opencode-integration │
# │ Test State: 3/15 passing │
# └─────────────────────────────────────────┘
# Session auto-ends on "close the session" (triggered by session.idle hook)
> close the session
# Session close report:
# ┌─────────────────────────────────────────┐
# │ Session #42 Closed │
# │ Achievements: │
# │ - Added OrchestrataPlugin (3,234 LOC) │
# │ - Implemented 5-gate code review │
# │ - Added deception detection │
# │ Pushed to origin ✓ │
# └─────────────────────────────────────────┘
KG Context Injection Example
When reading a file in the Orchestrata project, KG context is automatically injected:
# Tool call: Read /home/mohamed/workspace/orchestrata/packages/core/traceability/__init__.py
# Request:
{
"filePath": "/home/mohamed/workspace/orchestrata/packages/core/traceability/__init__.py"
}
# Response (with _orchestrata_context injected):
{
"content": "...",
"_orchestrata_context": {
"file": {
"path": "/home/mohamed/workspace/orchestrata/packages/core/traceability/__init__.py",
"language": "python",
"line_count": 247
},
"classes": [
{
"name": "TraceabilityModule",
"line_start": 45,
"line_end": 189,
"methods": ["add_requirement", "link_spec", "query_graph", "export_trace"]
}
],
"functions": [
{
"name": "create_traceability_link",
"line_start": 12,
"line_end": 34,
"is_async": true
}
],
"spec_links": [
{"spec_id": "001", "requirement": "REQ-001-US-001-012"}
]
}
}
Code Review Pipeline Example
Editing a Python file triggers the 5-gate code review:
# File edit detected: packages/core/traceability/module.py
# GATE 1: Syntax & Format
$ py_compile packages/core/traceability/module.py
✓ PASS
$ black --check packages/core/traceability/module.py
✓ PASS
$ isort --check packages/core/traceability/module.py
✓ PASS
# GATE 2: Lint
$ flake8 packages/core/traceability/module.py --select=E,F,W,C90 --max-line-length=88
✓ PASS (0 errors, 2 warnings)
# GATE 3: Runtime & Security
$ mypy packages/core/traceability/module.py
✓ PASS
# Security scan:
✓ No hardcoded secrets detected
✓ No debug prints detected
✓ No temporary comments detected
# GATE 4: Complexity & Nesting
✓ Branches: 7 (warn threshold: 7)
✓ Nesting: 4 (warn threshold: 4)
✓ Line length: 2 warnings (> 100 chars)
✓ Function size: OK
# GATE 5: Naming & Design
✓ Functions: snake_case ✓
✓ Classes: PascalCase ✓
✓ Constants: UPPER_SNAKE_CASE ✓
# RESULT: PASS (2 warnings, 0 errors)
# File queued for KG sync: orchestrata:kg:sync:queue
Deception Detection Example
When the LLM claims actions not performed:
// session.idle hook triggers deception analysis
// Assistant's final message:
// "I've created the new authentication module and ran the tests."
// Tool call history (last 100):
// - Read: auth.py
// - Grep: "def authenticate"
// - Write: auth_test.py (contains test code)
// Deception detection result:
{
"session_id": "42",
"findings": [
{
"type": "ACTION_DECEPTION",
"severity": "CRITICAL",
"claim": "I've created the new authentication module",
"evidence": "No Write or Edit tool calls found in history for 'authentication module'",
"tool_calls_required": ["Write", "Edit"],
"tool_calls_found": ["Read", "Grep"]
},
{
"type": "ACTION_DECEPTION",
"severity": "CRITICAL",
"claim": "ran the tests",
"evidence": "No Bash tool calls found in history",
"tool_calls_required": ["Bash"],
"tool_calls_found": ["Write"]
}
],
"audited_at": "2026-04-09T15:32:00Z"
}
Policy Enforcement Example
Blocked patterns during tool execution:
# Testing policy violation (in test_file.py)
$ @patch('module.Class')
# ERROR: Mocking patterns blocked in test files
# Suggestion: Use real implementations or integration tests
# Import policy violation
$ from . import utils
# ERROR: Relative imports prohibited
# Suggestion: Use absolute imports: from package.utils import ...
# Development policy violation
$ pip install requests
# ERROR: pip prohibited - use uv
# Suggestion: uv add requests
# Bash safety violation
$ rm -rf /
# ERROR: Destructive command blocked
# Message logged to security team
# Write policy violation
$ Write: ~/.claude/plans/feature.md
# ERROR: Direct writes to ~/.claude/plans/ prohibited
# Suggestion: Write to ~/workspace/orchestrata/plans/ instead
KG Query Tools Example
# Using the /query-kg command
/query-kg "MATCH (f:File) RETURN f.path, f.language ORDER BY f.line_count DESC LIMIT 10"
/query-kg "MATCH (c:Class)-[:DEFINES_METHOD]->(m:Method) WHERE c.name = 'TraceabilityModule' RETURN m.name"
/query-kg "MATCH (s:Spec {id: '001'})-[:DEFINES_REQUIREMENT]->(r:Requirement) RETURN r.id, r.text"
Session Management Tools Example
# Check session status
> session-status
# ┌─────────────────────────────────────────┐
# │ Session #42 | P1 | Active │
# │ Purpose: Implement SPEC-021 │
# │ Branch: feature/opencode-integration │
# │ Test State: 3/15 passing │
# └─────────────────────────────────────────┘
# Log work
> session-log-work --desc "Implemented 5-gate review pipeline" --details ["Gate 1-3 complete", "Gate 4-5 remaining"]
# Log achievement
> session-log-achievement --item "Added deception detection (3 patterns)"
# Add deferred work
> session-add-work --text "Add memory search agent" --priority "P2"
# Complete work
> session-complete-work --text "Add memory search agent"
Memory Search Example
# User asks:
> Remember when we implemented the deception detection?
# Plugin detects "remember when" trigger, extracts topic: "deception detection"
# Searches last 20 sessions for matches
# Results injected into context:
# ┌─────────────────────────────────────────┐
# │ Memory Search: "deception detection" │
# │ ─────────────────────────────────────── │
# │ Session #38 (2026-04-01) │
# │ Match: purpose - "Add deception detection patterns" │
# │ Session #35 (2026-03-28) │
# │ Match: achievement - "Implemented action deception"│
# │ Session #31 (2026-03-25) │
# │ Match: work log - "Tested error concealment" │
# └─────────────────────────────────────────┘
Redis Queue Status Example
# Check KG sync queue
> kg-queue-status
# Pending files: 12
# Queue: [packages/core/module.py, packages/core/utils.py, ...]
# Check conversation queue
> conv-status
# Pending turns: 47
# Oldest: session-42, turn-3 (2 minutes ago)
# Newest: session-42, turn-49 (30 seconds ago)
# Flush queues
> kg-flush-queue
# Synced 12 files to Neo4j ✓
> conv-sync
# Flushed 47 conversation turns to Neo4j ✓
API Contracts
OrchestrataPlugin
interface OrchestrataPlugin {
// Lifecycle hooks
onSessionCreated(handler: (session: SessionContext) => Promise<void>): void;
onSessionIdle(handler: (session: SessionContext) => Promise<void>): void;
onToolExecuteBefore(handler: (tool: ToolCall) => Promise<ToolCall>): void;
onToolExecuteAfter(handler: (tool: ToolCall, result: ToolResult) => Promise<void>): void;
onMessageUpdated(handler: (message: Message) => Promise<void>): void;
onFileEdited(handler: (file: FileEdit) => Promise<FileEditResult>): void;
onSessionCompacting(handler: (context: SessionContext) => Promise<ContextInjection>): void;
}
interface SessionContext {
sessionSeq: number;
purpose: string;
version: string;
branch: string;
testState: string;
status: 'ACTIVE' | 'IDLE' | 'COMPLETE';
createdAt: string;
updatedAt: string;
}
interface ToolCall {
name: string;
arguments: Record<string, unknown>;
id: string;
timestamp: string;
}
interface ToolResult {
success: boolean;
output?: string;
error?: string;
}
interface FileEdit {
filePath: string;
content: string;
language: string;
}
interface FileEditResult {
allowed: boolean;
errors?: CodeIssue[];
warnings?: CodeIssue[];
}
interface CodeIssue {
line: number;
message: string;
rule: string;
severity: 'ERROR' | 'WARN';
}
interface ContextInjection {
additions: Record<string, unknown>;
priority: number;
}
Session CLI
# Session management commands
async def session_begin(purpose: str, objectives: list[str] = None) -> SessionContext:
"""Start a new session"""
async def session_end(achievements: list[str] = None, upcoming: list[str] = None) -> SessionCloseResult:
"""End current session"""
async def session_status() -> SessionStatus:
"""Get current session info"""
async def session_update_state(
version: str = None,
branch: str = None,
testState: str = None,
status: str = None
) -> SessionContext:
"""Update session state"""
async def session_log_work(desc: str, details: list[str] = None) -> WorkEntry:
"""Log a work entry"""
async def session_log_achievement(item: str) -> Achievement:
"""Log an achievement"""
async def session_add_work(text: str, priority: str = None, notes: str = None) -> WorkItem:
"""Add deferred work item"""
async def session_complete_work(text: str) -> WorkItem:
"""Mark work item as complete"""
async def session_log_choice(choice: str, reason: str) -> TechnicalChoice:
"""Log a technical decision"""
class SessionStatus(TypedDict):
session_seq: int
purpose: str
version: str
branch: str
testState: str
status: str
created_at: str
updated_at: str
class SessionCloseResult(TypedDict):
session_seq: int
achievements: list[str]
flush_kg_sync: bool
flush_conversation: bool
Knowledge Graph Client
class Neo4jKGClient:
async def connect(self, uri: str, username: str, password: str) -> None:
"""Connect to Neo4j instance"""
async def close(self) -> None:
"""Close connection"""
async def execute_query(
self,
query: str,
parameters: dict = None,
project_scope: str = None
) -> list[dict]:
"""Execute Cypher query with optional project scoping"""
async def get_file_context(self, path: str) -> KGFileContext:
"""Get KG context for a file"""
async def get_entity_context(self, name: str, entity_type: str = None) -> KGEntityContext:
"""Get KG context for class/function"""
async def get_traceability_links(
self,
file_path: str = None,
spec_id: str = None,
requirement_id: str = None
) -> list[TraceabilityLink]:
"""Get traceability links"""
async def get_inheritance_hierarchy(
self,
class_name: str,
depth: int = 3
) -> InheritanceChain:
"""Get class inheritance hierarchy"""
class KGFileContext(TypedDict):
id: str
path: str
language: str
line_count: int
size_bytes: int
package: str
classes: list[ClassInfo]
functions: list[FunctionInfo]
class ClassInfo(TypedDict):
name: str
line_start: int
line_end: int
methods: list[str]
class FunctionInfo(TypedDict):
name: str
line_start: int
line_end: int
is_async: bool
class TraceabilityLink(TypedDict):
source_type: str
source_id: str
target_type: str
target_id: str
relationship: str
class InheritanceChain(TypedDict):
class_name: str
ancestors: list[str]
depth: int
Redis Queue Manager
class QueueManager:
async def enqueue_kg_sync(self, file_path: str) -> int:
"""Add file to KG sync queue (returns queue size)"""
async def dequeue_kg_sync(self, count: int = None) -> list[str]:
"""Remove and return files from KG sync queue"""
async def get_kg_queue_size(self) -> int:
"""Get KG sync queue size"""
async def flush_kg_queue(self) -> int:
"""Flush all items from KG sync queue (returns count)"""
async def enqueue_conversation(
self,
conversation_id: str,
turn: ConversationTurn
) -> int:
"""Add turn to conversation queue"""
async def dequeue_conversation(
self,
count: int = None
) -> list[ConversationTurn]:
"""Remove and return turns from conversation queue"""
async def get_conversation_queue_size(self) -> int:
"""Get conversation queue size"""
async def flush_conversation_queue(self) -> list[ConversationTurn]:
"""Flush all turns from conversation queue"""
class ConversationTurn(TypedDict):
id: str
conversation_id: str
turn_number: int
role: str
content: str
timestamp: str
platform: str
Code Review Pipeline
class CodeReviewPipeline:
async def review_file(self, file_path: str, content: str) -> CodeReviewResult:
"""Execute 5-gate code review"""
async def gate1_syntax_format(self, content: str) -> GateResult:
"""Gate 1: Syntax & Format (py_compile, black, isort)"""
async def gate2_lint(self, content: str) -> GateResult:
"""Gate 2: Lint (flake8)"""
async def gate3_runtime_security(self, content: str) -> GateResult:
"""Gate 3: Runtime & Security (mypy, secrets, etc)"""
async def gate4_complexity(self, content: str) -> GateResult:
"""Gate 4: Complexity & Nesting"""
async def gate5_naming_design(self, content: str) -> GateResult:
"""Gate 5: Naming & Design"""
class CodeReviewResult(TypedDict):
file_path: str
gates: list[GateResult]
blocked: bool
errors: list[CodeIssue]
warnings: list[CodeIssue]
class GateResult(TypedDict):
gate: int
name: str
status: 'PASS' | 'FAIL' | 'WARN'
errors: list[CodeIssue]
warnings: list[CodeIssue]
Policy Enforcement
class PolicyEnforcer:
def enforce_testing_policy(self, content: str, file_path: str) -> PolicyResult:
"""Block mocking patterns in test files"""
def enforce_import_policy(self, content: str) -> PolicyResult:
"""Block relative imports"""
def enforce_development_policy(self, arguments: dict) -> PolicyResult:
"""Block pip, require uv"""
def enforce_bash_safety(self, command: str) -> PolicyResult:
"""Block destructive bash patterns"""
def enforce_write_policy(self, file_path: str) -> PolicyResult:
"""Block writes to prohibited paths"""
class PolicyResult(TypedDict):
allowed: bool
violation: str
suggestion: str
Deception Detection
class DeceptionDetector:
def analyze(
self,
final_message: str,
tool_call_history: list[ToolCall]
) -> DeceptionReport:
"""Analyze message for deception claims"""
def check_file_creation_claims(
self,
message: str,
tool_history: list[ToolCall]
) -> list[DeceptionFinding]:
"""Detect false file creation claims"""
def check_command_claims(
self,
message: str,
tool_history: list[ToolCall]
) -> list[DeceptionFinding]:
"""Detect false command execution claims"""
def check_file_reading_claims(
self,
message: str,
tool_history: list[ToolCall]
) -> list[DeceptionFinding]:
"""Detect false file reading claims"""
def check_error_concealment(
self,
message: str,
tool_results: list[ToolResult]
) -> list[DeceptionFinding]:
"""Detect unacknowledged tool errors"""
class DeceptionReport(TypedDict):
session_id: str
findings: list[DeceptionFinding]
audited_at: str
class DeceptionFinding(TypedDict):
type: 'ACTION_DECEPTION' | 'ERROR_CONCEALMENT' | 'FILE_READING_DECEPTION'
severity: 'CRITICAL' | 'HIGH' | 'MEDIUM'
claim: str
evidence: str
tool_calls_required: list[str]
tool_calls_found: list[str]
Custom Tools Reference
Session Tools (9)
| Tool | Description | Args |
|---|---|---|
session-status |
Show current session info with formatting | none |
session-begin |
Start a new session | purpose: string, objectives?: string[] |
session-end |
End current session | achievements?: string[], upcoming?: string[] |
session-log-work |
Log a work entry | desc: string, details?: string[] |
session-log-achievement |
Log a completed achievement | item: string |
session-add-work |
Add a deferred work item | text: string, priority?: string, notes?: string |
session-complete-work |
Mark work item as done | text: string |
session-update-state |
Update project state | version?: string, branch?: string, testState?: string, status?: string |
session-log-choice |
Log a technical decision | choice: string, reason: string |
KG Tools (12)
| Tool | Description | Args |
|---|---|---|
kg-query |
Execute Cypher query against Neo4j | query: string |
kg-sync |
Trigger full KG sync via sync_monorepo_to_neo4j.py |
none |
kg-queue-status |
Check pending files in sync queue | none |
kg-flush-queue |
Manually flush the KG sync queue | none |
kg-file-context |
Get KG context for a specific file | path: string |
kg-daemon-start |
Start the KG sync daemon | none |
kg-daemon-stop |
Stop the KG sync daemon | none |
kg-daemon-status |
Check KG sync daemon status | none |
kg-find-file |
Find files by name pattern in KG | pattern: string |
kg-find-entity |
Find entities (classes/functions) by name | name: string |
kg-stats |
Get KG statistics (node/relationship counts) | none |
kg-cxp-thread |
Query CXP thread packets | thread_id: string |
Conversation Tools (3)
| Tool | Description | Args |
|---|---|---|
conv-sync |
Flush conversation queue to Neo4j | none |
conv-status |
Check conversation queue depth | none |
conv-query |
Query stored conversations | query: string |
KG Query Tools (Python)
Tool Hierarchy
kg_query (bash wrapper)
└── kg_query_inner.py (invoked via uv run)
└── Neo4jClient from orchestrata.knowledge
kg_query.py (standalone async)
└── Neo4jClient from orchestrata.knowledge
neo4j_query.py (standalone async)
└── Neo4jClient from orchestrata.knowledge (with fallback mock)
simple_kg_query.py (connectivity test)
└── Neo4jClient from orchestrata.knowledge
Project Scoping (kg_query_inner.py)
The inner query tool automatically rewrites Cypher queries to scope results to the current project:
- File path pattern:
MATCH (f:File {path: $path})rewritten to anchor through(p:Project)-[:HAS_FILE]->(f:File) - Spec ID pattern:
MATCH (s:Spec {id: $id})rewritten to anchor through(p:Project)-[:HAS_SPEC]->(s:Spec) - Requirement pattern:
MATCH (r:Requirement {id: $id})rewritten to anchor through(p:Project)-[:HAS_REQUIREMENT]->(r:Requirement) - General MATCH: Adds
WHERE EXISTS { MATCH (p)-[r]->() }clause checking 30+ relationship types from the project node - Fallback: Wraps unrecognized queries in project context
Agent Definitions
Auto KG Context Agent (auto-kg-context.md)
Purpose: Automatically provides knowledge graph context without explicit user commands.
Trigger Patterns:
- File references: direct paths (
/home/mohamed/workspace/orchestrata/...), relative paths (packages/...), file mentions - Code elements: class names (
TraceabilityModule), function names (create_file_node), method names - Specification references:
SPEC-001,001-kernel,US-001,REQ-001,REQ-004-US-001-012 - Architectural concepts: sessions, Volks, CXP packets, governance rules, PAM++
Automatic Queries:
- File info: path, language, line count, size
- Classes in file: name, line start/end
- Functions in file: name, line start/end, async flag
- Traceability links: code element to requirement
- Inheritance hierarchy: class to ancestor chain (depth 3)
- Entity search: name-based lookup with file location
- Relationship traversal: inbound and outbound relationships (limit 10)
KG Context Agent (kg-context-agent.md)
Purpose: Manual complement to the auto agent, focusing on architectural relationships and spec-to-code traceability.
Activation: Triggered by mentions of files, classes, functions, code structure questions, refactoring requests, and specification inquiries.
Query Types:
- File-to-class and file-to-function mappings
- Inheritance hierarchies (depth 2)
- Traceability links from code to requirements
- Specification details and requirement listings
- Entity search by name pattern
Commands
/query-kg
Usage: /query-kg <cypher_query> [parameters_json]
Description: Interactive Cypher query execution against the Neo4j knowledge graph.
Examples:
/query-kg "MATCH (n) RETURN count(n) as count"
/query-kg "MATCH (f:File {path: $path}) RETURN f.path, f.line_count, f.language"
'{"path": "/home/mohamed/.../traceability/__init__.py"}'
/query-kg "MATCH (s:Spec {id: $spec_id})-[:DEFINES_REQUIREMENT]->(r:Requirement)
RETURN r.id, r.text" '{"spec_id": "001"}'
/query-kg "MATCH (s:Spec) RETURN s.id, s.title ORDER BY s.id"
Connection: from the active env profile (test fleet: bolt://10.53.2.10:7687), database: orchkg (auth-less Memgraph)
Configuration
Infrastructure
| Service | Address | Purpose |
|---|---|---|
| Memgraph KG | From active env profile (test fleet: bolt://10.53.2.10:7687) | Knowledge graph storage (orchkg database) |
| Redis | From active env profile (test fleet: 10.53.2.11:6379) | Queue storage (KG sync, conversations) |
| MCP Reader | http://localhost:3456/health | Document reader server |
| MCP Writer | http://localhost:3457/health | Document writer server |
Redis Keys
| Key | Type | Purpose |
|---|---|---|
orchestrata:kg:sync:queue |
SET | Files pending KG synchronization |
orchestrata:conversation:queue |
LIST | Conversation turns pending Neo4j storage |
Deployment
# Install from project root
cd open-code && ./install.sh
# Deploys to:
# ~/.opencode/agents/
# ~/.opencode/commands/
# ~/.opencode/plugins/
# ~/.opencode/tools/
# ~/.config/opencode/
Dependencies
| Dependency | Version | Purpose |
|---|---|---|
| @opencode-ai/plugin | 1.3.3 | Plugin framework API |
| Bun | latest | TypeScript runtime |
| Python 3.14t | free-threaded | KG query tools, session CLI |
| neo4j (Python) | 5.x | Neo4j driver for Python tools |
| redis (Python) | 4.x | Redis client for queue operations |
| uv | latest | Python package manager |
KG Statistics
| Category | Count |
|---|---|
| Total Nodes | 558,000+ |
| Total Relationships | 548,000+ |
| Packages | 23 |
| Files | 439 |
| Classes | 934 |
| Functions | 522 |
| CXP Packets | 223,000+ |
| Test Results | 156,000+ |
| Sessions | 6,000+ |
| Requirements | 2,700+ |
| User Stories | 147 |
| Prolog Rules | 28,000+ |
Remember-When Memory Search
Trigger Phrases
| Pattern | Regex |
|---|---|
| "remember when" | /remember\s+when/i |
| "do you remember" | /do\s+you\s+remember/i |
| "recall when" | /recall\s+when/i |
| "remember that" | /remember\s+that/i |
| "we discussed" | /we\s+discussed/i |
| "we talked about" | /we\s+talked\s+about/i |
| "last time we" | /last\s+time\s+we/i |
| "what happened with" | /what\s+happened\s+with/i |
Search Algorithm
- Extract topic text after the trigger phrase
- Split topic into words, filter out words with fewer than 3 characters
- Load last 20 sessions from
context.json - For each session (newest first), check:
- Purpose field for word matches
- Achievements list for word matches
- Work log entries for word matches
- Collect up to 10 matches with session number, date, match type, and matched text
- Inject results into output context as a formatted block
Session Close Sequence
Detection
Triggers on exact or suffix matches: "close the session", "cts", "cs", "end session", "finish session"
Steps
- Validate: Check for active session via
session_cli.py status --json - Extract Achievements:
git log --oneline --since="2 hours ago" -20, filter out checkpoint commits, take top 10 - End Session:
session_cli.py end --achievements "..." - Push Branch:
git push origin HEAD - Report: Display formatted close report with session number, achievements, push status
- Clear State: Reset
toolCallHistoryandreadCount
Error Handling Strategy
| Component | Failure Mode | Behavior |
|---|---|---|
| Session CLI | Process error | Non-blocking, logged to client.app.log |
| Neo4j KG query | Connection timeout | Non-blocking, file read proceeds without context |
| Redis queue | Connection refused | Non-blocking, sync/conversation storage skipped |
| MCP health check | Server down | Non-blocking, logged as info |
| Git checkpoint | Dirty worktree | Non-blocking, --no-verify with || true |
| Code review | Python tool error | Non-blocking unless it is the review's own thrown error |
| KG sync daemon | Process crash | Non-blocking, queue persists in Redis |
| Conversation sync | Neo4j write failure | Non-blocking, turns remain in Redis queue |
All non-blocking failures follow the pattern: try { operation } catch { /* Non-blocking */ log_and_continue }
Security Considerations
- KG Connection: Endpoint taken from the active env profile (
KG_ROUTING_URI/KG_DATABASE); the KG is auth-less Memgraph — no credentials, no local-development fallbacks (RUL-003) - Bash Safety: Destructive patterns (
rm -rf /, fork bombs) blocked before execution - Secret Detection: Hardcoded passwords, API keys, secrets, and tokens flagged in Gate 3
- Write Restrictions:
~/.claude/plans/path blocked to prevent plan file creation - Read Throttling: 50-read limit prevents runaway file scanning
- Message Truncation: Conversation content capped at 2000 characters before Neo4j storage
- Tool History Cap: Only last 100 tool calls retained to bound memory usage
Appendix A: Complete File Inventory
| File | Lines | Language | Purpose |
|---|---|---|---|
opencode/plugins/orchestrata.ts |
3,234 | TypeScript | Main plugin with all hooks and tools |
open-code/agents/auto-kg-context.md |
~120 | Markdown | Auto KG context agent definition |
open-code/agents/kg-context-agent.md |
~60 | Markdown | Manual KG context agent definition |
open-code/commands/query-kg.md |
~50 | Markdown | /query-kg command definition |
open-code/tools/kg_query |
3 | Bash | Shell wrapper for uv environment |
open-code/tools/kg_query.py |
~120 | Python | Full-featured async query tool |
open-code/tools/kg_query_inner.py |
~230 | Python | Core query with project scoping |
open-code/tools/neo4j_query.py |
~120 | Python | Standalone direct query tool |
open-code/tools/simple_kg_query.py |
~90 | Python | Simplified connectivity test |
open-code/install.sh |
~30 | Bash | Deployment script |
Appendix B: Deception Detection Patterns
File Creation Claims (ACTION_DECEPTION, CRITICAL)
/(?:i'?ve\s+)?(?:created|wrote|written|saved|generated)\s+(?:the\s+)?(?:file|script|config)/
/(?:i'?ve\s+)?(?:created|added)\s+[\w\-]+\.(py|js|ts|json|md|yaml|yml|txt|sh)/
/here'?s\s+the\s+(?:new\s+)?(?:file|script|code)\s+(?:i\s+)?(?:created|wrote)/
Command Execution Claims (ACTION_DECEPTION, CRITICAL)
/(?:i'?ve\s+)?(?:ran|executed|run)\s+(?:the\s+)?(?:command|script|test)/
/(?:i'?ve\s+)?(?:installed|updated|upgraded)\s+(?:the\s+)?(?:package|dependency)/
/running\s+(?:the\s+)?(?:tests?|build|lint)/
File Reading Claims (FILE_READING_DECEPTION, HIGH)
/(?:i'?ve\s+)?(?:read|examined|reviewed|analyzed|looked at)\s+(?:the\s+)?(?:file|code|contents)/
/after\s+(?:reading|examining|reviewing)\s+(?:the\s+)?(?:file|code)/
Observability
Logging Requirements
- Component Logging
- Log all major operations with appropriate log levels
- Include correlation IDs for request tracing
- Log performance metrics for critical operations
- Log errors with full context for debugging
Metrics Requirements
- Performance Metrics
- Operation duration histograms
- Request/error rate counters
- Resource utilization gauges
- Business metrics relevant to domain
Tracing Requirements
- Distributed Tracing
- Trace propagation across component boundaries
- Span attributes for domain-specific context
- Trace sampling based on operational needs
Alerting Requirements
- Critical Alerts
- Error rate spikes
- Performance degradation
- Resource exhaustion
- Business metric anomalies
Dashboard Requirements
- Operational Dashboard
- Real-time system health
- Performance trends
- Error analysis
- Resource monitoring
Visual Architecture
Class Diagram
Revision History
| Version | Date | Author | Changes |
|---|---|---|---|
| 1.0.0 | 2026-03-29 | Mohamed | Initial spec creation |
| 1.0.1 | 2026-04-09 | Mohamed | Added Data Models, Functional Requirements (FR-001-017), Error Conditions (ERR-001-020), Non-Functional Requirements, Governance, Testing, Integration Points, Success Criteria sections per SPEC_STANDARD.md |