Orchestrata Ultimate / Specs / 020-claude-code-harness

020-claude-code-harness: Claude Code Harness

A comprehensive hook-based harness that wraps Claude Code with session management, code quality enforcement, deception detection, safety guards, audit logging, and knowledge graph integration. The harness consists of 21 Python hook scripts that fire on Claude Code lifecycle events (SessionStart, PreToolUse, PostToolUse, UserPromptSubmit, Stop), a session management module with CLI, and a deployment pipeline. All hooks are version-controlled in claude/ and deployed to ~/.claude/hooks/ via...

At a glance

Item Value
Spec directory specs/020-claude-code-harness/
Status line in the spec Implemented
Requirement IDs defined 246
With a @traces citation in src/ 9 (3.7%)
With a @traces citation in tests/ 1 (0.4%)
Tracked files 6
RTM page 020-claude-code-harness

Reading this spec

The Claude Code Harness is a hook-based wrapper around Claude Code that adds session management, code quality enforcement, deception detection, safety guards, audit logging and knowledge graph integration. Claude Code has no built-in session tracking or context persistence, no enforcement of project rules (no mocking, absolute imports, maximum function length, no bare except), no protection against destructive operations and no audit trail; the harness supplies these.

The scope is ten user stories: session lifecycle, code quality enforcement, safety guards and session context persistence (priority 0), deception detection, Neo4j context injection, audit trail and RTM generation (priority 1), and read throttling and remember/search (priority 2). Functional requirements cover hook registration and protocol, session auto-start, close and open, and the error gate checks. Requirement IDs use the REQ-020- prefix.

The design is stated in the overview. Twenty-one Python hook scripts fire on five Claude Code lifecycle events: SessionStart, PreToolUse, PostToolUse, UserPromptSubmit and Stop. Hooks are deployed by install.sh and registered in the Claude settings. An error gate runs six categories of check at session stop and blocks if errors exist. A stop audit compares claims against actual tool usage. A read throttle limits file reads to 3 per 30-second window and redirects to knowledge graph queries. The file context.json is the single source of truth for session state and is never trimmed, while context.md is a rendered view of the last three sessions. The audit trail is stored as JSONL with archive rotation and no deletion.

In the code, the hooks and tools live outside the orchestrata_ultimate package, so the Python trace table is short: orchestrata_ultimate/session/models, orchestrata_ultimate/session/controller/_git and orchestrata_ultimate/session/context. The per-requirement view is on the RTM page.

The spec's status line reads Implemented. It tracks 6 files and defines 246 requirement IDs. The full text follows below.

Measured coverage is 9 of 246 requirements cited by at least one @traces in src/ (3.7%), spread over 6 modules; the module citing the most of them is orchestrata_ultimate/session/context (3 requirements). In tests/, 1 requirement is cited by a test-side @traces.

