Skip to content

docs: name the runInteractive half of src/process.ts in the agent guides' module map - #113

Open
dichovsky wants to merge 1 commit into
mainfrom
docs/agent-guide-process-seam
Open

docs: name the runInteractive half of src/process.ts in the agent guides' module map#113
dichovsky wants to merge 1 commit into
mainfrom
docs/agent-guide-process-seam

Conversation

@dichovsky

@dichovsky dichovsky commented Aug 6, 2026

Copy link
Copy Markdown
Owner

Closes #105

CLAUDE.md and AGENTS.md are the files an agent reads before doing anything else, and their Module boundaries section is specifically the list an agent consults to decide which module owns a change. Its src/process.ts entry named one of that module's two exports. That is worse than an omission: the seams section directly above (:91-105, rewritten by #101) now introduces Io.runInteractive by name, so a reader meets the method, goes looking for its implementation in the module map, and finds src/process.ts described as being about version probes with no pointer from one to the other — the exact navigation the section exists to provide.

Verified on main @ 09e67cd against the code, not the issue body. src/process.ts exports two functions: nodeRunProcess (:17) and nodeRunInteractive (:66). bin/crew.ts:42 imports both and wires them to the two Io fields at :56-57. docs/design/architecture.md:142 already reads "real Io.runProcess (capture-only) + runInteractive (tmux attach)", so the agent guides were the drifted side.

What changed and why

One entry, identical hunk in both files, CLAUDE.md:152-153:152-155 and AGENTS.md at the same lines.

Claim Before After — and the evidence
Which Io members the module implements Io.runProcess only Both. src/process.ts:17 and :66; bin/crew.ts:42,56-57 wires the pair. Matches docs/design/architecture.md:142.
What runProcess is used for "for version probes" All nine call sites, enumerated from grep -rn "\.runProcess(" src/: platform-registry probes (src/platforms/shared.ts:239, ollama.ts:40, lmstudio.ts:42), git (src/worktree.ts:41, src/launcher/session.ts:626), tmux (src/launcher/tmux.ts:149 generic dispatch, :186 has-session, :170 tmux -V), and the Console's browser opener (src/ui/index.ts:120). The old scoping sent anyone tracing a git or tmux call looking for a runner that does not exist.
runProcess's timeout unstated bounded timeoutnodeRunProcess takes a required opts.timeoutMs (src/process.ts:20,27) and every caller passes one. This is the property that distinguishes it from runInteractive, and the seam bullet at :94-95 already draws that contrast.
runInteractive's shape and scope absent inherited stdio, no timeout, reserved for tmux attachsrc/process.ts:68 (stdio: 'inherit', no timeout), and src/launcher/tmux.ts:321 (attach-session) is its only caller in src/.

src/which.ts's clause is unchanged.

Deltas against the issue body — noted rather than silently absorbed

  1. The line numbers are :152-153, not :139-140. The issue was filed at 18:14 on 2026-08-06 against pre-docs: correct drifted command and Io-seam facts in agent guides #101 main; docs: correct drifted command and Io-seam facts in agent guides #101 merged at 21:20 the same day and added 17 net lines above this point, moving the entry down 13 lines. The text it quotes is verbatim correct.
  2. The issue's Acceptance asks only that the entry "names Io.runInteractive alongside Io.runProcess". Meeting it exposed a second false claim in the same sentence — "for version probes" — which is contradicted by the call sites. grep -rn "\.runProcess(" src/ returns nine, of which six are outside the platform registry; five of those six are not version probes of any kindgit twice (src/worktree.ts:41, src/launcher/session.ts:626), tmux dispatch and has-session (src/launcher/tmux.ts:149,186), and the browser opener (src/ui/index.ts:120). The sixth, src/launcher/tmux.ts:170, is literally tmux -V; it is not a platform-registry probe, but it is a version probe, so it carries no weight against the old wording and is excluded from the count above. The five do. Fixing the first claim and leaving the second standing in the same sentence was not a defensible stopping point, so both are corrected. No adjacent line, bullet, or section was touched.
  3. The byte-identity check does not return empty. diff <(tail -n +2 CLAUDE.md) <(tail -n +2 AGENTS.md) returns exactly one hunk, because tail -n +2 drops only the # CLAUDE.md / # AGENTS.md H1 and the guidance sentence the two files deliberately differ on is line 3, not line 2. The invariant is "exactly one hunk, and it is that sentence" — identical before and after this change. Same reading docs: correct drifted command and Io-seam facts in agent guides #101 recorded.

#104 does not reproduce — dropped, not closed

This PR was scoped to close #104 as well. It does not, and no CONTRIBUTING.md edit is included.

