Skip to content

feat: manage graft as an optional code-context-graph companion #167

Description

@pacphi

Executive brief

Add first-class, opt-in management of graft (@nanonets/graft)
as a per-repository code-context-graph companion, following the same shape as
#114 (deja-vu),
#115 (GitNexus), and
#117 (Graphify).

graft parses a repository with tree-sitter into a local, git-ignored graph of linked markdown nodes
(graft/*.md) plus a per-symbol JSON wiring graph (graft/.graph/wiring.json), then rides along in
Claude Code, Codex/AGENTS.md-reading CLIs, Cursor, Gemini, GitHub Copilot, Kiro, Windsurf, and AdaL —
via a 6-tool MCP server (graft_find_code, graft_file_api, graft_trace_calls, graft_find_all,
graft_repo_map, graft_check_freshness), marker-fenced instruction-file sections, and (for Claude
Code specifically) a live statusline plus post-edit hooks that keep the graph auto-synced every turn.
The structural graph (graft build, graft check) is deterministic tree-sitter — no LLM, no key,
no network
— and stays that way unless a user opts into graft build --deep for LLM-written
concept summaries under their own provider key.

This proposal maps the split you (the maintainer) already described in review: ak setup installs
the npm-global binary
(machine phase, no repo touched), graft init — the project-scoped wiring
step — runs only under ak setup --project
(or wherever project setup already runs today per
docs/SETUP.md), ak sync owns updates and heals wiring/graph drift, and ak dashboard gets a
graft card/row
from the same status facts, per docs/MANAGED-TOOLS.md's five invariants.

Relationship to #115 (GitNexus) and #117 (Graphify) — read before approving scope

This is the third proposed "build a local knowledge graph from this repo, expose it to agents"
companion in this backlog. All three remain unimplemented (open) as of this writing. Per the norm
#117 set for #115, here is the comparison a maintainer needs to disposition deliberately rather than
by accretion:

GitNexus (#115) Graphify (#117) graft (this issue)
Scope Code structure: symbols, call graphs, impact, diff-to-symbol Code + docs + papers + images + audio/video — broadest corpus Code structure only, same lane as GitNexus
Graph format LadybugDB (graph database) graph.json + Obsidian vault / wiki / HTML / GraphML / Neo4j Cypher export Plain linked markdown files + a JSON wiring graph — no database, no server, "reads like any other file in the repo"
Cost model Fully local/deterministic; no LLM calls, no per-run token cost Pass 1–2 free/local; Pass 3 (docs/papers/images) dispatches paid Claude subagents on every build touching non-code files Tier 1 (graft build) fully local/deterministic tree-sitter, $0; LLM concept-node/summary layer is a separate opt-in step (graft build --deep), never triggered automatically
Freshness model PostToolUse hook does a cheap git rev-parse HEAD check and nudges ("index is stale, run gitnexus analyze"); never auto-rebuilds; only fires from a live agent tool call Opt-in graphify hook install (git hooks) or --watch auto-rebuilds code changes free; non-code changes only nudge Every query re-stats the working tree first (~3ms, $0, no LLM) and rebuilds only what moved — includes uncommitted/unstaged edits, no "run the reindex" step exists in the happy path. For Claude Code specifically, a background rebuild also runs at the end of any turn that touched code. Strongest freshness guarantee of the three; the only one with no "opt in to staying fresh" step
Install ecosystem npm — already on this machine via mise's npm backend, not plain global npm (the reason #115 can't reuse #114's logic unchanged, and the reason #116's classifier exists) Python (pip/pipx/uv tool) — a wholly new ecosystem for Agentic Kit npm-global (npm install -g @nanonets/graft) — same install lane as ruflo/agentic-qe/hosts today; no evidence yet that this repo's install is mise-managed, so #116's classifier is not a hard prerequisite here (see Goals)
Host file injection AGENTS.md/CLAUDE.md tagged block (off by default), .claude/skills/gitnexus/ CLAUDE.md/AGENTS.md/GEMINI.md/Copilot/Antigravity/Kiro "always-on" blocks + 15+ per-host SKILL.md files Marker-fenced sections in AGENTS.md/GEMINI.md/.github/copilot-instructions.md; owned files for the rest (.claude/skills/graft/SKILL.md, .cursor/rules/graft.mdc, .kiro/steering/graft.md, .windsurf/rules/graft.md, .adal/skills/graft/SKILL.md). Also writes machine-wide, outside the repo, when the Codex/agents host is selected: ~/.codex/config.toml ([mcp_servers.graft]), ~/.codex/hooks/graft/graft-hooks.cjs, ~/.codex/hooks.json. --no-global skips these three. Neither GitNexus nor Graphify's proposals describe touching machine-wide config — this is a genuinely new risk class for this repo's third graph companion (see Risks)
License PolyForm Noncommercial 1.0.0 Apache-2.0 (relicensed from MIT) MIT — the most permissive of the three, and the only one with an OpenSSF Scorecard badge
Auto-update / self-maintenance None beyond the staleness nudge described above graphify hook install / --watch, opt-in, free for code graft upgrade (npm install -g latest) exists as a manual command; a machine-global, TTL-cached (24h), background-spawned update-check (~/.graft/update-check.json) independently nudges ⬆ graft X → Y available from CLI/hook/MCP entry points; a separate wiring-stamp reconciler (graft/.cache/wiring-stamp.json) re-runs init's writes (never a graph rebuild) when the installed binary version is ahead of what wrote the repo's wiring, replaying the exact flags (--no-global/--no-mcp/--no-hooks) the original init was given
Maturity Active, pre-1.0: 24 npm releases in ~5 weeks (0.1.0 on 2026-07-15 → 0.10.1, pushed 2026-08-18), 3591 GitHub stars, 317 forks, 57 open issues

A reasonable disposition once all three are read together: GitNexus and graft compete directly for
the same "structural code graph, $0 by default" niche, with graft's always-fresh-per-query model and
markdown-node design being a meaningfully different (arguably stronger) bet on freshness and
readability than GitNexus's graph-database + nudge-only approach, at the cost of graft being a
younger, faster-moving (pre-1.0) project versus GitNexus's more conservative footprint. Graphify
occupies clearly adjacent-but-different territory (multi-modal corpus, paid LLM passes) and is not in
direct competition with either. Setup should not silently let a user enable graft and GitNexus
together and pay to build two overlapping graphs of the same code
— same guidance #117 gave for
GitNexus/Graphify. This issue does not resolve which of GitNexus/graft the project should carry
forward (or whether both, clearly labeled); it names the overlap so a maintainer decides on purpose.

Why this belongs in Agentic Kit

graft's upstream CLI already provides the same shape of managed-companion primitives #114/#115/#117
established as the pattern:

  • a published npm package, @nanonets/graft, with a single graft bin;
  • graft init --dry-run / --agents <ids> / --yes / --no-global / --no-mcp / --no-hooks /
    --no-build / --all-agents / --list-agents — a scriptable, non-interactive wiring surface with
    no-TTY-writes-nothing-by-default behavior (CI/Dockerfile-safe out of the box);
  • graft check --json — a drift/freshness report Agentic Kit can parse without guessing;
  • graft version (installed + latest npm) and a documented, single self-update command
    (graft upgrade) Agentic Kit should own rather than let the user or graft's own nudge drive
    independently — see docs/MANAGED-TOOLS.md invariant 2 and checklist item 4;
  • an idempotent, merge-not-clobber writer for .claude/settings.json and every shared instruction
    file, matching this repo's own ADR-0023 fail-closed / no-clobber expectations;
  • no telemetry, MIT license, an OpenSSF Scorecard badge — a stronger trust posture than either sibling
    proposal.

Current Agentic Kit architecture

The seams #114/#115/#117 already document apply unchanged:

  • src/commands/setup.mjs — machine phase installs enabled global tools/hosts; project phase (ak setup --project, or automatically when .git exists in cwd per docs/SETUP.md) performs
    per-repo wiring. graft's own init/machine split maps directly onto this existing boundary
    arguably more cleanly than any prior companion, since graft's upstream CLI already separates "get
    the binary" (npm install -g) from "wire this repo" (graft init) the same way ak setup already
    separates machine and project phases.
  • src/commands/status.mjs, src/commands/sync.mjs, src/commands/uninstall.mjs,
    src/lib/versions.mjs, src/lib/adapters/lifecycle.mjs,
    tests/kit/adapter-lifecycle-conformance.test.mjs, docs/MANAGED-TOOLS.md,
    docs/ddd/integration-management.md — same contract described in feat: manage deja-vu as an optional cross-host session-memory companion #114/feat: manage GitNexus as an optional local code-intelligence companion #115/feat: manage Graphify as an optional multi-modal knowledge-graph companion #117.
  • ADR-0016 (Accepted) and ADR-0023 (Implemented) govern this exactly as they do the sibling proposals.
  • Relevant precedent from this repo's own history: issue ak setup ships ruflo without native SQLite bindings under npm 12; ak dual run then fails with a native↔WASM memory conflict #45 ("ak setup ships ruflo without native
    SQLite bindings under npm 12") is a direct analog to graft's native tree-sitter dependency tree
    (tree-sitter, tree-sitter-go, tree-sitter-java, tree-sitter-python, tree-sitter-typescript,
    plus tree-sitter-wasms/web-tree-sitter as a WASM path) — this needs the same
    clean-machine/cross-platform install proof ADR-0023 already requires, not a new standard.
  • Also relevant: this machine's ambidextrous dual-host bridge already owns
    [mcp_servers.ruflo] in ~/.codex/config.toml (see this repo's own CLAUDE.md). graft's init
    writes [mcp_servers.graft] into the same file. Two independent writers touching
    ~/.codex/config.toml is a new collision class this proposal must design around explicitly — see
    Risks.

Goals

  1. Let users opt into graft during ak setup (machine phase) or through an explicit config change.
  2. Install @nanonets/graft@latest globally via npm — the same lane ruflo/agentic-qe/hosts already
    use; no dependency on feat: reusable mise-backend-aware install-method classifier for managed/companion tools #116's mise-backend classifier unless disk evidence later shows a
    mise-installed graft on some user's machine (unlike feat: manage GitNexus as an optional local code-intelligence companion #115, nothing here requires it as a
    prerequisite).
  3. Run graft init only during project setup (ak setup --project, or wherever project setup
    already triggers per docs/SETUP.md), non-interactively, using ak's own already-resolved enabled
    host set to drive graft init --agents <ids> --yes.
  4. Default to graft build (structural, $0) on first wire; treat graft build --deep (LLM-enriched,
    costs tokens under the user's own key) as a separate, explicit opt-in — never triggered by setup or
    sync automatically.
  5. Keep graft's own machine-wide Codex writes (~/.codex/config.toml, ~/.codex/hooks.json, the hook
    shim) under explicit Agentic Kit control: default to --no-global when wiring the Codex/agents
    host during project setup, and let a separate, explicitly-opted-in flag hand that scope to graft
    instead of silently letting two tools race on the same file (see Risks).
  6. Surface presence, install method, ownership, version drift, per-host wiring, graph freshness
    (graft check --json), and degraded states in ak status and the Dashboard.
  7. Make ak sync the single owner of the npm package update (per docs/MANAGED-TOOLS.md invariant 2)
    and of wiring/graph drift repair — reusing graft's own idempotent graft init replay and
    graft check/graft build rather than reimplementing graft's wiring-diff logic.
  8. Detect and neutralize graft's own machine-global daily update-check nudge
    (~/.graft/update-check.json, spawned from CLI/hook/MCP entry points) as the "auto-update
    machinery" docs/MANAGED-TOOLS.md checklist item 4 requires Agentic Kit to detect and own, so
    ak status/ak sync remains the single drift story (invariant 4) rather than a second nudge
    surfacing independently inside a live agent session.
  9. Remove only Agentic Kit-owned wiring and packages on ak uninstall; preserve graft/'s local
    cache, graft/.cache/wiring-stamp.json, and any user notes appended below a node's generated block
    unless the user explicitly requests a data purge.
  10. Keep the integration local-first by default (structural graph never calls a model or the network
    except the npm install itself and the optional, explicitly-triggered update check), cross-platform
    (native tree-sitter bindings must be proven on Linux/macOS/Windows, per the ak setup ships ruflo without native SQLite bindings under npm 12; ak dual run then fails with a native↔WASM memory conflict #45 precedent), and
    testable against the shared adapter-lifecycle harness.

Non-goals

Primary use cases

1. Global install, zero repo footprint until opted in

ak setup --with-graft installs @nanonets/graft globally. No repo is touched. A user can run ak setup on a fresh machine and never see a graft/ directory appear anywhere until they explicitly
run project setup somewhere.

2. Project onboarding wires it in one step

ak setup --project in a repo the user has opted into graft for runs graft init --agents <ak's enabled hosts> --yes, builds the structural graph once, and verifies it — no manual per-host
configuration, matching #114's use case 1.

3. Fresh answers without a reindex step

A teammate pulls a large upstream change. The next graft ask/MCP call re-stats the tree and rebuilds
what moved automatically ($0, ~ms) — no ak sync or manual reindex is required for correctness; ak sync exists for package/wiring drift, not for keeping the graph fresh turn-to-turn, which graft
already owns end-to-end.

4. Drift repair

The npm package is upgraded, a host's wiring file goes missing, or .claude/settings.json's graft
block is stripped by an unrelated edit. ak status reports the observed problem via graft check --json plus host-file presence checks; ak sync performs the smallest owned repair by replaying
graft init with the recorded host set and flags.

5. Safe Codex coexistence

A user enables both the Codex host and graft. Setup defaults to --no-global for graft's Codex wiring
so Agentic Kit's own [mcp_servers.ruflo] entry in ~/.codex/config.toml is never at risk of being
overwritten or duplicated by a second independent writer; graft's Codex integration is limited to
AGENTS.md unless the user explicitly opts into graft's own global hook/MCP registration.

6. Clean removal

ak uninstall removes only Agentic Kit-owned wiring by default. --remove-graft also removes the
owned npm package after confirmation. graft/'s local cache and any user notes under generated node
blocks survive unless a separate, confirmed purge flag is passed.

Product principles

  1. Complement, do not duplicate GitNexus. If both are ever enabled, Setup discloses the overlap
    named above rather than silently building two graphs of the same code.
  2. Structural first, LLM enrichment is a separate decision. graft build --deep is never
    triggered by any Agentic Kit-driven path without explicit opt-in.
  3. Host intent controls wiring, same as feat: manage deja-vu as an optional cross-host session-memory companion #114/feat: manage GitNexus as an optional local code-intelligence companion #115/feat: manage Graphify as an optional multi-modal knowledge-graph companion #117 — graft is wired only for hosts Agentic Kit
    already has enabled, via --agents, never --all-agents.
  4. Agentic Kit's existing machine-wide surfaces are never contested. graft's ~/.codex/ writes
    default off; enabling them is a distinct, disclosed choice, not a side effect of enabling graft.
  5. One package update owner. ak sync updates the npm package; graft's own graft upgrade is
    never invoked by Agentic Kit, and graft's own background update-check nudge is detected and
    suppressed so it can't disagree with ak status.
  6. Observed truth drives status. Parse graft check --json, graft version, the package on disk,
    and per-host wiring-file presence; never infer healthy from process exit alone.
  7. Presence is not ownership. A mise/Homebrew/manual graft install is visible, never auto-updated
    or removed.
  8. Data removal is a separate decision, same shape as feat: manage deja-vu as an optional cross-host session-memory companion #114/feat: manage GitNexus as an optional local code-intelligence companion #115/feat: manage Graphify as an optional multi-modal knowledge-graph companion #117: wiring, package, and
    graft/'s local cache/notes are different deletion scopes.
  9. Reuse graft's own reconciliation instead of reimplementing it. graft's init is already
    idempotent and replays the exact flags a prior wiring was given (recorded in
    graft/.cache/wiring-stamp.json); Agentic Kit's sync adapter should drive that mechanism rather
    than hand-roll its own wiring diff.
  10. Unknown stays unknown. A malformed graft check --json payload, an unqueryable version, or a
    partially-wired repo is degraded/unknown, never reported healthy by default.

Proposed user experience

Setup

ak setup --with-graft                 # machine phase: npm install -g @nanonets/graft only
ak setup --no-graft                   # explicit opt-out (default until this ships)
ak setup --project                    # project phase, only if graft is enabled: graft init --agents <enabled hosts> --yes
ak setup --project --graft-deep       # also runs graft build --deep once, after confirming a provider key is set
ak setup --project --graft-codex-global   # opts Codex wiring into graft's own ~/.codex/ writes (off by default per Goal 5)

Interactive setup should default to No and, before mutation, explain:

  • a global npm package will be installed (machine phase) with no repo touched yet;
  • project setup will build a local, git-ignored code graph from this repo's source and wire it into
    the enabled agent hosts' instruction files (and, for Claude Code, a statusline + hooks);
  • the structural graph never calls a model or leaves the machine; LLM-enriched nodes are a separate,
    explicit choice under the user's own provider key;
  • Codex wiring stays inside AGENTS.md only unless the user explicitly opts graft into its own
    ~/.codex/ writes, which are machine-wide and shared by every repo.

Status

graft   ok    0.10.1 npm-managed · wired: claude,codex · graph fresh
graft   warn  npm 0.9.1 installed, 0.10.1 available · sync upgrades it
graft   warn  wiring stamp behind installed binary · sync refreshes
graft   warn  graft/ missing or graft check reports drift · sync rebuilds
graft   warn  installed externally · not owned by ak
graft   info  management disabled

The collector should distinguish: absent; present-external; present-owned; package update available;
per-host wired vs missing; wiring-stamp version behind the installed binary (graft's own signal);
graph fresh/stale/missing per graft check --json; whether Codex global wiring is enabled and by
whom; doctor/version check unavailable → unknown, not healthy.

Sync

ak sync should:

  1. install/upgrade @nanonets/graft via npm only when enabled — never call graft upgrade;
  2. read graft/.cache/wiring-stamp.json for the currently-recorded host set and flags, union with
    what's actually on disk (mirroring graft's own reconcileWiring logic), and replay graft init --agents <that set> --yes plus the recorded --no-global/--no-mcp/--no-hooks flags — reusing
    graft's own idempotent writer rather than diffing files by hand;
  3. run graft build (never --deep) only when graft check --json reports drift beyond what the
    query-time auto-refresh already handles (e.g., after a fresh clone with no graft/ yet);
  4. verify independently via graft check --json plus host-file presence, never trusting apply's exit
    code alone;
  5. leave the daily update-check nudge suppressed/ignored as ak's own drift read remains authoritative.

Repeated sync must be a true no-op.

Removal

ak uninstall                    # remove Agentic Kit-owned graft wiring (host files, MCP/hook entries)
ak uninstall --remove-graft     # also remove the owned npm package, after confirmation
ak uninstall --purge-graft-data # also delete graft/ and graft/.cache/, confirmed, exact-path guarded

Default uninstall preserves graft/'s local graph and any user notes below a node's generated block;
an external install is never touched; a data purge never runs unless separately confirmed.

Configuration and ownership model

Extend the existing versioned integration envelope (#114's precedent), not a new top-level boolean:

{
  "integrations": {
    "version": 3,
    "tools": {
      "graft": {
        "enabled": true,
        "deep": false,
        "hosts": ["claude", "codex"],
        "codexGlobal": false
      }
    },
    "ownership": {
      "graft": {
        "install": { "method": "npm", "package": "@nanonets/graft", "managedBy": "agentic-kit" },
        "wiredHosts": ["claude", "codex"],
        "wiringOpts": { "global": false, "mcp": true, "hooks": true }
      }
    }
  }
}

Must preserve: desired enablement; deep-enrichment opt-in; desired host set; whether graft's own
Codex-global writes are permitted; observed install method/ownership; the exact wiring opts last
applied (so sync's replay matches what the user actually chose, not graft init's all-true default).
Migration is additive; existing configs default to disabled/unowned.

Proposed architecture

Managed companion adapter

  • src/lib/graft.mjs — package/version read, graft check --json parsing, wiring-stamp read
    (graft/.cache/wiring-stamp.json), host-file presence checks.
  • src/lib/adapters/graft.mjs — detect/plan/apply/verify/undo against the shared lifecycle contract.

Do not add graft to HOST_REGISTRY or PROVIDER_REGISTRY — same rule as every prior companion.

Lifecycle contract

detect — read desired config; resolve npm install state (disk-first, per invariant 1); parse
graft check --json and the wiring stamp; inspect enabled-host wiring files (marker-fenced sections

  • owned skill/rule files); return normalized facts without writing.

plan — deterministically compute package install/upgrade, wiring replay (host set + opts diff),
graph (re)build (only if graft check reports drift beyond query-time auto-refresh), and undo
operations; disclose every host-file/.claude/settings.json/Codex-global mutation before it happens;
no-op for disabled or externally-owned state.

apply — install the npm artifact; invoke graft init --agents <ids> --yes with the recorded
wiring opts (defaulting --no-global unless codexGlobal is explicitly enabled); run graft build
(never --deep unless deep: true and a provider key is confirmed present) only when planned; record
ownership receipts only after verified success; report ok/degraded/failed/skipped.

verify — independently re-run graft check --json; observe actual host-file state; never trust
apply's exit code as proof.

undo — reverse order: Codex-global entries (if owned) → per-host wiring → npm package; preserve
external installs and user-modified wiring; retain receipts on partial failure.

Phased implementation plan

Phase 0 — ADR alignment and the GitNexus disposition call

QA gate: ADR is current; the GitNexus/graft disposition and the Codex-global-writer boundary are
both written down before Phase 1 starts.

Phase 1 — Detection and normalized facts

  • Add npm install/version detection (plain npm-global, matching the existing lane, not feat: reusable mise-backend-aware install-method classifier for managed/companion tools #116's
    classifier by default).
  • Parse graft check --json and graft/.cache/wiring-stamp.json fixtures, including malformed/
    missing/stale cases.
  • Map Agentic Kit host ids to graft's --agents ids (agents→Codex, claude, gemini, …).
  • Keep collection read-only; no network calls beyond what a pre-existing npm/version check already
    makes.

QA gate: every classification outcome (absent / external / owned-healthy / owned-drifted /
malformed-check / missing-stamp) is fixture-covered and honestly labeled.

Phase 2 — Setup and installation (machine phase only)

  • Add --with-graft/--no-graft to ak setup; persist opt-in intent; install the npm package.
  • No project mutation happens in this phase, by construction — this is the split the maintainer asked
    for, and it should be provably true (a machine-only setup run leaves zero graft/ directories
    anywhere).

QA gate: clean-machine ak setup --with-graft (no --project) installs the binary and touches no
repository; hermetic on Linux/macOS/Windows including native tree-sitter binding resolution (#45
precedent).

Phase 3 — Project wiring under ak setup --project

  • Wire graft init --agents <ids> --yes (structural build only) into project setup, gated on Goal 5's
    --no-global default for Codex.
  • Pre-mutation disclosure names every file graft init --dry-run reports before writing.
  • Verify via graft check --json before recording success.

QA gate: project setup with graft enabled produces the expected host files and a fresh graph; a
Codex-enabled run with codexGlobal: false leaves ~/.codex/config.toml's [mcp_servers.ruflo]
entry byte-identical.

Phase 4 — Sync, upgrades, and drift repair

  • Fold the npm package into the existing drift story (invariant 4); reconcile wiring via graft's own
    stamp-replay mechanism; rebuild only on graft check drift, never on a timer.
  • Suppress/ignore graft's own background update-check nudge as the checklist's "auto-update machinery"
    case (Goal 8).
  • Add the Dashboard card + banner fold from the same status facts.

QA gate: two consecutive syncs cause zero additional writes; status/JSON/Dashboard/plan agree;
graft's own update nudge never appears alongside a disagreeing ak status line in a fixture session.

Phase 5 — Safe removal, data purge, documentation

  • Add owned-wiring teardown, explicit package removal, and a separately confirmed graft/ +
    graft/.cache/ purge.
  • Update README/SETUP/MANAGED-TOOLS/UPGRADING/TROUBLESHOOTING and uninstall help.
  • Add adapter-conformance, clean-machine, and cross-platform regression evidence.

QA gate: pnpm run check passes; install → user drift → uninstall preserves user changes;
uninstall on a never-managed machine creates or removes nothing.

Test strategy

Adapter conformance

Shared lifecycle harness: read-only detection, deterministic planning, non-mutating dry-run, idempotent
apply, observed verification, ownership-scoped undo, honest degradation on malformed/unavailable
graft check output.

Installation matrix

State Expected
absent, disabled no action
absent, enabled ak setup --with-graft installs npm package only
npm-global, Agentic Kit-owned, healthy managed and upgradeable
npm-global, pre-existing usable but unowned until explicitly adopted
mise/Homebrew/manual external, detectable, never auto-updated/removed
owned package, wiring-stamp behind installed version sync replays graft init with recorded opts
owned package, graft check reports drift sync rebuilds structurally, never --deep
owned package, npm upgrade fails old version remains usable; reported failed, never green

Codex dual-writer matrix

Scenario Expected
Codex enabled, graft enabled, codexGlobal: false (default) ~/.codex/config.toml/hooks.json untouched by graft; graft wiring limited to AGENTS.md
Codex enabled, graft enabled, codexGlobal: true (explicit opt-in) graft's [mcp_servers.graft]/hook entries added without disturbing Agentic Kit's own [mcp_servers.ruflo] entry
Codex disabled after prior codexGlobal: true ownership Agentic Kit removes only graft's owned Codex-global entries

Data and privacy tests

  • structural build never calls a model or leaves the machine;
  • --deep never runs without explicit deep: true and a confirmed provider key;
  • default uninstall preserves graft/'s notes and cache;
  • purge refuses unresolved/broad paths and is exact-path guarded.

Acceptance criteria

  • graft is represented as an optional managed companion, not a host/provider or AgentDB/Ruflo
    replacement.
  • ak setup --with-graft (machine phase) installs the npm package and touches no repository.
  • graft init runs only under project setup (ak setup --project, or wherever project setup
    already triggers), scoped to Agentic Kit's own enabled host set via --agents/--yes.
  • Codex/agents wiring defaults to --no-global; graft's own ~/.codex/config.toml/hooks.json
    writes require a separate, explicit opt-in and never disturb Agentic Kit's own
    [mcp_servers.ruflo] entry.
  • graft build --deep never runs without explicit opt-in and a confirmed provider key.
  • ak status/JSON distinguish presence, ownership, install method, version drift, per-host wiring,
    graph freshness (graft check --json), and Codex-global-write ownership.
  • ak sync --dry-run is non-mutating; repeated ak sync is idempotent.
  • ak sync is the only caller of npm install -g @nanonets/graft@latest; Agentic Kit never invokes
    graft upgrade.
  • graft's own background update-check nudge is detected and does not produce a second, disagreeing
    drift story in ak-managed sessions.
  • Wiring drift repair reuses graft's own stamp-replay mechanism rather than a hand-rolled diff.
  • Default uninstall removes only Agentic Kit-owned wiring/package; graft/ and its notes survive
    unless a separately confirmed purge is requested.
  • The GitNexus/graft overlap (Relationship section) is disclosed to the user at setup time when
    both would be enabled together, not silently allowed.
  • Native tree-sitter dependency install is proven clean on Linux, macOS, and Windows (the ak setup ships ruflo without native SQLite bindings under npm 12; ak dual run then fails with a native↔WASM memory conflict #45
    precedent).
  • Shared lifecycle conformance, clean-machine, cross-platform, migration, and no-clobber tests
    pass.
  • pnpm run check passes.

Success measures

  1. A new opt-in installation reaches healthy verified state through one ak setup --with-graft +
    ak setup --project pair.
  2. A second setup/sync performs zero writes when nothing changed.
  3. A Codex + graft user's ~/.codex/config.toml never shows a diff attributable to graft unless they
    explicitly opted into codexGlobal.
  4. Package upgrade plus wiring-stamp replay converges in one sync, with no duplicate host entries.
  5. Uninstall leaves unrelated host configuration byte-equivalent and preserves graft/ by default.
  6. A user who also has GitNexus proposed/enabled sees the overlap named at setup time, not discovered
    later as duplicated cost.

Risks and mitigations

Risk Mitigation
Two independent writers (ak's Codex bridge, graft's own init) racing on ~/.codex/config.toml/hooks.json --no-global default for graft's Codex wiring; explicit opt-in required to hand that scope to graft; Codex dual-writer matrix test (above) as a named regression guard
Third overlapping "code knowledge graph" proposal alongside #115/#117 fragments the backlog / duplicates future implementation cost Relationship section forces an explicit maintainer disposition in Phase 0 before any code lands
graft's own daily update-check nudge disagrees with ak status's drift read inside a live agent session Detect and treat as "auto-update machinery" per docs/MANAGED-TOOLS.md checklist item 4; suppress/ignore rather than let it stand as a second source of truth
Native tree-sitter bindings fail to install on some platform/Node combination Cross-platform clean-machine proof required in Phase 2's QA gate, mirroring issue #45's ruflo/native-SQLite precedent
Claude Code supports one active statusLine entry; graft's own live statusline could collide with an existing kit- or aqe-owned statusline Detect an existing statusLine entry before wiring graft's; surface the conflict rather than silently overwriting (this needs its own design decision in Phase 3 — flagged here, not resolved)
Pre-1.0 project (24 releases in ~5 weeks) — upstream CLI surface may still be shifting Pin fixtures to a specific graft version in tests, same practice #116 already recommends for mise ls --json; treat graft check --json's shape as versioned, not assumed-stable
graft build --deep accidentally triggered by an automated path, incurring unexpected LLM spend under the user's key Explicit deep: true config gate plus a provider-key presence check before Phase 3/4 ever run it; never triggered by setup/sync defaults
Overlap with GitNexus leads a user to enable both and pay to build two structurally-similar graphs Setup-time disclosure named in Goals/Non-goals; not silently allowed

Definition of done

This issue is complete when a user can install graft's binary during ak setup's machine phase with
zero repository footprint, wire it into a specific project only via ak setup --project, have ak sync own every subsequent update and wiring/graph-drift repair (reusing graft's own idempotent
replay mechanism rather than duplicating it), see accurate presence/ownership/freshness state in ak status and the Dashboard, safely coexist with Agentic Kit's own Codex MCP bridge without either tool
clobbering the other's ~/.codex/config.toml entry, and cleanly remove everything Agentic Kit owns —
while the GitNexus/graft overlap this issue names has been deliberately dispositioned by a maintainer,
not silently absorbed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions