Launch GraphCode Nod sessions and read their event log - #592
Merged
Merged
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: scgopi <scgopireddy@gmail.com>
graphcode-nod runs in zmx like every backend: resolved from the app bundle (GRAPHCODE_NOD_PATH overrides), launched with --node/--engine/--loop-type and NOD_STATE, resumed with --resume <conversation-id>. One fold over events.jsonl (NodSessionFold) answers presence, the live line, usage, summary beats and the goal verdict; an open permissionAsked is Needs you. Messages go through control.sock as queued sends. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: scgopi <scgopireddy@gmail.com>
The goal poller armed a verdict read only for backends with a typed directive, so a Nod goal loop never resolved; and the live line was read only for busy sessions, so a loop waiting on a permission never said what it asked. Both now include Nod. Also NOD_PROJECT_PATH/NOD_GRAPH_FILE and --inherit for the graph layer, the README's NOD_STATE path, tests for the fold, readers, argv and control socket, a fake graphcode-nod, and scripts/nod-daemon-e2e.py driving an isolated daemon. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: scgopi <scgopireddy@gmail.com>
graphcoded runs from the support directory with no bundle, so the app now copies Contents/Helpers/nod to <support-dir>/bin/nod with its other helpers (copied, not linked, so a moved app keeps working). Timed loops launch --unattended; nodArguments takes --inherit for fresh launches. The session env carries NOD_NODE_ID and NOD_PROJECT_PATH instead of a graph file path. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: scgopi <scgopireddy@gmail.com>
FeatureRamps.nod is the app's; graphcoded and the CLI have no ramps. The app now mirrors it into <support-dir>/nod/ramp.on on each launch, as it does the codespace multiplex flag, and without it node creation is refused with a reason, and neither launcher resolves a runtime. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: scgopi <scgopireddy@gmail.com>
scgopi
force-pushed
the
feat/nod-launch
branch
from
October 2, 2026 05:21
93e9502 to
dda9433
Compare
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: scgopi <scgopireddy@gmail.com>
Signed-off-by: scgopi <scgopireddy@gmail.com>
scgopi
force-pushed
the
feat/nod-launch
branch
from
October 2, 2026 15:11
8dad0bf to
5d06c9b
Compare
Signed-off-by: scgopi <scgopireddy@gmail.com>
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
Wires GraphCode Nod into the session machinery: graphcoded and the app launch
graphcode-nodin zmx like every backend, and one fold over itsevents.jsonlgives the daemon presence, the live line, usage, summary beats and the goal verdict. Stacked on #583 (feat/nod-foundation, rebased onto 9766e57). Rebase onto main once that merges.isSpikedstays false for.nodexcept whenGRAPHCODE_NOD_PATHnames a runtime. The flip, and putting Helpers/nod in the bundle through Project.swift, come in NodProvider's integration PR once #590 and this are on main.Changes
executableNameisgraphcode-nod, resolved by absolute path (NodRuntimeLocator), never from PATH:GRAPHCODE_NOD_PATH, thenContents/Helpers/nod/graphcode-nod(app panes), then<support-dir>/bin/nod/graphcode-nod(graphcoded).nodArgumentsadds--node --cwd --engine --loop-type [--model] [--goal-file] [--inherit] [--unattended], andlaunchArgumentsadds[--briefing] --prompt. Resume is--resume <conversationID>. A main loop with no note still launches. Env isNOD_STATE,NOD_NODE_ID,NOD_PROJECT_PATH. Remote projects get no Nod launch yet.GhosttyTerminalView.launchPrefixbuilds the same argv and env for.nod, so the pane and the daemon cannot disagree.DaemonBootstrap.installHelperscopies the bundle'sContents/Helpers/noddirectory to<support-dir>/bin/nod(a copy, so a moved app keeps working). It is in the helper stamp, and optional, so bundles without it still install.NodSessionFold(Domain) is the only reader of the event log. Needs you comes from an openpermissionAsked, or a failure other thancontextFull. It also gives the live line (asks to run …while waiting), usage as running totals, the goal verdict and progress, andNodCardStatefor NodSetup's cards.NodSessionLogfeeds presence (.reported), activity, usage, summary beats andGoalVerdictReader.recordsGoalVerdictis now true for Nod. It banks the live run's conversation id intoSessionIDStore, so reboot, restart and app reopen all resume.NodControlClientspeakscontrol.sock.sendInput, and so.messageedges,node sendand heartbeats, sends a queuedsend, falling back to typing the line when the socket isn't up yet.FeatureRamps.nodis mirrored into<support-dir>/nod/ramp.onon each app launch (likepublishCodespaceMultiplexFlag). Without it, GraphStore andgraphcode node create --backend nodrefuse with "GraphCode Nod is not enabled on this install yet", and neither launcher resolves a runtime.goalDirective; before this, a Nod goal loop never resolved. The live line is now also read for a Nod loop in Needs you.NOD_STATEpath is corrected.scripts/fake-graphcode-nodspeaks the protocol without a model.scripts/nod-daemon-e2e.pydrives an isolated graphcoded (own support dir andZMX_DIR) through the CLI.Left for whichever of this and NodGraphLayer merges second:
inheritFile: node.lineage?.briefPath, andunattendedforlineage.kind == .compositeChildinZmxSessionLauncher.nodArguments. TheNOD_STATEhelper converges with #591'sNodStateDirectory, and the second to merge deletes its copy.Test plan
RED: xcodebuild test -only-testing:graphcodeTests/NodGraphStoreTests with GraphStore.swift from bd291d5 -> exit 65, aNodGoalLoopIsResolvedByItsRecordedVerdict expected state succeeded, found running; aNodLoopWaitingOnAHumanSaysWhatItAsks activity nil
GREEN: xcodebuild test -only-testing:graphcodeTests/NodGraphStoreTests -> pass, exit 0, 2 tests
REGRESSION: xcodebuild test -scheme graphcode on dda9433, private DerivedData -> pass, exit 0, 2038 tests in 223 suites
python3 scripts/nod-daemon-e2e.py .spm/debug-> 20/20 PASS, exit 0. It covers creation refused while the ramp flag is absent, then the runtime launching, the launch argv, the goal file,node sendarriving on control.sock as a queued send, reported idle and busy, an open ask showing as Needs you with "asks to run swift package resolve", usage, goalCheckmet:trueresolving the loop, a timed loop launched--unattended, a heartbeat landing in the same conversation, the conversation id banked, and restart resuming it with--resumeand no prompt.graphcode-cliandgraphcodedscheme builds exit 0. swiftlint has 0 errors, and swift-format lint --strict is clean.launchArgumentswith and without a prompt,resumeArguments,ZmxSessionLauncher.arguments/resumeArgumentsboth local andssh://, the app'slaunchPrefix/agentCommand/resumeCommand/sessionEnvironment/remoteCommandfor goal, time and turn loops with and without a prompt, plusSummaryModelWriter.invocationandTitleSuggestionClient.invocation. For claudeCode, codex, copilotCLI, openCode and pi, 1,845 argv lines in 285 labelled shapes are byte-identical.scripts/cli-smoke.shagainst a separate SwiftPM build -> exit 0.Checklist
git commit -s) per the DCOmake test)make check)