feat(client): compose the production HarnessClient from a profile name - #955
Closed
chughtapan wants to merge 2 commits into
Closed
feat(client): compose the production HarnessClient from a profile name#955chughtapan wants to merge 2 commits into
chughtapan wants to merge 2 commits into
Conversation
Nothing in production could build a HarnessClient: the only code that started a daemon and connected to it lived in test-utils, and it demanded a caller-supplied port and an injected checkpoint store. harnessClientForProfile takes a profile name and nothing else. It starts the slot's own daemon child, derives the loopback endpoint from the same persisted port the daemon binds, and provides a file-backed checkpoint store. The checkpoint directory is keyed by profile name because the store must be provided before the client reads its identity from the daemon's status tool, and one slot is exactly one AgentId. The daemon supervisor moves out of test-utils to the source root; only the port reservation a test performs before writing a slot stays behind. The packaged round-trip test now drives the production composition instead of a parallel test-only path with an in-memory store. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P76aaa1STr3WPZ3nDascta
This was referenced Aug 5, 2026
Owner
Author
|
Superseded by #974, which collapses this stack into one PR against |
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.
Plan step 9. Stacked on #954. This is the step that makes a production
HarnessClientconstructible at all.What was missing
The only code that started a daemon and connected a client to it lived in
test-utils, demanded a caller-supplied port, and needed an injected checkpoint store. Combined with the slot change in #954, nothing was left blocking — but nothing was wired either.The composition
It starts the slot's own daemon child, derives the loopback endpoint from the same persisted port the daemon binds, and provides a file-backed checkpoint store. No URL, no port, no store from the caller — which is exactly what the adapters need in steps 10 and 11.
The checkpoint directory is keyed by profile name, not AgentId. That is forced, not stylistic:
acquireHarnessClientreadsagentIdfrom the status tool inside its own body, so the identity does not exist at the moment the store must be provided. One slot is exactly one AgentId, so the profile name is a valid agent scope.The daemon supervisor moves from
test-utils/process/packaged-moltzapd.tstosrc/moltzapd-child.tsviagit mv, so the proven readiness-polling and shutdown behavior is preserved rather than rewritten. Only the port reservation a test performs before writing a slot stays behind, intest-utils/process/reserve-port.ts.The round-trip test now proves production
harness-adapters.integration.test.tspreviously called the test-only acquirer and suppliedKeyValueStore.layerMemory. It now callsharnessClientForProfile— so the one ungated end-to-end proof for both adapters exercises the real composition and a real file-backed store.acquireHarnessClientandKeyValueStorebecame unused imports there, which is the clean signal that the parallel test path is gone.Architecture findings this surfaced, and how they were resolved
Three real ones, none suppressed blindly:
require-boundary-owned-types—harness-client.tsmay not mentionnodedirectly. Resolved by moving the node-touching composition into the node-boundary module rather than waiving the rule.harness/, creating.↔harness. Reverted; the module sits at the source root where its imports point one way.no-large-folder/file-implicit-boundary-module— the package genuinely gained a module, andharness-client.tsgenuinely is a boundary (it is the./harness-clientsubpath export). Both recorded inscripts/gen-architecture-configs.mjs, since the config is generated and a hand edit would be overwritten byarch:config:check.connectMcpOncewas also rewritten Effect-natively instead of carrying anasyncsuppression into production source —sloppy-code-guardand the eslint rule were both asking for the same thing, and the rewrite drops atry/catchtoo.Gates
pnpm nx run workspace:precommit— exit 0 (this runslint:sloppy-code-guard, whichpnpm lintalone does not)pnpm typecheckandpnpm nx run-many -t typecheck:tests— 0 errorspnpm lint— 0 warnings, 0 errors;arch:check0 findings on every packagepnpm nx run-many -t test— all 9 projects greengit grep layerMemory packages/returns only pure-unit testsADR conformance (R-pass)
http://127.0.0.1:<mcpPort>/mcp; port-zero and bind fallback rejected20260728-endpoint-daemon-speaks-modern-mcpCONFORMS20260801-harness-client-owns-runtime-contextCONFORMSlayerFileSystemstock behavior is accepted as-is.No new divergence introduced; no #926 ledger row changes.
🤖 Generated with Claude Code
https://claude.ai/code/session_01P76aaa1STr3WPZ3nDascta