# AgentTeam Insight Graph Builder Compatibility Graph Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Add a `agentteam-insight graph` subcommand that analyzes an input repository in full or incremental mode and writes compatibility-safe `.agentteam-insight/knowledge-graph.json`, `meta.json`, `config.json`, and `fingerprints.json` files. Public CLI remains limited to `agentteam-insight graph` and `agentteam-insight wiki`.

> **Current status note (#t1505):** this original implementation plan predates the #t1480 parity audit. Treat it as historical scaffolding plus package/task context, not as evidence that full UA semantic parity is already complete. Current truth is tracked in `docs/research/2026-07-02-agentteam-insight-graph-builder-compat-parity-audit.md`; the active branch is converging batch-by-batch toward full parity. #t1501–#t1504 converged the release-facing AgentTeam Insight / Graph Builder naming, CLI, artifact, docs, PR, and Web/KB automation surface. #t1505 is design-only: it records the remaining OpenCode/skills production gaps and the tests required to close them before a later implementation batch can claim those gaps are fixed.

**Architecture:** Implement a Go-native `kits/agentteam-insight/internal/graphbuilder` pipeline with clear packages for schema validation, persistence, scanning, extraction, import graph, batching, fingerprints, graph assembly, layers, tour, and optional agent enhancement. The Go pipeline is being reconciled against Understand-Anything's semantic stages before graph persistence through the #t1480 follow-up batches, while keeping Go package boundaries idiomatic and separate from the existing `codeanalysis` markdown and `codewiki` wiki flows.

**Tech Stack:** Go 1.25, existing `kits/agentteam-insight` CLI conventions, Go stdlib `go/parser` for first-class Go extraction, deterministic JSON validation/writers, optional OpenCode agent runner through existing `opencoderuntime`, and Understand-Anything's TypeScript `validateGraph()` as compatibility gate.

---

## 0. Source references and hard constraints

### Source artifacts already collected

- Understand-Anything source repo: `/Users/lonng/devel/ai/Understand-Anything`, observed HEAD `54754a6f9705`.
- AgentTeam Insight group worktree: `/Users/lonng/devel/pingcap/agentteam/.worktrees/agentteam-insight-graph-builder-plan`.
- Group branch: `plan/agentteam-insight-graph-builder-ua`, based on `origin/main` `6496f571e` when planning started.
- UA semantics report: `docs/research/2026-07-02-graph-builder-compat-semantics.md`.
- AgentTeam Insight entrypoint/package report: `docs/research/2026-07-02-agentteam-insight-graph-builder-cli-scan.md`.

### User requirements that must not drift

- The generated graph must be directly consumable by the Understand-Anything dashboard.
- Full and incremental modes must converge toward Understand-Anything's core analysis flow before graph JSON is written; current status and remaining gaps are tracked in the #t1480 parity audit.
- The implementation must be modular and organized in idiomatic Go packages, not a mechanical copy of UA's TypeScript/prompt directory layout.
- Codex2 and GLM2 work in independent worktrees; Planner owns the group worktree and cherry-picks only reviewed commits into it.
- Reviewer2 is the final plan/schema gate before implementation and final code gate before PR merge.

### Non-goals for the first implementation PR

- Do not replace the public `agentteam-insight graph` or `agentteam-insight wiki` outputs with legacy aliases.
- Do not make UA dashboard a AgentTeam web app in the same PR.
- Do not promise byte-for-byte equality for LLM-written summaries, tags, layers, or tour prose.
- Do not expose arbitrary local file forwarding or absolute local paths in graph files.
- Do not integrate MeshX/KB automation presets until the local CLI and UA compatibility gate pass.
- Do not generate `domain-graph.json` in the first implementation PR; keep domain/knowledge schema compatibility only.

---

## 1. Required file and package structure

### Modified CLI files

- Modify: `kits/agentteam-insight/main.go`
  - Expose `graph` as a top-level command beside `wiki`; do not expose a public `analyze` command.
  - Add `graphbuilder.CommandRunner` to `commandRunners`.
  - Add `runGraph()` and `parseGraphOptions()`.
- Modify: `kits/agentteam-insight/main_test.go`
  - Add tests for option parsing, runner injection, stdout summary, and `--jobs > 1` isolation behavior.

### New Go packages under `kits/agentteam-insight/internal/graphbuilder`

```text
kits/agentteam-insight/internal/graphbuilder/
  options.go                  # Options, Mode, Result, CommandRunner, Command types
  run.go                      # RunCommand and Run orchestration
  progress.go                 # [graph-builder] progress logging helpers
  schema/
    graph.go                  # UA-compatible Go graph structs, enum constants, unknown-field preservation hooks
    aliases.go                # NODE/EDGE/COMPLEXITY/DIRECTION alias maps ported from UA
    validate.go               # sanitize -> normalize aliases -> auto-fix -> drop-broken -> fatal validator
    normalize.go              # node ID canonicalization and edge/layer/tour reference filtering
  persistence/
    paths.go                  # .agentteam-insight path layout, worktree redirect, safe relative paths
    store.go                  # atomic JSON read/write, write order, trash/intermediate handling
  scanner/
    scanner.go                # file enumeration, language/category/line counting, git metadata
    ignore.go                 # .agentteam-insightignore + .gitignore compatible matcher
    language.go               # extension/language/category classification
  extractor/
    extractor.go              # Extractor interface and StructuralAnalysis DTO
    golang/extractor.go       # Go extractor using go/parser/go/ast
    generic/extractor.go      # content-hash-only fallback for unsupported languages
    noncode/extractor.go      # markdown/config/docs lightweight parser hooks
  importgraph/
    graph.go                  # import resolution, neighbor map, import edges
  batching/
    batches.go                # deterministic semantic batches and batch file naming helpers
  graphbuilder/
    builder.go                # StructuralAnalysis -> GraphNode/GraphEdge skeleton
  fingerprint/
    store.go                  # FingerprintStore and file fingerprints
    compare.go                # NONE/COSMETIC/STRUCTURAL compare rules
    classify.go               # SKIP/PARTIAL/ARCHITECTURE/FULL_UPDATE decision rules
  assembler/
    merge.go                  # merge batch graphs; prune changed file nodes/edges for incremental
    normalize.go              # dedupe, tested_by direction fixer, dangling-edge cleanup
  layers/
    heuristic.go              # deterministic layer fallback, normalizer
  tour/
    heuristic.go              # deterministic tour fallback, normalizer
  agent/
    runner.go                 # optional OpenCode/agent enhancement interface
    opencode_server.go        # future server-backed TaskRunner lifecycle
    source_subset.go          # future session-local source copy + manifest map
    skills_bundle.go          # future allowlisted skill/reference materializer
    prompts/
      file_analyzer.md
      architecture_analyzer.md
      tour_builder.md
      assemble_reviewer.md
  compat/
    ua_validator.go           # helper to run UA validateGraph in integration tests when available
  testdata/
    fixtures/
      tiny-go-repo/
      tiny-ts-repo/
      incremental-go-repo/
```

### Dependency direction

```text
main -> internal/graphbuilder
graphbuilder/run -> scanner, extractor, importgraph, batching, graphbuilder, fingerprint, assembler, layers, tour, agent, persistence, schema
scanner -> no graph schema dependency; returns scanner.FileInfo
extractor -> extractor.StructuralAnalysis only
importgraph -> scanner.FileInfo + extractor.StructuralAnalysis
batching -> scanner.FileInfo + importgraph.Graph
fingerprint -> extractor.StructuralAnalysis
schema -> no runtime dependencies
persistence -> schema + fingerprint
assembler/graphbuilder/layers/tour -> schema
agent -> schema + opencoderuntime
compat -> test-only helper around external UA repo
```

Guardrails:

- `schema` must not import `persistence`, `agent`, or `opencoderuntime`.
- `persistence` must not import `agent`.
- `main.go` must not contain analysis logic beyond CLI flag parsing and command dispatch.
- Existing `codeanalysis` and `codewiki` packages stay independent.

---

## 2. UA-compatible data contracts

### 2.1 `knowledge-graph.json`

The Go root struct must marshal to this UA-compatible shape and must keep `kind` optional. UA currently accepts `kind: "codebase" | "knowledge"`; first PR writes `codebase`.

```go
type KnowledgeGraph struct {
    Version string      `json:"version"`
    Kind    string      `json:"kind,omitempty"`
    Project ProjectMeta `json:"project"`
    Nodes   []GraphNode `json:"nodes"`
    Edges   []GraphEdge `json:"edges"`
    Layers  []Layer     `json:"layers"`
    Tour    []TourStep  `json:"tour"`
}

type ProjectMeta struct {
    Name          string   `json:"name"`
    Languages     []string `json:"languages"`
    Frameworks    []string `json:"frameworks"`
    Description   string   `json:"description"`
    AnalyzedAt    string   `json:"analyzedAt"`
    GitCommitHash string   `json:"gitCommitHash"`
}
```

`ProjectMeta` is not passthrough in UA. Unknown project fields may be ignored by the Go writer; they are not part of the compatibility contract.

#### GraphNode

UA has exactly **21 canonical node types**:

```text
file,function,class,module,concept,
config,document,service,table,endpoint,pipeline,schema,resource,
domain,flow,step,
article,entity,topic,claim,source
```

`GraphNode` fields:

```go
type GraphNode struct {
    ID            string          `json:"id"`
    Type          string          `json:"type"`
    Name          string          `json:"name"`
    FilePath      string          `json:"filePath,omitempty"`
    LineRange     []int           `json:"lineRange,omitempty"`
    Summary       string          `json:"summary"`
    Tags          []string        `json:"tags"`
    Complexity    string          `json:"complexity"` // simple|moderate|complex
    LanguageNotes string          `json:"languageNotes,omitempty"`
    DomainMeta    *DomainMeta     `json:"domainMeta,omitempty"`
    KnowledgeMeta *KnowledgeMeta  `json:"knowledgeMeta,omitempty"`
    Extra         json.RawMessage `json:"-"` // implementation detail for passthrough fields
}
```

UA `GraphNodeSchema` is `.passthrough()`, so Go read/write must preserve unknown node fields when it updates an existing graph. Implement this with a custom marshal/unmarshal `Extra map[string]json.RawMessage` pattern or a documented equivalent.

Node ID rules:

- File-like nodes: `<type>:<relative-path>`.
- Function/class nodes: `<type>:<relative-path>:<name>`.
- Table/endpoint nodes: `<type>:<relative-path>:<name>`.
- Module/concept/domain/article/entity/topic/claim/source nodes: `<type>:<slug>`.
- Flow nodes: `flow:<slug>`.
- Step nodes: `step:<flowSlug>:<relative-path>:<stepSlug>`.

#### GraphEdge

UA has exactly 35 canonical edge types:

```text
imports,exports,contains,inherits,implements,
calls,subscribes,publishes,middleware,
reads_from,writes_to,transforms,validates,
depends_on,tested_by,configures,
related,similar_to,
deploys,serves,provisions,triggers,
migrates,documents,routes,defines_schema,
contains_flow,flow_step,cross_domain,
cites,contradicts,builds_on,exemplifies,categorized_under,authored_by
```

`GraphEdge` fields:

```go
type GraphEdge struct {
    Source      string  `json:"source"`
    Target      string  `json:"target"`
    Type        string  `json:"type"`
    Direction   string  `json:"direction"` // forward|backward|bidirectional
    Description string  `json:"description,omitempty"`
    Weight      float64 `json:"weight"` // clamped to [0,1]
}
```

UA `GraphEdgeSchema` is **not** passthrough. Do not preserve arbitrary unknown edge fields in the canonical writer; reject or drop them during normalization.

#### Layer and TourStep

```go
type Layer struct {
    ID          string   `json:"id"`
    Name        string   `json:"name"`
    Description string   `json:"description"`
    NodeIDs     []string `json:"nodeIds"`
}

type TourStep struct {
    Order          int      `json:"order"`
    Title          string   `json:"title"`
    Description    string   `json:"description"`
    NodeIDs        []string `json:"nodeIds"`
    LanguageLesson string   `json:"languageLesson,omitempty"`
}
```

UA `LayerSchema` and `TourStepSchema` are not passthrough. The Go validator must filter dangling `nodeIds`; it does not need to preserve unknown layer/tour fields.

#### DomainMeta and KnowledgeMeta

```go
type DomainMeta struct {
    Entities                []string        `json:"entities,omitempty"`
    BusinessRules           []string        `json:"businessRules,omitempty"`
    CrossDomainInteractions []string        `json:"crossDomainInteractions,omitempty"`
    EntryPoint              string          `json:"entryPoint,omitempty"`
    EntryType               string          `json:"entryType,omitempty"` // http|cli|event|cron|manual
    Extra                   json.RawMessage `json:"-"`
}

type KnowledgeMeta struct {
    Wikilinks []string        `json:"wikilinks,omitempty"`
    Backlinks []string        `json:"backlinks,omitempty"`
    Category  string          `json:"category,omitempty"`
    Content   string          `json:"content,omitempty"`
    Extra     json.RawMessage `json:"-"`
}
```

UA `DomainMetaSchema` and `KnowledgeMetaSchema` are `.passthrough()`. Preserve unknown keys inside these two metadata objects.

### 2.2 Metadata and companion files

`meta.json` uses UA `AnalysisMeta`:

```go
type AnalysisMeta struct {
    LastAnalyzedAt string       `json:"lastAnalyzedAt"`
    GitCommitHash  string       `json:"gitCommitHash"`
    Version        string       `json:"version"`
    AnalyzedFiles  int          `json:"analyzedFiles"`
    Theme          *ThemeConfig `json:"theme,omitempty"`
}

type ThemeConfig struct {
    PresetID string `json:"presetId"`
    AccentID string `json:"accentId"`
}
```

`AnalysisMeta` and `ThemeConfig` are not passthrough in UA. Unknown fields are not part of the first PR compatibility contract.

`config.json` uses UA `ProjectConfig`:

```go
type ProjectConfig struct {
    AutoUpdate     bool   `json:"autoUpdate"`
    OutputLanguage string `json:"outputLanguage,omitempty"`
}
```

`fingerprints.json` uses UA `FingerprintStore` and file-level signatures:

```go
type FingerprintStore struct {
    Version       string                     `json:"version"`
    GitCommitHash string                     `json:"gitCommitHash"`
    GeneratedAt   string                     `json:"generatedAt"`
    Files         map[string]FileFingerprint `json:"files"`
}

type FileFingerprint struct {
    FilePath              string                  `json:"filePath"`
    ContentHash           string                  `json:"contentHash"`
    Functions             []FunctionFingerprint   `json:"functions"`
    Classes               []ClassFingerprint      `json:"classes"`
    Imports               []ImportFingerprint     `json:"imports"`
    Exports               []string                `json:"exports"`
    TotalLines            int                     `json:"totalLines"`
    HasStructuralAnalysis bool                    `json:"hasStructuralAnalysis"`
}
```

`diff-overlay.json` is a dashboard-consumed optional companion file:

```go
type DiffOverlay struct {
    ChangedNodeIDs  []string `json:"changedNodeIds"`
    AffectedNodeIDs []string `json:"affectedNodeIds"`
}
```

First implementation PR must implement the `DiffOverlay` type and validator in the schema/persistence layer, but does not need to generate `diff-overlay.json` from git diffs by default. Generating it from an explicit `agentteam-insight graph diff` or a future flag is a follow-up task because the main goal is the canonical graph and incremental graph state.

`domain-graph.json` is also optional. It is explicitly out of scope for the first implementation PR: the first PR must not block on domain graph generation, but must not make the main graph incompatible with future `kind:"knowledge"` or domain/knowledge node support.

Persistence invariant:

1. Write and fsync `knowledge-graph.json` only after validation succeeds.
2. Write and fsync `fingerprints.json`.
3. Write and fsync `meta.json` only after `fingerprints.json` succeeds.
4. Write `config.json` whenever output language or auto-update config changes.

This ordering prevents UA issue #152, where new meta plus missing fingerprints forces every incremental run to degrade to full rebuild.

---

## 3. Pipeline equivalence

### 3.1 Full mode

`agentteam-insight graph --mode full --input <repo> --output <repo>` must run:

1. **Pre-flight**
   - Resolve input root, output root, `.agentteam-insight` root.
   - Detect git commit hash.
   - Detect worktree and redirect graph state to the main checkout root when required.
   - Load or initialize config.
2. **Ignore**
   - Read `.agentteam-insightignore` when present.
   - Merge `.gitignore`-style rules.
3. **Scan**
   - Enumerate candidate files.
   - Record relative path, size lines, file category, language, and filtered reason.
   - Persist `intermediate/scan-result.json` for future incremental reuse.
4. **Extract**
   - Run deterministic extractors.
   - Go extractor uses `go/parser` and `go/ast` for functions, types, methods, imports, exports, and line ranges.
   - Unsupported languages use generic fallback with `hasStructuralAnalysis=false`.
5. **Import graph and batching**
   - Build file import adjacency.
   - Produce deterministic batches and `neighborMap`.
   - Use only `batch-<index>.json` and `batch-<index>-part-<part>.json` names.
6. **Graph build / analyze**
   - Deterministically create file/function/class nodes and contains/imports/calls skeleton edges.
   - Optional agent enhancement fills summary/tags/languageNotes and semantic edges, but must output UA-compatible graph fragments.
7. **Assemble**
   - Merge batch graph fragments.
   - Normalize node IDs.
   - Dedupe by `(source,target,type)`.
   - Drop dangling edges.
   - Fix `tested_by` direction to production -> test.
8. **Layers / tour**
   - Generate deterministic layer and tour fallbacks.
   - Optional agent enhancement may improve names/descriptions.
   - Normalize envelope, filter node IDs, and sort tour by order.
9. **Review / validate**
   - Run Go validator.
   - Run UA `validateGraph()` compatibility gate in integration tests.
10. **Save**
   - Sanitize file paths before persistence.
   - Write graph, fingerprints, meta, config in the required order.
   - Move transient intermediates other than `scan-result.json` into `.trash-<timestamp>`.

### 3.2 Incremental mode

`agentteam-insight graph --mode incremental` must run:

1. Read `meta.json`, `knowledge-graph.json`, and `fingerprints.json`.
2. Diff `meta.gitCommitHash..HEAD` to collect changed, deleted, and new files.
3. Recompute fingerprints for current changed/new files.
4. Compare old/new fingerprints:
   - `NONE`: content hash identical.
   - `COSMETIC`: content differs but structural signature unchanged.
   - `STRUCTURAL`: signature changed, file added/deleted, or structural analysis missing.
5. Classify update:
   - `SKIP`: no structural changes.
   - `PARTIAL_UPDATE`: localized structural changes.
   - `ARCHITECTURE_UPDATE`: directory structure changed or more than 10 structural files.
   - `FULL_UPDATE`: more than 30 structural files or more than 50% of graph files.
6. For partial/architecture update:
   - Remove old nodes whose `filePath` is in changed/deleted paths.
   - Remove old edges whose source or target is removed.
   - Re-run scan/extract/batch/analyze for changed/new files.
   - Merge retained graph plus fresh batch graph.
7. Re-run layers/tour only for architecture update.
8. Save using the same write ordering as full mode.

---

## 4. Work split and cherry-pick workflow

### Branches / worktrees

- Planner group worktree: `/Users/lonng/devel/pingcap/agentteam/.worktrees/agentteam-insight-graph-builder-plan`.
- Planner group branch: `plan/agentteam-insight-graph-builder-ua`.
- Codex2 implementation worktrees use `feature/codex2-agentteam-insight-graph-builder-<slice>`.
- GLM2 implementation/compat worktrees use `feature/glm2-agentteam-insight-graph-builder-<slice>`.

### Rules

- Each worker commits only their assigned package slice.
- Each worker reports commit SHA, worktree path, verification commands, and changed files.
- Planner cherry-picks only commits that pass the slice gate into the group worktree.
- Reviewer2 reviews from the group worktree or final PR, not from an unmerged worker worktree.
- PR merge uses PR comment `/merge` and the CI/CD merge lane; no direct local or provider merge.

---

## 5. Implementation tasks

### Task 1: CLI skeleton and command contract

**Owner:** Codex2
**Reviewer:** Reviewer2
**Files:**
- Modify: `kits/agentteam-insight/main.go`
- Modify: `kits/agentteam-insight/main_test.go`
- Create: `kits/agentteam-insight/internal/graphbuilder/options.go`
- Create: `kits/agentteam-insight/internal/graphbuilder/run.go`
- Create: `kits/agentteam-insight/internal/graphbuilder/progress.go`

- [ ] Add `graph` to `commandRunners` and `run()` dispatch.
- [ ] Implement flags: `--input`, `--output`, `--mode full|incremental|auto`, `--jobs`, `--output-language`, `--review`, `--isolate-opencode-runtime`, `--model`, `--opencode`, `--opencode-agent`, `--opencode-arg`, `--task-timeout`.
- [ ] Define `Options`, `Mode`, `Result`, `CommandRunner`, and `Command` in `internal/graphbuilder`.
- [ ] Enforce: `--input` required; `--output` defaults to `--input`; `--jobs > 1` requires `--isolate-opencode-runtime` when agent enhancement is enabled.
- [ ] Unit test runner injection without invoking OpenCode.
- [ ] Run:

```bash
cd kits/agentteam-insight && go test ./...
git diff --check
```

Expected: all tests pass; no whitespace errors.

### Task 2: Schema, aliases, validator, and ID normalization

**Owner:** GLM2 for parity checklist + Codex2 for Go implementation
**Reviewer:** Reviewer2
**Files:**
- Create: `kits/agentteam-insight/internal/graphbuilder/schema/graph.go`
- Create: `kits/agentteam-insight/internal/graphbuilder/schema/aliases.go`
- Create: `kits/agentteam-insight/internal/graphbuilder/schema/validate.go`
- Create: `kits/agentteam-insight/internal/graphbuilder/schema/normalize.go`
- Create: `kits/agentteam-insight/internal/graphbuilder/schema/validate_test.go`

- [ ] Port all 21 UA node types and 35 edge types.
- [ ] Add Go schema/validator support for optional `diff-overlay.json` (`changedNodeIds`, `affectedNodeIds`) while leaving default generation for a follow-up task.
- [ ] Port node, edge, complexity, and direction alias maps from UA `schema.ts`.
- [ ] Implement sanitize -> normalize aliases -> auto-fix -> drop-broken -> fatal validator.
- [ ] Preserve unknown optional fields only where UA is passthrough: `GraphNode`, `DomainMeta`, and `KnowledgeMeta`. Do not preserve arbitrary unknown fields on `GraphEdge`, `Layer`, `TourStep`, `ProjectMeta`, `AnalysisMeta`, or `ThemeConfig`.
- [ ] Implement node ID normalization for file/function/class/table/endpoint/module/step.
- [ ] Test auto-fix for missing summary/tags/complexity/direction/weight.
- [ ] Test dangling edges are dropped and no valid nodes is fatal.
- [ ] Test layer/tour node IDs are filtered to valid node IDs.
- [ ] Run:

```bash
cd kits/agentteam-insight && go test ./internal/graphbuilder/schema -count=1
cd kits/agentteam-insight && go test ./...
git diff --check
```

Expected: schema package and full agentteam-insight tests pass.

### Task 3: Persistence, path safety, worktree redirect, and UA layout

**Owner:** Codex2
**Reviewer:** Reviewer2
**Files:**
- Create: `kits/agentteam-insight/internal/graphbuilder/persistence/paths.go`
- Create: `kits/agentteam-insight/internal/graphbuilder/persistence/store.go`
- Create: `kits/agentteam-insight/internal/graphbuilder/persistence/store_test.go`

- [ ] Implement `.agentteam-insight` root path resolution.
- [ ] Implement worktree redirect by comparing `git rev-parse --git-dir` and `git rev-parse --git-common-dir`.
- [ ] Implement relative file path sanitizer: inside input root -> relative slash path; outside absolute path -> basename; never persist absolute local paths.
- [ ] Implement JSON writers for `knowledge-graph.json`, `fingerprints.json`, `meta.json`, `config.json`.
- [ ] Enforce write order: graph -> fingerprints -> meta -> config.
- [ ] Preserve `intermediate/scan-result.json`; move transient intermediates into `.trash-<timestamp>` after successful save.
- [ ] Unit test write order by injecting a recorder filesystem abstraction or a package-local writer interface.
- [ ] Run:

```bash
cd kits/agentteam-insight && go test ./internal/graphbuilder/persistence -count=1
cd kits/agentteam-insight && go test ./...
git diff --check
```

Expected: no absolute paths in persisted graph fixtures.

### Task 4: Scanner and ignore handling

**Owner:** Codex2
**Reviewer:** Reviewer2
**Files:**
- Create: `kits/agentteam-insight/internal/graphbuilder/scanner/scanner.go`
- Create: `kits/agentteam-insight/internal/graphbuilder/scanner/ignore.go`
- Create: `kits/agentteam-insight/internal/graphbuilder/scanner/language.go`
- Create: `kits/agentteam-insight/internal/graphbuilder/scanner/scanner_test.go`

- [ ] Enumerate files under `--input` using slash-separated relative paths.
- [ ] Ignore `.git`, `.agentteam-insight/.trash-*`, binary files, vendored dependency directories, and rules from `.agentteam-insightignore` and `.gitignore`.
- [ ] Classify file category as `code|config|docs|infra|data|script|markup`.
- [ ] Detect project language list and framework hints from package manifests and common config files.
- [ ] Persist `intermediate/scan-result.json` for incremental reuse.
- [ ] Unit test `.agentteam-insightignore` and `.gitignore` merging.
- [ ] Run:

```bash
cd kits/agentteam-insight && go test ./internal/graphbuilder/scanner -count=1
cd kits/agentteam-insight && go test ./...
git diff --check
```

Expected: scan fixture is deterministic across repeated runs.

### Task 5: Extractors, import graph, and deterministic graph skeleton

**Owner:** Codex2
**Reviewer:** Reviewer2
**Files:**
- Create: `kits/agentteam-insight/internal/graphbuilder/extractor/extractor.go`
- Create: `kits/agentteam-insight/internal/graphbuilder/extractor/golang/extractor.go`
- Create: `kits/agentteam-insight/internal/graphbuilder/extractor/generic/extractor.go`
- Create: `kits/agentteam-insight/internal/graphbuilder/importgraph/graph.go`
- Create: `kits/agentteam-insight/internal/graphbuilder/graphbuilder/builder.go`
- Create tests in the same packages.

- [ ] Define `StructuralAnalysis` with functions, classes/types, imports, exports, calls, line ranges, total lines, and `hasStructuralAnalysis`.
- [ ] Implement Go extractor with `go/parser` and `go/ast`.
- [ ] Implement generic fallback with content hash, total lines, and `hasStructuralAnalysis=false`.
- [ ] Resolve Go imports to internal files where possible.
- [ ] Generate `file:`, `function:`, and `class:` nodes.
- [ ] Generate `contains`, `imports`, and direct Go `calls` edges when resolvable.
- [ ] Unit test node IDs, line ranges, import edges, and no dangling edges.
- [ ] Run:

```bash
cd kits/agentteam-insight && go test ./internal/graphbuilder/extractor/... ./internal/graphbuilder/importgraph ./internal/graphbuilder/graphbuilder -count=1
cd kits/agentteam-insight && go test ./...
git diff --check
```

Expected: deterministic graph skeleton for a tiny Go fixture.

### Task 6: Fingerprint and incremental classifier

**Owner:** Codex2
**Reviewer:** Reviewer2
**Files:**
- Create: `kits/agentteam-insight/internal/graphbuilder/fingerprint/store.go`
- Create: `kits/agentteam-insight/internal/graphbuilder/fingerprint/compare.go`
- Create: `kits/agentteam-insight/internal/graphbuilder/fingerprint/classify.go`
- Create tests in `kits/agentteam-insight/internal/graphbuilder/fingerprint`.

- [ ] Implement `FileFingerprint` and `FingerprintStore` matching UA schema.
- [ ] Compute SHA-256 `contentHash`.
- [ ] Compare functions/classes/imports/exports with the UA line-count ±50% threshold.
- [ ] Return `NONE`, `COSMETIC`, or `STRUCTURAL` with details.
- [ ] Implement update actions: `SKIP`, `PARTIAL_UPDATE`, `ARCHITECTURE_UPDATE`, `FULL_UPDATE`.
- [ ] Use thresholds: `>30` structural files, `>50%` of graph files, `>10` structural files for architecture update, and top-level directory changes.
- [ ] Unit test each action and the conservative path when `hasStructuralAnalysis=false`.
- [ ] Run:

```bash
cd kits/agentteam-insight && go test ./internal/graphbuilder/fingerprint -count=1
cd kits/agentteam-insight && go test ./...
git diff --check
```

Expected: classifier matches UA decision table.

### Task 7: Batching, assembler, and incremental merge semantics

**Owner:** Codex2
**Reviewer:** Reviewer2
**Files:**
- Create: `kits/agentteam-insight/internal/graphbuilder/batching/batches.go`
- Create: `kits/agentteam-insight/internal/graphbuilder/assembler/merge.go`
- Create: `kits/agentteam-insight/internal/graphbuilder/assembler/normalize.go`
- Create tests in both packages.

- [ ] Build deterministic batches from file size, language, and import adjacency.
- [ ] Enforce batch file names `batch-<i>.json` and `batch-<i>-part-<k>.json`.
- [ ] Merge graph fragments with node ID normalization and edge dedupe.
- [ ] Implement `MergeGraphUpdate(existing, fresh, changedFilePaths, gitCommitHash, now)`.
- [ ] Prune nodes whose `filePath` is changed/deleted.
- [ ] Prune old edges if either source or target is removed.
- [ ] Fix `tested_by` direction so production node points to test node.
- [ ] Unit test partial update does not append duplicate old changed-file nodes.
- [ ] Run:

```bash
cd kits/agentteam-insight && go test ./internal/graphbuilder/batching ./internal/graphbuilder/assembler -count=1
cd kits/agentteam-insight && go test ./...
git diff --check
```

Expected: incremental merge preserves retained nodes and removes all stale references.

### Task 8: Layers and tour deterministic fallback

**Owner:** GLM2 for UA parity and fixture expectations + Codex2 for Go implementation
**Reviewer:** Reviewer2
**Files:**
- Create: `kits/agentteam-insight/internal/graphbuilder/layers/heuristic.go`
- Create: `kits/agentteam-insight/internal/graphbuilder/tour/heuristic.go`
- Create tests in both packages.

- [ ] Generate layers by top-level directory, language, and entry-point heuristics.
- [ ] Generate at least one tour step for README/entry/main/package roots when available.
- [ ] Normalize layer IDs as `layer:<slug>`.
- [ ] Filter layer/tour node IDs through schema validator.
- [ ] Sort tour steps by `order` starting at 1.
- [ ] Unit test minimal graph still gets a non-empty layer and tour when valid file nodes exist.
- [ ] Run:

```bash
cd kits/agentteam-insight && go test ./internal/graphbuilder/layers ./internal/graphbuilder/tour -count=1
cd kits/agentteam-insight && go test ./...
git diff --check
```

Expected: dashboard can show layer/tour panels without LLM enhancement.

### Task 9: Full and incremental orchestrator

**Owner:** Codex2
**Reviewer:** Reviewer2
**Files:**
- Modify: `kits/agentteam-insight/internal/graphbuilder/run.go`
- Create: `kits/agentteam-insight/internal/graphbuilder/run_test.go`
- Create fixtures under `kits/agentteam-insight/internal/graphbuilder/testdata/fixtures`.

- [ ] Implement full mode using the exact stage order in section 3.1.
- [ ] Implement auto mode: full when no valid graph/fingerprints/meta exists, otherwise incremental.
- [ ] Implement incremental mode using the exact stage order in section 3.2.
- [ ] Return stdout summary counts: analyzed files, nodes, edges, layers, tour steps, graph path, action.
- [ ] Test full mode writes required files.
- [ ] Test incremental cosmetic-only change returns `SKIP` and does not rewrite graph nodes.
- [ ] Test structural change prunes old changed-file nodes and writes fresh nodes.
- [ ] Run:

```bash
cd kits/agentteam-insight && go test ./internal/graphbuilder -count=1
cd kits/agentteam-insight && go test ./...
git diff --check
```

Expected: fixture repository produces a valid `.agentteam-insight` directory.

### Task 10: UA validator and dashboard compatibility gate

**Owner:** GLM2
**Reviewer:** Reviewer2
**Files:**
- Create: `kits/agentteam-insight/internal/graphbuilder/compat/ua_validator.go`
- Create: `kits/agentteam-insight/internal/graphbuilder/compat/ua_validator_test.go`
- Create: `kits/agentteam-insight/scripts/validate-ua-graph.mjs` if a script is clearer than inline shell.

- [ ] Add a test helper that can run UA `validateGraph()` when `UNDERSTAND_ANYTHING_ROOT` is set.
- [ ] Keep tests skipped with a clear message when the env var is absent, so normal AgentTeam CI is not tied to a local external checkout.
- [ ] Add a documented manual gate command:

```bash
cd /Users/lonng/devel/ai/Understand-Anything/understand-anything-plugin/packages/core
pnpm build
node -e 'import("./dist/schema.js").then(({validateGraph})=>{const fs=require("fs"); const g=JSON.parse(fs.readFileSync(process.argv[1],"utf8")); const r=validateGraph(g); if(!r.success) throw new Error(r.fatal||"invalid"); console.log("ok", r.issues.length)})' <fixture-repo>/.agentteam-insight/knowledge-graph.json
```

- [ ] Add dashboard smoke instructions:

```bash
cd /Users/lonng/devel/ai/Understand-Anything/understand-anything-plugin/packages/dashboard
GRAPH_DIR=<fixture-repo> pnpm dev
```

Expected: generated graph passes UA validator and dashboard loads without fatal validation error.

### Task 11: Optional agent enhancement seam

**Owner:** Codex2
**Reviewer:** Reviewer2
**Files:**
- Create: `kits/agentteam-insight/internal/graphbuilder/agent/runner.go`
- Create: prompt files under `kits/agentteam-insight/internal/graphbuilder/agent/prompts/`
- Add tests with fake runner.

- [ ] Define agent interfaces for file analysis, project scanner enrichment, architecture layers, tour, and assemble review.
- [ ] Ensure agent output is graph fragment JSON, not markdown.
- [ ] Reuse `opencoderuntime.Prepare()` and existing isolation conventions.
- [ ] Keep deterministic fallback as default when agent runner is disabled.
- [ ] Test fake runner can fill summaries/tags without breaking schema validation.
- [ ] Run:

```bash
cd kits/agentteam-insight && go test ./internal/graphbuilder/agent ./internal/graphbuilder -count=1
cd kits/agentteam-insight && go test ./...
git diff --check
```

Expected: LLM enhancement is optional and cannot make graph persistence bypass validation.

### Task 11A: Server-backed OpenCode runner, source subset, and skills materialization design (#t1505)

**Owner:** Codex2
**Reviewer:** Reviewer2
**Status:** Design/acceptance only in #t1505. Do not claim implementation until
the code and tests below land in a later batch.

**Files for the future implementation:**
- Modify: `kits/agentteam-insight/main.go`
- Modify: `kits/agentteam-insight/main_test.go`
- Modify: `kits/agentteam-insight/internal/graphbuilder/run.go`
- Modify: `kits/agentteam-insight/internal/graphbuilder/run_test.go`
- Modify: `kits/agentteam-insight/internal/graphbuilder/agent/runner.go`
- Create: `kits/agentteam-insight/internal/graphbuilder/agent/opencode_server.go`
- Create: `kits/agentteam-insight/internal/graphbuilder/agent/opencode_server_test.go`
- Create: `kits/agentteam-insight/internal/graphbuilder/agent/source_subset.go`
- Create: `kits/agentteam-insight/internal/graphbuilder/agent/source_subset_test.go`
- Create: `kits/agentteam-insight/internal/graphbuilder/agent/skills_bundle.go`
- Create: `kits/agentteam-insight/internal/graphbuilder/agent/skills_bundle_test.go`
- Embed: `kits/agentteam-insight/internal/graphbuilder/agent/skills/**`

- [ ] **Add the production CLI/server entry.** Add `--opencode-server <addr|auto>`
  as the production file-analyzer path. When no test fake runner is injected and
  agent enhancement is enabled, `Run` must construct a server-backed TaskRunner
  instead of shelling out to one-off `opencode run --dir <tmp>`. `auto` starts a
  fresh server for the graph run; an explicit address reuses a caller-managed
  server only for the duration of that run.
- [ ] **Define lifecycle interfaces.** Introduce an `OpenCodeServerStarter`
  with `Start(ctx, workDir) (Client, stop func(context.Context) error, error)`
  and an `OpenCodeClient` with `CreateSession`, `RunTask`, and `CloseSession`.
  `Run` owns exactly one server lifecycle per `agentteam-insight graph` invocation.
- [ ] **Enforce session isolation.** Create one independent OpenCode session per
  file-analyzer batch or future intent (`file-analyzer`,
  `assemble-reviewer`, `graph-reviewer`, `architecture-analyzer`,
  `tour-builder`). Sessions must not share task workdirs; `Run` must close every
  session and call `stop` once at the end, including cancellation/error paths.
- [ ] **Test with fakes, not a real server.** Add a fake Starter/Client
  integration test that proves:
  1. one server is started for one graph run;
  2. two batch tasks create two distinct sessions;
  3. each session receives the expected task manifest and workdir;
  4. `CloseSession` runs for each session;
  5. `stop` runs once on success and once on an injected task failure.
- [ ] **Copy only session-local source evidence.** Before dispatching a batch,
  copy only `request.files` into `workDir/sources/<relative-path>` using
  path-cleaning that rejects absolute paths, `..`, symlink escapes, and
  non-regular files. The task manifest must add a source map:

  ```json
  {
    "sourcesRoot": "sources",
    "sourceMap": {
      "cmd/app/main.go": "sources/cmd/app/main.go"
    }
  }
  ```

  Prompt text must refer to `sources/<relative-path>` and not to the original
  absolute repository path. The manifest may keep original relative paths for
  graph IDs and provenance, but must not expose the absolute input root as a
  source-reading instruction.
- [ ] **Deny external repository reads.** Change the generated `opencode.json`
  for file-analyzer tasks to:

  ```json
  {
    "permission": {
      "external_directory": "deny",
      "question": "deny",
      "task": "deny",
      "todowrite": "deny"
    }
  }
  ```

  Add tests that create a sentinel file in the original repo, run the fake
  client/runner against only session-local sources, and assert the manifest and
  prompt do not require reading that sentinel or any absolute repo path.
- [ ] **Materialize only allowlisted Graph Builder skills.** Embed a
  AgentTeam Insight skill bundle under `agent/skills/` and materialize only these
  runtime files into each task workdir:
  - `.agents/skills/agentteam-insight/file-analyzer/SKILL.md`
  - `.agents/skills/agentteam-insight/assemble-reviewer/SKILL.md`
  - `.agents/skills/agentteam-insight/graph-reviewer/SKILL.md`
  - `.agents/skills/agentteam-insight/architecture-analyzer/SKILL.md`
  - `.agents/skills/agentteam-insight/tour-builder/SKILL.md`
  - referenced files under `.agents/skills/agentteam-insight/references/`
    that are explicitly listed by the bundle manifest.
- [ ] **Record bundle version/hash.** Write
  `.agentteam-insight/intermediate/skills-manifest.json` and a copy in the task
  workdir with `{schema, bundleVersion, files:[{path, sha256}], generatedAt}`.
  Tests must assert stable hashes for fixture skills, no files outside the
  allowlist are materialized, repeated materialization is idempotent, stale
  previously-materialized files are removed, and two concurrent task workdirs do
  not share mutable skill files.
- [ ] **Keep UA compatibility scripts out of runtime.** The UA validator and
  smoke scripts remain compatibility gates only. They must not be copied as
  runtime skills or required for normal `agentteam-insight graph` execution.
- [ ] **Run after implementation:**

```bash
cd kits/agentteam-insight && go test ./internal/graphbuilder/agent ./internal/graphbuilder -count=1
cd kits/agentteam-insight && go test ./... -count=1
git diff --check
```

Expected after a later code batch: the production path can be exercised with
fake server/client tests, file-analyzer sessions need only local copied sources,
OpenCode cannot read outside the task workdir, and Graph Builder skills are
materialized from a bounded allowlist with recorded hashes.

### Task 12: Final integration, docs, and PR gate

**Owner:** Planner coordinates; Codex2 executes PR prep; Reviewer2 gates
**Files:**
- Modify: `kits/agentteam-insight/main.go`
- Modify: `kits/agentteam-insight/main_test.go`
- Modify/new: `kits/agentteam-insight/internal/graphbuilder/**`
- Create: `docs/pr/2026-07-02-agentteam-insight-graph-builder-ua.md`

- [ ] Run full verification:

```bash
cd kits/agentteam-insight && go test ./...
git diff --check origin/main..HEAD
```

- [ ] Run UA compatibility gate against at least one generated fixture graph.
- [ ] Write PR description with schema, full/incremental, package layout, validator, known non-goals, and verification.
- [ ] Reviewer2 verifies graph schema parity, incremental invariants, Go package boundaries, and dashboard loadability.
- [ ] Create PR with `tea pulls create` after reviewer says implementation branch is ready.
- [ ] Set PR watch and review context.
- [ ] Merge only by PR comment `/merge` after CI and Reviewer2 PR gate pass.

---

## 6. Acceptance gates

### Plan/schema gate before implementation

Reviewer2 must confirm:

- `knowledge-graph.json`, `meta.json`, `config.json`, and `fingerprints.json` contracts match UA.
- D1-D17 deterministic requirements are mapped to implementation tasks.
- Go package layout is modular and idiomatic.
- Full and incremental flows are reconciled against UA semantics before graph JSON is written; use the #t1480 parity audit for current gap status.
- Test matrix includes Go unit tests and UA `validateGraph()` compatibility.

### Batch code gates

Each implementation batch must report:

- Worktree path and commit SHA.
- Changed files.
- Scope boundary and non-goals.
- Fresh verification output.
- Whether any UA parity invariant changed.

### Final PR gate

Reviewer2 must confirm:

- Graph generated by `agentteam-insight graph` can be loaded by UA dashboard.
- Incremental update prunes and merges exactly as specified.
- No absolute local paths are persisted.
- `fingerprints.json` is written before `meta.json`.
- Public CLI remains limited to `agentteam-insight graph` and `agentteam-insight wiki`; removed legacy commands stay rejected.
- If `--opencode-server` is claimed complete, fake Starter/Client tests prove
  one server per run, per-batch/per-intent independent sessions, and stop/
  cleanup on success/failure.
- If file-analyzer agent execution is claimed complete, manifests and prompts
  use session-local `sources/<relative-path>` paths, generated OpenCode config
  denies `external_directory`, and tests prove no original repository read is
  required.
- If embedded skills are claimed complete, the Graph Builder skills bundle is
  materialized from an allowlist, every file hash is recorded, stale files are
  cleaned, and concurrent sessions are isolated.
- Final grep/allowlist gate is documented: compatibility validator, smoke, and
  research audit files may retain UA/Understand references; public CLI,
  artifacts, Web automation, PR title/body, and user-facing docs may not
  retain old `agentteam-code` or public Understand-Anything command/artifact
  narrative.
- CI is green before merge.

---

## 7. Risks and mitigations

1. **Schema drift from UA**
   - Mitigation: Keep UA enum/alias tables copied from the observed source; add UA validator gate and research references in PR.
2. **LLM output variability**
   - Mitigation: Deterministic skeleton must be useful without LLM; LLM fields pass through validator and cannot bypass schema.
3. **Incremental false positives or stale edges**
   - Mitigation: Golden tests for cosmetic, structural, deleted, and directory-change cases; prune both source and target stale edges.
4. **Go package sprawl**
   - Mitigation: Keep leaf packages small, with dependency direction enforced by review checklist.
5. **Tree-sitter parity cost**
   - Mitigation: Start with Go stdlib extractor and generic fallback; add TS/tree-sitter expansion in a later PR only after graph contract is stable.
6. **Dashboard reads only UA paths**
   - Mitigation: Default output writes `<input>/.agentteam-insight/*`; `--output` means project root, not raw graph file path.

---

## 8. Reviewer checklist

- [ ] `graph` is a top-level AgentTeam Insight command, not a `codeanalysis` or `codewiki` side effect.
- [ ] Package layout follows Go boundaries and one-way dependencies.
- [ ] Graph schema supports all UA node/edge/layer/tour/meta fields and preserves unknown fields only for UA passthrough schemas: `GraphNode`, `DomainMeta`, and `KnowledgeMeta`.
- [ ] Validator order matches UA: sanitize, aliases, auto-fix, drop-broken, fatal.
- [ ] Full pipeline writes graph/fingerprint/meta/config in the expected layout.
- [ ] Incremental pipeline uses fingerprint comparison and update classifier before deciding partial/full.
- [ ] Partial update removes stale changed/deleted file nodes and any edge touching them.
- [ ] Path sanitizer prevents absolute local paths in persisted JSON.
- [ ] UA validator/manual dashboard gate is documented and executed before PR gate.
- [ ] Final integration follows the repository merge policy.
