Repository navigation
refactor(daemon): publish a single package entrypoint - #3781
Conversation
ADR 0033's daemon section described the transitional `./testing/` entries as still standing. Record the final state and name the owner of the surface instead of restating what R83 now enforces, and restore the rule header package-entry-surface.ts lost when it was generalised. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…vate Both callCommand functions now convert through envelopeToRpcResult, so responseToRpcResult has no caller outside harness-rpc.ts. Fallow flagged the export as dead surface; the conversion stays one function with one entry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Size Report
Startup median (7 runs, lower is better):
|
There was a problem hiding this comment.
All reported issues were addressed across 11 files
You’re at about 96% of the monthly reviewed-line limit. You may want to disable incremental reviews to conserve quota. Reviews will continue until that limit is exceeded. If you need help avoiding interruptions, please contact contact@cubic.dev.
Reply with feedback, questions, or to request a fix.
View guided diff | Turn on auto-fix | Re-trigger cubic
The pin matched `^[ \t]*export\s*\*` against the entry's text, so it refused a comment that mentions a star and accepted `export type * from`, which publishes a module's whole type surface just the same. Read the parsed AST instead: `ExportAllDeclaration` is the one node every star shape builds — `export *`, `export * as ns`, and both `export type` forms — and prose builds none. facade-exports.ts records the same failure mode from #1555: a hand-enumerated export-form scanner misses exactly the form that widens the surface. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
This PR is ready at ac076f1. The daemon now has a single package entrypoint, and I found no problems in the diff. Not blocking: the entry-surface check in scripts/layering/package-entry-surface.ts (https://github.com/callstack/agent-device/blob/ac076f1/scripts/layering/package-entry-surface.ts#L88) passes with nothing parsed if the daemon entry file is moved or renamed, so you could treat a missing entry source as a violation; the daemon entry './src/index.ts' is a bare literal while TEST_KIT_ENTRY is a named constant, so one shared ENTRY_FILE constant would tidy that (https://github.com/callstack/agent-device/blob/ac076f1/scripts/layering/package-entry-surface.ts#L28); and the crop-before-scale screenshot test, the test-title rename and the provider-scenarios dedup are unrelated to this change, but I do not ask for a split. You can take or leave all three. The earlier thread on the star check missing I judged this from the diff and the PR body. I did not run the layering lane, the unit tests or the mutation, and I could not read your local receipt. I also did not run the parser, so the CI is still pending. Only Smoke Tests is queued, so it has not run and there is no failure to read. The diff changes no production code, and Smoke runs the built CLI and daemon through the bare entry, which is unchanged. It must finish green before merge, and nothing else stands in the way. |
|
…ment * origin/main: refactor(daemon): publish a single package entrypoint (#3781) fix(daemon-client): wait for an acknowledged quiesce instead of killing the daemon (#3780) fix(daemon): refuse leases for providers without a registered runtime (#3773) # Conflicts: # packages/daemon/src/sessions/handlers/__tests__/lease.test.ts # src/daemon-client/daemon-client-ensure.ts
…refactor/daemon-runtime-no-process-globals * origin/refactor/host-environment: refactor(cli): resolve one transport per run and one host per MCP tool call; default the lease provider cwd to the bound host refactor(daemon): publish a single package entrypoint (#3781) fix(daemon-client): wait for an acknowledged quiesce instead of killing the daemon (#3780) fix(daemon): refuse leases for providers without a registered runtime (#3773)
What
@agent-device/daemonpublishes exactly one package entry:".". The 18 transitional./testing/*subpaths are deleted, the layering checker pins that shape for both single-entrypackages under one declaration, and three test-hygiene commits land alongside.
Production behaviour does not change. Outside the manifest, the checker and the removed test-support
surface, this branch touches only test files and docs.
Depends on the consumer migrations in #3728, #3733 and #3742, all of which are on
main.Export surface: 19 → 1
packages/daemon/package.jsonexportskeysorigin/main0563666b0)"."+ 18./testing/*".""."is byte-identical to the entry onmain(types+default→./src/index.ts), verified bydiffing the key against
origin/main.No source module was deleted, and none should have been. Each of the 18 removed subpaths pointed
at a module other code still needs: the 15 production targets each have 1–118 non-test importers
(
session-state.ts118,session-store.ts74,context.ts58, …,request-finalization.ts1), andthe 3
src/__tests__/support/fixtures are each imported relatively by in-package tests that movedthere in #3733. So no Fallow baseline entry needed moving or removing —
pnpm check:fallowreports noissues in the changed files.
R83 / R84
node --experimental-strip-types scripts/layering/check.ts, which measures head and merge-base withthe same function:
R83 drops by exactly 18 — the 18 deleted subpaths. The 13 remaining are other packages' fixtures,
untouched here. R84 is unchanged at 152. The
beforehalf was reproduced independently: the samecheck run at
0563666b0in a clean worktree reports31 test-only export(s) remain against 31and152 unmatched test(s) remain against 152.The 18 subpaths have zero importers
Every tracked reference to a daemon testing specifier at
origin/main— exhaustivegit grepoverthe whole tree with no path exclusions:
Those 8 hits are checker inputs, not consumers. One is a prose example inside the
resolveWorkspaceSpecifierdoc comment inmodel.ts, describing how a pattern key is stored; theother 7 are planted specifiers that feed R11's façade rule synthetic import sites. That file builds
its own synthetic daemon manifest with its own
./testing/keys (see itsdaemonManifestconst), soit never reads the real manifest and does not care whether the daemon publishes the namespace. The
same two files are the only hits at this head, both still valid.
Nothing inside the package imports itself through
@agent-device/daemon/testing/*: that grep coverspackages/daemon/**, and package self-imports would have to name the package. The deleted namespacealso appears in no Vitest alias, Stryker config or workflow.
The pin
scripts/layering/package-entry-surface.ts(R83) already held test-kit's single-entry pin.ec8c515a0extends that one declaration rather than adding a rule beside it: the test-kit-only body became
checkEntrySurface(...), driven by anENTRY_SURFACESlist thatcheckPackageEntrySurfacesmapsover — test-kit plus the daemon. There is still exactly one entry-surface declaration and one call
site (
scripts/layering/check.ts:627);grep -rn "checkTestKitIsolation" scripts/returns nothing.Each pinned package is asserted on both halves:
exportsis exactly"."with every conditionresolving to its declared entry file, and its
src/index.tscontains no star re-export.Planted violations
Both planted in the real tree and run through the real checker (
node --experimental-strip-types scripts/layering/check.ts), not just the unit lane.Extra subpath — re-added
"./testing/context"topackages/daemon/package.json:export *— appendedexport * from './server/http/daemon-runtime.ts';topackages/daemon/src/index.ts:Both are mirrored as checker tests beside the rule (
package-entry-surface.test.ts), each assertingthe violation's file and message and that the clean workspace reports none. The star test plants all
four shapes (
export *,export * as ns,export type *,export type * as ns) and pairs them withthe closest negative: an entry whose comment and template literal mention
export *while it nameseverything, which must pass. Lane: 427 tests, 0 failures.
Crop before scale
src/commands/capture/runtime/screenshot.test.tsgains a case whose backend crops insidecaptureScreenshot, mirroring the daemon's bound backend (screenshot-runtime.ts:373crops the filebefore returning), so the 40×20 crop must reach the runtime's 0.5 scale and land at 20×10.
Mutation — move
resizePngFileToScalefrom after the capture to before it insrc/commands/capture/runtime/screenshot.ts, so scaling runs on the pre-capture frame and the croplands last:
The output is the unscaled crop: the case fails for exactly the order it claims. Reverted; both cases
pass again.
Commits
ec8c515a015bd4849596f3abe72f902cf15e40618c28b0d7c8f14f8d652e315ac076f13af902cf15eis a rename only: the title now says--scalesuppresses logical density metadata, andthe diff is the one
test(...)line — no assertion changed.40618c28bputs oneenvelopeToRpcResult(envelope, id, statusCode)intest/integration/provider-scenarios/harness-rpc.ts, used by bothcallCommandfunctions inharness.tsandharness-proxy.ts, with neither copy of the inline conversion left behind andJsonRpcResponseEnvelopedeclared once.8d652e315follows up on it: with both call sites converted,responseToRpcResulthad no caller outside its module andpnpm check:fallowfailed the branch onthat dead export, so it is now module-private.
0d7c8f14frecords the closed surface in ADR 0033 and deletes the prose the gate now enforces ratherthan restating it, plus restores the
Catches/Evidence/Cost/Kill criterionheader the rule filelost when it was generalised.
docs/agents/*andAGENTS.mdneeded no edit: neither described a./testing/*export even onmain(git grep "testing/" origin/main -- docs/agents/ AGENTS.mdisempty), so there was nothing to delete there.
ac076f13aanswers the cubic review thread: the star check matched^[ \t]*export\s*\*against theentry's text, so it accepted
export type * from— which publishes a module's type surface just thesame — and would have flagged a comment that mentions a star. It now parses the entry and refuses any
ExportAllDeclaration, the one node every star shape builds. Restoring the regex fails the newexport type *case, which is the proof the gap was real.facade-exports.tsrecords the same failuremode from #1555, so this follows in-repo precedent.
Gate receipt (exact head
ac076f13a)pnpm check:affected --run --head ac076f13a1295dd5e216e3e9d07f3df929f9dbb6— all runnable checks passed(
status: passed,exit 0,exactCommit: true,checkoutChanged: false; base0563666b0;09:48:01Z → 09:56:47Z). Receipt:
.tmp/validation/run-87Srlt/receipt.json.36 checks passed, 2 deduplicated into the related-test run, 25 skipped as GitHub-authoritative
or parked. The 2 deduplicated are
unitandprovider-integration, both "covered by relatedtests" by the runner's own bookkeeping; the provider-scenarios lane was also run on its own for
this PR —
pnpm test:integration:provider, 64 files / 192 tests, all passing.Passed:
format,lint,typecheck,layering,di-seams.fallow,mcp-metadata,build,package,integration-node.macos-coverage,vitest-related,integration-progress,replay-compat,daemon-wire-compat.affected-selector,gate-manifest,gate-manifest-model,depgraph,tmpdir-leaks.tmpdir-leaks-model,coverage-model,coverage-crap-model,wire-compat-model,production-exports.bundle-owner-files,fixture-cache,fixture-fallback,command-docs,docs-links.docs-prose,agent-guidance,xctest-selection,packaged-runner-swift,maestro-conformance.mutation-model.Individually, on this head:
pnpm format/format:check,pnpm check:quick(lint + typecheck),the layering check (R83 13 / 31, R84 152 / 152,
OK),pnpm check:fallow(no issues in thechanged files),
pnpm check:gate-manifest(57 checks across 25 lanes),pnpm check:doc-prose,pnpm check:doc-links, andpnpm test:integration:provider.🤖 Generated with Claude Code