Skip to content

feat(hosts): wire Droid (Factory CLI) and the Pi coding agent into graft init - #373

Open
bitnom wants to merge 2 commits into
trailhq:mainfrom
Apothic-AI:hosts-droid-pi
Open

bitnom wants to merge 2 commits into
trailhq:mainfrom
Apothic-AI:hosts-droid-pi

Conversation

@bitnom

@bitnom bitnom commented Sep 13, 2026

Copy link
Copy Markdown

Adds the two agents graft couldn't yet wire to graft init:

  • Droid (Factory CLI): an AGENTS.md instruction section (Droid reads AGENTS.md per Factory's docs) plus a repo-level .factory/mcp.json MCP registration — the committed, team-shared level of droid's user/folder/project trio (MCP docs), matching how cursor/gemini/kiro are wired. Detected via ~/.factory or a repo .factory dir. Selecting droid alongside the generic agents row runs two identical AGENTS.md upserts — the fenced section is still written exactly once.
  • Pi coding agent: a graft-owned skill at .pi/skills/graft/SKILL.md (pi discovers .pi/skills/ from the cwd upward). Pi's own README documents a no-MCP philosophy, so wiring is deliberately skill + AGENTS.md only — no MCP registration — and the graft binary on PATH stays the integration surface. Detected via ~/.pi or a repo .pi dir.

Retraction needs no new code: both targets derive from the same registries init writes through, so graft uninstall removes the skill file and the .factory/mcp.json key for free.

Evidence

  • Full suite: 1224 passed / 0 failed.
  • New tests: droid detection (home + repo probes), AGENTS.md single-section invariant with the shared-file rows, pi skill file shape (name: graft frontmatter), pi MCP absence, .factory/mcp.json merge + re-run convergence, registry id list.

…aft init

Droid: AGENTS.md section (it reads AGENTS.md per Factory's docs) plus a
repo-level .factory/mcp.json MCP registration — the committed, team-shared
level of droid's user/folder/project trio, matching how cursor/gemini/kiro
are wired. Detected via ~/.factory or a repo .factory dir; selecting it
alongside the generic agents row is two identical AGENTS.md upserts, so the
fenced section is still written once.

Pi: a graft-owned skill at .pi/skills/graft/SKILL.md — pi discovers .pi/skills/
from the cwd upward, and its README's "No MCP" philosophy means the wiring is
deliberately skill + AGENTS.md only, with no MCP registration. Detected via
~/.pi or a repo .pi dir.

Retraction needs no new code: both targets derive from the same registries
init writes through, so graft uninstall removes the skill file and the
.factory/mcp.json key for free.
@trailhq-graft

trailhq-graft Bot commented Sep 13, 2026

Copy link
Copy Markdown

🌱 graft blast radius

1 area changed → 6 areas can be affected. 16 dependent symbols, depth 2.
Tests: 1 area updated its tests.
Tag: @anirudhkumar-nanonets — 7 of 7 areas · @shhdwi — 5 of 7 areas

flowchart TB
  A0(("CLI Wiring<br/>6 symbols"))
  A1(("Host Integrations<br/>4 symbols"))
  A2(("Claude Initialization<br/>2 symbols"))
  A3(("Brain Connectivity<br/>2 symbols"))
  A4(("MCP Server<br/>1 symbol"))
  AX(("1 smaller area<br/>1 symbol"))
  classDef reached fill:#D9EDF3,stroke:#3AA7C9,stroke-width:1.5px,color:#0E313C;
  class A0,A1,A2,A3,A4 reached;
  classDef tail fill:#EEF2F3,stroke:#9AA4A9,stroke-width:1px,color:#3A4247;
  class AX tail;
Loading
Can be affected Symbols Nearest hop Reached from
CLI Wiring 6 src/cli.ts:L1088-L1173 wireTarget — calls, depth 1 Host Configuration
Host Integrations 4 src/hosts/antigravity.ts:L1-L47 antigravity.ts — imports, depth 2 Host Configuration
Claude Initialization 2 src/claude/hooks.ts:L1-L463 hooks.ts — imports, depth 2 Host Configuration
Brain Connectivity 2 src/brain/wire.ts:L1-L148 wire.ts — imports, depth 1 Host Configuration
MCP Server 1 src/mcp/server.ts:L1-L152 server.ts — imports, depth 2 Host Configuration
Telemetry Tracking 1 src/telemetry/track.ts:L1-L156 track.ts — imports, depth 2 Host Configuration
Who knows this code — 2 people across 7 areas
Area Who knows it
Host Configuration · changed @shhdwi — 8 commits, last 1mo ago · @anirudhkumar-nanonets — 6 commits, last 4d ago
CLI Wiring · affected @anirudhkumar-nanonets — 40 commits, last 4d ago · @shhdwi — 23 commits, last 1mo ago
Host Integrations · affected @shhdwi — 5 commits, last 1mo ago · @anirudhkumar-nanonets — 2 commits, last 13d ago
Claude Initialization · affected @anirudhkumar-nanonets — 17 commits, last 12d ago · @shhdwi — 11 commits, last 1mo ago
Brain Connectivity · affected @anirudhkumar-nanonets — 1 commit, last 4d ago
MCP Server · affected @anirudhkumar-nanonets — 5 commits, last 13d ago · @shhdwi — 2 commits, last 2mo ago
Telemetry Tracking · affected @anirudhkumar-nanonets — 2 commits, last 14d ago

Ownership is git history over each area's own files, weighted towards recent work (120-day half-life). Merge commits and bots are dropped, and you are dropped from your own PR. A name with no @ has no GitHub handle in its commit email — tag them by hand, or add a .mailmap entry. A suggestion from history, not a CODEOWNERS rule.

All 16 dependent symbols, grouped by area

CLI Wiring — 6 symbols in 4 files

  • src/cli.ts:L1088-L1173 — wireTarget (calls, depth 1)
    1094: plan: ReturnType<typeof planInit>;
  • src/cli.ts:L1-L1407 — cli.ts (calls, depth 1)
    18: import { runHostsInit } from "./hosts/init.js";
  • src/upkeep-run.ts:L42-L51 — rewriteWiring (calls, depth 1)
    50: runHostsInit(repo, { agents: others, global: opts.global, mcp: opts.mcp, hooks: opts.hooks });
  • src/upkeep.ts:L1-L333 — upkeep.ts (imports, depth 1)
    11: * 2. **Wiring staleness** — `graft init` copies hooks, shims, skill text and
  • src/cli-picker.ts:L1-L385 — cli-picker.ts (imports, depth 2)
    2: * `graft init`'s agent picker and `--dry-run` plan printer.
  • src/upkeep-run.ts:L1-L82 — upkeep-run.ts (imports, depth 2)
    9: import { runHostsInit } from './hosts/init.js';

Host Integrations — 4 symbols in 4 files

  • src/hosts/antigravity.ts:L1-L47 — antigravity.ts (imports, depth 2)
    20: function skillPath(home: string): string {
  • src/hosts/claude-global.ts:L1-L126 — claude-global.ts (imports, depth 2)
    5: * Why this exists. Everything `graft init` writes for Claude Code lands *in* the
  • src/hosts/codex-hooks.ts:L1-L91 — codex-hooks.ts (imports, depth 2)
    62: const targets = hookTargets(home);
  • src/hosts/cursor-hooks.ts:L1-L110 — cursor-hooks.ts (imports, depth 2)
    29: import type { PlannedWrite } from './plan.js';

Claude Initialization — 2 symbols in 2 files

  • src/claude/hooks.ts:L1-L463 — hooks.ts (imports, depth 2)
    50: * A query now brings the graph up to date first, so `graft init` raises the
  • src/claude/init.ts:L1-L105 — init.ts (imports, depth 2)
    86: const skillPath = skill;

Brain Connectivity — 2 symbols in 2 files

  • src/brain/wire.ts:L1-L148 — wire.ts (imports, depth 1)
    12: * instruction block: instructions are static and rewritten by `init`, rules
  • src/brain/connect.ts:L1-L111 — connect.ts (imports, depth 2)

MCP Server — 1 symbol in 1 file

  • src/mcp/server.ts:L1-L152 — server.ts (imports, depth 2)
    74: // refreshes rule files an older `graft init` wrote, and kicks off the cached

Telemetry Tracking — 1 symbol in 1 file

  • src/telemetry/track.ts:L1-L156 — track.ts (imports, depth 2)
Test signal per changed area — 1 ✓

Reached = a node under a test path has a resolved edge into the changed symbol. It undercounts anything called indirectly — through a CLI, a spawned process or a dynamic import — so read a low ratio as “look here”, never as a coverage gate.

  • Host Configuration — 3 of 7 reached · 2 test files changed here: test/hosts-init.test.ts, test/hosts-registry.test.ts
    • not reached: installProjectAgentSkill, projectAgentSkillTargets, skillPath, targets
9 test suites also reference this code

12 symbols, kept out of the diagram and the table so they cannot crowd out the areas a reviewer has to look at.

  • test/claude-init.test.ts
  • test/cli-picker.test.ts
  • test/hosts-antigravity.test.ts
  • test/hosts-claude-global.test.ts
  • test/hosts-cursor-hooks.test.ts
  • test/hosts-plan.test.ts
  • test/hosts-retract.test.ts
  • test/upkeep-hooks.test.ts
  • test/upkeep.test.ts

⚠️ 1 changed file not in the graph (CHANGELOG.md) — no parser claims the extension, or the index predates the file.

graft blast · origin/main...HEAD · depth 2 · 11 changed files

Open the interactive graph → — click an area to see its dependent symbols at file:line.

github-actions Bot added a commit that referenced this pull request Sep 13, 2026
…files

One picker row wires every agent that reads project-level STANDARD files:
the AGENTS.md instruction section plus graft's skill at
.agents/skills/graft/SKILL.md — the Agent-Skills-standard location droid
documents as its compatibility scope and pi documents as a skill dir, so
one write covers both (and the next standard-reading tool needs no new
registry entry). Strictly project-scoped: no machine-wide config, unlike
the agents row's ~/.codex writes.

Vendor rows keep their vendor-specific halves; the overlaps are deliberate
and idempotent (identical AGENTS.md content upserts to 'unchanged', and
pi resolving the same skill name from .pi/skills/ and .agents/skills/
resolves by precedence). Retraction derives the skill target like every
other write, so graft uninstall removes it for free.

Also: the shim-resolution fakes claim versions above any real release —
the shim's candidate list includes the test runner's own node install, so
a machine with a real global graft joined the version race and the 0.x
fakes stopped being hermetic.
@bitnom

bitnom commented Sep 14, 2026

Copy link
Copy Markdown
Author

Intent to restructure the init rows (follow-up). This PR adds project-agents additively, but the end-state we want is a restructure: project-agents becomes the canonical instructions+skill row, vendor rows slim down to their genuinely vendor-specific writes (droid → .factory/mcp.json only; pi absorbed into project-agents), and the agents row reduces to its machine-wide Codex pieces. Today's rows mix three axes in one bundle (shared conventions, vendor config, machine-wide hooks) and the picker can't express "standard files only, nothing outside this repo" as a result. Deferred from this PR so the row-semantics change gets its own review — this PR's additive row is a strict improvement on its own.

github-actions Bot added a commit that referenced this pull request Sep 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant