# ADR-001: Unified Knowledge Graph for Context Assembly

**Date:** 2026-03-18
**Status:** Accepted
**Deciders:** cwarner

## Context

Harness Engineering's current context system is a collection of standalone static analyzers with no unified data model:

- **Context assembly** (`packages/core/src/context/`): Glob-based file grouping, fixed token budget ratios, hardcoded phase-to-category mappings. No semantic understanding, no relationship awareness.
- **State management** (`packages/core/src/state/`): Flat JSON + append-only markdown logs. Decisions, learnings, and failures are stored but never linked to the code they affect. No querying, no indexing.
- **Entropy detection** (`packages/core/src/entropy/`): Point-in-time snapshots rebuilt from scratch each run. File-to-file dependency edges with no semantic meaning. Dead code detection via reachability from entry points only.
- **Constraint enforcement** (`packages/core/src/constraints/`): Glob-pattern layer assignment. Import edges without weights, reasons, or cross-cutting concern awareness.
- **MCP resources** (`packages/mcp-server/src/resources/`): Five independent blobs (project, skills, rules, learnings, state) with no relationships between them.

These systems cannot answer questions like:

- "What code does this learning apply to?"
- "What's the full dependency chain from this entry point to this symbol?"
- "What decisions affected this module?"
- "Show me all files semantically related to authentication"
- "Which learnings are relevant to the code I'm about to change?"

Meanwhile, the OmniContext project (`/Users/cwarner/Projects/omnicontext`) demonstrated that a graph-based approach with 20 node types, 12 edge types, ContextQL noise-pruning, and Fusion Layer (keyword + semantic) search can achieve 99%+ context reduction while maintaining relationship awareness. OmniContext has completed Phases 1-6 (18/18 milestones) but exists as a separate project with significant overlap.

The goal is to build the best possible context system for AI agent interaction — one that understands code structure, organizational knowledge, runtime behavior, and the relationships between all of them — and deprecate OmniContext.

## Decision

Build a **Unified Knowledge Graph** as a new `packages/graph` package within the Harness Engineering monorepo. This graph becomes the single source of truth for all context assembly, replacing the existing context, entropy, constraint, and state systems.

### Core Architecture

**1. Graph Store** — LokiJS-backed in-memory graph database

Node types (minimum):

- **Code**: `repository`, `module`, `file`, `class`, `interface`, `function`, `method`, `variable`
- **Knowledge**: `adr`, `decision`, `learning`, `failure`, `issue`, `document`, `skill`, `conversation`
- **VCS**: `commit`, `build`, `test_result`
- **Observability**: `span`, `metric`, `log` (future)
- **Structural**: `layer`, `pattern`, `constraint`, `violation`

Edge types (minimum):

- **Code relationships**: `contains`, `imports`, `calls`, `implements`, `inherits`, `references`
- **Knowledge relationships**: `applies_to`, `caused_by`, `resolved_by`, `documents`, `violates`, `specifies`, `decided`
- **VCS relationships**: `co_changes_with`, `triggered_by`, `failed_in`
- **Execution relationships**: `executed_by`, `measured_by` (future)

Nodes carry optional `embedding?: number[]` for vector search.

**2. Graph Storage & Lifecycle**

The graph is a **derived artifact** — not stored in source control. It is generated from source files, documentation, state, and external systems on demand.

- **Storage location**: `.harness/graph/` (LokiJS JSON file + HNSWLib vector index + connector sync metadata)
- **`.gitignore`d**: Like `node_modules` or `dist/`, the graph is always regenerable
- **Population**: `harness scan` performs full ingestion; `harness watch` keeps it fresh via filesystem events
- **Portability**: Any developer can rebuild the graph from scratch. External connector data is cached locally but re-pullable.

**3. Ingestion Pipeline** — Multi-source graph population

The ingestion pipeline uses a **connector architecture** — pluggable adapters that pull from both local and external sources, creating graph nodes linked to code via the Fusion Layer.

#### Local Connectors (always available)

- **Code ingestion**: Tree-sitter AST parsing (TypeScript, Go, Rust, Java) with worker pool architecture. Produces code nodes + structural edges. Topological post-processing establishes cross-module relationships.
- **Knowledge ingestion**: Parses ADRs, AGENTS.md sections, learnings, failures, decisions. Links to code nodes via Fusion Layer (keyword heuristic + vector similarity).
- **State ingestion**: Converts harness state (progress, blockers, handoffs) into graph nodes linked to relevant code and knowledge nodes.
- **Constraint ingestion**: Layer definitions and forbidden-import rules become `constraint` nodes with `violates` edges to offending code.
- **Git history ingestion**: Commit messages and PR descriptions become `commit` nodes. Co-change analysis produces `co_changes_with` edges between frequently co-modified files. Blame data enriches code nodes with ownership metadata.

#### External Connectors (configured per-project)

Each external connector implements a common interface:

```typescript
interface GraphConnector {
  name: string;
  source: string;
  ingest(store: GraphStore, config: ConnectorConfig): Promise<IngestResult>;
  schedule?: string; // cron expression for auto-refresh
}
```

- **Jira / Linear / GitHub Issues**: Pulls issues via API (filtered by project, label, status). Creates `issue` nodes with metadata (assignee, status, priority, labels). Fusion Layer links issues to code nodes via keyword matching on component names + vector similarity on issue description vs code docstrings. Edges: `issue --applies_to--> function:handleAuth`, `issue --caused_by--> commit:abc123`.

- **Slack / Discord**: Ingests channel history via API (filtered by channel, timeframe, keyword). Creates `conversation` nodes with metadata (author, channel, timestamp). Named entity recognition extracts file/function/module mentions from message text. Edges: `conversation --references--> file:src/billing.ts`, `conversation --decided--> adr:003`.

- **Confluence / Notion / Google Docs**: Pulls pages via API or reads exported markdown. Creates `document` nodes with sections as child nodes. Fusion Layer links sections to code they describe. Edges: `document --documents--> module:auth`, `document_section --specifies--> interface:UserAPI`.

- **CI/CD (GitHub Actions, etc.)**: Pulls build/test results. Creates `build` and `test_result` nodes. Links failures to code nodes that caused them. Edges: `test_result --failed_in--> function:validateInput`, `build --triggered_by--> commit:def456`.

#### Connector Configuration

Connectors are configured in `harness.config.json`:

```json
{
  "graph": {
    "connectors": [
      {
        "source": "jira",
        "config": {
          "apiKeyEnv": "JIRA_API_KEY",
          "baseUrlEnv": "JIRA_BASE_URL",
          "project": "ENG",
          "filters": { "status": ["In Progress", "Done"], "labels": ["backend"] },
          "schedule": "0 */4 * * *"
        }
      },
      {
        "source": "slack",
        "config": {
          "apiKeyEnv": "SLACK_BOT_TOKEN",
          "channels": ["#engineering", "#incidents"],
          "lookbackDays": 90,
          "schedule": "0 */6 * * *"
        }
      }
    ]
  }
}
```

