Harness Intelligence Wiki
SpecsCLICodex TypeScript MCP

Codex TypeScript MCP: execution plan

Codex TypeScript MCP execution plan

Authority and current state

The user authorized Full Delivery on 2026-09-28. The scope is the retained SPEC (commit d52cf6de) and ARCHITECTURE (commit 3f0809e3), plus GitHub issues #239, #240, #241 and #242. Everything lands on branch spec/codex-typescript-mcp in PR #243. Issue #231 is out of scope: its fix is already on main (ffee129a) and only a release is pending.

  • task_identity_mode: provider-task. Typegraph tasks are Linear tasks. Bug tasks are GitHub issues.
  • Backlog projection (Linear, workspace Devpunks, Root HARNESS INTELLIGENCE, Project CLI). The user approved this placement on 2026-09-28.
    • Initiative IP-456 was reused. Epic IP-476 was created. Milestone V4.5 Codex TypeScript Semantic Reads was created.
    • Stories: IP-477 (runtime), IP-478 (entries), IP-479 (health).
    • Tasks: IP-480, IP-481, IP-482, IP-483, IP-484.
    • Blockers: IP-480 → IP-481 → IP-482 → IP-483. IP-484 is blocked by IP-481 and IP-482.
    • All of the above was read back.
  • Open product decisions: none. Spike evidence recorded below replaces the unknowns listed in the architecture.

Spike evidence (2026-09-28, Linux x86_64, Node 24.19.0, codex-cli 0.156.1)

  • An exact install reproduces the tested dependency set: Typegraph 0.9.56, TypeScript 7.0.2, @effect/tsgo 0.36.5 and MCP SDK 1.30.1.
    • Command: npm install --ignore-scripts with overrides pinning @effect/tsgo and the SDK.
    • Result: 110 packages, 216 MB. The lock is 88,844 bytes.
  • The load probe calls Typegraph's ApiClient.create({projectRoot, tsconfig}), then projectFiles().
    • apps/cli passes with 225 files in 187 ms; packages/contract passes with 8 files.
    • The root tsconfig.json fails with "0 source files".
  • Codex runs sh -c 'TYPEGRAPH_PROJECT_ROOT="$(git rev-parse --show-toplevel)" exec node <runtime>/node_modules/typegraph-mcp/dist/server.cjs' with TYPEGRAPH_TSCONFIG set. ts_type_info returned string in codex exec.
  • Approval mode:
    • default_tools_approval_mode accepted "approve", "prompt" and unset. All three completed under the global approval_policy = "never" in codex exec.
    • Vendor docs say approve means "Tools execute without user intervention".
    • Decision: generated entries use default_tools_approval_mode = "approve". Interactive desktop prompting is not observable on this headless host; it goes in the runbook as a limitation (AC-023).

Locked design

  • D1 Registry pin: new Registry item typegraph-runtime (kind: "tools", no files).
    • Its meta.hi.toolRuntime holds { id, version, node, server, manifest, lockfile }, where manifest and lockfile are exact JSON text.
    • pack-typescript lists it in registryDependencies, so the Pack is the only selector (Q10, C4).
    • Source data lives in apps/cli/src/data/tool-runtimes/typegraph-mcp/{package.json,package-lock.json}.
    • Older 6.0.x CLIs ignore the extra meta field (the decode is verified by a test). cliVersionRange stays unchanged.
    • The data stores no digest (HI-CLI-004).
  • D2 Tool Runtime: installed at <dataHome>/hi-tools/typegraph-mcp/<version>, where dataHome is $XDG_DATA_HOME or ~/.local/share.
    • A receipt .hi-runtime.json records the SHA-256 of the lock, computed at install time.
    • A match (same receipt hash and server present) is reused with no writes (AC-006).
    • Otherwise: write the manifest and lock to a sibling temp dir, run npm ci --ignore-scripts --no-audit --no-fund, write the receipt, then atomic rename.
    • Preconditions: node must be ≥22.18 and npm must be on the command environment PATH. A failure returns a reason (AC-005).
    • Project files are never touched. Nothing deletes the runtime (AC-007).
  • D3 Discovery: candidates are git ls-files -z --cached --others --exclude-standard entries whose basename is tsconfig.json.
    • Excluded: the Recorded Shape wikiRoot subtree, and solution-only configs (files: [] with no include).
    • If one candidate's directory contains another's, both are ambiguous: they are reported and get no entry.
    • The settings override typescript.compilerProjects: string[] replaces discovery with the listed tsconfig paths (AC-010).
    • Files are parsed read-only as JSONC (AC-011).
  • D4 Probe: node --input-type=module -e <probe> runs with cwd set to the runtime dir, one project at a time, bounded to 4 in parallel with a 60 s timeout each.
    • It prints one JSON line: {ok, files, reason?}.
    • No process outlives the call (AC-031).
  • D5 Codex entries: HI owns a fenced block in .codex/config.toml: # BEGIN hi typegraph (generated by hi update; edits are restored) … # END hi typegraph.
    • The block has one table [mcp_servers.typegraph_<slug>] per probe-passing project. The slug is the tsconfig dir with non-alphanumerics mapped to _; the root maps to root.
    • Fields: command = "sh" and args = ["-c", 'TYPEGRAPH_PROJECT_ROOT="$(git rev-parse --show-toplevel)" exec node "${XDG_DATA_HOME:-$HOME/.local/share}/hi-tools/typegraph-mcp/<version>/node_modules/typegraph-mcp/dist/server.cjs"']. The path is portable: no absolute home path.
    • Also: env = { TYPEGRAPH_TSCONFIG = "<path>" }, enabled_tools = the five reads, default_tools_approval_mode = "approve", startup_timeout_sec = 20, tool_timeout_sec = 60.
    • Every byte outside the block is preserved. If the block is missing, it is appended. With no eligible projects or the Pack deselected, the block is removed.
    • A user table outside the block with the same name is a conflict: it is reported and skipped.
    • No top-level approval_policy is written, and ~/.codex is never touched (AC-022).
  • D6 Pipeline step: new STEP between the Installed Record (012) and managed lint (013) in registry/pipeline.ts, behind an injectable runner.
    • When typegraph-runtime is in the resolved items: runtime → discovery → probe → block.
    • When it is not: remove the block only (Q20).
    • The outcome is attached to UpdateReport and rendered by lifecycle presentation.
  • D7 hi check: optional semanticReads output, present when the Installed Record lists typegraph-runtime.
    • Fields: runtime {installed, version, path, reason?}, registered {servers[], count}, compilerProjects[{tsconfig, server, probe: "pass"|"fail"|"ambiguous", registered, reason?}].
    • Human output shows them as three distinct lines. Registry status is independent (AC-024 to AC-026).
  • D8 Guidance (AC-030): a TypeScript-Pack-conditional section in the Built handoff template. It says the five reads are available, and that a tsconfig, dependency or branch change needs a new Codex session. The runbook gets the same text.

Bug fixes (root causes from readonly investigation, 2026-09-28)

  • #239: tools-command.ts never passes a runtime. tool-management.ts:158 defaults to makeToolCommandRuntime({}), whose empty env has no PATH.
    • Fix: pass makeToolCommandRuntime(runtime.commandEnvironment), make runtime required, and delete defaultRuntime.
  • #240: features/operator-skill/target.ts:21-24 still has maximumExclusive: "6.0.0".
    • Fix: derive the range from the running CLI major (<major>.0.0 up to <major+1>.0.0), and add a guard test using version.
  • #241: surface Packs (frontend, backend) carry no technologies, so packsForWorkspace never matches them. Default Packs are also added to every workspace scope.
    • Fix: in builders/prompts.ts, gate surface Packs per workspace using the same surface signals shape.ts uses. Publish the catalog's existing promptSurfaces into Pack meta, and route default Packs by it.
  • #242:
    • Detection walks the filesystem without git ignore rules. Fix: make repository-detector.ts and shape.ts evidence skip git-ignored paths, falling back to the current skip list outside git.
    • docsSpec is hard-coded to docs/AGENTS.md. Fix: render it only when a docs/ directory exists; the Recorded Shape gets an optional docsRoot.
    • hi update already re-detects the shape (the claim about a sticky shape is disproved). Stale Software Scopes stay in settings; hi update never edits them (remove by hand).

Tasks and waves

