npm package: @mxcro/gentic
Description: Claude Code control plane plugin — evidence-first AI development enforced by deterministic gates
Latest version: 0.1.2

# gentic

Control plane plugin for Claude Code. Enforces evidence-first AI development through deterministic hooks, structured commands, specialized agents, and a queryable MCP server.

**Zero dependencies. Plain JS. No build step.**

```
npm: @mxcro/gentic
node: >= 22
platforms: macOS, Linux (Windows via WSL2)
```

---

## Table of Contents

- [What It Does](#what-it-does)
- [Quick Start](#quick-start)
- [Architecture](#architecture)
- [Hooks](#hooks)
- [Commands](#commands)
- [Agents](#agents)
- [MCP Server](#mcp-server)
- [Session Ledger](#session-ledger)
- [Configuration](#configuration)
- [CLI Reference](#cli-reference)
- [Workflows](#workflows)
- [Safety Model](#safety-model)
- [Development](#development)
- [Troubleshooting](#troubleshooting)

---

## What It Does

gentic wraps Claude Code's agent loop with three control surfaces:

| Surface | Mechanism | Direction |
|---------|-----------|-----------|
| **Hooks** | Deterministic gates on tool use, session lifecycle, and completion | Push (automatic) |
| **MCP Server** | Queryable repo intelligence via JSON-RPC over stdio | Pull (on-demand) |
| **Subagents** | Tool-restricted specialists that enforce separation of concerns | Delegated |

Together they enforce:
- **Safety** — Dangerous commands blocked before execution. File edits risk-classified. Secrets redacted from all persistence.
- **Visibility** — Every file change logged to a per-session JSONL ledger with timestamps, risk levels, and diffs.
- **Discipline** — Verification required before completion. Plans precede patches. Reviews precede shipping.

---

## Quick Start

### Install (per project)

From your project root:

```bash
npx @mxcro/gentic@latest init
```

This is idempotent. It creates:

| Artifact | Location | Purpose |
|----------|----------|---------|
| Runtime directory | `.gentic/` | Sessions, logs, reports |
| Hook registrations | `.claude/settings.json` | Claude Code hook wiring |
| MCP server registration | `.claude/.mcp.json` | MCP tool access |
| Slash commands | `.claude/commands/gentic/*.md` | `/gentic:*` commands |
| Agent definitions | `.claude/agents/*.md` | Specialized subagents |
| Config file | `gentic.json` | Runtime configuration |
| Gitignore entry | `.gitignore` | Excludes `.gentic/` |

Existing `.claude/settings.json` is backed up before merging.

### Install (global)

Run `gentic init` from `~` to write to `~/.claude/*`. Hooks then run in every Claude Code project. Session data still lands in each project's `.gentic/`. Machine-specific — rerun if you change users/machines.

**Recommendation:** Per-project for team reproducibility. Global only for personal "always on" policy.

### Update

```bash
npx @mxcro/gentic@latest init
```

### Uninstall

```bash
npx @mxcro/gentic uninstall          # Removes hooks/commands/agents, preserves sessions
npx @mxcro/gentic uninstall --all    # Also removes .gentic/ (sessions, logs, reports)
```

---

## Architecture

```
┌─────────────────────────────────────────────────────────┐
│                     Claude Code                          │
│                                                          │
│  User prompt ──▶ [snapshot-inject] ──▶ Agent loop        │
│                                         │                │
│                    ┌────────────────────┘                 │
│                    ▼                                      │
│              Tool call                                    │
│                    │                                      │
│         ┌─────────┼──────────┐                           │
│         ▼         ▼          ▼                            │
│   [guard-bash] [edit-gate]  ...   ◀── PreToolUse hooks   │
│         │         │          │                            │
│         ▼         ▼          ▼                            │
│      Execute    Execute   Execute                        │
│         │         │          │                            │
│         ▼         ▼          ▼                            │
│   [diff-digest] [post-failure-log]  ◀── PostToolUse      │
│                                                          │
│  Agent done ──▶ [stop-gate] ◀── requires Verification:   │
│                                   and Risk: markers       │
│                                                          │
│  Compact ──▶ [compact-summarize] ◀── preserves state     │
│                                                          │
│  ┌─────────────────────────────────────────────────┐     │
│  │ MCP Server (stdio)                              │     │
│  │  repo_snapshot | cochange_graph | reference_graph│     │
│  │  diff_digest   | ledger_search                  │     │
│  └─────────────────────────────────────────────────┘     │
│                                                          │
│  ┌─────────────────────────────────────────────────┐     │
│  │ Subagents (tool-restricted)                     │     │
│  │  cartographer | librarian | architect | surgeon  │     │
│  │  verifier | reviewer | scribe | researcher      │     │
│  │  auditor | debugger                             │     │
│  └─────────────────────────────────────────────────┘     │
└─────────────────────────────────────────────────────────┘
```

### Data Flow

1. **SessionStart** — `session-start.js` creates/rotates a session ledger directory
2. **Every user prompt** — `snapshot-inject.js` injects a bounded repo snapshot + session digest into context
3. **Every Bash call** — `guard-bash.js` checks against dangerous patterns; blocks or asks
4. **Every Write/Edit** — `edit-gate.js` classifies file risk; escalates critical paths to user
5. **After Write/Edit** — `diff-digest.js` logs the change to the session's `changes.jsonl`
6. **After tool failure** — `post-failure-log.js` records the failure to the ledger
7. **Before compaction** — `compact-summarize.js` summarizes the session so state persists across context window resets
8. **On stop** — `stop-gate.js` checks for `Verification:` and `Risk:` markers; blocks if missing
9. **Statusline** — `statusline.js` shows model, task, context usage, and session changes

---

## Hooks

Hooks are the push-based control surface. They execute automatically on Claude Code lifecycle events.

### Hook Summary

| Hook | Event | Fail Mode | Purpose |
|------|-------|-----------|---------|
| `session-start` | SessionStart | open | Create session ledger, prune old sessions |
| `guard-bash` | PreToolUse (Bash) | **closed** | Block dangerous shell commands |
| `edit-gate` | PreToolUse (Write\|Edit) | open | Risk-classify file paths |
| `diff-digest` | PostToolUse (Write\|Edit) | open | Log changes to session ledger |
| `post-failure-log` | PostToolUseFailure | open | Log tool failures to ledger |
| `snapshot-inject` | UserPromptSubmit | open | Inject repo snapshot + session digest |
| `compact-summarize` | PreCompact | open | Preserve session state across compaction |
| `stop-gate` | Stop | open | Require verification before completion |
| `statusline` | Notification | open | Display status bar info |

**Fail mode:**
- `open` — Hook crash/timeout = allow the action (safe default for non-security hooks)
- `closed` — Hook crash/timeout = block the action (used for security-critical hooks like `guard-bash`)

### guard-bash (Safety Gate)

Blocks dangerous shell patterns before Bash tool execution. Patterns are matched against the command string after stripping quoted regions (reduces false positives from `echo "rm -rf"`).

**Hard-blocked patterns** (deny):
- Filesystem destruction: `rm -rf /`, `mkfs`, `dd if=`, fork bombs
- Privilege escalation: `chmod 777`, `chown root`
- Code execution from network: `curl | sh`, `wget | sh`, `eval $(curl`
- Git destruction: `git push --force main`, `git reset --hard`, `git clean -f`
- Secret exfiltration: `env | curl`, `cat .env | wget`
- Process manipulation: `kill -9 -1`, `shutdown`, `reboot`
- Backdoors: `xmrig`, `nc -l`, `/dev/tcp`

**Borderline patterns** (ask by default):
- `rm -r` (non-forced recursive delete)
- `chmod` (permission change)
- `git push --force` (non-main branches)

Customizable via `gentic.json`:
```json
{
  "guardBash": {
    "extraPatterns": [
      { "pattern": "\\bdocker\\s+rm", "label": "docker container removal" }
    ],
    "disabledPatterns": ["killall"],
    "borderlineAction": "ask"
  }
}
```

### edit-gate (Risk Classification)

Classifies file paths into risk levels before Write/Edit operations:

| Level | Action | Default Paths |
|-------|--------|---------------|
| **critical** | `ask` (user prompt) | `.github/workflows/`, `Dockerfile`, `docker-compose`, `infra/`, `deploy/`, `.env`, `terraform/`, `k8s/` |
| **high** | `allow` with warning | `package.json`, `tsconfig.json`, `.eslintrc`, `gentic.json`, `Cargo.toml`, `go.mod` |
| **medium** | silent allow | `src/`, `lib/`, `app/`, `core/`, `server/`, `api/` |
| **low** | silent allow | `test/`, `docs/`, `*.md`, `README`, `LICENSE` |

Customizable via `gentic.json`:
```json
{
  "risk": {
    "criticalPaths": [".github/workflows/", "Dockerfile", "infra/", "deploy/"],
    "highPaths": ["package.json", "tsconfig.json"]
  }
}
```

### stop-gate (Completion Gate)

When the agent tries to stop after making changes, this hook checks for:

1. **Verification marker** — A line matching `^Verification:\s+` in the assistant output
2. **Risk marker** — A line matching `^Risk:\s+` in the assistant output
3. **Ledger fallback** — If assistant output unavailable, checks for verification entries in the session ledger

If markers are missing, the hook exits with code 2 (block), forcing the agent to run verification before completing.

### snapshot-inject (Context Awareness)

On every user prompt, injects two pieces of context:

1. **Repo snapshot** (≤6KB) — File tree, manifests, git state, hotspots, risk zones
2. **Session digest** (≤4KB) — Recent changes from the ledger, sorted by risk level (critical first)

Total injection budget: ≤10KB. Secrets are redacted before injection.

### diff-digest (Change Tracking)

After every Write/Edit, logs a structured entry to `changes.jsonl`:

```json
{
  "timestamp": "2025-01-15T14:32:01.234Z",
  "tool": "Edit",
  "filePath": "src/api/handler.ts",
  "riskLevel": "medium",
  "riskLabel": "Source code",
  "editType": "patch",
  "linesAdded": 5,
  "linesRemoved": 2,
  "diff": "- old code\n+ new code",
  "diff_basis": "payload",
  "session": "session-id"
}
```

For Write operations, diffs against the git baseline (HEAD → index → none cascade).

### compact-summarize (State Persistence)

Before Claude Code compacts the context window, summarizes the session into a concise block that survives compaction:

```
=== Gentic Session Summary (pre-compaction) ===

Changes: 12 operations across 5 files
Risk: 0 critical, 1 high, 3 medium, 8 low

Most-modified files:
  src/api/handler.ts (4 ops, +45/-12, risk:medium)
  src/core/engine.ts (3 ops, +30/-5, risk:medium)

Verification: 3/3 passed

=== End Summary ===
```

---

## Commands

Commands are slash commands available inside Claude Code after installation. They live in `.claude/commands/gentic/` as markdown files that define execution prompts for the agent.

### Command Reference

| Command | Purpose | Spawns Agent |
|---------|---------|--------------|
| `/gentic:snapshot` | Repo overview — file tree, manifests, git state, hotspots, risk zones | cartographer |
| `/gentic:context <path>` | Neighborhood context pack — imports, tests, co-change neighbors, references | librarian |
| `/gentic:research <topic>` | Deep codebase research — patterns, conventions, dependencies, prior art | researcher |
| `/gentic:plan <request>` | Implementation plan — ordered tasks, risk assessment, must-haves, verification plan | architect |
| `/gentic:patch [plan]` | Apply changes — minimal diffs, per-task atomic commits, deviation handling | surgeon |
| `/gentic:verify` | Run all project checks + 3-level artifact verification + stub detection | verifier |
| `/gentic:ship [--skip-review] [--force]` | Full release gate — verify + review + ship/no-ship verdict | verifier → reviewer |
| `/gentic:quick <task>` | Small task with safety rails — skip full ceremony, keep guardrails | surgeon → verifier |
| `/gentic:debug <symptom>` | Hypothesis-driven bug diagnosis — reproduce, test, narrow to root cause | debugger |
| `/gentic:audit [plan]` | Plan vs. reality comparison — gaps, drift, stubs, scope creep | auditor |
| `/gentic:resume [session-id]` | Reconstruct previous session state from ledger data | scribe |
| `/gentic:progress` | Current session dashboard — changes, verification, plan completion | scribe |

### Typical Workflow

```
/gentic:snapshot                    # Orient — understand the repo
/gentic:context src/api/handler.ts  # Focus — understand the neighborhood
/gentic:research "error handling"   # Research — understand patterns
/gentic:plan "add pagination"       # Plan — decompose with risk + must-haves
/gentic:patch                       # Execute — surgical edits, atomic commits
/gentic:verify                      # Check — tests, stubs, wiring
/gentic:ship                        # Ship — verify + review + verdict
```

For smaller tasks:
```
/gentic:quick "fix typo in error message"
```

For debugging:
```
/gentic:debug "API returns 500 on user creation"
```

To resume after a context reset or new session:
```
/gentic:resume
/gentic:progress
```

### Plan Format

Plans use XML task format with goal-backward must-haves:

```xml
<plan>
  <objective>Add pagination to user listing</objective>
  <discovery_level>0</discovery_level>

  <must_haves>
    <truths>
      <truth>GET /users?page=1&limit=10 returns paginated results</truth>
    </truths>
    <artifacts>
      <artifact path="src/api/pagination.ts" provides="Pagination helper"/>
    </artifacts>
    <key_links>
      <link from="controller.ts" to="pagination.ts" via="import and usage"/>
    </key_links>
  </must_haves>

  <tasks>
    <task type="auto">
      <name>Add pagination middleware</name>
      <files>src/api/middleware/pagination.ts</files>
      <action>Create pagination helper...</action>
      <verify>File exists, exports parsePagination</verify>
      <done>parsePagination returns correct offset/limit</done>
      <risk level="low">New file, no existing code affected</risk>
    </task>
  </tasks>

  <verification_plan>
    <check name="Unit tests" command="npm test" covers="1,2"/>
  </verification_plan>
</plan>
```

**Context budget:** 2-3 tasks per plan (~50% context usage). Larger work splits into multiple plans.

### Deviation Rules

During patching, the surgeon handles unplanned issues automatically:

| Rule | Trigger | Action |
|------|---------|--------|
| Rule 1 | Bug (type error, broken behavior) | Auto-fix, track |
| Rule 2 | Missing critical (validation, security) | Auto-add, track |
| Rule 3 | Blocking issue (missing dep, broken import) | Auto-fix, track |
| Rule 4 | Architectural change (schema, breaking API) | **STOP**, return to user |

### Verification Levels

The verifier checks artifacts at three levels:

| Level | Check | Example |
|-------|-------|---------|
| 1. Exists | File is present on disk | `src/api/pagination.ts` exists |
| 2. Substantive | Real implementation, not a stub | Not just `return {}` or `TODO` |
| 3. Wired | Connected to the rest of the system | Imported and used by controller |

Stubs detected: `TODO`, `FIXME`, `return null`, `return {}`, `=> {}`, empty handlers, unwired components.

### Ship Verdicts

| Verification | Goal Status | Review | Verdict |
|-------------|-------------|--------|---------|
| pass | verified | approve | **SHIP** |
| pass | verified | comment (low) | **SHIP** (with notes) |
| pass | verified | request-changes | **NO-SHIP** |
| pass | gaps_found | any | **NO-SHIP** |
| fail | any | any | **NO-SHIP** |

---

## Agents

Agents are tool-restricted subagents spawned by commands. They enforce separation of concerns through explicit tool allow/deny lists.

| Agent | Model | Allowed Tools | Purpose |
|-------|-------|---------------|---------|
| **cartographer** | haiku | Read, Glob, Grep | Builds bounded repo snapshots |
| **librarian** | sonnet | Read, Glob, Grep | Produces file neighborhood context packs |
| **researcher** | sonnet | Read, Glob, Grep | Deep codebase research and analysis |
| **architect** | sonnet | Read, Glob, Grep | Implementation plans with risk assessment |
| **surgeon** | sonnet | Read, Write, Edit, Glob, Grep, Bash | Applies minimal diffs, per-task atomic commits |
| **verifier** | haiku | Bash, Read, Glob, Grep | Runs checks, verifies artifacts, detects stubs |
| **reviewer** | sonnet | Read, Glob, Grep | Critiques diffs for security, performance, correctness |
| **scribe** | haiku | Read, Glob, Grep | Builds session handoff/resume documents |
| **auditor** | sonnet | Read, Glob, Grep | Validates implementation against plans |
| **debugger** | sonnet | Read, Glob, Grep, Bash | Hypothesis-driven bug diagnosis |

**Key design principle:** Read-only agents cannot write files. Write-capable agents cannot spawn sub-agents. This prevents cascading uncontrolled modifications.

---

## MCP Server

The MCP server exposes gentic's intelligence tools to Claude Code via JSON-RPC over stdio.

### Tools

| Tool | Parameters | Returns |
|------|-----------|---------|
| `repo_snapshot` | `maxDepth?`, `includeHotspots?`, `includeRiskZones?` | Bounded JSON snapshot (≤5KB) — tree, manifests, git, hotspots, risks |
| `cochange_graph` | `path` (required), `maxResults?`, `since?` | Files that frequently change alongside the target |
| `reference_graph` | `query` (required), `maxResults?`, `fileTypes?` | Files referencing a symbol/path via ripgrep |
| `diff_digest` | `path` (required) | Structured diff summary with risk classification |
| `ledger_search` | `pattern?`, `field?`, `ledger?`, `maxSessions?` | Search across session ledger entries |

### Security

- **Path traversal prevention** — All path params normalized and jailed to repo root. Symlink escape detection.
- **Response size limit** — All responses bounded to ≤5KB.
- **Secret redaction** — All responses pass through `redactSecrets()` before returning.
- **Input validation** — Required parameters enforced, types checked, enums validated.
- **Crash recovery** — Uncaught exceptions and unhandled rejections logged to `.gentic/logs/`.
- **Graceful degradation** — Returns `{ ok: false }` if git or ripgrep unavailable (rg is the only search backend, no grep fallback).

---

## Session Ledger

Every Claude Code session gets its own JSONL ledger under `.gentic/sessions/<timestamp>/`.

### Ledger Files

| File | Content |
|------|---------|
| `changes.jsonl` | Every Write/Edit operation — file path, risk level, lines changed, diff summary |
| `verifications.jsonl` | Every test/lint/check result — command, status, duration |

### Atomicity

Writes use `O_APPEND` + single `writeSync` for atomic JSONL appends. No partial lines, no corruption from concurrent hooks.

### Session Lifecycle

1. **SessionStart** hook creates the session directory and writes `.gentic/.current-session`
2. **Retention** — Old sessions auto-pruned by `retentionCount` (default: 30)
3. **Resume** — `/gentic:resume` reads the ledger to reconstruct previous session state

### Redaction

All ledger entries pass through `redactSecrets()` which catches:
- API keys (`sk-*`, `ghp_*`, `ghs_*`, `AKIA*`, `xox*-*`)
- Bearer tokens
- PEM private keys
- Credentials in URLs (`://user:pass@`)
- Environment variables matching `SECRET`, `TOKEN`, `KEY`, `PASSWORD`, `CREDENTIAL`, `API_KEY`, `AUTH`, `PRIVATE`

Benign environment variables (`PATH`, `HOME`, `NODE_ENV`, etc.) are not redacted.

---

## Configuration

All configuration lives in `gentic.json` at the project root. Hooks read it at runtime — no build step needed.

### Full Default Config

```json
{
  "$schema": "./config/gentic-schema.json",
  "hooks": {
    "session-start": { "enabled": true, "failMode": "open" },
    "guard-bash":    { "enabled": true, "failMode": "closed" },
    "edit-gate":     { "enabled": true, "failMode": "open" },
    "stop-gate":     { "enabled": true, "failMode": "open" },
    "diff-digest":   { "enabled": true, "failMode": "open" },
    "snapshot-inject": { "enabled": true, "failMode": "open" },
    "compact-summarize": { "enabled": true, "failMode": "open" },
    "post-failure-log": { "enabled": true, "failMode": "open" },
    "statusline":    { "enabled": true, "failMode": "open" }
  },
  "snapshot": {
    "maxDepth": 3,
    "maxSizeBytes": 6144,
    "includeHotspots": true,
    "includeRiskZones": true
  },
  "session": {
    "retentionCount": 30,
    "ledgerMaxSizeBytes": 1048576,
    "redactSecrets": true
  },
  "risk": {
    "criticalPaths": [".github/workflows/", "Dockerfile", "docker-compose", "infra/", "deploy/"],
    "highPaths": ["package.json", "tsconfig.json", ".eslintrc", "gentic.json"]
  },
  "guardBash": {
    "extraPatterns": [],
    "disabledPatterns": [],
    "borderlineAction": "ask"
  },
  "stopGate": {
    "verificationPattern": "^Verification:\\s+",
    "riskPattern": "^Risk:\\s+"
  },
  "failClosed": []
}
```

### Configuration Reference

| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `hooks.<name>.enabled` | bool | `true` | Toggle individual hooks on/off |
| `hooks.<name>.failMode` | `"open"` \| `"closed"` | varies | Behavior on hook crash/timeout |
| `snapshot.maxDepth` | number | `3` | Directory tree depth for snapshots |
| `snapshot.maxSizeBytes` | number | `6144` | Max snapshot size (1024-10240) |
| `snapshot.includeHotspots` | bool | `true` | Include git-derived most-changed files |
| `snapshot.includeRiskZones` | bool | `true` | Include untested/complex/sensitive files |
| `session.retentionCount` | number | `30` | Sessions to keep before auto-pruning |
| `session.ledgerMaxSizeBytes` | number | `1048576` | Max size per ledger file (1MB) |
| `session.redactSecrets` | bool | `true` | Redact secrets before writing to ledger |
| `risk.criticalPaths` | string[] | see above | Paths that trigger "ask" on edit |
| `risk.highPaths` | string[] | see above | Paths that show a warning on edit |
| `guardBash.extraPatterns` | array | `[]` | Additional dangerous command patterns |
| `guardBash.disabledPatterns` | string[] | `[]` | Built-in pattern labels to disable |
| `guardBash.borderlineAction` | `"ask"` \| `"allow"` | `"ask"` | Action for borderline commands |
| `stopGate.verificationPattern` | string | `"^Verification:\\s+"` | Regex for verification marker detection |
| `stopGate.riskPattern` | string | `"^Risk:\\s+"` | Regex for risk marker detection |
| `failClosed` | string[] | `[]` | Hook names that fail-closed (block on error) |

### Config via CLI

```bash
gentic config                          # Show full config
gentic config get snapshot.maxDepth    # Get a value
gentic config set session.retentionCount 50    # Set a value
gentic config reset                    # Reset to defaults
```

### Schemas

- `config/gentic-schema.json` — JSON Schema for `gentic.json`
- `config/hooks-schema.json` — JSON Schema for hook registration format

---

## CLI Reference

```
gentic init [--force]              Install gentic into project (idempotent)
gentic status [--json]             Show current gentic state
gentic session list                List all sessions
gentic session show [id]           Show session details
gentic session prune [--keep N]    Remove old sessions (default keep: 30)
gentic session export [id]         Export session as JSON
gentic config                      Show config
gentic config get <key.path>       Get a config value
gentic config set <key.path> <val> Set a config value
gentic config reset                Reset to defaults
gentic uninstall [--all]           Remove gentic (--all removes .gentic/ too)
gentic --version                   Show version
gentic --help                      Show help
```

---

## Workflows

### Full Ceremony (New Feature)

```
/gentic:snapshot        →  Situational awareness
/gentic:research "..."  →  Understand existing patterns
/gentic:plan "..."      →  Decompose into tasks with risk + must-haves
/gentic:patch           →  Execute plan, atomic commits
/gentic:verify          →  Run checks, verify artifacts at 3 levels
/gentic:ship            →  Verify + review + verdict
/gentic:audit           →  Compare plan vs. reality (optional)
```

### Quick Fix

```
/gentic:quick "fix the null check in handler.ts"
```

Skips the plan/patch ceremony but keeps: read-before-edit, deviation rules, atomic commits, verification.

### Debug Cycle

```
/gentic:debug "API returns 500 on user creation"
    → Debugger: reproduce, hypothesize, test, diagnose
/gentic:quick "fix the null check identified by debug"
    → Surgeon: apply fix with verification
```

### Cross-Session Continuity

```
# Session 1: work gets interrupted
/gentic:progress        →  See where you are

# Session 2: resume
/gentic:resume          →  Reconstruct previous session state
/gentic:progress        →  See remaining work
/gentic:patch           →  Continue where you left off
```

---

## Safety Model

### Fail-Open vs. Fail-Closed

| Hook | Default | Rationale |
|------|---------|-----------|
| `guard-bash` | **closed** | Safety-critical — must block if uncertain |
| All others | open | Prefer availability — a failed snapshot inject shouldn't block work |

Override via `gentic.json`:
```json
{
  "failClosed": ["stop-gate", "edit-gate"]
}
```

### Secret Redaction

Applied consistently across all surfaces:
- Session ledger entries (diff-digest, post-failure-log)
- MCP server responses
- Snapshot injection context
- Hook error output

### Path Security

MCP server paths are:
1. Normalized (no double slashes, no trailing separators)
2. Traversal-checked (`..` rejected)
3. Symlink-resolved and re-verified against repo root
4. Jailed — resolved path must start with `cwd + path.sep`

### Timeout Handling

All hooks run through `run.js` which enforces timeouts via `SIGKILL`. Fail-closed hooks block on timeout; fail-open hooks allow.

---

## Development

### Repo Layout

```
src/            CLI entry + core modules
  cli.js          CLI entry point
  core/
    config.js     Config loading, validation, defaults
    snapshot.js   Bounded repo snapshot generator
    ledger.js     Session ledger read/write
    ledger-append.js  Atomic JSONL append
    logger.js     File logging
    redact.js     Secret redaction
  mcp/
    server.js     MCP server (JSON-RPC over stdio)
cli/            CLI subcommands
  init.js         Install flow
  status.js       Status display
  session.js      Session management
  config.js       Config get/set
  uninstall.js    Uninstall flow
hooks/          Hook scripts
  run.js          Wrapper runner (timeout + failMode)
  guard-bash.js   Dangerous command blocker
  edit-gate.js    File risk classifier
  stop-gate.js    Completion gate
  diff-digest.js  Change logger
  snapshot-inject.js  Context injector
  compact-summarize.js  Pre-compaction summary
  post-failure-log.js  Failure logger
  session-start.js  Session initializer
  statusline.js   Status bar display
commands/       Claude Code slash commands
  gentic/*.md     Command definitions
agents/         Claude Code subagent definitions
  *.md            Agent role + tool restrictions
config/         Schemas
  gentic-schema.json
  hooks-schema.json
test/           Node test runner tests
```

### Running Tests

```bash
npm test                    # All tests
node --test test/some.test.js   # Single test
```

### Local Development

```bash
node src/cli.js --help      # Run CLI locally
node src/cli.js init        # Test init flow
npm pack --dry-run          # Check package contents
```

### Publishing

```bash
npm version patch           # Bump version, create git tag
git push --follow-tags      # CI publishes on tag push
```

CI workflows:
- `.github/workflows/ci.yml` — Tests on PR/push to `master`
- `.github/workflows/publish.yml` — Tests + publishes on tag push (`v*.*.*`)

Required secret: `NPM_TOKEN` with publish rights for `@mxcro/gentic`.

---

## Troubleshooting

| Problem | Solution |
|---------|----------|
| Hooks not running | Check `.claude/settings.json` includes gentic entries. Re-run `npx @mxcro/gentic@latest init`. |
| MCP not connected | Check `.claude/.mcp.json` points to the installed `server.js`. Re-run init. |
| guard-bash false positive | Add the pattern label to `guardBash.disabledPatterns` in `gentic.json`. |
| Too many user prompts from edit-gate | Remove the path from `risk.criticalPaths` or disable: `hooks.edit-gate.enabled: false`. |
| stop-gate blocking completion | Add `Verification: <status>` and `Risk: <assessment>` lines to your response, or run `/gentic:verify`. |
| Snapshot too large | Reduce `snapshot.maxDepth` or `snapshot.maxSizeBytes` in `gentic.json`. |
| Old sessions piling up | `gentic session prune --keep 10` or reduce `session.retentionCount`. |
| Publish fails in CI | Ensure `NPM_TOKEN` secret exists with publish rights. |
| ripgrep not found | Install `rg` — the MCP server's `reference_graph` tool requires it. Other tools degrade gracefully. |

---

## License

MIT