TermAl

Feature Brief: Instruction Debugger

Status

Partially implemented. TermAl ships an instruction search/debugger workspace tab backed by GET /api/instructions/search. The full provenance graph and effective-stack model below remains future design work.

This brief describes a provenance and debugging surface for agent instruction documents such as CLAUDE.md, AGENTS.md, GEMINI.md, and related Markdown-based prompt files.

Related: Code Navigation MCP follows the same principle of returning compact, provenance-rich navigation context instead of forcing agents to read broad file sets.

Problem

The current instruction-file story is opaque.

When a user opens an instruction document, they can read what it says, but they cannot answer the harder debugging questions:

This is a real debugging workflow, not just documentation browsing. The user is effectively debugging a resolution system made of Markdown files, path scopes, agent-specific hierarchy rules, and local conventions.

Today TermAl already has:

What is missing is an instruction-specific provenance model.

Core idea

Add an Instruction Debugger that answers:

The debugger should expose three complementary views:

  1. Trace Shows the causal chain for one instruction or document.
  2. Effective Stack Shows all active instructions for a session and optional file path, ordered by precedence.
  3. Graph Shows the full document relationship graph for overview, dead-file discovery, and navigation.
  4. Search Finds phrase matches and reverse-traces every path back to the full root set.

The graph is useful, but it is not the primary debugging surface. The primary surface is the trace and reverse root search.

Reverse provenance and roots

The debugger should support reverse provenance queries:

This is closer to a gcroot-style query than a simple tree inspector.

The important output is not “who is the parent?” but:

By default, the debugger should prefer completeness over brevity. The user can collapse to shortest path or active-only path after the full root set is known.

Two levels of provenance

The feature needs to distinguish between two related but different questions.

Document provenance

How did this Markdown file become part of the active instruction set?

Examples:

Instruction provenance

How did this specific paragraph, heading section, or instruction block survive resolution and become effective?

Examples:

If TermAl only models document provenance, the user still cannot debug why a specific instruction is active. The debugger needs both levels.

Ground truth vs inference

TermAl does not own the instruction semantics of every agent runtime. Some resolution steps are directly observable from local files; others are only inferable from known agent conventions.

The debugger should make that explicit.

Each discovered relation should carry a provenance quality:

This prevents the UI from presenting guessed causality as hard truth.

Goals

Non-goals for v1

User experience

Entry points

Recommended entry points:

Trace view

The trace view is the highest-value workflow.

Example:

AGENTS.md
  -> activated for project root
  -> subdirectory scope matched src/**
  -> docs/agents/backend.md became active
  -> instruction at docs/agents/backend.md:12 won precedence
  -> overrides AGENTS.md:44

For each step, show:

The trace view should support:

Effective stack view

For a selected session and optional file path, show:

This is the equivalent of a compiler include list or CSS cascade inspector.

Graph view

The graph view is the overview and navigation layer.

Nodes:

Edges:

Graph interactions:

The graph should not flatten all relations to file-to-file edges. Where possible, an edge should originate from a specific span or line range inside the source file so the user can answer “which line pulled that file in?”

Search view

The search view answers:

Search flow:

  1. user enters a phrase such as dependency injection
  2. debugger finds matching instruction spans
  3. for each match, debugger reverse-traces all reachable roots
  4. UI groups results by match span, then by root

Each result should show:

Example:

Match: .claude/reviewers/rust.md:9
"Prefer dependency injection where ownership boundaries are unstable."

Roots:
- CLAUDE.md
  -> reviewers.md:12
  -> .claude/reviewers/rust.md:9

- AGENTS.md
  -> docs/agents/backend.md:18
  -> .claude/reviewers/rust.md:9

Inspector

Every view should feed the same right-side inspector with:

Resolution context

Every debugger query should be evaluated against an explicit context:

struct InstructionResolutionContext {
    session_id: String,
    agent: Agent,
    workdir: String,
    target_path: Option<String>,
    command_name: Option<String>,
    project_id: Option<String>,
}

Without context, “is this active?” is not answerable.

The same file may be active for one session, inactive for another, and only conditionally active for a given command or subdirectory.

Root model

The debugger should distinguish between two classes of roots.

Structural roots

These are top-level entry points in the instruction system, for example:

Activation roots

These are context anchors that explain why a structural root mattered for this resolution:

Both root classes matter. A structural root without activation context does not fully explain why the span is relevant, and activation context without the structural root does not show where the instruction came from.

Data model

Instruction document

struct InstructionDocument {
    id: String,
    path: String,
    kind: InstructionDocumentKind,
    title: Option<String>,
    discovered_by: ProvenanceKind,
    applies_to_agents: Vec<Agent>,
}

Examples of kind:

Instruction span

struct InstructionSpan {
    id: String,
    document_id: String,
    line_start: u32,
    line_end: u32,
    heading_path: Vec<String>,
    text: String,
}

This is the unit the user actually debugs. A span is usually a paragraph, section, or command block, not a whole file.

Provenance edge

struct ProvenanceEdge {
    id: String,
    from_id: String,
    to_id: String,
    relation: ProvenanceRelation,
    condition: Option<String>,
    matched: bool,
    precedence: Option<i32>,
    provenance_kind: ProvenanceKind,
    detail: Option<String>,
}

Examples of relation:

Effective instruction

struct EffectiveInstruction {
    span_id: String,
    active: bool,
    precedence_rank: i32,
    overridden_span_ids: Vec<String>,
    overridden_by_span_id: Option<String>,
    explanation: Vec<String>,
}

Reverse path

struct InstructionRootPath {
    match_span_id: String,
    root_id: String,
    activation_root_ids: Vec<String>,
    edge_ids: Vec<String>,
    active: bool,
    shortest: bool,
}

This is the core result shape for phrase search and full-root trace queries.

Backend architecture

1. Instruction adapters

Add agent-specific instruction adapters that know how to discover candidate documents and explain known hierarchy rules.

Examples:

Each adapter should:

This follows the same general adapter shape already used elsewhere in TermAl for agent-specific runtime differences.

2. Shared instruction index

Build a backend index keyed by workdir plus agent type.

The index should cache:

Invalidate when:

3. Effective resolution pass

Given a resolution context:

  1. collect candidate documents from the adapter
  2. extract spans from those documents
  3. apply known scope and precedence rules
  4. build the effective stack
  5. retain the losing candidates so the debugger can explain them

The losing candidates matter. A debugger that only returns the winners cannot explain why something disappeared.

4. Reverse reachability

Given a selected span or phrase match:

  1. locate all matching spans
  2. walk reverse provenance edges from each span
  3. enumerate all reachable structural roots
  4. attach activation roots for the current context
  5. return all paths, with optional shortest-path summaries

The backend should not stop after finding the first parent or first root.

API plan

Graph snapshot

GET /api/instructions/graph?sessionId={id}&targetPath={path?}

Returns:

{
  "documents": [],
  "spans": [],
  "edges": [],
  "context": {},
  "summary": {
    "activeDocuments": 0,
    "activeSpans": 0,
    "inactiveSpans": 0,
    "overrideEdges": 0
  }
}

Purpose:

Effective stack

GET /api/instructions/effective?sessionId={id}&targetPath={path?}&commandName={name?}

Returns the ordered list of active and inactive candidate instruction spans for the current context.

Trace

GET /api/instructions/trace?sessionId={id}&spanId={id}

Returns the causal chain for one span, including:

GET /api/instructions/search?sessionId={id}&q={phrase}&targetPath={path?}&commandName={name?}

Returns:

{
  "matches": [
    {
      "spanId": "span-1",
      "path": ".claude/reviewers/rust.md",
      "lineStart": 9,
      "lineEnd": 9,
      "text": "Prefer dependency injection where ownership boundaries are unstable.",
      "active": true,
      "rootCount": 2,
      "activeRootCount": 1
    }
  ],
  "paths": [],
  "roots": [],
  "context": {}
}

Purpose:

Source lookup

Recommended helper endpoint:

GET /api/instructions/source?sessionId={id}&path={file}

Purpose:

Frontend plan

Workspace integration

Add a new workspace tab kind:

This should fit the existing generic workspace tab system rather than becoming a special overlay. The user should be able to keep the debugger open alongside a session, source editor, diff preview, filesystem, and git status.

View layout

Recommended layout for the debugger tab:

Recommended top-bar controls:

Source navigation

Clicking any document or span should:

When the current source tab is an instruction file, TermAl should offer a contextual action:

That action should open the debugger focused on the clicked line or nearest instruction span. If the user has a text selection, the debugger should open in Search mode seeded with that phrase.

Diagnostics

The debugger should surface problems directly in the UI:

These are not secondary details. They are often the actual bug.

Relation to graph/canvas export

An Obsidian-style canvas is useful as a presentation layer, but it should be built on top of the native provenance model, not instead of it.

Recommended order:

  1. native document/span/edge model
  2. native debugger tab and inspector
  3. native reverse root search
  4. optional export to .canvas / JSON Canvas

That keeps the feature grounded in debugging value instead of treating the graph as the product.

Implementation phases

Phase 1: backend discovery and normalization

Phase 2: effective stack and trace

Phase 3: workspace tab and inspector

Phase 4: diagnostics and polish

Testing plan

Backend:

Frontend:

Acceptance criteria

Why this matters

Instruction files are not passive notes. They are part of the execution environment for the agent.

If the user cannot explain where an instruction came from, they cannot trust the agent’s behavior, and they cannot safely evolve a hierarchical Markdown-based instruction system. The instruction debugger turns that opaque behavior into something inspectable, navigable, and debuggable.