TaskIdentityOwner (subagent)Active write scopeDepends onRED target
T1GitHub #239apps-cli-srccli/tools-command.ts, integrations/tool-management.ts(+test), features/tool-ensure/*, cli/command-surface.test.ts—command-surface.test.ts: hi tools ensure --json with fake gh on PATH has no tool-install-failed
T2GitHub #240apps-cli-srcfeatures/operator-skill/target.ts, features/operator-skill/*target*.test.ts, integrations/skills-cli-target-delegation.test.ts—policy accepts active version → Resolved
T3GitHub #241, #242apps-cli-srcintegrations/repository-detector.ts(+test), registry/shape.ts(+test), registry/builders/prompts.ts(+test), registry/publisher/sources/packs.ts(+test), registry/model.ts (RecordedShape.docsRoot, HiPackMeta.promptSurfaces only), data/catalog/packs.ts read-only—React/Next workspace gets frontend skills; misc not in workspace scopes; ignored output/** manifests and .py skipped; no docs.md spec without docs/
T4IP-480 (+ probe half of IP-481)apps-cli-srcnew features/typescript-semantic-reads/runtime.ts, probe.ts (+tests), new data/tool-runtimes/typegraph-mcp/*—matching receipt → no reinstall; Node <22.18 → reason; probe of files: [] → fail reason
T5IP-481 discovery + IP-482 blockapps-cli-srcnew features/typescript-semantic-reads/discovery.ts, codex-config.ts (+tests)—this-repo-shaped fixture → 10 projects, none for root/wiki; block splice preserves outside bytes; restore after edit; remove on empty
T6IP-480/481/482 wiringapps-cli-srcregistry/model.ts (toolRuntime), registry/publisher/sources/{packs,tools}.ts or new typegraph-runtime.ts, registry/publisher/source.ts, registry/settings.ts, registry/pipeline.ts(+test), cli/lifecycle.ts, data/registry/handoff/AGENT-HANDOFF.md.tmpl, registry/builders/prompts.ts (handoff flag only)T3, T4, T5pipeline.test.ts: TS Pack → block written; no Pack → no runtime/no table; deselect → block removed, runtime kept
T7IP-484apps-cli-srcregistry/check.ts(+test), cli/check-command.ts, cli/command-surface.test.tsT1, T4, T5, T6runtime installed + zero tables → installed true, registered false, status current
T8IP-483parentnone (evidence only)T6, T7live hi update on this repo; Codex witnesses AC-027..029; two worktrees AC-019; measurements AC-032
T9docsdocsdocs/runbooks/codex-typescript-mcp.md, docs/runbooks/hi-cli-scaffolding.md, docs/README.md, wiki mirrors via sync, IMPLEMENTATION-NOTES.md, CHANGELOG.md, BASELINE_CHANGELOG.md, apps/cli/package.json versionT8wiki check:content + tests; release:classify passes

Waves:

  • W1 = T1, T2, T3, T4, T5. Their write scopes are disjoint. T4 and T5 add only new files.
  • W2 = T6, then T7. They are sequential because T7 reads T6's pipeline and settings schema, and both touch the report surface.
  • W3 = T8, then T9.
  • Review follows W3: review-phase / autoreview on the branch diff.

Validation gates (shared-machine ceiling on every heavy command)

  • Per task: the focused vitest files named above, via systemd-run --user --scope -p MemoryMax=16G -p CPUQuota=400% nice -n 10 bun run --cwd apps/cli test -- <files>.
  • After W2:
    • bun run --cwd apps/cli check-types
    • bun run --cwd apps/cli lint
    • bun run --cwd apps/cli test:source
    • bun run --cwd apps/cli registry:build (HI-CLI-004: items validate, no Managed Artifact hash)
  • Docs: bun run --cwd apps/wiki check:content plus wiki tests, and git diff --check.
  • Release: bun run release:classify -- --base origin/main --head HEAD.

Rules activated

HI-CLI-001, HI-CLI-002 (version bump), HI-CLI-003, HI-CLI-004, HI-DOCS-001, HI-WIKI-001, HI-WIKI-003, HI-REPO-004 (not applicable: no skill source edits). Each is evaluated in IMPLEMENTATION-NOTES.

On this page