Build the GraphCode Nod runtime (graphcode-nod) - #590
Merged
Merged
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: scgopi <scgopireddy@gmail.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: scgopi <scgopireddy@gmail.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: scgopi <scgopireddy@gmail.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: scgopi <scgopireddy@gmail.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: scgopi <scgopireddy@gmail.com>
…, honour --inherit Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: scgopi <scgopireddy@gmail.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: scgopi <scgopireddy@gmail.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: scgopi <scgopireddy@gmail.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: scgopi <scgopireddy@gmail.com>
Policy #1190: no claude.ai login. Claude Code runs with inherited credentials stripped and a config directory of Nod's own, ships beside graphcode-nod, and a rejected key fails the turn instead of retrying. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: scgopi <scgopireddy@gmail.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: scgopi <scgopireddy@gmail.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: scgopi <scgopireddy@gmail.com>
Owner
Author
|
Gate on Follow-up commit adds only |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: scgopi <scgopireddy@gmail.com>
4 of 5 tasks
Signed-off-by: scgopi <scgopireddy@gmail.com>
scgopi
force-pushed
the
feat/nod-runtime
branch
from
October 2, 2026 15:11
68a0398 to
fb67fcf
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The GraphCode Nod runtime: a TypeScript package in
NodRuntime/that builds thegraphcode-nodexecutable, with the Claude Agent SDK and the GitHub Copilot SDK behind one engine interface. Stacked on #583 (feat/nod-foundation). Please retarget tomainbefore #583's branch is deleted.Changes
events.jsonlis append-only, andseqcontinues across resumes. A torn last line is tolerated.control.socktakes oneNodCommandper line and replies{"ok":…}in order. A plain PTY line is a queuedsend.src/engine.ts). The Claude adapter runs one long-lived streaming query per session. A PreToolUseaskforces every Bash, edit, web and MCP call throughcanUseTool, so the human's own Claude allow rules can't bypass the gate. The Copilot adapter puts the gate in its single permission handler.additionalContexton both engines.stopinterrupts the turn, rejects pending hunks, denies open asks and clears the queue.NodSettingsand the allowlist.*anda|b|c. A compound command must be allowlisted in every part, and command substitution is never allowlisted.network. Containment is checked on real paths.--unattended) fail withpermissionUnavailableinstead of waiting.goalCheckturn naming the unmet clauses, with a limit of 20 in a row.markGoalDoneis supported.presence,activity(same encoding) andusagezmx labels andsessions/<node>.id/.historyasPresenceHooks.failureevents (signInExpired,contextFull,spendCap,permissionUnavailable,engineError).--resume,--inheritbriefs (turn 1 as ahandoff; Claude forks the parent conversation), and-pprint mode.anthropic-api-keyitem in Keychain serviceapp.graphcode.nod. Claude Code runs with inherited credentials stripped and its ownCLAUDE_CONFIG_DIR. A rejected key fails within seconds. Copilot uses thegithub-tokenitem, or else the Copilot CLI's own login.scripts/package.shbuilds theContents/Helpers/nod/folder:bun build --compile(graphcode-nod, ~64 MB), the Claude Code the Agent SDK bundles (~228 MB, Anthropic's signature kept), and the Copilot runtime (~86 MB). It has hardened-runtime JIT entitlements. Agent runtimes are located explicitly, because a compiled binary can't reach the SDKs' platform packages. The runtime takesNOD_STATEandNOD_NODE_IDfrom the launcher (agreed with NodLaunch).test/contract.test.tscompiles the realNodProtocol.swiftand checks both directions: Swift decodes all 18 event types the runtime writes, and the runtime parses all 10 commands Swift encodes..github/workflows/nod-runtime.ymlruns typecheck,bun testand a compile on NodRuntime changes.Not in this PR (agreed with NodGraphLayer): wiring the graphcode MCP server,
sendDraftand inbound mail classification fromfeat/nod-graph-layer. Until then the runtime answersfork,sendDraftand compositerunPlanwithok:false.Smoke runs against real engines
Copilot engine, packaged binary (
/tmp/nodpkg/graphcode-nod, headcbc6f0c9). Goal loop in a throwaway git repo, review mode, driven overcontrol.sock(accept every hunk, allow every ask, one steer). 27 records written:The
goalCheckrecord carried evidence for each clause, for example"evidence":"The bash output includes hello nod, matching the output of cat hello.txt.". Copilot print mode from the packaged binary, with the SDK platform package hidden, printedpkg-copilot-ok.Claude engine. No Anthropic API key exists on this Mac, so I couldn't run a full session under the policy.
app.graphcode.nodand removed it afterwards (trap-guarded). The packaged binary launched its shippedclaude, with the SDK platform package hidden and noclaudeonPATH. The result wasThe Anthropic API key was rejectedin 4 s, exit 1, and asignInExpiredfailure event in session mode. Any fallback to the human's Claude login would have produced an answer instead.Test plan
Real-engine smoke on the Claude engine found the gate classifying
/private/tmp/...edits as outside a worktree opened as/tmp/.... The test below was run against the previous gate, then the fixed one.RED: cd NodRuntime && bun test test/permissions.test.ts with src/permissions.ts from fa789cf^ -> (fail) classification - worktree containment compares real paths, for files that don't exist yet too; 19 pass, 1 fail
GREEN: cd NodRuntime && bun test test/permissions.test.ts -> pass, 20 tests
REGRESSION: cd NodRuntime && bun test -> pass, 91 tests across 8 files, 0 fail; tsc --noEmit exit 0
The contract test fails when a TypeScript event field drifts (
filesinstead offilesChangedgives SwiftDecodingError.keyNotFound).xcodebuild gate, private DerivedData, in progress on
a6942057; numbers to follow in a comment. On the pre-rebase head (same NodRuntime, foundation before 9766e57):xcodebuild testexit 0 (2009 tests in 216 suites passed),graphcode-clibuild exit 0,graphcodedbuild exit 0. This PR changes no app Swift sources;NodRuntime/test/swift/main.swiftis compiled standalone by the contract test.Checklist
git commit -s) per the DCObun testin NodRuntime; xcodebuild gate above)