* reland(sidecar): converge product clients after weekly release
Restore the sidecar convergence from #7244 after the release-scheduling revert in #7634. This tree matches the previously reviewed and cross-platform QA-accepted implementation at d83d4e032f.
* fix(sidecar): clarify identity and cache witnesses
Generated-By: looper 0.11.2 (runner=fixer, agent=codex)
* fix(packaged): probe cross-source desktop owners
Generated-By: looper 0.11.2 (runner=fixer, agent=codex)
* fix(sidecar): preserve cross-source launch ownership
Generated-By: looper 0.11.2 (runner=fixer, agent=codex)
* test(pack): assert cross-source Windows launch ownership
Generated-By: looper 0.11.2 (runner=fixer, agent=codex)
* fix(sidecar): align HyperFrames with client boundary
Generated-By: looper 0.11.2 (runner=fixer, agent=codex)
* fix(e2e): keep HyperFrames fixture in helper lane
Generated-By: looper 0.11.2 (runner=fixer, agent=codex)
* docs(sidecar): restore review and handoff contracts
Generated-By: looper 0.11.2 (runner=fixer, agent=codex)
* fix(sidecar): restore cache and daemon boundaries
Generated-By: looper 0.11.2 (runner=fixer, agent=codex)
* fix(pack): restore sourcemaps and Linux smoke discovery
Generated-By: looper 0.11.2 (runner=fixer, agent=codex)
* fix(sidecar): make payload handoff generation-atomic
* fix(sidecar): preserve packaged action and mode parity
Generated-By: looper 0.11.2 (runner=fixer, agent=codex)
* test(pack): align Linux cleanup resource count
Generated-By: looper 0.11.2 (runner=fixer, agent=codex)
* fix(packaged): preserve headless sidecar mode
* test: normalize source line endings
* fix(daemon): launch Codex cmd shims on Windows
---------
Co-authored-by: Looper <looper@noreply.github.com>
8.2 KiB
tools-pack build cache contract
This file is the source of truth for the tools-pack build-graph cache: the
cache under --cache-dir that stores packaged build artifacts as
content-addressed nodes. Read it before changing any node key, adding a node,
or changing what a node writes.
It records current state only, not change history — same convention as
specs/current/ci.md.
Out of scope: the GitHub Actions cache that wraps this store. That layer is
owned by .github/; it restores and saves the store as an opaque directory and
carries no correctness obligation (see Why coarse restore is safe below).
Cache model
A node is { id, key, outputs, build, invalidate }, acquired through
ToolPackCache (src/cache.ts).
keyHash = hash(node.id + "\n" + node.key); the entry lives atentries/<node.id>/<keyHash>/with amanifest.json.- An entry is accepted only when
manifest.key === node.keyexactly. A mismatch is reported askey mismatchand the node rebuilds (cache.ts:270-282). There is no fuzzy or prefix matching inside the store. invalidateis an additional per-node veto applied to an otherwise-valid entry (for examplewin.packaged-appre-validates its native rebuild output).materializecopies entry outputs to their workspace locations. Steps that run on the materialization path execute on both the hit and the miss path.
Why coarse restore is safe
Because acceptance is an exact node.key comparison, a restored store is a
pool of candidates, not an authority. Entries that do not match are ignored.
An outer layer may therefore restore a broader or older store than strictly
requested without risking a wrong build — it only affects how much work is
skipped, never what is produced.
This property is what the surrounding CI caching depends on. Do not weaken it by introducing prefix or best-effort matching inside the store.
Node inventory
The build-graph cache is almost entirely Windows-specific.
| Node | Platform |
|---|---|
<platform>.workspace-build |
all |
win.resource-tree |
win |
win.workspace-tarballs |
win |
win.packaged-app |
win |
win.electron-builder-dir |
win |
win.nsis-payload-base |
win |
win.nsis-payload-overlay |
win |
win.nsis-installer |
win |
win.portable-zip |
win |
win.launcher-payload-base |
win |
win.launcher-payload |
win |
mac and linux have <platform>.workspace-build only.
Determinant rules
R1 — A node key must cover every input that determines the node's output.
Inputs include file content, configuration values, tool versions, and process
environment. An input that is read by build but absent from key is a
defect, not an optimization.
R2 — A node key must carry the key of every upstream node it consumes. Re-deriving an upstream node's own inputs is not a substitute: upstream keys carry inputs that are not file content (see R3), so re-derivation silently drops them.
Existing links: win.workspace-tarballs carries workspaceBuildKey;
win.packaged-app carries tarballsKey; win.electron-builder-dir carries
packagedAppKey and resourceTreeKey; win.nsis-installer carries
basePayloadKey and overlayPayloadKey; win.launcher-payload carries
sourceKey.
R3 — Build outputs are never direct key inputs. hashPackageSourcePath
excludes dist, .next, out, node_modules, and .od. A node that
consumes another node's build output must obtain that output's identity
through R2, not by hashing the output tree.
R4 — A node key must not restate a list that already exists as a constant. Derive key inputs from the constant instead. Two independent restatements of the same list drift silently and produce stale entries with no signal.
R5 — Every declared input needs a witness. See Changing a cache node.
Materialization-time parameters
Some values deliberately do not enter node keys. They are stamped onto the output every time the node is materialized, so cached content stays parameter-agnostic and is specialized on the way out.
Current materialization-time parameters:
- App version.
win.packaged-appomits it. It is applied through electron-builderextraMetadata.version, then rewritten on materialization byrewriteUnpackedAppPackageVersionandrewriteWinExecutableVersion, then verified byassertMaterializedUnpackedVersionConsistency— a fail-closed check over the apppackage.jsonversion, theopen-design-config.jsonappVersion, and the Windows executable fixed file version. - Namespace / channel and runtime endpoints.
win.electron-builder-diromits them.open-design-config.json— which carriesnamespace,amrProfile,telemetryRelayUrl,updateMetadataUrl,posthogKey/posthogHost,webOutputMode, andnamespaceBaseRoot— is regenerated on the materialization path bywritePackagedConfig.
The downstream win.nsis-payload-overlay, win.nsis-installer,
win.portable-zip, and win.launcher-payload nodes carry namespace and the
full packagedVersion in their keys, because their content includes the
already-stamped payload. win.nsis-payload-base instead carries only
versionCore: its content excludes Open Design.exe,
resources/app/package.json, and resources/open-design-config.json, which
are assigned to the version-bearing overlay.
win.launcher-payload-base is the exception: its key carries namespace, but
version identity reaches it only indirectly through the upstream sourceKey;
the final win.launcher-payload archive explicitly carries the
version-bearing manifest and configBody.
Requirement. A value may be a materialization-time parameter only when both hold:
- it is re-applied unconditionally on the materialization path, so the hit and miss paths converge; and
- the applied value is verified by a fail-closed assertion.
Adding a materialization-time parameter without (2) is not permitted.
Known asymmetry: app version satisfies (2). The other regenerated config fields —
namespace,amrProfile,telemetryRelayUrl,updateMetadataUrl,posthogKey,posthogHost,webOutputMode,namespaceBaseRoot, and the packaged entrypoint fields — currently satisfy only (1): they are rewritten but not asserted.
Signing boundary
Signing material never enters cache content. resolveWinSigningCacheKey
(src/win/sign.ts) contributes only the certificate SHA-1, digest algorithm,
timestamp algorithm, and timestamp URL, and appears in the keys of
win.nsis-payload-overlay, win.nsis-installer, and win.portable-zip.
win.nsis-payload-base correctly omits signing: it is built before
ensureSignedUnpacked(), while the overlay is built after. Keep that ordering
when changing the payload split.
Confidence tiers
Borrowed from specs/current/ci.md.
certain— the key provably covers the node's full input closure, and a witness test demonstrates it (see below). Onlycertainnodes may participate in cross-run cache reuse policies built on top of this store.- low confidence — anything else.
Grading is fail-closed: a node is low confidence until a witness proves otherwise. A newly added node is low confidence by default.
Declared low-confidence points
Recorded so that grading stays checkable. These are known and accepted; do not extend them.
<platform>.workspace-build— file mode (executable bit) is not hashed byhashPackageSourcePath.win.launcher-payload— theseed: "nsis-base"branch takes content from the NSIS base payload but carries only the literal"nsis-base", notWIN_ARCHIVE_CACHE_VERSION. Bumping that constant without bumping the launcher payload cache versions mismatches.
Changing a cache node
- Read this file and
AGENTS.mdin this directory. - If the change alters what
buildreads or writes, update the key in the same commit. - Bump the node's
schemaVersion/ cache-version constant whenever key semantics change. - Add or update the node's witness test in
tests/. A witness proves both halves:- mutating each declared input changes the key;
- mutating a known non-input (for example a package's
disttree) leaves the key unchanged.
- Never introduce prefix or best-effort matching inside the store.