API keys are always referenced via environment variable names (`apiKeyEnv`), never stored as values in the config file. See [Security & Privacy](#security--privacy) for details.

#### Connector Lifecycle

- **Initial sync**: `harness ingest --source jira` (or `--all` for everything)
- **Incremental sync**: Each connector tracks `lastSyncTimestamp` in `.harness/graph/sync-metadata.json`. Only pulls new/changed items on subsequent runs.
- **Scheduled sync**: Optional cron-based auto-refresh via `schedule` field.
- **Manual refresh**: `harness ingest --source slack --full` forces a complete re-pull.
- **Linking**: After ingestion, the Fusion Layer runs a linking pass — matching new external nodes to existing code nodes via keyword + semantic similarity. Confidence scores are stored on edges.

#### How External Nodes Link to Code

The Fusion Layer uses a two-signal approach for every external node:

1. **Keyword signal (deterministic)**: Extract component names, file paths, function names, and module names mentioned in the external content. Direct string match against graph node names/paths.
2. **Semantic signal (probabilistic)**: Embed the external content (issue description, Slack message, doc section) and find top-N most similar code nodes by cosine similarity.
3. **Score fusion**: Weighted combination (default 60% keyword / 40% semantic). Edges are created only above a configurable confidence threshold (default 0.6).

This ensures external knowledge is always anchored to specific code — not floating as disconnected context.

**4. ContextQL Query Engine** — Deterministic graph traversal with noise pruning

- BFS traversal from root nodes with configurable depth, type filters, and edge filters
- Automatic noise pruning: structural queries exclude observability nodes unless explicitly requested
- DSL support for declarative queries
- Projection (field selection) to minimize context payload
- Bidirectional traversal (inbound + outbound edges)

**5. Vector Store** — HNSWLib with pure-TS fallback

- Dimension-agnostic (adapts to configured embedding model — 1536 for OpenAI ada-002, 1024 for some local models, etc.)
- Lazy loading of native binary; graceful degradation to brute-force cosine similarity in pure TypeScript
- Incremental index updates on graph mutations
- Semantic search across all node types
- Provider-tagged vectors for safe model switching (see [Embedding Provider Strategy](#embedding-provider-strategy))

**6. Fusion Layer** — Combined keyword + semantic context resolution

- Keyword extraction from natural language queries
- Vector similarity search against embedded nodes
- Score fusion: weighted combination of deterministic (keyword match) and probabilistic (cosine similarity) signals
- Intent classification pipeline: classify → discover targets → extract constraints

**7. MCP Integration** — Graph-powered tools replacing static resources

New MCP tools (see [Package Impact: mcp-server](#new-tools-6) for full details):

- `query_graph`, `search_similar`, `find_context_for`, `get_relationships`, `get_impact`, `ingest_source`

Existing MCP resources (`harness://project`, `harness://skills`, etc.) become graph queries rather than static file reads. See [Package Impact: Modified Resources](#modified-resources-4-of-5) for details.

**8. Context Assembly** — Graph-driven replacement for budget/filter/generate

- Token budgeting informed by graph density (modules with many edges get more tokens)
- Phase-aware filtering via graph queries (not glob patterns)
- AGENTS.md generation from graph structure (not glob grouping)
- Dynamic context expansion: start from intent, traverse to relevant context, prune noise

### Package Structure

```
packages/graph/
├── src/
│   ├── store/
│   │   ├── GraphStore.ts         # LokiJS-backed node/edge CRUD
│   │   ├── VectorStore.ts        # HNSWLib wrapper with fallback
│   │   └── Serializer.ts         # Persistence (JSON initially, Protobuf later)
│   ├── query/
│   │   ├── ContextQL.ts          # BFS traversal + noise pruning
│   │   ├── DSL.ts                # Query DSL parser
│   │   └── Projection.ts         # Field selection / context reduction
│   ├── ingest/
│   │   ├── CodeIngestor.ts       # Tree-sitter AST parsing + worker pool
│   │   ├── KnowledgeIngestor.ts  # ADR, doc, learning, failure ingestion
│   │   ├── StateIngestor.ts      # Harness state → graph nodes
│   │   ├── ConstraintIngestor.ts # Layer/constraint → graph nodes
│   │   ├── GitIngestor.ts        # Commit/PR/blame → graph nodes
│   │   ├── TopologicalLinker.ts  # Post-parse cross-module linking
│   │   └── connectors/
│   │       ├── ConnectorInterface.ts # Common connector contract
│   │       ├── JiraConnector.ts      # Jira/Linear issue ingestion
│   │       ├── SlackConnector.ts     # Slack/Discord history ingestion
│   │       ├── ConfluenceConnector.ts # Confluence/Notion doc ingestion
│   │       ├── CIConnector.ts        # GitHub Actions/CI result ingestion
│   │       └── SyncManager.ts        # Incremental sync + scheduling
│   ├── search/
│   │   ├── FusionLayer.ts        # Keyword + semantic score fusion
│   │   ├── IntentEngine.ts       # NL → classify → discover → constrain
│   │   └── Embeddings.ts         # Embedding generation (multi-provider)
│   ├── context/
│   │   ├── Assembler.ts          # Graph-driven context assembly
│   │   ├── Budget.ts             # Graph-density-aware token budgeting
│   │   └── Pruner.ts             # Noise pruning heuristics
│   └── types.ts                  # Node, edge, query type definitions
├── __tests__/
└── package.json
```

### Dependencies

**Required:**

- `lokijs` — In-memory graph storage (~1.5MB)
- `tree-sitter` + language parsers — AST parsing (~2-3MB for TS/Go/Rust/Java)
- `zod` — Schema validation (already in monorepo)

**Optional (graceful degradation):**

- `hnswlib-node` — Native vector search. Falls back to brute-force cosine similarity.
- `@ai-sdk/*` — Embedding generation. Falls back to no-embedding mode (keyword-only search).

### Migration Path

1. **Phase 1 — Graph Foundation**: Build `packages/graph` with store, query engine, and code ingestion. Validate with tests.
2. **Phase 2 — Knowledge Layer**: Add knowledge, state, and git ingestion. Wire up MCP tools (`query_graph`, `search_similar`).
3. **Phase 3 — External Connectors**: Build connector architecture + first external connectors (Jira, Slack). Incremental sync + scheduling.
4. **Phase 4 — Context Assembly**: Replace `packages/core/src/context/*` with graph-driven assembly. Create harness-context-assembler skill. Deprecate old context APIs.
5. **Phase 5 — Entropy Migration**: Replace entropy snapshot with graph queries. Dead code = unreachable nodes. Drift = stale edges. Update detect-doc-drift and cleanup-dead-code skills.
6. **Phase 6 — Constraint Migration**: Replace constraint checking with graph traversal. Layer violations = edge type violations. Update enforce-architecture skill.
7. **Phase 7 — Tier-1 Skill Migration**: Update remaining Tier-1 skills (code-review, validate-context, parallel-agents, onboarding) to use graph queries.
8. **Phase 8 — New Skills & Personas**: Create 5 new skills (impact-analysis, dependency-health, hotspot-detector, test-advisor, knowledge-mapper). Create 2 new personas (Graph Maintainer, Codebase Health Analyst). Update existing personas.
9. **Phase 9 — Tier-2 Skills & Remaining Connectors**: Update Tier-2 skills (execution, planning, architecture-advisor, refactoring, align-documentation). Add remaining connectors (Confluence, CI).
10. **Phase 10 — Deprecation**: Deprecate OmniContext. Remove old context/entropy/constraint systems. Harness graph is the single system.

Each phase is independently shippable.

## Impact on Existing Skills and Personas

### Tier 1 — Transformed (7 skills)

These skills currently perform implicit graph analysis through brittle file searches, grep, and CLI tool output. The graph replaces their context assembly with direct queries.

| Skill                            | Current Approach                                                                                             | With Graph                                                                                                                              |
| -------------------------------- | ------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------- |
| **harness-code-review**          | Grep for imports, `find` for test files, search docs for mentions. 1:1 context ratio gathered heuristically. | `query_graph` returns precise dependency chain, related tests, relevant docs — all linked by edges. Context ratio becomes graph-driven. |
| **validate-context-engineering** | Reads AGENTS.md, checks file existence, Levenshtein suggestions for broken links.                            | Graph IS the source of truth. Validation becomes: "are all code nodes documented?" — a single graph query.                              |
| **detect-doc-drift**             | Regex pattern matching between doc references and code symbols. Rebuilt from scratch each run.               | Query for `documents` edges where the target code node has changed since the edge's `lastVerified` timestamp. Drift = stale edges.      |
| **cleanup-dead-code**            | Static analysis via `harness cleanup`. Manual false-positive review. Misses dynamic imports.                 | Graph reachability query from entry point nodes. Includes transitive analysis. `imports` edges capture dynamic imports if parsed.       |
| **harness-parallel-agents**      | Manual verification of task independence — human checks file overlap, state overlap, import overlap.         | `get_impact` query per task → compute node overlap → automated independence score. Zero manual verification needed.                     |
| **enforce-architecture**         | Runs `harness check-deps` CLI → parses text output. Post-hoc validation only.                                | Direct traversal of `imports` edges against `layer` node constraints. Real-time, in-process, with richer error context.                 |
| **harness-onboarding**           | Reads potentially stale AGENTS.md + harness.config.json. Static orientation.                                 | Dynamic orientation generated from graph queries — module map, dependency diagram, entry points, patterns. Always current.              |

### Tier 2 — Significantly Improved (5 skills)

| Skill                            | Improvement                                                                                                                                                                                                  |
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **harness-execution**            | Task dependency tracking via graph. Query: "what files does this task touch? Do they conflict with the next task?" Enables smarter execution ordering and blockage detection.                                |
| **harness-planning**             | Discover module dependencies from graph for realistic task decomposition. Query: "what modules does this feature touch, and what are their dependencies?" Enables accurate effort estimation and sequencing. |
| **harness-architecture-advisor** | Pattern discovery automated. Query: "how are similar features structured in this codebase?" Instead of manually exploring via Glob/Grep.                                                                     |
| **harness-refactoring**          | Precise impact analysis. Query: "if I move this function, what modules, tests, and docs are affected?" Currently relies on grep which misses indirect consumers.                                             |
| **align-documentation**          | Auto-suggest which docs to update. Query: "which `documents` edges point to nodes that changed in this diff?"                                                                                                |

### Tier 3 — Minor Improvements (15 skills)

harness-debugging (follow error propagation through `calls` edges), harness-tdd (suggest test targets from `imports` graph), harness-diagnostics (route errors based on graph location), harness-brainstorming (discover patterns via graph analysis), harness-pre-commit-review (change impact via graph), harness-integrity (depends on improved code-review), harness-verification, harness-git-workflow, harness-state-management, harness-skill-authoring, initialize-harness-project, add-harness-component, check-mechanical-constraints, harness-verify. These benefit from better context but don't fundamentally change their workflow.

### Impact on All 3 Existing Personas

| Persona                      | Current Approach                                                  | With Graph                                                                                                                                                     |
| ---------------------------- | ----------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Architecture Enforcer**    | Runs CLI checks post-hoc. No historical tracking.                 | Direct graph queries for real-time boundary validation. Can track historical violations over time by comparing graph snapshots.                                |
| **Documentation Maintainer** | Brittle pattern matching for drift detection. Manual doc updates. | Graph comparison: "which code nodes changed since their `documents` edge was last verified?" Automatic update suggestions with precise file/section targeting. |
| **Entropy Cleaner**          | Static analysis rebuilt from scratch each run. No trend data.     | Persistent graph enables trend analysis — entropy hotspots over time, progressive debt accumulation, churn pattern detection.                                  |

### New Skills Enabled by the Graph

These skills are impossible without a relationship model. They represent capabilities that don't exist in Harness today.

**1. harness-impact-analysis**

- **Purpose**: Answer "if I change X, what breaks?"
- **How**: Reverse-traverse `calls`, `imports`, `implements` edges from changed nodes. Return affected modules, tests, documentation, and downstream consumers.
- **Cognitive mode**: analytical-reporter
- **Triggers**: on_pr, manual
- **Why it doesn't exist today**: Current system has no reverse-dependency traversal. Grep finds direct importers but misses transitive consumers.

**2. harness-dependency-health**

- **Purpose**: Analyze structural health of the codebase and surface problems before they become incidents.
- **How**: Graph metrics — hub detection (nodes with high fan-in), orphan detection (unreachable nodes), cycle detection (circular edge paths), deep chain detection (fragile dependency paths >N hops). Output: health score + specific recommendations.
- **Cognitive mode**: analytical-reporter
- **Triggers**: scheduled weekly, manual
- **Why it doesn't exist today**: Current `check-deps` only validates layer rules. No holistic health analysis.

**3. harness-hotspot-detector**

- **Purpose**: Identify modules that represent structural risk via co-change analysis.
- **How**: Combine graph structure with git history (`co_changes_with` edges). Detect: files that always change together but live apart (should be co-located), modules that change most frequently (highest risk), high logical coupling with low structural coupling (hidden dependencies).
- **Cognitive mode**: analytical-reporter
- **Triggers**: scheduled weekly, manual
- **Why it doesn't exist today**: No co-change data. No way to correlate git history with code structure.

**4. harness-test-advisor**

- **Purpose**: Answer "I changed these files — what tests should I run?"
- **How**: Traverse `imports`/`calls` edges from changed file nodes. Find all test file nodes with edges to affected nodes. Rank by graph distance (direct importers first, transitive second).
- **Cognitive mode**: advisory-guide
- **Triggers**: on_pr, manual
- **Why it doesn't exist today**: Test selection is currently "run all" or manual. No way to compute affected test surface.

**5. harness-knowledge-mapper**

- **Purpose**: Replace manual AGENTS.md maintenance with auto-generated, always-current knowledge maps.
- **How**: Query graph for module structure, entry points, dependency diagrams, API surfaces. Generate markdown documentation derived from graph — never stale because it's computed, not authored. Detect undocumented modules automatically (code nodes with no `documents` edges).
- **Cognitive mode**: constructive-architect
- **Triggers**: on_commit (main branch), scheduled daily, manual
- **Why it doesn't exist today**: AGENTS.md is manually maintained. `validate-context-engineering` checks it but can't generate it intelligently.

**6. harness-context-assembler**

- **Purpose**: The core skill for graph-powered context assembly. Takes an agent's intent and returns optimal context within token budget.
- **How**: Accept intent ("implement feature X", "fix bug Y", "review PR Z"). Use Fusion Layer to identify relevant graph nodes. Apply ContextQL noise pruning. Respect token budget via graph-density-aware allocation. Return assembled context with relationship metadata.
- **Cognitive mode**: meticulous-implementer
- **Triggers**: automatic (invoked by other skills before they begin work)
- **Why it doesn't exist today**: Context assembly is currently static (phase → glob patterns → fixed budget ratios). No intent-awareness, no relationship-awareness.

### New Personas Enabled by the Graph

**1. Graph Maintainer**

- **Role**: Keep the knowledge graph fresh, monitor connector health, detect graph anomalies, ensure data quality.
- **Skills**: harness-dependency-health, harness-knowledge-mapper, validate-context-engineering
- **Triggers**: scheduled daily (full re-scan + incremental connector sync), on_commit to main (re-ingest changed files), on connector failure (alert + retry)
- **Why**: The graph is now infrastructure — it needs a caretaker. Stale graph = stale context = agent mistakes.

**2. Codebase Health Analyst**

- **Role**: Proactively identify structural problems, coupling risks, and architectural drift before they become incidents.
- **Skills**: harness-hotspot-detector, harness-dependency-health, harness-impact-analysis, cleanup-dead-code
- **Triggers**: scheduled weekly, on_pr (for PRs touching >10 files)
- **Why**: No existing persona does proactive structural analysis. Current personas are reactive (enforce rules, fix drift, clean entropy). This persona looks forward.

### Skill Migration Summary

| Category                              | Count |
| ------------------------------------- | ----- |
| Existing skills transformed           | 7     |
| Existing skills improved              | 5     |
| Existing skills minimally affected    | 15    |
| New skills enabled                    | 6     |
| Existing personas critically impacted | 3/3   |
| New personas enabled                  | 2     |

## Impact on Existing Packages

### Dependency Architecture

The graph package sits between `types` and `core` in the dependency hierarchy:

```
packages/types        (no deps — unchanged)
    ↓
packages/graph        (NEW — depends on types)
    ↓
packages/core         (depends on types, graph)
    ↓
packages/cli          (depends on core, graph, linter-gen)
packages/mcp-server   (depends on core, graph, cli, linter-gen, types)
packages/eslint-plugin (depends on types — reads graph via config)
packages/linter-gen   (no graph dependency — unchanged)
```

### packages/types — NO CHANGES

All exports remain unchanged. Graph-specific types (`GraphNode`, `GraphEdge`, `ContextQLParams`, etc.) live in `packages/graph/src/types.ts`, not here. The `types` package stays as the foundation layer for `Result<T,E>`, workflow types, and skill context types.

### packages/core — CRITICAL CHANGES

The core package is the most impacted. Four of its six major modules are replaced or significantly modified by graph queries.

#### core/context/ — MOSTLY REPLACED

| Export                   | Status     | Details                                                                                                         |
| ------------------------ | ---------- | --------------------------------------------------------------------------------------------------------------- |
| `validateAgentsMap()`    | DEPRECATED | Replaced by `graph.query({type: 'documented'})`. Graph knows which nodes have documentation edges.              |
| `validateKnowledgeMap()` | DEPRECATED | Replaced by `graph.integrity()`. Graph validates its own structural consistency.                                |
| `checkDocCoverage()`     | MODIFIED   | Queries graph for code nodes without `documents` edges instead of filename matching.                            |
| `generateAgentsMap()`    | MODIFIED   | Generates from graph topology (modules, entry points, dependency chains) instead of glob grouping.              |
| `contextFilter()`        | MODIFIED   | Uses graph traversal to find phase-relevant nodes instead of hardcoded phase→category maps.                     |
| `contextBudget()`        | MODIFIED   | Budget ratios informed by graph density (modules with many edges get more tokens) instead of fixed percentages. |

#### core/constraints/ — SIGNIFICANTLY MODIFIED

| Export                      | Status    | Details                                                                                                     |
| --------------------------- | --------- | ----------------------------------------------------------------------------------------------------------- |
| `validateDependencies()`    | MODIFIED  | Queries graph `imports` edges against `layer` node constraints instead of parsing files.                    |
| `buildDependencyGraph()`    | MODIFIED  | Returns a view of the knowledge graph filtered to code nodes + import edges, not a separate data structure. |
| `detectCircularDeps()`      | MODIFIED  | Uses graph's built-in cycle detection instead of standalone DFS.                                            |
| `defineLayer()`             | MODIFIED  | Registers layer as a graph node with metadata instead of static config object.                              |
| `resolveFileToLayer()`      | MODIFIED  | Traverses `contains` edges from file node to layer node.                                                    |
| `createBoundaryValidator()` | UNCHANGED | Zod schema validation is orthogonal to graph.                                                               |

#### core/entropy/ — SIGNIFICANTLY MODIFIED

| Export                      | Status    | Details                                                                                                                    |
| --------------------------- | --------- | -------------------------------------------------------------------------------------------------------------------------- |
| `EntropyAnalyzer`           | MODIFIED  | Orchestrates graph-based analysis instead of building standalone snapshots.                                                |
| `buildSnapshot()`           | MODIFIED  | Produces a `CodebaseSnapshot` from graph state instead of parsing all files from scratch. Graph already has AST nodes.     |
| `detectDocDrift()`          | MODIFIED  | Queries `documents` edges with staleness check (code node `lastModified` > edge `lastVerified`) instead of regex matching. |
| `detectDeadCode()`          | MODIFIED  | Graph reachability query from entry point nodes. Includes transitive analysis through `calls`/`imports` edges.             |
| `detectPatternViolations()` | MODIFIED  | Patterns stored as graph constraint nodes. Violations are `violates` edges.                                                |
| `applyFixes()`              | UNCHANGED | Fix application is file I/O, not graph-dependent.                                                                          |

#### core/feedback/ — MODERATELY MODIFIED

| Export                | Status    | Details                                                                                                                 |
| --------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------- |
| `analyzeDiff()`       | MODIFIED  | Cross-references diff against graph constraints (layer violations, boundary schemas) in addition to forbidden patterns. |
| `requestPeerReview()` | MODIFIED  | Review agents receive graph context (affected nodes, constraint state) instead of static `harness://rules` blob.        |
| `createSelfReview()`  | MODIFIED  | Self-review checklist includes graph-derived items ("this change affects 12 downstream consumers").                     |
| `parseDiff()`         | UNCHANGED | Git diff parsing is orthogonal to graph.                                                                                |
| `logAgentAction()`    | UNCHANGED | Action logging stays file-based.                                                                                        |

#### core/state/ — MODERATELY MODIFIED

| Export                        | Status    | Details                                                                                                     |
| ----------------------------- | --------- | ----------------------------------------------------------------------------------------------------------- |
| `loadRelevantLearnings()`     | MODIFIED  | Queries graph for learning nodes linked to currently-relevant code nodes, instead of loading all learnings. |
| `appendLearning()`            | MODIFIED  | Also creates a `learning` graph node with `applies_to` edges to relevant code.                              |
| `appendFailure()`             | MODIFIED  | Also creates a `failure` graph node with `caused_by` edges.                                                 |
| `loadState()` / `saveState()` | UNCHANGED | Flat state file persists alongside graph. State tracks agent position; graph tracks entity relationships.   |
| `runMechanicalGate()`         | UNCHANGED | Gate checks are command execution, not graph queries.                                                       |

#### core/validation/, core/workflow/, core/pipeline/, core/ci/ — NO CHANGES

These modules are orthogonal to the graph (structural validation, orchestration, skill execution, CI checks).

#### Backward Compatibility Strategy

All modified functions support a **hybrid mode** during migration:

```typescript
async function validateDependencies(opts: { graph?: GraphStore; layers?: LayerConfig[] }) {
  // Graph-first, config-fallback
  if (opts.graph?.isLoaded()) {
    return validateFromGraph(opts.graph);
  }
  // Legacy path
  return validateFromConfig(opts.layers);
}
```

Deprecated functions emit console warnings directing users to graph equivalents.

### packages/cli — MODERATE CHANGES

#### Modified Commands

| Command                | Change                                                                        |
| ---------------------- | ----------------------------------------------------------------------------- |
| `harness validate`     | Calls graph-based validation when graph exists, falls back to legacy.         |
| `harness check-deps`   | Queries graph for dependency violations instead of parsing files.             |
| `harness check-docs`   | Queries graph for documentation coverage.                                     |
| `harness fix-drift`    | Uses graph staleness data to identify and fix drift.                          |
| `harness state manage` | Learning/failure append also writes to graph.                                 |
| `harness init`         | Initializes `.harness/graph/` directory alongside existing `.harness/` setup. |

#### New Commands

| Command                                              | Purpose                                                                                                                                    |
| ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `harness scan [path]`                                | Full graph ingestion — parse code, docs, state, constraints. Creates/rebuilds `.harness/graph/`.                                           |
| `harness watch [path]`                               | Filesystem watcher that incrementally updates graph on file changes.                                                                       |
| `harness ingest --source <name>`                     | Run a specific external connector (jira, slack, confluence, ci). `--all` runs all configured connectors. `--full` forces complete re-pull. |
| `harness query <dsl>`                                | Execute a ContextQL query against the graph. Returns filtered context.                                                                     |
| `harness graph status`                               | Show graph statistics — node/edge counts by type, connector sync status, staleness.                                                        |
| `harness graph export --format <json\|mermaid\|dot>` | Export graph for visualization or external tooling.                                                                                        |

### packages/mcp-server — SIGNIFICANT CHANGES

#### Modified Tools (13 of 23)

All tools that call into `core/context`, `core/constraints`, `core/entropy`, `core/feedback`, or `core/state` are affected. They inherit the changes from core — graph-first with config-fallback.

Key tools: `validate_project`, `check_dependencies`, `check_docs`, `detect_entropy`, `apply_fixes`, `check_phase_gate`, `validate_cross_check`, `validate_knowledge_map`, `manage_state`, `manage_handoff`, `create_self_review`, `analyze_diff`, `request_peer_review`.

#### New Tools (6)

| Tool                | Purpose                                                                                                                                   |
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `query_graph`       | Execute ContextQL queries. Input: DSL string or structured params. Output: filtered nodes + edges.                                        |
| `search_similar`    | Semantic search via vector store. Input: natural language query. Output: ranked similar nodes.                                            |
| `find_context_for`  | Intent-driven context assembly via Fusion Layer. Input: intent string + token budget. Output: assembled context optimized for the intent. |
| `get_relationships` | Traverse edges from a node. Input: node ID + direction + depth. Output: related nodes.                                                    |
| `get_impact`        | Impact analysis. Input: node ID or file path. Output: all affected downstream nodes (tests, docs, consumers).                             |
| `ingest_source`     | Trigger connector ingestion. Input: source name. Output: ingestion result with counts.                                                    |

#### Modified Resources (4 of 5)

| Resource              | Change                                                                                                   |
| --------------------- | -------------------------------------------------------------------------------------------------------- |
| `harness://project`   | Generates from graph structure instead of reading static AGENTS.md. Falls back to AGENTS.md if no graph. |
| `harness://rules`     | Queries graph for `constraint` and `layer` nodes instead of reading `harness.config.json`.               |
| `harness://learnings` | Queries graph for `learning` nodes with relationship context instead of reading flat markdown.           |
| `harness://state`     | Enriches state with graph metadata (current node context, related decisions).                            |
| `harness://skills`    | UNCHANGED — reads skill.yaml files directly.                                                             |

#### New Resources (3)

| Resource                  | Purpose                                                                              |
| ------------------------- | ------------------------------------------------------------------------------------ |
| `harness://graph`         | Full graph summary — node/edge counts by type, health status, connector sync status. |
| `harness://entities`      | All entity nodes with types and metadata. Queryable subset of graph.                 |
| `harness://relationships` | All edges with types, confidence scores, and timestamps.                             |

### packages/eslint-plugin — MINOR CHANGES

The 5 built-in rules are modified to **read constraints from graph when available**, falling back to `harness.config.json`:

```typescript
// Before: read config only
const config = getConfig(context.filename);
const layers = config?.layers ?? [];

// After: graph-first, config-fallback
const graphConstraints = getGraphConstraints(projectRoot);
const layers = graphConstraints?.layers ?? config?.layers ?? [];
```

No new rules are needed. The graph doesn't change what's enforced — it changes where enforcement data comes from. The eslint-plugin does NOT depend on `packages/graph` directly; it reads a cached constraint manifest that the graph generates.

### packages/linter-gen — NO CHANGES

The linter generator reads YAML rule definitions and produces ESLint rule files via Handlebars templates. This pipeline is orthogonal to the graph. Optional future enhancement: `harness linter generate --from-graph` to derive rules from graph constraints, but this is not required for the initial rollout.

### Package Impact Summary

| Package           | Exports Deprecated | Exports Modified      | New Exports          | New Dependencies                       | Effort |
| ----------------- | ------------------ | --------------------- | -------------------- | -------------------------------------- | ------ |
| **types**         | 0                  | 0                     | 0                    | none                                   | 0      |
| **graph** (NEW)   | —                  | —                     | ~30                  | lokijs, tree-sitter, hnswlib-node, zod | Large  |
| **core**          | 2                  | ~18                   | ~7                   | @harness-engineering/graph             | Large  |
| **cli**           | 0                  | 6 commands            | 6 commands           | @harness-engineering/graph             | Medium |
| **mcp-server**    | 0                  | 13 tools, 4 resources | 6 tools, 3 resources | @harness-engineering/graph             | Medium |
| **eslint-plugin** | 0                  | 5 rules (impl only)   | 0                    | none                                   | Small  |
| **linter-gen**    | 0                  | 0                     | 0                    | none                                   | 0      |

## Documentation Plan

### New Documentation to Create

#### Package Documentation

- **packages/graph/README.md** — Package overview, API reference, quick start, dependency list

#### Technical Specifications

- **docs/changes/graph-system-design/proposal.md** — Graph store, ContextQL, ingestion pipeline, vector store, Fusion Layer technical spec

#### Implementation Plans

- **docs/plans/graph-implementation-plan.md** — 10-phase plan (from Migration Path) expanded into executable detail

#### Guides

- **docs/guides/graph-connectors.md** — How to configure and use external connectors (Jira, Slack, Confluence, CI) — setup, auth, filtering, scheduling
- **docs/guides/graph-context-assembly.md** — How agents use the graph for context — query patterns, intent-driven assembly, noise pruning
- **docs/guides/writing-custom-connectors.md** — How to implement the `GraphConnector` interface for new external sources

#### Skills (6 new skills x 2 platforms)

- harness-impact-analysis, harness-dependency-health, harness-hotspot-detector, harness-test-advisor, harness-knowledge-mapper, harness-context-assembler — each with SKILL.md + skill.yaml for both claude-code and gemini-cli

#### Personas (2 new)

- **agents/personas/graph-maintainer.yaml**
- **agents/personas/codebase-health-analyst.yaml**

### Existing Documentation to Update

#### Critical (must update during rollout)

| Document                            | What Changes                                                                                                              |
| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| **AGENTS.md**                       | Add `packages/graph/` to project structure. Add graph concepts to key concepts. Update context assembly references.       |
| **README.md**                       | Add `packages/graph` to package table. Update MCP tools count. Update feature list.                                       |
| **docs/standard/principles.md**     | Reframe Principle 1 (Context Engineering) to show graph as its full realization.                                          |
| **docs/standard/index.md**          | Add graph as the evolution beyond Level 3 adoption.                                                                       |
| **docs/reference/cli.md**           | Document new commands: `harness scan`, `harness ingest`, `harness query`, `harness watch`, `harness graph status/export`. |
| **docs/reference/configuration.md** | Add `graph` section to `harness.config.json` schema — connectors, storage location, embedding config.                     |
| **packages/core/README.md**         | Major rewrite — show which modules are replaced by graph and the migration path. Document deprecated exports.             |
| **packages/cli/README.md**          | Add graph commands, flags, examples.                                                                                      |
| **agents/skills/README.md**         | Categorize skills as graph-transformed (7), graph-enhanced (5), graph-enabled (6 new).                                    |

#### High Priority (update as skills are migrated)

| Document                                     | What Changes                                                               |
| -------------------------------------------- | -------------------------------------------------------------------------- |
| **7 Tier-1 skill SKILL.md files**            | Update context gathering to use graph queries instead of file search/grep. |
| **5 Tier-2 skill SKILL.md files**            | Add graph-aware capabilities to relevant phases.                           |
| **3 existing persona .yaml files**           | Update skills lists, add graph-powered triggers.                           |
| **docs/standard/implementation.md**          | Add graph as enhancement to Level 3 adoption.                              |
| **docs/standard/kpis.md**                    | Show how graph enables better KPI measurement.                             |
| **docs/guides/issue-tracker-integration.md** | Reframe as graph connector setup guide.                                    |

#### Medium Priority (update opportunistically)

docs/guides/getting-started.md, docs/guides/best-practices.md, docs/guides/automation-overview.md, docs/guides/day-to-day-workflow.md, examples/multi-tenant-api/README.md, packages/types/README.md.

### Documentation Summary

| Category                | Count                                           |
| ----------------------- | ----------------------------------------------- |
| New docs to create      | 8 + 12 skill files + 2 persona files = 22 files |
| Critical updates        | 9 existing docs                                 |
| High priority updates   | ~15 existing docs                               |
| Medium priority updates | ~6 existing docs                                |
| No update needed        | ~10 docs                                        |

## Design Considerations

### Testing Strategy

**Unit tests**: Each module in `packages/graph` (GraphStore, ContextQL, VectorStore, each ingestor, each connector, FusionLayer) gets its own test suite with in-memory fixtures. No external dependencies required for unit tests.

**Connector mocking**: External connectors (Jira, Slack, Confluence, CI) are tested against recorded API response fixtures, not live services. Each connector implements `GraphConnector` interface — tests inject a mock HTTP client that returns fixture data. The `SyncManager` is tested with an in-memory clock for schedule advancement.

**Integration tests**: End-to-end tests that run `harness scan` on a fixture project (small TypeScript repo checked into `packages/graph/__fixtures__/`), then execute ContextQL queries and verify results. These validate the full pipeline: parse → ingest → link → query.

**Performance benchmarks**: Tracked in CI via Vitest bench. Key thresholds:

- `harness scan` on 10K-file repo: < 30 seconds
- ContextQL query (depth 3, 50K nodes): < 50ms
- Vector search (10K embedded nodes): < 100ms
- LokiJS memory ceiling: ~500K nodes before considering ArangoDB migration path

**Graph corruption recovery**: If `.harness/graph/` is corrupted or schema-incompatible, `harness scan` detects this on load (schema version check) and rebuilds from scratch. The graph is always regenerable — corruption is an inconvenience (re-scan), not data loss.

### Concurrency & Multi-Agent

**Single-process model**: LokiJS is single-process, in-memory. This is acceptable because:

- `harness scan` and `harness watch` are developer-machine processes, not server processes
- Parallel agents in worktrees each get their own `.harness/graph/` copy (worktrees are filesystem-isolated)
- MCP server runs in a single process and serializes graph access naturally

**Worktree isolation**: When agents use git worktrees, each worktree has its own `.harness/graph/` directory. The graph is cheap to rebuild (~seconds for typical repos), so each worktree runs its own `harness scan`. No shared graph, no locking needed.

**Future scaling**: If a shared graph becomes necessary (e.g., CI server serving multiple agents), the `GraphStore` interface abstracts over the storage backend. LokiJS can be swapped for ArangoDB (networked, multi-client) without changing query logic. This is a future optimization, not a launch requirement.

### Schema Evolution

**Version field**: The graph persistence file includes a `schemaVersion` number. On load, if the version doesn't match the current code's expected version, the graph is discarded and rebuilt via `harness scan`.

**Why rebuild-over-migrate**: The graph is a derived artifact. Unlike a database with user data, nothing in the graph is irreplaceable — it's all derivable from source files, docs, state, and external connectors. Migration scripts add complexity for zero benefit. Re-scan is the migration strategy.

**Connector data**: External connector data (Jira issues, Slack messages) is cached in the graph but re-pullable. After a schema change and re-scan, connectors re-sync. `lastSyncTimestamp` is reset, triggering a full re-pull.

### Embedding Provider Strategy

**Provider-tagged vectors**: Each embedding stored in the vector index includes a `provider` + `model` tag in its metadata:

```typescript
{
  nodeId: "function:handleAuth",
  embedding: [0.12, -0.34, ...],
  provider: "openai",
  model: "text-embedding-ada-002",
  dimensions: 1536
}
```

**Provider switch = re-embed**: If the configured embedding provider changes, the vector index is invalidated and rebuilt. This is triggered automatically when the provider/model in config doesn't match the provider/model in the index metadata.

**Graceful degradation**: If no embedding provider is configured (no API key), the vector store operates in **keyword-only mode**. The Fusion Layer falls back to 100% keyword signal, 0% semantic signal. This means the graph works fully without any AI API — embeddings are an enhancement, not a requirement.

**Dimensionality**: The vector store is dimension-agnostic. HNSWLib is initialized with whatever dimensions the configured model produces (1536 for ada-002, 1024 for some local models, etc.). Switching dimensions requires re-indexing.

### Security & Privacy

**API key storage**: Connector API keys are stored in environment variables, NOT in `harness.config.json`. The config file references variable names:

```json
{
  "graph": {
    "connectors": [
      {
        "source": "jira",
        "config": {
          "apiKeyEnv": "JIRA_API_KEY",
          "baseUrlEnv": "JIRA_BASE_URL"
        }
      }
    ]
  }
}
```

**Sensitive data in graph**: External connector data (Slack messages, Jira descriptions) may contain PII or secrets. Mitigations:

- The graph is `.gitignore`d — never committed to source control
- The graph is local to each developer's machine — no centralized storage
- Connectors support content filtering (e.g., only ingest issue titles + labels, not full descriptions)
- Optional redaction patterns in connector config: `"redact": ["\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Z|a-z]{2,}\\b"]` strips emails before ingestion

**Embedding privacy**: When using external embedding APIs (OpenAI, Anthropic), code content is sent to the provider for embedding. For sensitive codebases, configure a local embedding model (Ollama) to keep all data on-machine.

### Developer Experience & Onboarding

**Graph is optional**: All existing commands work without a graph. The hybrid mode (graph-first, config-fallback) means:

- No graph → commands behave exactly as they do today
- Graph exists → commands use graph for richer results
- Graph is stale → commands still work, with a warning

**First-run experience**:

```bash
harness init          # scaffolds project (unchanged)
harness scan          # NEW: builds graph (optional, ~5-15s for typical repos)
harness validate      # works with or without graph
```

**Staleness detection**: Every command that reads the graph checks the `lastScanTimestamp` in `.harness/graph/metadata.json`. If the graph is older than a configurable threshold (default: 24 hours), a warning is emitted:

```
⚠ Graph is 3 days old. Run `harness scan` to refresh.
```

Commands never fail due to staleness — they use stale data with a warning.

**Tree-sitter portability**: Tree-sitter requires native compilation, which can fail on some platforms. Mitigations:

- Tree-sitter is an optional dependency. If it fails to install, `harness scan` falls back to regex-based parsing (extracts imports/exports but not full AST). This produces a less detailed graph but still functional.
- Pre-built binaries are available for common platforms (macOS ARM/x86, Linux x86, Windows x86). The `optionalDependencies` pattern in package.json handles this.
- CI environments can use the Docker image which includes pre-compiled tree-sitter.

### Offline / Disconnected Mode

The graph operates in two layers:

1. **Local layer** (always available): Code parsing, doc ingestion, state ingestion, git history, constraint ingestion. These work entirely offline.
2. **External layer** (requires network): Jira, Slack, Confluence, CI connectors. These require API access.

When offline:

- Local layer is fully functional. `harness scan` rebuilds code/doc/state graph.
- External layer uses cached data from last successful sync. Connector nodes remain in the graph with their last-known state.
- `harness ingest` commands fail gracefully with "connector unavailable — using cached data" message.
- No graph queries fail. External nodes may be stale but are still queryable.

Embedding generation also requires network (for cloud providers). When offline with no local model configured, the vector store operates in keyword-only mode.

## Alternatives Considered

### Graph Overlay (Option B)

Add a graph layer alongside existing systems via adapters. Existing context/entropy/constraints continue as-is. Graph observes their outputs and provides semantic search and relationship queries on top.

Not chosen because: Creates permanent dual-system complexity. The graph is only as good as what existing systems expose — missing AST-level relationships. The "overlay" pattern tends to become permanent tech debt. Given no hard constraints on timeline or breaking changes, a clean replacement is preferable.

### Context Query Engine (Option C)

Build an on-demand query engine that constructs graph-like views at query time from source files. No persistent graph. Vector index maintained separately.

Not chosen because: Performance degrades at scale (parsing files on every query). Cannot answer temporal or cross-cutting queries without full scans. Caching complexity risks creating an accidental graph store. Limited capability ceiling doesn't match the goal of "best possible context system."

## Consequences

### Positive

- **Unified data model**: One graph replaces 6 disconnected systems (context, entropy, constraints, state, MCP resources, dependency tracking)
- **Semantic search**: Find similar code, related learnings, applicable decisions via vector similarity — not just string matching
- **Relationship-aware context**: Agents receive context that includes not just files but the connections between them
- **99%+ context reduction**: ContextQL noise pruning delivers only relevant nodes, not entire file trees
- **Extensible**: New node types (telemetry, CI results, PR reviews) can be added without schema changes
- **OmniContext deprecated cleanly**: Single system, no overlap, no confusion

### Negative

- **3-4 month build** — mitigated by phased delivery (each phase independently shippable) and existing domain knowledge from OmniContext
- **Tree-sitter native dependency** — mitigated by lazy loading, optional installation, and regex-based fallback for basic parsing
- **Breaking changes to existing context APIs** — mitigated by adapter layer during transition and phased migration
- **Embedding cost** — mitigated by optional embedding generation, local model support (Ollama), and keyword-only fallback
- **Operational surface area** — mitigated by LokiJS simplicity (single JSON file) and no external database requirements

### Neutral

- Existing skills that use `harness://project` and other MCP resources will need updating to use graph-powered equivalents, but the API surface can remain similar
- The `packages/core/src/entropy/` snapshot model has value as a "build once, query many" pattern that the graph adopts (scan → persist → query)

## Action Items

Organized by migration phase. Each phase is independently shippable.

### Phase 1 — Graph Foundation

- [x] Write docs/changes/graph-system-design/proposal.md — owner: cwarner
- [x] Write docs/plans/graph-implementation-plan.md — owner: cwarner
- [x] Create `packages/graph` package with TypeScript config, dependencies, and test setup — owner: cwarner
- [x] Implement GraphStore (LokiJS CRUD, node/edge types, persistence) — owner: cwarner
- [x] Implement ContextQL (BFS traversal, noise pruning, type/edge filtering, DSL) — owner: cwarner
- [x] Implement VectorStore (HNSWLib wrapper, fallback, incremental updates) — owner: cwarner
- [x] Implement CodeIngestor (tree-sitter parsing, worker pool, topological linking) — owner: cwarner
- [x] Write packages/graph/README.md — owner: cwarner

### Phase 2 — Knowledge Layer

- [x] Implement KnowledgeIngestor (ADR, docs, learnings, failures → graph nodes) — owner: cwarner
- [x] Implement GitIngestor (commits, PRs, blame, co-change analysis) — owner: cwarner
- [x] Implement FusionLayer (keyword + semantic score fusion, intent classification) — owner: cwarner
- [x] Integrate graph into core/state (modify loadRelevantLearnings, appendLearning, appendFailure) — owner: cwarner
- [x] Add 6 new MCP tools (query_graph, search_similar, find_context_for, get_relationships, get_impact, ingest_source) — owner: cwarner
- [x] Add 3 new MCP resources (harness://graph, harness://entities, harness://relationships) — owner: cwarner

### Phase 3 — External Connectors

- [x] Implement connector architecture (interface, SyncManager, incremental sync) — owner: cwarner
- [x] Implement JiraConnector (issue ingestion + Fusion Layer linking) — owner: cwarner
- [x] Implement SlackConnector (channel history ingestion + NER linking) — owner: cwarner
- [x] Add new CLI commands (scan, watch, ingest, query, graph status, graph export) — owner: cwarner
- [x] Write docs/guides/graph-connectors.md, graph-context-assembly.md, writing-custom-connectors.md — owner: cwarner

### Phase 4 — Context Assembly

- [x] Implement graph-driven context Assembler (replaces budget/filter/generate) — owner: cwarner
- [x] Integrate graph into core/context (deprecate validateAgentsMap, validateKnowledgeMap; modify checkDocCoverage, generateAgentsMap, contextFilter, contextBudget) — owner: cwarner
- [x] Create harness-context-assembler skill — owner: cwarner
- [x] Modify 4 existing MCP resources to serve graph-derived data — owner: cwarner

### Phase 5 — Entropy Migration

- [x] Integrate graph into core/entropy (modify EntropyAnalyzer, buildSnapshot, detectDocDrift, detectDeadCode, detectPatternViolations) — owner: cwarner
- [x] Update detect-doc-drift and cleanup-dead-code skills to use graph queries — owner: cwarner

### Phase 6 — Constraint Migration

- [x] Integrate graph into core/constraints (modify validateDependencies, buildDependencyGraph, detectCircularDeps, defineLayer) — owner: cwarner
- [x] Update enforce-architecture skill to use graph queries — owner: cwarner
- [x] Update 5 eslint-plugin rules to read constraints from graph with config-fallback — owner: cwarner
- [x] Modify 6 existing CLI commands to use graph-first with config-fallback — owner: cwarner

### Phase 7 — Tier-1 Skill Migration

- [x] Update remaining Tier-1 skills (code-review, validate-context, parallel-agents, onboarding) to use graph queries — owner: cwarner
- [x] Integrate graph into core/feedback (modify analyzeDiff, requestPeerReview, createSelfReview) — owner: cwarner
- [x] Modify 13 existing MCP tools to use graph-enhanced core functions — owner: cwarner

### Phase 8 — New Skills & Personas

- [x] Create harness-impact-analysis skill — owner: cwarner
- [x] Create harness-dependency-health skill — owner: cwarner
- [x] Create harness-hotspot-detector skill — owner: cwarner
- [x] Create harness-test-advisor skill — owner: cwarner
- [x] Create harness-knowledge-mapper skill — owner: cwarner
- [x] Update 3 existing personas (Architecture Enforcer, Documentation Maintainer, Entropy Cleaner) to use graph — owner: cwarner
- [x] Create Graph Maintainer persona — owner: cwarner
- [x] Create Codebase Health Analyst persona — owner: cwarner

### Phase 9 — Tier-2 Skills & Remaining Connectors

- [x] Update 5 Tier-2 skills (execution, planning, architecture-advisor, refactoring, align-documentation) — owner: cwarner
- [x] Implement ConfluenceConnector (page/section ingestion + linking) — owner: cwarner
- [x] Implement CIConnector (build/test result ingestion + failure linking) — owner: cwarner

### Phase 10 — Deprecation & Documentation

- [x] Update critical docs (AGENTS.md, README.md, principles.md, cli.md, configuration.md, core README, cli README, skills README) — owner: cwarner
- [x] Update high-priority docs (12 skill SKILL.md files, 3 persona yamls, implementation.md, kpis.md, issue-tracker guide) — owner: cwarner
- [x] Deprecate OmniContext — owner: cwarner

## Completion

**All 10 phases completed: 2026-03-18**

The Unified Knowledge Graph is fully integrated into Harness Engineering. OmniContext is deprecated — the harness graph is the single context system.

### Final Statistics

- **Graph package**: 20+ node types, 17+ edge types, 4 connectors, 6 adapters
- **Core enhancements**: context, entropy, constraints, feedback — all graph-enhanced with backward compatibility
- **MCP integration**: 6 graph tools, 3 graph resources, 4+ existing tools wired to graph
- **Skills**: 7 transformed, 5 enhanced, 5 new graph-powered skills
- **Personas**: 2 new (Graph Maintainer, Codebase Health Analyst), 3 updated
- **Tests**: 698+ tests across graph, core, and mcp-server packages