#104 asks that CONTRIBUTING.md:24-25 name build:web and all three typecheck projects. On current main they already do — commit 52e6bdd ("docs: retract two false claims this PR introduced, and finish CONTRIBUTING"), the last commit of PR #101, rewrote exactly those lines three hours after #104 was filed:

npm run build          # tsc -p tsconfig.build.json + build:web → dist/ (the publishable artifact)
npm run build:docs     # esbuild docs-site/ → dist-docs/ (CI gate; not in the package)
npm run typecheck      # 3 tsconfigs, all noEmit: root (incl. tests), web/, docs-site/

Every clause of #104's Acceptance is satisfied, including "matching the corrected wording now in CLAUDE.md/AGENTS.md so the three files agree" — CLAUDE.md:57-59 and AGENTS.md:57-59 carry those three lines verbatim. Confirmed by git blame -L 23,30 CONTRIBUTING.md. #101's PR body describes only :36 and :99 because it was written before its own final commit; the merged tree is what counts.

Per .github/ISSUE_TRIAGE.md ("If the underlying problem is already fixed, say so … and apply invalid — do not close it yourself"), #104 is left open for a human to label invalid and close. No line was invented to justify touching the file.

Verification

Tests: none added — claiming the docs-only exemption, which CONTRIBUTING.md:98 ("tests are not applicable for docs-only changes") and .github/ISSUE_TRIAGE.md both grant. The diff is two Markdown files, zero code.

Proven, not assumed, that nothing guards them. grep -rn "CLAUDE.md\|AGENTS.md\|CONTRIBUTING.md" tests/ returns only tests/integration/commands/init.test.ts, which writes and reads a CLAUDE.md inside a temporary fixture cwd to exercise crew init's guide-append path — it never reads the repository's own copy. tests/unit/docs-facts.test.ts derives from src/cli.ts, src/platforms/registry.ts, src/store/schema.ts, package.json, vitest.config.ts, and ADR H1 headings, never these files, so docs-site/generated/facts.json needed no regeneration. Both files were run anyway: 2 files, 19 tests, all passing.

Run on the pushed tree under Node 24.19.0:

Command Exit Result
npm run typecheck 0 clean, all three projects
npm run lint 0 clean
npm run format:check 0 clean
npm run build:docs 0 dist-docs/main.js 102.1kb
npx vitest run tests/unit/docs-facts.test.ts tests/integration/commands/init.test.ts 0 19 passed
diff <(tail -n +2 CLAUDE.md) <(tail -n +2 AGENTS.md) 1 the one expected hunk (the line-3 guidance sentence), byte-identical otherwise — re-checked after the edit and before the push

The full suite was not run: the diff touches no src/** or bin/** file, so coverage cannot have moved and CI's test:coverage is authoritative.

Wrapping is hand-maintained — Prettier never reflows Markdown prose here, so format:check passes either way. To be precise about why, since earlier PR bodies in this repo have stated it wrongly: proseWrap: "preserve" is Prettier's default, not a configured value. .prettierrc sets only singleQuote, semi, trailingComma, printWidth: 100, and tabWidth: 2 — it does not mention proseWrap, and printWidth therefore does not apply to prose. Same behavior, correctly attributed. The four new lines are 88 / 92 / 80 / 58 characters, inside both files' existing band (max line is 102 in CLAUDE.md, 100 in AGENTS.md, both pre-existing and untouched). No paragraph outside the edited bullet was reflowed.

Contract impact

None. CLAUDE.md and AGENTS.md sit outside the four-tier authority order in docs/README.md:9-12 entirely — they restate what src/ already does, so the code is the correct side. No ADR is amended, no FR-*/NFR-* moves, no CLI grammar rule, record type, error code, command, or flag changes. package.json is untouched. CURRENT_SCHEMA_VERSION stays 7.

Out of scope

Related open PRs

No open PR touches CLAUDE.md, AGENTS.md, or CONTRIBUTING.md — checked at file level. #110 (docs/adr/*, product-spec.md), #111 (README.md, EXAMPLES.md, architecture.md, data-model.md, tests/tools/), and #112 (docs/design/*.md) are all disjoint. Whichever change lands next against this pair must re-confirm the byte-identity invariant.

The module-boundaries list is where an agent looks to decide which module
owns a change. The seams section above it introduces `Io.runInteractive`
by name, but the `src/process.ts` entry described only `Io.runProcess` —
so the reader met the method and then found no module claiming it. The
same entry scoped `runProcess` to "version probes", which sent anyone
tracing a `git` or `tmux` call looking for a runner that does not exist.

`docs/design/architecture.md` already gets this right; the agent guides
were the drifted side.
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.

Docs: CLAUDE.md/AGENTS.md describe src/process.ts as runProcess only, omitting nodeRunInteractive

1 participant