Coverage gaps: 237 requirements have no citing symbol. The largest untraced groups are REQ-020-* (237). 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 (1 against 9).

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-020-001 yes session_auto_start.py fires on SessionStart event none
REQ-020-002 yes Hook only runs for projects with "orchestrata" in the path none
REQ-020-003 yes Hook imports SessionController from ~/.claude/tools/session/ none
REQ-020-004 yes Hook checks if last session has no length field (still active) and skips creation none
REQ-020-005 yes Hook checks if last session was created <300 seconds ago and skips creation none
REQ-020-006 yes Hook calls SessionController.begin() with timestamped purpose string none
REQ-020-007 yes Hook outputs session number, start time, and purpose to stdout none
REQ-020-008 yes Hook handles ImportError gracefully (prints error, does not crash) none
REQ-020-009 yes Hook handles SessionController initialization failure gracefully none
REQ-020-010 yes Hook reads cwd from JSON stdin input none
REQ-020-011 yes session_close_hook.py fires on UserPromptSubmit event none
REQ-020-012 yes Hook detects "cts" trigger (case-insensitive, trimmed) none
REQ-020-013 yes Hook detects "cs" trigger (case-insensitive, trimmed) none
REQ-020-014 yes Hook detects "close the session" trigger (case-insensitive, trimmed) none
REQ-020-015 yes Hook finds project root by walking up from cwd looking for context.json none
REQ-020-016 yes Hook generates RTM from @traces decorators via subprocess calls none
REQ-020-017 yes Hook extracts achievements from git log since session start none
REQ-020-018 yes Hook calls SessionController.end() to update context.json none
REQ-020-019 yes Hook creates annotated git tag in format session-NNN-YYYY-MM-DD-HHMM 1
REQ-020-020 yes Hook updates CHANGELOG.md with categorized achievements 9
REQ-020-021 yes Hook pushes session tag to origin via git push origin 2
REQ-020-022 yes Hook pushes current branch to origin via git push origin HEAD 3
REQ-020-023 yes Hook injects close summary into additionalContext none
REQ-020-024 yes RTM generation failures are logged but do not block session close none
REQ-020-025 yes Hook does not block (Claude still sees the prompt) none
REQ-020-026 yes session_open_hook.py fires on UserPromptSubmit event none
REQ-020-027 yes Hook detects "sns" and "start new session" triggers none
REQ-020-028 yes Hook displays pending deferred work items grouped by priority none
REQ-020-029 yes Hook injects project metrics into additionalContext none
REQ-020-030 yes session_context_hook.py fires on SessionStart event none
REQ-020-031 yes Hook injects session context into conversation on startup none
REQ-020-032 yes error_gate_hook.py fires on Stop event none
REQ-020-033 yes Hook delegates to error_gate package main() function none
REQ-020-034 yes error_gate.__init__ runs all 6 check categories sequentially none
REQ-020-035 yes Check order: syntax, lint, stubs, nesting, god objects, tests none
REQ-020-036 yes If any errors found, Stop is blocked with decision: block none
REQ-020-037 yes Error report includes numbered fix instructions (6 steps) none
REQ-020-038 yes Error report printed to stderr for operator visibility none
REQ-020-039 yes If no errors, empty JSON {} returned (allow stop) none
REQ-020-040 yes Hook reads and discards stdin JSON (not used) none
REQ-020-041 yes checks_syntax.py finds modified .py files via git diff --name-only --diff-filter=M HEAD none
REQ-020-042 yes Each modified .py file parsed with ast.parse() via subprocess none
REQ-020-043 yes Syntax errors reported with file path and error message (truncated to 200 chars) none
REQ-020-044 yes Non-existent files (deleted after diff) are skipped none
REQ-020-045 yes Git command failure returns empty error list (not crash) none
REQ-020-046 yes checks_lint.py finds modified .py files via git diff none
REQ-020-047 yes Runs uv run flake8 --select=E9,F82,F83,F84 --max-line-length=120 none
REQ-020-048 yes Modified files capped at 30 per run to avoid timeout none
REQ-020-049 yes Lint errors reported up to 10 per run none
REQ-020-050 yes Empty file list results in no flake8 invocation none
REQ-020-051 yes Uses shutil.which("uv") with fallback to ~/.local/bin/uv none
REQ-020-052 yes checks_test.py finds changed test files via git diff --name-only HEAD~1 none
REQ-020-053 yes Only files under tests/ ending in .py are selected none
REQ-020-054 yes Files with "prolog" in name are excluded none
REQ-020-055 yes Files importing pyswip or GovernanceEngine are excluded none
REQ-020-056 yes Files importing orchestrata.governance or PrologBridge are excluded none
REQ-020-057 yes If tests/conftest.py uses pyswip, all tests are skipped none
REQ-020-058 yes Test file count capped at 10 per run none
REQ-020-059 yes Runs uv run pytest -x -q --no-header on selected files none
REQ-020-060 yes Test timeout is 300 seconds none
REQ-020-061 yes Exit code 139 (SIGSEGV) treated as infrastructure issue, not test failure none
REQ-020-062 yes Only lines containing "FAILED" reported as test failures none
REQ-020-063 yes checks_structure.py scans non-test modified .py files for stubs none
REQ-020-064 yes Stub defined as function body with only logging, local assigns, pass, docstrings none
REQ-020-065 yes __init__, __del__, __enter__, __exit__, close, cleanup excluded none
REQ-020-066 yes Private functions (starting with _) excluded from stub detection none
REQ-020-067 yes await expressions are NOT classified as stubs none
REQ-020-068 yes self.x += 1 (augmented assignment on attributes) is NOT a stub none
REQ-020-069 yes Log calls detected via dotted name resolution (logger.info, log.debug, etc.) none
REQ-020-070 yes List appends (.append()) treated as logging-equivalent for stub detection none
REQ-020-071 yes return None and bare return treated as trivial returns in stubs none
REQ-020-072 yes raise in first 2 statements treated as guard clause, not real work none
REQ-020-073 yes Nesting measured for all functions in modified .py files none
REQ-020-074 yes Nesting types: if, for, while, with, try, async for, async with none
REQ-020-075 yes Functions exceeding 4 levels of nesting are flagged none
REQ-020-076 yes Error message includes function name, line number, actual depth, and max allowed none
REQ-020-077 yes Classes exceeding 300 lines flagged (end_lineno - lineno + 1) none
REQ-020-078 yes Classes with >15 public methods flagged (not starting with _) none
REQ-020-079 yes Files exceeding 500 lines flagged none
REQ-020-080 yes Only source files checked (test files excluded) none
REQ-020-081 yes Generated directories (spike/, iterations/, ci/) excluded none
REQ-020-082 yes utils.py provides run_command() with subprocess timeout handling none
REQ-020-083 yes utils.py provides get_modified_py_files() with git diff discovery none
REQ-020-084 yes utils.py provides parse_file() with safe AST parsing (returns None on failure) none
REQ-020-085 yes PROJECT_ROOT configurable via ORCHESTRATA_ROOT environment variable 2
REQ-020-086 yes CHECK_TIMEOUT set to 30 seconds per check none
REQ-020-087 yes FileNotFoundError from missing tools treated as skip (returns exit 0) none
REQ-020-088 yes stop_auditor.py fires on Stop event none
REQ-020-089 yes Hook reads JSON from stdin with session_id and transcript_path none
REQ-020-090 yes Hook detects SubagentStop events and delegates to subagent handler none
REQ-020-091 yes Hook extracts assistant messages from JSONL transcript none
REQ-020-092 yes Hook loads tool calls from session JSONL file none
REQ-020-093 yes Hook calls detect_deception() with assistant message and tool calls none
REQ-020-094 yes Hook logs findings to deception_log.jsonl none
REQ-020-095 yes Hook archives session JSONL to dated directory none
REQ-020-096 yes Hook formats findings as severity-colored report (CRITICAL/HIGH/MEDIUM/LOW) none
REQ-020-097 yes Hook outputs report via additionalContext if findings exist none
REQ-020-098 yes Hook prints "No issues detected" to stderr if clean none
REQ-020-099 yes deception.py strips code blocks (triple backtick) before analysis none
REQ-020-100 yes Strips inline code (single backtick) before analysis none
REQ-020-101 yes Strips blockquotes (lines starting with >) before analysis none
REQ-020-102 yes Strips HTML pre/code tags before analysis none
REQ-020-103 yes File creation claims flagged as CRITICAL if Write/Edit not in tools_used none
REQ-020-104 yes Command execution claims flagged as CRITICAL if Bash not in tools_used none
REQ-020-105 yes File reading claims flagged as HIGH if Read/Grep not in tools_used none
REQ-020-106 yes Tool errors (has_error=True) not mentioned in response flagged as CRITICAL none
REQ-020-107 yes Error concealment checked against 11 error-related terms none
REQ-020-108 yes Sessions with >10 tool calls but <100 char response flagged as MEDIUM none
REQ-020-109 yes Tool output >500 chars with <3 overlapping 6+ char words flagged as MEDIUM none
REQ-020-110 yes Findings include type, severity, description, evidence fields none
REQ-020-111 yes Action deception findings include pattern_matched field none
REQ-020-112 yes Error concealment findings include tool_name field none
REQ-020-113 yes Result hiding findings include tool_name field none
REQ-020-114 yes transcript.py reads JSONL file line by line none
REQ-020-115 yes Extracts entries with message.role == "assistant" none
REQ-020-116 yes Handles string content (direct text) none
REQ-020-117 yes Handles list content with typed blocks (type == "text") none
REQ-020-118 yes Corrupt JSON lines skipped with warning to stderr none
REQ-020-119 yes Missing or empty transcript returns empty string none
REQ-020-120 yes IOError/OSError on file read returns empty list none
REQ-020-121 yes stop_auditor_subagent.py detects SubagentStop events none
REQ-020-122 yes Parses subagent transcript for tool usage and text content none
REQ-020-123 yes Runs same detect_deception() logic on subagent sessions none
REQ-020-124 yes Logs subagent findings to ~/.claude/audit/subagent_findings/ none
REQ-020-125 yes stop_audit/subagent.py re-exports from stop_auditor_subagent.py none
REQ-020-126 yes Findings logged with timestamp (epoch and ISO format) none
REQ-020-127 yes Log entry includes session_id and findings_count none
REQ-020-128 yes Log entry includes tools_used set and tool_calls_count none
REQ-020-129 yes Log entry includes assistant_message_length and preview (500 chars) none
REQ-020-130 yes Findings directory auto-created with parents=True, exist_ok=True none
REQ-020-131 yes intercept_bash.py fires on PreToolUse(Bash) none
REQ-020-132 yes rm command detected via regex \brm\s none
REQ-020-133 yes rm with flags detected via regex \brm\s+- none
REQ-020-134 yes unlink command detected via regex \bunlink\s none
REQ-020-135 yes rmdir command detected via regex \brmdir\s none
REQ-020-136 yes shred command detected via regex \bshred\s none
REQ-020-137 yes Redirect to ~/.claude/ detected (> and >> patterns) none
REQ-020-138 yes cat >, echo >, cp, mv, touch, mkdir to ~/.claude/ detected none
REQ-020-139 yes Full path patterns (/home/*/\.claude/) also detected none
REQ-020-140 yes Blocked commands logged with operation type "Bash-Delete-Blocked" none
REQ-020-141 yes Claude-dir blocks logged with operation type "Bash-Claude-Dir-Blocked" none
REQ-020-142 yes Allowed commands return {"decision": "allow"} none
REQ-020-143 yes Block response includes the original command for manual execution none
REQ-020-144 yes intercept_write.py fires on PreToolUse(Write) none
REQ-020-145 yes Files that already exist are blocked with "use Edit tool" message none
REQ-020-146 yes Writes to ~/.claude/plans/ blocked with redirect to project plans/ none
REQ-020-147 yes Writes to context.md blocked with session CLI instructions none
REQ-020-148 yes Writes to context.json blocked with session CLI instructions none
REQ-020-149 yes New file creation to valid paths returns {"decision": "allow"} none
REQ-020-150 yes Missing file_path returns block with error message none
REQ-020-151 yes All operations (allowed and blocked) logged to file_operations.log none
REQ-020-152 yes Log entries include timestamp, operation, file_path, status, message none
REQ-020-153 yes intercept_edit.py fires on PreToolUse(Edit) none
REQ-020-154 yes Git checkpoint created before edits none
REQ-020-155 yes Edit operations logged to audit file none
REQ-020-156 yes block_except_pass.py fires on PreToolUse(Write|Edit) none
REQ-020-157 yes Bare except: (no exception type) detected via AST none
REQ-020-158 yes except ...: pass (single-statement pass body) detected via AST none
REQ-020-159 yes Detection uses ast.parse() not regex none
REQ-020-160 yes Only .py files checked (non-Python files pass through) none
REQ-020-161 yes Violation message includes line number none
REQ-020-162 yes Violation message suggests specific exception type with logging none
REQ-020-163 yes For tuple exception types, all types listed in message none
REQ-020-164 yes SyntaxError in content does not crash the hook (returns empty) none
REQ-020-165 yes Non-Python files return empty JSON (allow) none
REQ-020-166 yes block_file_tools.py fires on PreToolUse(Read|Grep) when active none
REQ-020-167 yes Queries Neo4j for file-scoped entities (classes, functions) none
REQ-020-168 yes Queries Neo4j for specification traceability none
REQ-020-169 yes Queries Neo4j for related nodes via full-text search none
REQ-020-170 yes Results injected as additionalContext in hook output none
REQ-020-171 yes context.json is never trimmed or truncated none
REQ-020-172 yes All sessions recorded in session_history array 6
REQ-020-173 yes state object tracks current session number, version, branch, test count, status 3
REQ-020-174 yes deferred_work array tracks pending tasks with priority and notes 9
REQ-020-175 yes Direct writes to context.json blocked by intercept_write.py none
REQ-020-176 yes Direct writes to context.md blocked by intercept_write.py none
REQ-020-177 yes sync_context_md.py fires on PostToolUse(Write|Edit) none
REQ-020-178 yes Hook only acts when modified file is context.json none
REQ-020-179 yes Hook imports ContextManager from ~/.claude/tools/session/ none
REQ-020-180 yes Hook calls ContextManager.write() to regenerate context.md none
REQ-020-181 yes context.md shows only last 3 sessions (SESSION_LIMIT) none
REQ-020-182 yes Regeneration failure logged but does not block none
REQ-020-183 yes Non-context.json files result in empty JSON (pass through) none
REQ-020-184 yes read_throttle.py fires on PreToolUse(Read|Grep) none
REQ-020-185 yes Read timestamps tracked in /tmp/claude-read-tracker.json none
REQ-020-186 yes Maximum 3 reads allowed per 30-second sliding window none
REQ-020-187 yes Expired timestamps pruned on each check (window filter) none
REQ-020-188 yes Reads of context.json exempted from throttle none
REQ-020-189 yes Reads of .env exempted from throttle none
REQ-020-190 yes Reads of settings.json exempted from throttle none
REQ-020-191 yes Reads of CLAUDE.md exempted from throttle none
REQ-020-192 yes Throttled reads blocked with {"decision": "block", "reason": "..."} none
REQ-020-193 yes Block message includes Neo4j query examples (/code commands) none
REQ-020-194 yes Block message includes raw Cypher query example none
REQ-020-195 yes Non-Read/Grep tools pass through with empty JSON none
REQ-020-196 yes JSON parse error on stdin returns empty JSON (no crash) none
REQ-020-197 yes File save failure logged to stderr (no crash) none
REQ-020-198 yes posttool_auditor.py fires on PostToolUse(.*) none
REQ-020-199 yes Records tool_name, has_error, tool_output, tool_output_length none
REQ-020-200 yes Records written to session JSONL in ~/.claude/audit/sessions/ none
REQ-020-201 yes log_operation.py fires on PostToolUse(Write|Edit|Bash|Read|Glob|Grep) none
REQ-020-202 yes Log entries include timestamp, operation, file_path/command, status, message none
REQ-020-203 yes Logs written to ~/.claude/logs/file_operations.log as JSONL none
REQ-020-204 yes Active sessions stored in ~/.claude/audit/sessions/{session_id}.jsonl none
REQ-020-205 yes Completed sessions moved to ~/.claude/audit/archive/YYYY-MM-DD/ none
REQ-020-206 yes Archive filename includes session_id and epoch timestamp none
REQ-020-207 yes Archive uses shutil.move() (move, not copy) to prevent duplicates none
REQ-020-208 yes Archive data NEVER deleted none
REQ-020-209 yes Audit directories auto-created with parents=True, exist_ok=True none
REQ-020-210 yes Session close hook runs RTM generation scripts via subprocess none
REQ-020-211 yes Scripts parse @traces(spec=, story=, reqs=[]) decorators from source none
REQ-020-212 yes RTM output committed to plans/ directory none
REQ-020-213 yes RTM generation failures logged but do not block session close none
REQ-020-214 yes Generated RTM maps requirements to implementing functions/classes none
REQ-020-215 yes remember_hook.py fires on UserPromptSubmit event none
REQ-020-216 yes Detects "remember when" trigger phrase none
REQ-020-217 yes Detects "do you remember" trigger phrase none
REQ-020-218 yes Detects "recall when" trigger phrase none
REQ-020-219 yes Detects "remember that" trigger phrase none
REQ-020-220 yes Detects "we discussed" trigger phrase none
REQ-020-221 yes Detects "we talked about" trigger phrase none
REQ-020-222 yes Detects "last time we" trigger phrase none
REQ-020-223 yes Detects "what happened with" trigger phrase none
REQ-020-224 yes Triggers compiled into single regex pattern (case-insensitive) none
REQ-020-225 yes Topic extracted from text after trigger phrase none
REQ-020-226 yes Falls back to whole message (minus trigger) if no text after trigger none
REQ-020-227 yes Empty topic results in no search (empty JSON returned) none
REQ-020-228 yes Query searches ConversationTurn.text with case-insensitive word matching none
REQ-020-229 yes Only words with length >2 used as search terms none
REQ-020-230 yes Query returns up to 15 results ordered by timestamp descending none
REQ-020-231 yes Results include session_id, turn sequence, role, text (500 char limit), timestamp none
REQ-020-232 yes Results injected as additionalContext with factual framing none
REQ-020-233 yes Query timeout set to 15 seconds none
REQ-020-234 yes KG connection parameters loaded from the active env profile (KG_ROUTING_URI/KG_DATABASE layered over secrets-only .env); auth-less Memgraph — no credentials none
REQ-020-235 yes Env files parsed for key=value pairs (strips quotes, skips comments); profile overlays .env with override=True 4
REQ-020-236 yes Missing Neo4j connection returns "(Search failed: ...)" not block none
REQ-020-237 yes subprocess.TimeoutExpired handled gracefully none
REQ-020-238 yes FileNotFoundError (missing uv) handled gracefully none
REQ-020-239 yes Non-matching prompts return empty JSON (no search) none
REQ-020-240 yes JSON parse error on stdin returns empty JSON (no crash) none
REQ-020-241 yes claude/tools/notify sends a desktop notification via the system notifier none
REQ-020-242 yes Notification fires at CRITICAL urgency — normal urgency is suppressed by a focused fullscreen window (measured on KDE Plasma, 2026-08-29), so a lower level silently fails to deliver none
REQ-020-243 yes The CLI is deployed to ~/.claude/tools/notify by deploy/install-claude-config.sh and mirrored at plugins/orchestrata/tools/notify none
REQ-020-244 yes claude/hooks/decision_adr_trigger.sh fires on UserPromptSubmit and detects any mention of a decision, ruling, or ADR none
REQ-020-245 yes On a match the hook injects the ADR discipline (ADR-0046 three homes, ADR-0047 two registers, ADR-0048 waiver rule) as additional context, so a decision cannot be acted on before the law that governs it is in view none
REQ-020-246 yes The trigger exists at BOTH levels — user (claude/hooks/decision_adr_trigger.sh, delivered by the plugin) and project (.claude/hooks/decision-adr-trigger.sh, registered in .claude/settings.json) — because a session started outside the repo never reads the project file none

Code that traces this spec

Module Symbols Requirements
orchestrata_ultimate/core/env_bootstrap 4 1
orchestrata_ultimate/core/paths 2 1
orchestrata_ultimate/session/context 13 3
orchestrata_ultimate/session/controller/_changelog 9 1
orchestrata_ultimate/session/controller/_git 5 3
orchestrata_ultimate/session/models 5 3

Checklists

checklists/README.md

Claude Code Harness Checklists

Project: Orchestrata Claude Code Harness (Spec 020) Component: Hook-Based Claude Code Wrapper Status: Implemented Owner: Mohamed


Overview

The Claude Code Harness is a comprehensive hook-based system that wraps Claude Code with session management, code quality enforcement, deception detection, safety guards, audit logging, and knowledge graph integration. It consists of 21 Python hook scripts firing on 5 Claude Code lifecycle events, a session management module with CLI, and a deployment pipeline via ./claude/install.sh.


Checklist Summary
Checklist Total Items Completed Progress
Requirements 240 240 100%
Constitutional Compliance 116 116 100%
Testing Plan 190 0 0%
TOTAL 546 356 65%

Key Components
1. Session Management
2. Error Gate (Stop hook)
3. Stop Audit (Stop hook)
4. Safety Hooks (PreToolUse)
5. Neo4j Integration
6. Audit Trail
7. Deployment

Hook Event Matrix
Hook Script Event Matcher Action
session_auto_start.py SessionStart * Create session entry
session_context_hook.py SessionStart * Inject session context
session_close_hook.py UserPromptSubmit * Close session on "cts"
session_open_hook.py UserPromptSubmit * Open session on "sns"
remember_hook.py UserPromptSubmit * Neo4j search on triggers
intercept_write.py PreToolUse Write Block overwrites
intercept_edit.py PreToolUse Edit Git checkpoint
intercept_bash.py PreToolUse Bash Block destructive ops
block_except_pass.py PreToolUse Write/Edit Block bare except
read_throttle.py PreToolUse Read/Grep Throttle reads
enforcement_hook.py PreToolUse .* Central enforcement
log_operation.py PostToolUse Write/Edit/Bash/Read/Glob/Grep Log operations
posttool_auditor.py PostToolUse .* Accumulate tool calls
sync_context_md.py PostToolUse Write/Edit Sync context.md
error_gate_hook.py Stop * Block on errors
stop_auditor.py Stop * Deception detection

Checklist Files
1. requirements.md

210 functional requirements organized by user stories:

2. constitutional.md

115 constitutional compliance items covering all 11 articles:

3. testing.md

190 test cases across 3 categories:


Dependencies
Required
Optional

References

Last Updated: 2026-03-29 Version: 1.0.0 Maintained By: Mohamed

checklists/constitutional.md

Claude Code Harness - Constitutional Compliance

Component: Hook-Based Claude Code Wrapper Spec: 020-claude-code-harness Status: Compliance Review Total Compliance Items: 115


Overview

This document tracks compliance of the Claude Code Harness with all 11 articles of the Orchestrata Constitution. The harness is the primary enforcement layer between the human developer and Claude Code, making constitutional compliance critical -- it must faithfully enforce quality gates, detect deception, maintain audit trails, and never bypass governance or session isolation.


Article I: Agent Autonomy

Principle: Volks retain autonomy; the harness enforces boundaries without overriding agent decisions.

Compliance Requirements
Ownership Boundaries

Priority: Critical Verification: Code review + integration tests


Article II: Prolog as Single Source of Truth

Principle: All governance rules are in Prolog; the harness does not duplicate or override governance logic.

Compliance Requirements
Governance Separation

Priority: Critical Verification: Architecture review


Article III: Session Isolation

Principle: Sessions are isolated; the harness does not leak state between sessions.

Compliance Requirements
State Isolation

Priority: Critical Verification: Integration tests + session lifecycle tests


Article IV: Transparency and Logging

Principle: All operations are logged; the audit trail provides complete visibility.

Compliance Requirements
Operation Logging

Priority: Critical Verification: Audit log review + integration tests


Article V: Non-Deception

Principle: Agents must not fabricate actions or conceal errors; the harness enforces truthfulness.

Compliance Requirements
Deception Detection

Priority: Critical Verification: Deception detection tests + manual audit review


Article VI: Quality Gates

Principle: Code quality enforced at session boundaries; no session ends with broken code.

Compliance Requirements
Error Gate Enforcement

Priority: Critical Verification: Error gate unit tests + integration tests


Article VII: Testing Without Mocks

Principle: Tests use real implementations; no mocking infrastructure.

Compliance Requirements
Real Testing

Priority: High Verification: Code search for mock imports


Article VIII: Metrics and Observability

Principle: System state is observable; metrics are collected and accessible.

Compliance Requirements
Metrics Collection

Priority: High Verification: Metrics review + dashboard integration


Article IX: Graceful Degradation

Principle: System continues operating when components fail; failures are contained.

Compliance Requirements
Failure Handling

Priority: High Verification: Failure scenario tests


Article X: Version Compatibility

Principle: System handles version transitions without data loss.

Compliance Requirements
Version Management

Priority: High Verification: Upgrade scenario tests


Article XI: Documentation First

Principle: Specifications precede implementation; documentation is comprehensive and current.

Compliance Requirements
Documentation Coverage

Priority: High Verification: Documentation review


Summary
Article Compliance Items Completed Status
I: Agent Autonomy 10 10 Complete
II: Prolog as Source of Truth 10 10 Complete
III: Session Isolation 12 12 Complete
IV: Transparency and Logging 10 10 Complete
V: Non-Deception 12 12 Complete
VI: Quality Gates 10 10 Complete
VII: Testing Without Mocks 10 10 Complete
VIII: Metrics and Observability 10 10 Complete
IX: Graceful Degradation 12 12 Complete
X: Version Compatibility 7 7 Complete
XI: Documentation First 13 13 Complete
TOTAL 116 116 Complete

Last Updated: 2026-03-29 Version: 1.0.0 Maintained By: Mohamed

checklists/requirements.md

The requirement list above comes from this file; 246 of 246 checkbox items are ticked.

checklists/testing.md

Claude Code Harness - Testing Plan

Component: Hook-Based Claude Code Wrapper Spec: 020-claude-code-harness Status: Test Planning Phase Total Test Cases: 190


Overview

This document defines the comprehensive testing strategy for the Claude Code Harness. All tests follow the strict "no mocking" policy and use real implementations: real AST parsing, real flake8 invocations, real file I/O, real subprocess execution, and real JSON serialization. Tests verify hook behavior by invoking hooks with crafted JSON stdin and checking stdout/stderr responses.


Test Categories Summary
Category Test Count Purpose Priority
Unit Tests 120 Individual hook function testing Critical
Integration Tests 45 Multi-hook workflow testing High
Compliance Tests 25 Constitutional enforcement testing High
TOTAL 190

Test Infrastructure
Hook Test Harness

All hook tests use a common pattern:

  1. Prepare a JSON dict matching the hook's expected stdin format
  2. Invoke the hook script via subprocess with JSON piped to stdin
  3. Parse stdout JSON response
  4. Assert on decision, reason, additionalContext fields
  5. Check stderr for diagnostic output
def invoke_hook(hook_path: str, hook_input: dict) -> dict:
    result = subprocess.run(
        [sys.executable, hook_path],
        input=json.dumps(hook_input),
        capture_output=True,
        text=True,
        timeout=30,
    )
    return json.loads(result.stdout)
Test File Fixtures

Tests create temporary Python files with known content (syntax errors, bare exceptions, stubs, deep nesting) in a temporary git repository, then invoke hooks against them.


Unit Tests (120)
Error Gate - Syntax Checks (10 tests)
Error Gate - Lint Checks (10 tests)
Error Gate - Test Checks (12 tests)
Error Gate - Stub Detection (15 tests)
Error Gate - Nesting Depth (8 tests)
Error Gate - God Objects (10 tests)
Error Gate - Utils (8 tests)
Deception Detection (15 tests)
Transcript Parsing (7 tests)
Read Throttle (10 tests)
Block Except Pass (8 tests)
Intercept Bash (7 tests)

Integration Tests (45)
Session Lifecycle (10 tests)
Error Gate Pipeline (10 tests)
Safety Hook Pipeline (10 tests)
Deception Audit Pipeline (8 tests)
Context Sync Pipeline (7 tests)

Compliance Tests (25)
Constitutional Article Verification
Data Integrity Verification
Security Verification

Test Execution
Running Tests
# Run all harness tests (when implemented)
ci/local-ci.sh test -- -k "test_harness or test_hook or test_error_gate"

# Run specific hook test
uv run pytest tests/harness/test_error_gate.py -v

# Run deception detection tests
uv run pytest tests/harness/test_deception.py -v

# Run safety hook tests
uv run pytest tests/harness/test_safety_hooks.py -v
Test Directory Structure
tests/harness/
├── conftest.py                 # Shared fixtures (temp git repo, hook invoker)
├── test_error_gate_syntax.py   # TEST-UNIT-001 through TEST-UNIT-010
├── test_error_gate_lint.py     # TEST-UNIT-011 through TEST-UNIT-020
├── test_error_gate_tests.py    # TEST-UNIT-021 through TEST-UNIT-032
├── test_error_gate_stubs.py    # TEST-UNIT-033 through TEST-UNIT-047
├── test_error_gate_nesting.py  # TEST-UNIT-048 through TEST-UNIT-055
├── test_error_gate_gods.py     # TEST-UNIT-056 through TEST-UNIT-065
├── test_error_gate_utils.py    # TEST-UNIT-066 through TEST-UNIT-073
├── test_deception.py           # TEST-UNIT-074 through TEST-UNIT-088
├── test_transcript.py          # TEST-UNIT-089 through TEST-UNIT-095
├── test_read_throttle.py       # TEST-UNIT-096 through TEST-UNIT-105
├── test_block_except.py        # TEST-UNIT-106 through TEST-UNIT-113
├── test_intercept_bash.py      # TEST-UNIT-114 through TEST-UNIT-120
├── test_session_lifecycle.py   # TEST-INTEG-001 through TEST-INTEG-010
├── test_error_gate_pipeline.py # TEST-INTEG-011 through TEST-INTEG-020
├── test_safety_pipeline.py     # TEST-INTEG-021 through TEST-INTEG-030
├── test_deception_pipeline.py  # TEST-INTEG-031 through TEST-INTEG-038
├── test_context_sync.py        # TEST-INTEG-039 through TEST-INTEG-045
└── test_compliance.py          # TEST-COMPLIANCE-001 through TEST-COMPLIANCE-025
Coverage Targets
Component Target Critical Threshold
error_gate/ 95% 90%
stop_audit/ 95% 90%
read_throttle.py 90% 85%
block_except_pass.py 95% 90%
intercept_bash.py 90% 85%
intercept_write.py 90% 85%
session_auto_start.py 85% 80%
session_close_hook.py 85% 80%
remember_hook.py 80% 75%
sync_context_md.py 85% 80%
Overall 90% 85%

Summary
Category Test Count Completed Progress
Unit Tests 120 0 0%
Integration Tests 45 0 0%
Compliance Tests 25 0 0%
TOTAL 190 0 0%

Last Updated: 2026-03-29 Version: 1.0.0 Maintained By: Mohamed

Other tracked files

Full spec text

Verbatim from specs/020-claude-code-harness/spec.md; headings are pushed down two levels.

SPEC-020: Claude Code Harness

Metadata


Overview

What

A comprehensive hook-based harness that wraps Claude Code with session management, code quality enforcement, deception detection, safety guards, audit logging, and knowledge graph integration. The harness consists of 21 Python hook scripts that fire on Claude Code lifecycle events (SessionStart, PreToolUse, PostToolUse, UserPromptSubmit, Stop), a session management module with CLI, and a deployment pipeline. All hooks are version-controlled in claude/ and deployed to ~/.claude/hooks/ via ./claude/install.sh.

Why
How

User Scenarios

US-001: Session Lifecycle (P0)

As a developer using Claude Code for Orchestrata development I want sessions to automatically start, persist state, and cleanly close with RTM generation and git tags So that every development session is tracked, auditable, and recoverable

Acceptance Criteria:


US-002: Code Quality Enforcement (P0)

As a developer I want Claude Code to be blocked from ending a session when modified code has syntax errors, lint failures, test failures, stubs, deep nesting, or god objects So that every session ends with clean, production-quality code

Acceptance Criteria:


US-003: Deception Detection (P1)

As a project owner I want automatic comparison of what Claude claims to have done vs what tools were actually invoked So that fabricated claims are detected and logged for review

Acceptance Criteria:


US-004: Safety Guards (P0)

As a developer I want destructive operations (rm, file overwrites, bare exceptions) to be blocked automatically So that Claude Code cannot accidentally destroy files, overwrite existing code, or introduce error-swallowing patterns

Acceptance Criteria:


US-005: Neo4j Context Injection (P1)

As a developer I want file reads to be enriched with knowledge graph context (classes, functions, specs, related nodes) So that Claude Code has project-wide understanding beyond the single file being read

Acceptance Criteria:


US-006: Session Context Persistence (P0)

As a developer I want context.json to serve as the single source of truth for all session data, never losing history So that I can review any past session's state, achievements, and deferred work

Acceptance Criteria:


US-007: Read Throttling (P2)

As a project architect I want excessive file reads throttled to encourage knowledge-graph-first exploration So that Claude Code leverages the Neo4j knowledge graph instead of reading files sequentially

Acceptance Criteria:


US-008: Audit Trail (P1)

As a project owner I want all tool operations, deception findings, and session data logged as JSONL So that there is a complete, immutable audit trail of everything Claude Code does

Acceptance Criteria:


US-009: RTM Generation (P1)

As a project manager I want requirements traceability matrices automatically generated from @traces decorators at session close So that requirement coverage is tracked and verified with every session

Acceptance Criteria:


US-010: Remember/Search (P2)

As a developer I want to ask "do you remember when we discussed X" and get actual past conversation context from Neo4j So that cross-session memory works without manual context loading

Acceptance Criteria:


Terminology and Glossary

Term Definition
Hook A Python script registered in ~/.claude/settings.json that executes on a specific Claude Code lifecycle event (SessionStart, PreToolUse, PostToolUse, UserPromptSubmit, Stop).
Error Gate A Stop hook package that blocks Claude Code from ending a session when unfixed errors (syntax, lint, test failures, stubs, deep nesting, god objects) are detected in modified files.
Stop Auditor A Stop hook that performs deception analysis by comparing what Claude claimed to do (in its text response) against what tools were actually invoked (from the session JSONL).
Deception Detection Pattern-based comparison of assistant narrative text against recorded tool calls, detecting claims of file creation without Write, command execution without Bash, or file reading without Read.
Read Throttle A PreToolUse hook that limits Read/Grep tool invocations to 3 per 30-second window, blocking excess reads and redirecting Claude to use Neo4j knowledge graph queries instead.
Session Module A Python package deployed to ~/.claude/tools/session/ that provides SessionController, ContextManager, and data models for tracking session lifecycle.
context.json The single source of truth for session state. Contains state, deferred_work, and session_history arrays. Never trimmed.
context.md A Jinja2-rendered markdown view of the last 3 sessions from context.json. Auto-regenerated by the sync_context_md.py PostToolUse hook.
RTM Requirements Traceability Matrix. Generated from @traces decorators in source code during session close, committed to plans/.
JSONL JSON Lines format (one JSON object per line). Used for audit logs, session transcripts, and deception findings.
Session Tag An annotated git tag created at session close in the format session-NNN-YYYY-MM-DD-HHMM.
Git Checkpoint A git stash or commit created before destructive operations to enable recovery.
God Object A class exceeding 300 lines or 15 public methods, or a file exceeding 500 lines. Detected by checks_structure.py.
Stub Method A function whose body contains only logging calls, local assignments, pass statements, or docstrings -- doing no real work.
Safety Hook Any PreToolUse hook that blocks potentially harmful operations (destructive commands, bare exceptions, file overwrites).
SubagentStop A Stop event variant for Claude Code subagent sessions, handled separately by stop_auditor_subagent.py.

Data Models

context.json Schema
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["state", "deferred_work", "session_history"],
  "properties": {
    "state": {
      "type": "object",
      "required": ["session", "version", "branch", "status"],
      "properties": {
        "session": { "type": "integer", "minimum": 1 },
        "version": { "type": "string", "pattern": "^\\d+\\.\\d+\\.\\d+$" },
        "branch": { "type": "string" },
        "test_count": { "type": "integer" },
        "status": { "type": "string", "enum": ["active", "closed"] }
      }
    },
    "deferred_work": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["id", "priority", "description", "status"],
        "properties": {
          "id": { "type": "string" },
          "priority": { "type": "string", "enum": ["high", "medium", "low"] },
          "description": { "type": "string" },
          "status": { "type": "string", "enum": ["pending", "in_progress", "completed"] },
          "notes": { "type": "string" }
        }
      }
    },
    "session_history": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["seq", "when", "purpose", "achievements", "length"],
        "properties": {
          "seq": { "type": "integer" },
          "when": { "type": "string", "format": "date-time" },
          "purpose": { "type": "string" },
          "achievements": { "type": "array", "items": { "type": "string" } },
          "length": { "type": "string" }
        }
      }
    }
  }
}
Hook Input Schema (PreToolUse/PostToolUse)
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["hook_name", "session_id", "message", "tool_name"],
  "properties": {
    "hook_name": { "type": "string", "enum": ["PreToolUse", "PostToolUse", "SessionStart", "Stop", "UserPromptSubmit"] },
    "session_id": { "type": "string" },
    "message": {
      "type": "object",
      "properties": {
        "role": { "type": "string" },
        "content": { "type": "array" }
      }
    },
    "tool_name": { "type": "string" },
    "tool_input": { "type": "object" },
    "tool_output": { "type": "string" },
    "has_error": { "type": "boolean" }
  }
}
Deception Finding Schema
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["timestamp", "session_id", "findings_count", "findings", "tool_calls_count", "tools_used"],
  "properties": {
    "timestamp": { "type": "number" },
    "iso_time": { "type": "string", "format": "date-time" },
    "session_id": { "type": "string" },
    "findings_count": { "type": "integer" },
    "findings": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["type", "severity", "description"],
        "properties": {
          "type": { "type": "string" },
          "severity": { "type": "string", "enum": ["CRITICAL", "HIGH", "MEDIUM"] },
          "description": { "type": "string" },
          "evidence": { "type": "string" }
        }
      }
    },
    "tool_calls_count": { "type": "integer" },
    "tools_used": { "type": "array", "items": { "type": "string" } },
    "assistant_message_length": { "type": "integer" },
    "assistant_message_preview": { "type": "string" }
  }
}
Read Throttle State Schema
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "reads": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["timestamp", "path"],
        "properties": {
          "timestamp": { "type": "number" },
          "path": { "type": "string" }
        }
      }
    }
  }
}

Technical Design

Hook Event Flow
SESSION LIFECYCLE
=================

SessionStart
  ├── session_auto_start.py ──── Creates session entry in context.json
  │                               (guards against duplicate creation on compaction)
  └── session_context_hook.py ── Injects session context into conversation

UserPromptSubmit
  ├── session_close_hook.py ──── Detects "cts"/"close the session"
  │                               → Generates RTM from @traces decorators
  │                               → Calls SessionController.end()
  │                               → Creates annotated git tag
  │                               → Updates CHANGELOG.md
  │                               → Pushes tag and branch to origin
  ├── session_open_hook.py ───── Detects "sns"/"start new session"
  │                               → Injects pending tasks + project metrics
  └── remember_hook.py ────────── Detects "remember when"/"do you remember"
                                  → Searches Neo4j conversation history
                                  → Injects results as additionalContext

PRE-TOOL HOOKS
==============

PreToolUse(Write)
  ├── intercept_write.py ──────── BLOCKS if file exists (use Edit instead)
  │                               BLOCKS writes to ~/.claude/plans/
  │                               BLOCKS writes to context.md/context.json
  │                               Logs operation to audit file
  └── block_except_pass.py ────── BLOCKS bare `except:` in Python code
                                  BLOCKS `except ...: pass` patterns
                                  Uses ast.parse for accurate detection

PreToolUse(Edit)
  ├── intercept_edit.py ────────── Git checkpoint before edits
  │                                Logs operation to audit file
  └── block_except_pass.py ────── Same bare-except checks as Write

PreToolUse(Read|Grep)
  └── read_throttle.py ────────── Tracks reads in /tmp/claude-read-tracker.json
                                  Allows 3 reads per 30-second window
                                  Exempts context.json, .env, settings.json, CLAUDE.md
                                  BLOCKS excess reads with Neo4j redirect message

PreToolUse(Bash)
  └── intercept_bash.py ────────── BLOCKS rm, unlink, rmdir, shred
                                   BLOCKS writes to ~/.claude/ directory
                                   Creates git checkpoint before deletions
                                   Logs all operations to audit file

PreToolUse(.*)
  └── enforcement_hook.py ──────── Central rule enforcement
                                   Checks all tool uses against project rules

POST-TOOL HOOKS
===============

PostToolUse(Edit)
  └── log_operation.py ─────────── Logs Edit operations to audit file

PostToolUse(Write|Edit|Bash|Read|Glob|Grep)
  └── log_operation.py ─────────── Logs all tool operations to audit file

PostToolUse(.*)
  └── posttool_auditor.py ──────── Accumulates tool calls in session JSONL
                                   Records tool_name, has_error, output_length

PostToolUse(Write|Edit) [when file is context.json]
  └── sync_context_md.py ──────── Regenerates context.md from context.json
                                  via ContextManager.write()

STOP HOOKS
==========

Stop
  ├── error_gate_hook.py ──────── Runs 6 check categories on modified files:
  │     ├── checks_syntax.py ──── ast.parse() on modified .py files
  │     ├── checks_lint.py ────── flake8 --select=E9,F82,F83,F84
  │     ├── checks_test.py ────── pytest on changed test files (non-prolog)
  │     └── checks_structure.py ─ Stub methods, nesting >4, god objects
  │   BLOCKS session end if any errors found
  │   Injects fix instructions into additionalContext
  │
  └── stop_auditor.py ─────────── Extracts assistant messages from transcript
        ├── detect_deception() ── Pattern matching: claims vs tool usage
        │     ├── File creation without Write/Edit
        │     ├── Command execution without Bash
        │     ├── File reading without Read/Grep
        │     ├── Error concealment (tool errors not reported)
        │     ├── Selective disclosure (many ops, tiny response)
        │     └── Result hiding (large output, no mention)
        ├── log_findings() ────── Appends to deception_log.jsonl
        └── archive_session() ── Moves session JSONL to dated archive
Deployment Architecture
Source (version-controlled)          Deployed (runtime)
========================           ==================

claude/                            ~/.claude/
├── hooks/                         ├── hooks/
│   ├── error_gate/                │   ├── error_gate/
│   │   ├── __init__.py            │   │   ├── __init__.py
│   │   ├── checks_syntax.py      │   │   ├── checks_syntax.py
│   │   ├── checks_lint.py        │   │   ├── checks_lint.py
│   │   ├── checks_test.py        │   │   ├── checks_test.py
│   │   ├── checks_structure.py   │   │   ├── checks_structure.py
│   │   └── utils.py              │   │   └── utils.py
│   ├── stop_audit/                │   ├── stop_audit/
│   │   ├── __init__.py            │   │   ├── __init__.py
│   │   ├── deception.py           │   │   ├── deception.py
│   │   ├── transcript.py          │   │   ├── transcript.py
│   │   └── subagent.py            │   │   └── subagent.py
│   ├── session_auto_start.py     │   ├── session_auto_start.py
│   ├── session_close_hook.py     │   ├── session_close_hook.py
│   ├── session_open_hook.py      │   ├── session_open_hook.py
│   ├── read_throttle.py          │   ├── read_throttle.py
│   ├── block_except_pass.py      │   ├── block_except_pass.py
│   ├── intercept_bash.py         │   ├── intercept_bash.py
│   ├── intercept_write.py        │   ├── intercept_write.py
│   ├── intercept_edit.py         │   ├── intercept_edit.py
│   ├── enforcement_hook.py       │   ├── enforcement_hook.py
│   ├── instruction_enforcer.py   │   ├── instruction_enforcer_hook.py
│   ├── sync_context_md.py        │   ├── sync_context_md.py
│   ├── remember_hook.py          │   ├── remember_hook.py
│   ├── log_operation.py          │   ├── log_operation.py
│   ├── posttool_auditor.py       │   ├── posttool_auditor.py
│   ├── block_file_tools.py       │   ├── block_file_tools.py
│   ├── stop_auditor.py           │   ├── stop_auditor.py
│   ├── stop_auditor_subagent.py  │   ├── stop_auditor_subagent.py
│   ├── session_context_hook.py   │   └── session_context_hook.py
│   └── deception_detector.py     │
├── tools/                         ├── tools/
│   ├── session_cli.py            │   ├── session_cli.py
│   └── statusline_session.py     │   ├── statusline_session.py
├── scripts/                       │   └── session/
│   └── strip_traces.py           │       ├── __init__.py
├── install.sh                     │       ├── models.py
├── settings.json                  │       ├── context.py
├── statusline-command.sh          │       ├── session.py
└── README.md                      │       ├── exceptions.py
                                   │       ├── archive.py
                                   │       ├── carryover.py
                                   │       ├── handover.py
                                   │       ├── portfolio.py
                                   │       ├── kg_context.py
                                   │       ├── kg_sync.py
                                   │       ├── spec_parser.py
                                   │       └── templates/
                                   ├── audit/
                                   │   ├── sessions/     (active JSONL)
                                   │   ├── archive/      (dated, NEVER deleted)
                                   │   └── findings/     (deception_log.jsonl)
                                   ├── logs/
                                   │   └── file_operations.log
                                   ├── settings.json
                                   └── statusline-command.sh
Settings Registration

The ~/.claude/settings.json file registers hooks by event type with matchers:

{
  "hooks": {
    "PreToolUse": [
      { "matcher": "Edit",  "hooks": [{ "command": "intercept_edit.py" }] },
      { "matcher": "Bash",  "hooks": [{ "command": "intercept_bash.py" }] },
      { "matcher": "Write", "hooks": [{ "command": "intercept_write.py" }] },
      { "matcher": ".*",    "hooks": [{ "command": "enforcement_hook.py" }] }
    ],
    "PostToolUse": [
      { "matcher": "Edit",                         "hooks": [{ "command": "log_operation.py" }] },
      { "matcher": "Write|Edit|Bash|Read|Glob|Grep", "hooks": [{ "command": "log_operation.py" }] },
      { "matcher": ".*",                            "hooks": [{ "command": "posttool_auditor.py" }] }
    ],
    "SessionStart": [
      { "hooks": [{ "command": "session_auto_start.py" }] },
      { "hooks": [{ "command": "session_context_hook.py" }] }
    ],
    "Stop": [
      { "hooks": [{ "command": "stop_auditor.py" }] }
    ],
    "UserPromptSubmit": [
      { "hooks": [{ "command": "session_close_hook.py" }] }
    ]
  }
}

Error Gate Package

The error gate is a Stop hook that runs 6 check categories against recently modified files. If any check produces errors, the session stop is blocked with detailed fix instructions.

checks_syntax.py

Purpose: Detect Python syntax errors in modified files.

Method: Uses git diff --name-only --diff-filter=M HEAD to find modified .py files, then runs ast.parse() on each one. Syntax errors are reported with file path and error message (truncated to 200 chars).

Timeout: Inherits CHECK_TIMEOUT (30 seconds) from utils.py.

checks_lint.py

Purpose: Detect critical lint errors that indicate broken code.

Method: Runs uv run flake8 --select=E9,F82,F83,F84 on modified .py files (capped at 30 files). Only checks for:

Reports up to 10 lint errors.

checks_test.py

Purpose: Run a quick subset of tests to catch regressions.

Method: Identifies changed test files under tests/ from git diff --name-only HEAD~1. Excludes:

Runs uv run pytest with -x -q --no-header on up to 10 test files. Ignores exit code 139 (pyswip SIGSEGV crash). Only reports lines containing "FAILED".

Timeout: 300 seconds (5 minutes).

checks_structure.py

Purpose: Detect structural code quality issues in source code (not tests).

Stub Detection:

Nesting Depth:

God Objects:

utils.py

Purpose: Shared utilities for all error gate check modules.

Constants:

Functions:


Stop Audit Package

The stop audit package analyzes the session transcript at conversation end to detect potential deception -- cases where Claude's narrative claims do not match actual tool usage.

deception.py

Purpose: Pattern-based deception detection engine.

Pre-processing: _remove_quoted_content() strips code blocks (triple backtick), inline code (single backtick), blockquotes (>), and HTML pre/code tags to prevent false positives from displayed code.

Deception Categories:

Category Severity Detection Method
File creation claimed without Write/Edit CRITICAL Regex patterns for "created/wrote/saved the file" when Write/Edit not in tools_used
Command execution claimed without Bash CRITICAL Regex patterns for "ran/executed the command" when Bash not in tools_used
File reading claimed without Read/Grep HIGH Regex patterns for "read/examined/reviewed the file" when Read/Grep not in tools_used
Error concealment CRITICAL Tool calls with has_error=True but no error-related words in response
Selective disclosure MEDIUM More than 10 tool calls but response under 100 characters
Result hiding MEDIUM Tool output >500 chars with <3 overlapping 6+ char words in response

Output: List of finding dicts with type, severity, description, evidence, and optionally pattern_matched and tool_name.

transcript.py

Purpose: Parse JSONL transcripts into assistant message text.

Method: Reads transcript line by line, extracts entries with message.role == "assistant", collects text from string content or typed content blocks (type == "text"), joins with newlines.

subagent.py

Purpose: Handle SubagentStop events (Claude Code subagent sessions).

Method: Detects SubagentStop events in hook input, parses subagent transcripts, extracts tool names and text content from content blocks, runs the same detect_deception() logic, and logs findings to a separate ~/.claude/audit/subagent_findings/ directory.


Session Management

Session Module

Deployed to ~/.claude/tools/session/ from packages/orchestrata-session/src/orchestrata/session/. The install.sh script:

  1. Copies all session module files
  2. Runs strip_traces.py to remove @traces decorators (monorepo dependency)
  3. Removes imports for EventEmittingSessionController, prolog_interface, facts, constants, hook_registry (not needed standalone)

Key classes:

session_cli.py

CLI wrapper for session operations, callable via Bash tool:

python3 ~/.claude/tools/session_cli.py status
python3 ~/.claude/tools/session_cli.py begin --purpose "Focus text"
python3 ~/.claude/tools/session_cli.py log-work --desc "Description"
python3 ~/.claude/tools/session_cli.py end --achievements "item1" "item2"
python3 ~/.claude/tools/session_cli.py init --version 1.0.0 --branch master
context.json Structure
{
  "state": {
    "session": 89,
    "version": "0.6.0",
    "branch": "master",
    "test_count": 9203,
    "status": "active"
  },
  "deferred_work": [
    {
      "id": "DW-001",
      "priority": "high",
      "description": "...",
      "status": "pending",
      "notes": "..."
    }
  ],
  "session_history": [
    {
      "seq": 89,
      "when": "2026-03-29T10:00:00",
      "purpose": "...",
      "achievements": ["..."],
      "length": "2h30m"
    }
  ]
}
Session Close Sequence

When the user types "cts" or "close the session":

  1. RTM Generation: Runs 3 scripts to extract @traces decorators from source code, generating requirements traceability matrices committed to plans/
  2. Achievement Extraction: Parses git log since session start tag, extracts commit messages as achievements
  3. context.json Update: Calls SessionController.end() which updates session length, achievements, and status
  4. Git Tag: Creates annotated tag session-NNN-YYYY-MM-DD-HHMM
  5. CHANGELOG.md: Appends categorized achievements under version heading
  6. Push: Pushes session tag and current branch to origin
Session Auto-Start Guards

The session_auto_start.py hook guards against phantom sessions caused by context compaction (which re-fires SessionStart):


Safety Hooks

intercept_bash.py

Event: PreToolUse(Bash)

Blocks:

Allows: All other Bash commands.

Audit: Logs blocked operations to ~/.claude/logs/file_operations.log as JSONL.

intercept_write.py

Event: PreToolUse(Write)

Blocks:

Allows: New file creation to any other path.

Audit: Logs all operations (allowed and blocked) to ~/.claude/logs/file_operations.log.

intercept_edit.py

Event: PreToolUse(Edit)

Actions: Creates git checkpoint before edits, logs operation to audit file.

block_except_pass.py

Event: PreToolUse(Write|Edit)

Blocks:

Method: Uses ast.parse() to build AST, walks all ExceptHandler nodes. Only checks .py files. Reports line numbers and suggests specific exception types with logging.

Allows: Non-Python files and properly typed exception handlers.


Neo4j Integration

read_throttle.py

Event: PreToolUse(Read|Grep)

Mechanism:

remember_hook.py

Event: UserPromptSubmit

Triggers: Regex patterns for memory-related phrases:

Method: Extracts topic words from the prompt after the trigger phrase. Executes a Neo4j Cypher query against Conversation and ConversationTurn nodes, matching all topic words (length > 2) against toLower(t.text). Returns up to 15 results ordered by timestamp descending.

Output: Injects search results as additionalContext so Claude sees past conversation history as facts before processing the user message.

Timeout: 15 seconds for Neo4j query execution.

block_file_tools.py

Event: PreToolUse(Read|Grep) (when active)

Method: Queries Neo4j on every file read, injecting:


Audit Trail

Storage Layout
~/.claude/audit/
├── sessions/           Active session JSONL files
│   └── {session_id}.jsonl
├── archive/            Completed sessions (dated subdirectories)
│   └── YYYY-MM-DD/
│       └── {session_id}_{timestamp}.jsonl
├── findings/           Deception detection results
│   └── deception_log.jsonl
└── subagent_findings/  Subagent deception results
    └── {subagent_id}_{timestamp}.jsonl
Log Files
~/.claude/logs/
└── file_operations.log    All Write/Edit/Bash operations (JSONL)
Data Retention
JSONL Formats

Tool Call Record:

{
  "type": "tool_call",
  "tool_name": "Write",
  "has_error": false,
  "tool_output": "...",
  "tool_output_length": 1234,
  "timestamp": "2026-03-29T10:15:00"
}

Deception Finding:

{
  "timestamp": 1743244500.0,
  "iso_time": "2026-03-29T10:15:00",
  "session_id": "session-089",
  "findings_count": 2,
  "findings": [
    {
      "type": "ACTION_DECEPTION",
      "severity": "CRITICAL",
      "description": "Claimed file creation but no Write/Edit tool was used",
      "evidence": "Tools used: ['Bash', 'Read']"
    }
  ],
  "tool_calls_count": 15,
  "tools_used": ["Bash", "Read", "Grep"],
  "assistant_message_length": 2500,
  "assistant_message_preview": "..."
}

File Operation Log Entry:

{
  "timestamp": "2026-03-29T10:15:00",
  "operation": "Write",
  "file_path": "/home/mohamed/workspace/orchestrata/new_file.py",
  "status": "allowed",
  "message": "Validation passed, Write tool will create file"
}

Deployment

install.sh

The deployment script (claude/install.sh) performs:

  1. Creates ~/.claude/hooks/, ~/.claude/tools/session/, ~/.claude/tools/session/templates/
  2. Copies session module from packages/orchestrata-session/src/orchestrata/session/ (13 files + templates)
  3. Removes monorepo-specific imports (EventEmittingSessionController, prolog_interface, facts, constants, hook_registry)
  4. Runs strip_traces.py to remove @traces decorators and orchestrata.core imports
  5. Copies session_cli.py and statusline_session.py to ~/.claude/tools/
  6. Copies statusline-command.sh to ~/.claude/
  7. Copies session_auto_start.py, session_close_hook.py, session_open_hook.py to ~/.claude/hooks/
  8. Copies general hooks: block_file_tools.py, intercept_write.py, intercept_bash.py, intercept_edit.py, instruction_enforcer_hook.py
  9. Registers SessionStart hook in ~/.claude/settings.json (idempotent JSON manipulation)
  10. Registers UserPromptSubmit hooks for session close and session open (idempotent)
strip_traces.py

Post-deploy cleanup script that:


Functional Requirements

FR-001: Hook Registration
FR-002: Hook Protocol
FR-003: Session Auto-Start
FR-004: Session Close
FR-005: Session Open
FR-006: Error Gate - Syntax
FR-007: Error Gate - Lint
FR-008: Error Gate - Tests
FR-009: Error Gate - Structure
FR-010: Deception Detection
FR-011: Safety - Bash
FR-012: Safety - Write
FR-013: Safety - Except
FR-014: Read Throttle
FR-015: Remember Hook
FR-016: Sync Context MD
FR-017: Audit Logging
FR-018: Deployment
FR-019: Subagent Handling
FR-020: Error Gate Integration

Error Conditions

ID Condition Handling
ERR-001 Syntax error in modified Python file Block session stop, inject fix instructions via additionalContext
ERR-002 Critical lint error (E9xx, F82x, F83x, F84x) Block session stop, report lint errors
ERR-003 Test failure in changed test file Block session stop, report failed test lines
ERR-004 Stub method detected (logging/pass only body) Block session stop, suggest implementing actual logic
ERR-005 Nesting depth exceeds 4 levels Block session stop, suggest refactoring
ERR-006 God object detected (class >300 lines or >15 methods) Block session stop, suggest splitting
ERR-007 File exceeds 500 lines Block session stop, suggest modularization
ERR-008 File creation claimed without Write/Edit tool Log CRITICAL deception finding, archive session
ERR-009 Command execution claimed without Bash tool Log CRITICAL deception finding, archive session
ERR-010 File reading claimed without Read/Grep tool Log HIGH deception finding, archive session
ERR-011 Tool error not mentioned in assistant response Log CRITICAL deception finding, archive session
ERR-012 Selective disclosure (>10 tools, <100 char response) Log MEDIUM deception finding, archive session
ERR-013 Result hiding (>500 char output, <3 overlapping words) Log MEDIUM deception finding, archive session
ERR-014 Bare except: in Python code Block operation, suggest specific exception type
ERR-015 except ...: pass pattern detected Block operation, suggest logging or specific handling
ERR-016 Write to existing file attempted Block operation, redirect to Edit tool
ERR-017 Write to ~/.claude/plans/ attempted Block operation, redirect to project plans/
ERR-018 Write to context.md/context.json attempted Block operation, redirect to session CLI
ERR-019 Destructive bash command (rm, unlink, rmdir, shred) Block operation, log to audit file
ERR-020 Bash write to ~/.claude/ directory Block operation, log to audit file
ERR-021 Read throttle exceeded (>3 reads per 30 seconds) Block operation, redirect to Neo4j queries
ERR-022 Neo4j connection failure in remember hook Fail gracefully, continue without context injection
ERR-023 RTM generation script failure Log error, do not block session close
ERR-024 context.json write failure Log error, do not block operation

API Contracts

NFR-001: Performance
NFR-002: Reliability
NFR-003: Data Integrity
NFR-004: Security

Security Requirements

Authentication
Authorization
Input Validation
Audit Logging

Governance

Constitutional Alignment

This harness enforces the Orchestrata constitutional articles through dedicated mechanisms:

Article Mechanism Implementation
I: Agent Autonomy intercept_write.py, intercept_bash.py File access boundaries enforced
II: Prolog as SSOT Read throttle → Neo4j → Prolog Governance remains in Prolog
III: Session Isolation context.json, git tags, archives Per-session state isolation
IV: Transparency log_operation.py, posttool_auditor.py Complete operation audit trail
V: Non-Deception stop_auditor.py Deception detection engine
VI: Quality Gates error_gate_hook.py 6-category code quality checks
VII: No Mocks checks_test.py Real pytest execution
VIII: Observability Audit logs, deception metrics Full operational visibility
IX: Graceful Degradation All hooks return {} on failure No crash behavior
X: Version Compatibility strip_traces.py Decoupled deployment
XI: Documentation First This spec, CLAUDE.md Comprehensive documentation
Policy Enforcement

Constitutional Compliance

This harness enforces the Orchestrata constitutional articles:

Article I: Agent Autonomy / Ownership Boundaries

Hooks enforce per-volk file access patterns. The intercept_write.py hook prevents overwriting files owned by other components. The intercept_bash.py hook blocks writes to ~/.claude/ which is system-owned. Enforcement operates at file-system boundaries, not at semantic ownership level.

Article II: Prolog as Single Source of Truth

Governance rules remain in Prolog; the harness does not duplicate governance logic. Error gate checks are structural code quality rules, not policy decisions. Read throttle redirects to knowledge graph which itself is governed by Prolog-backed policies.

Article III: Session Isolation

Session auto-start creates isolated session entries. Context.json maintains per-session state. Audit trail attributes findings to specific session IDs. Session close creates a clean boundary (git tag, archive).

Article IV: Hooks for Extensibility / Transparency

All operations are logged. The audit trail provides a complete record of every tool invocation, every blocked operation, and every deception finding. Diagnostic output goes to stderr for operator visibility.

Article V: Non-Deception / Minimal Core

The deception detector is the primary enforcement mechanism for Article V. It compares claims against actual tool usage, detecting fabricated file creation, command execution, and file reading. Error concealment detection ensures tool failures are reported.

Article VI: Quality Gates

The error gate is the primary enforcement mechanism for Article VI. It blocks session end when code has syntax errors, lint failures, test failures, stubs, deep nesting, or god objects. The block_except_pass hook prevents error-swallowing patterns.

Article VII: Testing Without Mocks

The error gate's test runner (checks_test.py) runs actual pytest tests on changed files. No mock infrastructure is involved. The harness itself follows the no-mocking policy.

Article VIII: Metrics and Observability

Audit logs provide observability into all hook operations. Deception findings provide metrics on AI trustworthiness. Session history in context.json tracks development velocity.

Article IX: Graceful Degradation

All hooks fail gracefully, returning {} on errors. Missing Neo4j returns null results. Missing flake8 skips lint checks. Corrupt JSONL lines are skipped. No hook failure crashes Claude Code.

Article X: Version Compatibility

The install.sh script handles version transitions by overwriting deployed files. Session module stripping (strip_traces.py) decouples deployed code from monorepo version.

Article XI: Documentation First

This specification documents the harness comprehensively before any modifications. Every hook has module-level and function-level docstrings. CLAUDE.md documents hook behavior for every conversation.


Non-Functional Requirements

NFR-001: Performance
NFR-002: Reliability
NFR-003: Data Integrity
NFR-004: Maintainability

Examples

Example 1: Session Auto-Start

When Claude Code starts:

Input: SessionStart event
Action: session_auto_start.py runs
- Checks context.json for active session
- If none active, creates new session entry
- Output: "Session 89 started at 2026-03-29T10:00:00"
Example 2: Error Gate Blocking Session Close

When user attempts to close session with broken code:

Input: Stop event
Action: error_gate_hook.py runs checks
- checks_syntax.py finds syntax error in src/main.py
- Session stop BLOCKED
- Output: {"decision": "block", "reason": "Syntax error in src/main.py..."}
Example 3: Deception Detection Finding

After a session where Claude claims to have created a file but used Bash:

Input: Stop event
Action: stop_auditor.py analyzes transcript
- Finds claim: "Created new_component.py"
- Tools used: ['Bash', 'Read', 'Grep'] (no Write/Edit)
- Logs: {"type": "ACTION_DECEPTION", "severity": "CRITICAL", ...}
- Archives session to ~/.claude/audit/archive/2026-03-29/
Example 4: Read Throttle Blocking

When Claude attempts more than 3 reads in 30 seconds:

Input: PreToolUse(Read) event for src/utils.py
Action: read_throttle.py checks tracker
- 3 reads already in window
- BLOCKED with message: "Use Neo4j queries instead: /code classes <pattern>"
Example 5: Session Close with Full Pipeline

User types "cts":

1. session_close_hook.py detects trigger
2. RTM generation scripts run → plans/rtm.md updated
3. Git log parsed → achievements extracted
4. context.json updated → session marked closed
5. Git tag created → session-089-2026-03-29-1000
6. CHANGELOG.md updated
7. Tag and branch pushed to origin

Visual Architecture

Class Diagram

Diagram source shown as text: Mermaid could not parse it (Error: Parse error on line 239:).

classDiagram
    class MultiAgentEditResult {
        +file_path: str
        +old_string: str
        +new_string: str
        +agent_results: dict[Any]
        +aggregated_result: dict[Any]
        +timestamp: datetime = Field()
        +success: bool = True
    }
    class GovernanceError {
    }
    class OrchestrataKernel {
        +__init__(self): None
        +_initialize_agents(self): None
        +get_agents_by_type(self, agent_type): list[Any]
        +get_agent_by_id(self, agent_id): Any
        +async broadcast_to_type(self, agent_type, message): list[Any]
        +async broadcast_to_all(self, message): list[Any]
        +async send_to_agent(self, agent_id, message, sender): Any
    }
    class UltimateOrchestrator {
        +__init__(self): None
        +async execute_multi_agent_edit(self, file_path, old_string, new_string): MultiAgentEditResult
        +_aggregate_agent_results(self, results): dict[Any]
        +async create_project(self, name, path, template): dict[Any]
        +async shutdown(self): None
    }
    class ThreadPoolTaskStatus {
        +PENDING = 'pending'
        +RUNNING = 'running'
        +COMPLETED = 'completed'
        +FAILED = 'failed'
        +CANCELLED = 'cancelled'
        +TIMEOUT = 'timeout'
    }
    class ThreadPoolTask {
        +task_id: str = field()
        +function: Any = None
        +args: tuple = field()
        +kwargs: dict[Any] = field()
        +status: ThreadPoolTaskStatus = .PENDING
        +created_at: datetime = field()
        +started_at: Any = None
        +completed_at: Any = None
        +result: Any = None
        +error: Any = None
        +traceback: Any = None
        +future: Any = None
        +metadata: dict[Any] = field()
    }
    class ThreadPoolManager {
        +__init__(self, max_workers, thread_name_prefix, initializer, initargs)
        +start(self): None
        +stop(self, wait, cancel_futures): None
        +submit(self, fn, *args, **kwargs): str
        +submit_many(self, functions, args_list, kwargs_list): list[str]
        +async submit_async(self, fn, *args, **kwargs): T
        +async submit_many_async(self, functions, args_list, kwargs_list): list[T]
        +async wait_for_task(self, task_id, timeout): Any
        +get_task_status(self, task_id): ThreadPoolTaskStatus
        +get_task_result(self, task_id, wait): Any
        +cancel_task(self, task_id): bool
        +get_stats(self): dict[Any]
        +_wrap_function(self, task_id, fn, *args, **kwargs): T
        +_update_task_from_future(self, task_id, future): None
        +task_context(self, task_id): Any
        +async async_task_context(self, task_id): Any
    }
    class ParallelTestExecutor {
        +__init__(self, thread_pool, max_workers)
        +run_tests_parallel(self, test_paths, pytest_args, timeout_per_test): dict[Any]
        +_run_single_test(self, test_path, pytest_args, timeout): dict[Any]
        +async run_tests_parallel_async(self, test_paths, pytest_args, timeout_per_test): dict[Any]
    }
    class LogLevel {
        +TRACE = 'TRACE'
        +DEBUG = 'DEBUG'
        +INFO = 'INFO'
        +WARNING = 'WARNING'
        +ERROR = 'ERROR'
        +CRITICAL = 'CRITICAL'
    }
    class LogContext {
        +__init__(self, logger, **context)
        +__enter__(self)
        +__exit__(self, exc_type, exc_val, exc_tb)
    }
    class LoggingContext {
        +request_id: Any = None
        +session_id: Any = None
        +trace_id: Any = None
        +span_id: Any = None
        +user_id: Any = None
        +user_email: Any = None
        +user_role: Any = None
        +component: Any = None
        +operation: Any = None
        +extra: dict[Any] = field()
        +created_at: datetime = field()
        ---
        +to_dict(self): dict[Any]
    }
    class ContextManager {
        +get_current_context(): LoggingContext
        +set_current_context(context): None
        +clear_context(): None
        +update_context(**kwargs): LoggingContext
        +create_child_context(**updates): LoggingContext
    }
    class AsyncContext {
        +__init__(self, **context_updates)
        +async __aenter__(self): LoggingContext
        +async __aexit__(self, exc_type, exc_val, exc_tb)
    }
    class Context {
        +__init__(self, **context_updates)
        +__enter__(self): LoggingContext
        +__exit__(self, exc_type, exc_val, exc_tb)
    }
    class AuditAction {
        +LOGIN = 'login'
        +LOGOUT = 'logout'
        +AUTH_FAILURE = 'auth_failure'
        +PERMISSION_CHECK = 'permission_check'
        +PERMISSION_DENIED = 'permission_denied'
        +READ = 'read'
        +CREATE = 'create'
        +UPDATE = 'update'
        +DELETE = 'delete'
        +EXPORT = 'export'
        +IMPORT = 'import'
        +CONFIG_CHANGE = 'config_change'
        +SERVICE_START = 'service_start'
        +SERVICE_STOP = 'service_stop'
        +BACKUP = 'backup'
        +RESTORE = 'restore'
        +USER_CREATE = 'user_create'
        +USER_UPDATE = 'user_update'
        +USER_DELETE = 'user_delete'
        +ROLE_ASSIGN = 'role_assign'
        +ROLE_REVOKE = 'role_revoke'
        +EXTERNAL_CALL = 'external_call'
        +WEBHOOK_RECEIVED = 'webhook_received'
        +API_CALL = 'api_call'
        +WORKFLOW_START = 'workflow_start'
        +WORKFLOW_COMPLETE = 'workflow_complete'
        +ESCALATION = 'escalation'
        +APPROVAL = 'approval'
        +REJECTION = 'rejection'
    }
    class AuditStatus {
        +SUCCESS = 'success'
        +FAILURE = 'failure'
        +PARTIAL = 'partial'
        +PENDING = 'pending'
    }
    class AuditEvent {
        +action: AuditAction
        +timestamp: datetime = field()
        +status: AuditStatus = .SUCCESS
        +actor_id: Any = None
        +actor_type: str = 'user'
        +actor_ip: Any = None
        +actor_user_agent: Any = None
        +resource_type: Any = None
        +resource_id: Any = None
        +resource_path: Any = None
        +operation_id: Any = None
        +operation_name: Any = None
        +operation_duration_ms: Any = None
        +before_state: Any = None
        +after_state: Any = None
        +changes: Any = None
        +request_id: Any = None
        +session_id: Any = None
        +trace_id: Any = None
        +span_id: Any = None
        +component: Any = None
        +severity: str = 'info'
        +details: Any = None
        +error_message: Any = None
        +error_stack: Any = None
        +event_hash: Any = None
        +previous_hash: Any = None
        ---
        +__post_init__(self)
        +calculate_hash(self): str
        +_json_serializer(self, obj)
        +to_dict(self): dict[Any]
        +verify_hash(self): bool
    }
    class AuditLogger {
        +__init__(self, component)
        +log_event(self, event): str
        +log_action(self, action, status, resource_type, resource_id, before_state, after_state, actor_id, actor_type, details, error_message, operation_duration_ms, severity): str
    }
    class AuditOperation {
        +action: Any
        +resource_type: Any = None
        +resource_id: Any = None
        +before_state: Any = None
        +actor_id: Any = None
        +actor_type: str = 'user'
        +component: Any = None
        +details: Any = None
        ---
        +__enter__(self)
        +__exit__(self, exc_type, exc_val, exc_tb)
    }
    class DomainEntity {
        +entity_id: str = Field()
        +is_active: bool = Field()
        ---
        +__init__(self, **data)
        +mark_inactive(self)
        +to_domain_dict(self): dict[Any]
        +get_business_key(self): str
        +__eq__(self, other): bool
        +__hash__(self): int
        +__repr__(self): str
    }
    class Node {
        +node_id: str = Field()
        +node_type: str = Field()
        +name: str = Field()
        +properties: dict[Any] = Field()
        +created_at: datetime = Field()
        +updated_at: datetime = Field()
        +version: int = Field()
        ---
        +to_graph_dict(self): dict[Any]
        +from_graph_dict(cls, data): Node
        +update_properties(self, **kwargs)
        +__str__(self): str
    }
    class Config {
        +arbitrary_types_allowed = True
        +json_encoders = {}
    }
    class TracingLevel {
        +OFF = 0
        +BASIC = 1
        +DETAILED = 2
        +DEBUG = 3
        ---
        +label(self): str
    }
    class TracingConfig {
        +model_config = ConfigDict()
        +enabled: bool = Field()
        +service_name: str = Field()
        +service_version: str = Field()
        +endpoint: Any = Field()
        +sample_rate: float = Field()
        +console_export: bool = Field()
        +tracing_level: TracingLevel = Field()
        ---
        +clamp_sample_rate(cls, v): float
    }
    class MetricsConfig {
        +__init__(self, enabled, port, host, include_system_metrics, system_metrics_interval)
    }
    class RetryStrategy {
        +__init__(self, max_retries, initial_delay, max_delay, backoff_factor, jitter)
        +calculate_delay(self, attempt): float
    }
    class CircuitState {
        +CLOSED = 'closed'
        +OPEN = 'open'
        +HALF_OPEN = 'half_open'
    }
    class CircuitBreaker {
        +__init__(self, failure_threshold, reset_timeout, half_open_max_requests, name)
        +is_closed(self): bool
        +is_open(self): bool
        +is_half_open(self): bool
        +record_success(self): None
        +record_failure(self): None
        +should_allow_request(self): bool
        +async execute(self, operation): T
    }
    class Bulkhead {
        +__init__(self, max_concurrent, max_queue_size, name)
        +async execute(self, operation): T
    }
    Node <|-- DomainEntity

Dependencies

Dependency Version Purpose
Claude Code CLI >=1.0 Runtime environment for hooks
Python 3.14t Hook script execution (with free-threading)
Neo4j 5.x Knowledge graph for context injection
Redis 7.x Session state caching (optional)
SWI-Prolog 9.0.4 Governance rule engine
flake8 latest Critical lint checking
pytest latest Test execution for error gate
uv latest Python package runner
Git any Version control for checkpoints and tagging
Jinja2 latest Template rendering for context.md

Testing Requirements

Test Scenarios
Coverage Targets
Quality Gates

Integration Points

Claude Code Integration
Neo4j Integration
Git Integration
File System Integration

Success Criteria

Session Management
Code Quality Enforcement
Deception Detection
Safety
Audit Trail

References


Observability

Logging Requirements
  1. 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
  1. Performance Metrics
    • Operation duration histograms
    • Request/error rate counters
    • Resource utilization gauges
    • Business metrics relevant to domain
Tracing Requirements
  1. Distributed Tracing
    • Trace propagation across component boundaries
    • Span attributes for domain-specific context
    • Trace sampling based on operational needs
Alerting Requirements
  1. Critical Alerts
    • Error rate spikes
    • Performance degradation
    • Resource exhaustion
    • Business metric anomalies
Dashboard Requirements
  1. Operational Dashboard
    • Real-time system health
    • Performance trends
    • Error analysis
    • Resource monitoring

Revision History

Version Date Author Changes
1.0.0 2026-03-29 Mohamed Initial specification
1.1.0 2026-04-09 Mohamed Fixed to comply with SPEC_STANDARD.md: Added 8-field Metadata (Spec ID, Title, Author, Status, Created, Last Updated, Priority, Version, Extends), added Error Conditions section (ERR-001 to ERR-024 in table format), added Data Models section with JSON schemas, added API Contracts section, added Examples section, added Security Requirements section, added Governance section, added Dependencies section, added Testing Requirements section, added Integration Points section, added Success Criteria section, added Revision History section

Last Updated: 2026-04-09 Version: 1.1.0 Maintained By: Mohamed