A collection of production-ready Effect utilities and integrations.
Namespace priorities express queue order across the shared projects. Lower numbers start first; any explicit priority precedes an unspecified priority.
| Priority | Work |
|---|---|
| 1 | effect-utils delivery |
| 2 | Smalltalk, PTY and tooling delivery |
| 3 | LiveStore delivery |
| 4 | effect-utils background |
| 5 | Smalltalk and tooling background |
| 6 | LiveStore background |
Delivery includes required-check prerequisites, main verification, releases and actual deployments. Background includes optional benchmarks, advisory reports and maintenance. A scheduled verification is still delivery. Priorities do not reserve capacity or preempt running jobs; there is no new concurrency cap.
For effect-utils, required product checks, cache contract proofs, live integrations, compiled-product publication and required Storybook play tests use 1 on both platforms. Optional Storybook previews, cold-bootstrap/GC proofs, Devenv performance, Nix closure measurements, source-shape measurements on main, measurement reports, pipeline traces, alignment notices and review-request notifications use 4. The required PR source-shape check retains delivery priority. Shapes, caches, access controls, required checks and workflow frequency are independent of these labels.
devenv tasks run lint:check:standalone-staging (included in PR lint:check)
checks nix/standalone-staging.json. Each standalone source must import only
Node builtins (with or without the node: prefix), including re-exports,
dynamic imports and require. Whole-declaration import type / export type
edges are erased and ignored. Inline-only import { type X } still resolves its
module under Node's type stripping, so it is checked as a runtime edge (even
though Bun elides it). This matches the repository's verbatimModuleSyntax
policy and the isolated Node proof. Non-literal runtime dependencies are rejected.
An explicitly rewritten
edge may name another isolation-checked source; the pnpm source-input stager uses
this for its store-path rewrite of sync-resolver.ts.
Import-form fixtures run both runtimes explicitly (NODE_BIN / BUN_BIN, or
node / bun on the task PATH), independently of the test runner's host runtime.
Each source is also imported by Node 24 from a fresh directory with no
node_modules, stripping TS types and applying only the declared store-path
rewrite. CLI entries must reach their exact declared argument-validation error;
other initialization errors fail. The native hook receives an explicit fixture
entrypoint for its resolver registration.
The inventory's extensions map is the single extension authority shared by the
Nix scanner and isolation checks. A true value permits isolated Node imports;
false keeps JSX/TSX visible to the scanner but rejects standalone entries with
an explicit unsupported-extension diagnostic instead of silently skipping them.
The completeness check scans every position in tracked and untracked, non-ignored
*.nix files for JS/TS filename references, including comments, strings,
interpolation, shell code, globs and output names. It does not parse staging
constructs. Every file containing such a reference must have a nixFiles entry:
stages: true requires at least one isolation-checked source; otherwise
noStandaloneStaging requires a one-line reason (workspace execution, deliberate
closure, fixture, build rules, or non-source names). Each listed source must still
appear as a path/reference fragment in its declared Nix file. Stale source and
file classifications fail.
This part-1 gate is deliberately file-level: a new staging inside an already
classified file, including a noStandaloneStaging file, is not detected.
Extensions assembled by computation, such as "x." + "ts", also evade the token
scan. The consumer lane in #1994 part 2 is the backstop and gates published;
this part-1 inventory guard does not replace that consumer proof.
@overeng/gh-ci-utils provides read-only
artifact inspection through the same configured GitHub authentication as its CI commands:
gh-ci-utils artifacts list 123 --repo example-org/example-repo --page 1
gh-ci-utils artifacts members 123 --repo example-org/example-repo --artifact 456
gh-ci-utils artifacts read 123 --repo example-org/example-repo --artifact 456 --member cost.json
gh-ci-utils artifacts read 123 --repo example-org/example-repo --artifact 456 --member log.txt --offset 1048576 --length 65536
gh-ci-utils artifacts read 123 --repo example-org/example-repo --artifact 456 --member log.txt --tail-bytes 65536Output is terminal-safe JSON with explicit repository, run, and artifact provenance.
The members response includes totalCount, equal to members.length (including
directory entries). Artifact names never imply a job association. Expired artifacts,
missing artifacts or members, and run mismatches fail explicitly. Member reads select
one exact portable relative path; there is no automatic extraction or binary/raw output.
Reads without window flags return the complete member with the existing output shape.
For larger text members, --length M selects the first M bytes; --offset N --length M
selects a byte range, and --tail-bytes M selects the last M bytes. Offset requires
length; tail is mutually exclusive with either offset or length. Values must be
nonnegative safe integers, and length/tail must be at most 262144 bytes (256 KiB).
Invalid selections fail with ArtifactError reason invalid-selection before download.
Windows count UTF-8 bytes, not characters or lines. Start edges advance past partial
codepoints and end edges retreat to complete codepoints; no replacement characters
are introduced. Offsets beyond EOF clamp to EOF. Zero-byte windows are valid; an
empty window inside a codepoint reports the next codepoint boundary as its offset.
Windowed content adds window: { offset, length, totalBytes } describing the actual
aligned bytes returned, while decompressedBytes remains the entire member size.
The whole selected member is still streamed and checked for CRC integrity, valid
UTF-8 and binary content, including bytes outside the window. Corruption fails with
unsafe-archive; binary or malformed UTF-8 content fails with binary-content.
Hard limits are 100 artifacts per page (pages 1–1000), 1 MiB metadata responses,
32 MiB compressed downloads, 1024 ZIP entries, 1024-byte member paths, 8 MiB
decompressed per member, and 256 KiB selected text/escaped JSON output including its
envelope and final newline. Limits apply to actual streamed bytes as well as advertised
sizes. Windowing does not increase any limit or skip full-member validation. The entire
escaped JSON document must still fit: even a valid 256 KiB window can fail with
limit-exceeded because of metadata or JSON/terminal escaping; request a smaller
window instead. Oversized output fails instead of silently truncating.
Only unencrypted stored/DEFLATE members without
ZIP64 member fields are supported. Bounded ZIP64 directory records are supported by
the maintained parser; directory/member counts, offsets and sizes are independently
bounded. Unsafe/duplicate paths, symlinks, special files, inconsistent headers,
and corrupt selected-member contents are rejected. Metadata enumeration does not
decompress members. Signed storage redirects are allowlisted and receive no GitHub
authorization header.
Full-featured Effect-native Notion API client with type-safe schema generation.
Effect-native HTTP client for the Notion API with typed queries
- Schema-aware queries - Pass Effect schemas to get fully typed results with automatic decoding
- Markdown conversion - Convert pages/blocks to Markdown with customizable transformers
- Streaming API - Auto-pagination via Effect Streams for all list operations
Comprehensive Effect schemas for all Notion API types
- Complete coverage - Schemas for all 27 block types and 21+ property types
- Property transforms -
asString,asNumber,asOptionvariants for ergonomic access - Write support - Dedicated write schemas for creating/updating pages
CLI tool to generate type-safe schemas from your Notion databases
- Schema generation - Generate typed schemas from live Notion databases
- Drift detection - Track schema changes with
diffcommand for CI/CD - API wrapper generation - Generate typed CRUD operations with
--include-api
| Package | Description |
|---|---|
| @overeng/effect-ai-claude-cli | Claude CLI provider for Effect AI |
Use your Claude Code subscription instead of paying for API calls. Implements Effect AI's LanguageModel interface by delegating to the claude CLI.
- Subscription-based - Use your existing Claude Code subscription (much cheaper than API)
- No API keys - CLI handles authentication via your subscription
- Full LanguageModel support - Works with
@effect/aiChat, generateText, etc.
Headless form library for Effect Schemas with accessible React Aria implementation.
| Package | Description |
|---|---|
| @overeng/effect-schema-form | Headless form component with schema introspection |
| @overeng/effect-schema-form-aria | Styled React Aria components with Tailwind CSS (Storybook) |
- Schema introspection - Automatically generate form fields from Effect Schema structure
- Headless architecture - Bring your own components or use pre-built React Aria implementation
- Tagged struct support - Automatic handling of discriminated unions with labeled groups
- Flexible rendering - Provider pattern, render props, or hooks API for full control
- Accessible by default - React Aria Components with WCAG compliance
React hooks and utilities for building Effect-powered applications.
| Package | Description |
|---|---|
| @overeng/effect-react | React integration for Effect runtime with hooks and context providers |
| @overeng/react-inspector | DevTools-style inspectors with Effect Schema support (Storybook) |
- EffectProvider - Initialize Effect runtime from a Layer and provide to React tree
- Hooks API -
useEffectRunner,useEffectCallback,useEffectOnMountfor running effects in components - Automatic error handling - Built-in error boundaries with custom error components
- DevTools inspectors - Browser-style object/table inspectors with Effect Schema awareness
- Type-safe runtime access - Direct access to Effect runtime for advanced use cases
@overeng/outline provides theme-free outline models and accessible
React Aria navigation. Import @overeng/outline/model for DOM-independent hierarchy normalization,
active-section selection, and fixed-pitch preview geometry.
Callers own stable section IDs, ordered measurements, the reading edge, and scrolling. An
OutlineScrollAdapter connects those measurements to getActiveSection; useOutlineRail owns hover,
focus retention, the keyboard opener, and Escape focus return. Render OutlineLink with a navigation
callback or native section hrefs. Pass the active ID from actual scroll position, not the last click.
The package supplies no theme, document discovery, domain extraction, or virtualization.
Run devenv tasks run test:outline for the focused behavioral suite. Its scoped
buck2:editor:publish:test:outline prerequisite publishes the package's Buck-owned dependency view
plus the root and OpenTelemetry bootstrap views, without materializing unrelated package views.
@overeng/otel-browser provides scoped Effect tracing and OTLP/HTTP traces and metrics for browser
applications. Compose BrowserTelemetry.layer({ identity, environment: 'dev', endpoint: '/otlp' })
with BrowserPlatform.layerWindow, using a validated ServiceIdentity from @overeng/otel-contract.
Set endpoint: undefined for the bounded, in-memory span ring without network export. The endpoint must be
same-origin; the application server owns collector relay.
Optional Interactions.layer, LongFrames.layer, and WebVitals.layer record browser performance
without coupling telemetry to a UI framework. Scoped listeners and observers are removed at shutdown.
The transport uses beacon/keepalive on page hide and drops offline exports rather than retaining
an unbounded queue. @overeng/otel-browser/vite supplies otlpDevProxy() for development and preview;
it reads OTEL_EXPORTER_OTLP_ENDPOINT and strips application cookies before collector forwarding.
DOM-free W3C propagation lives in @overeng/otel-contract/Traceparent: decode/encode validate
version-00 context, while headers, wsUrl, and withField carry the current span over HTTP,
WebSocket upgrade URLs, and messages. Server consumers use fromUrl and fromField.
The public browser adapters and imperative telemetry methods use named arguments, for example
telemetry.recordSpan({ name: 'browser.render', startMs: 10, endMs: 25 }) and
Traceparent.wsUrl({ url: new URL('/stream', location.href) }). UI histograms are defined through
schema-first OtelMetric contracts, preserving their exported metric identities and bucket policies.
| Package | Description |
|---|---|
| @overeng/utils/node/playwright | Effect-native Playwright wrappers with OTEL integration |
- Service tags -
PwPage,PwBrowserContextfor dependency injection - Structured errors - All operations wrapped with
PwOpErrorfor consistent error handling - OTEL spans - Automatic tracing with cross-process trace propagation
- Test helpers -
withTestCtxfor automatic layer provision in Playwright tests
Effect 4 bindings for authenticated peer-to-peer QUIC and schema-framed messages in Node and Bun desktop/server applications. See the package README for usage and limitations.
| Package | Description |
|---|---|
| @overeng/effect-iroh | Effect wrapper for the iroh binding |
| Package | Description |
|---|---|
| @overeng/utils | Distributed locks, log bridging, and debug utilities |
Key features:
- SharedWorker→Tab log bridging via BroadcastChannel (
@overeng/utils/browser) - Scope/finalizer debugging and active handles monitoring
- File system-backed distributed locks with TTL expiration
- Workspace-aware command helpers with optional logging/retention
| Package | Description |
|---|---|
| @overeng/genie | TypeScript-based config file generator |
| @overeng/oxc-config | Shared oxlint and oxfmt configuration |
Genie generates package.json, tsconfig.json, and GitHub workflow files from TypeScript sources (.genie.ts files). Features include:
- Type-safe config - Define configs as TypeScript with full autocomplete
- Consistent formatting - Auto-formats via oxfmt
- Read-only protection - Generated files are read-only by default
- CI integration -
--checkmode verifies files are up to date
The content-address Rust contract is compiled from its Effect schema with
devenv tasks run content-address:contract:generate. This task bootstraps the
generator's dependency view from the current standalone Buck sources before
running packages/@overeng/content-address/src/generate-contract.ts; it does not
require the contract to pass freshness first. genie:check (including the CI
freshness lane) runs content-address:contract:check, which uses that same runtime
and requires byte-identical regeneration of the committed contract and provenance.
The check restores checkout read-only permissions without rewriting any bytes.
This repo uses devenv to provide a consistent toolchain. Run commands inside the shell:
devenv shellSource-side generator freshness (genie:check) needs the root dependency view:
it directly runs buck2:editor:bootstrap for only . and packages/@overeng/otel-contract,
never whole-workspace publication. The static generator closure checker remains
self-contained. Shell entry, genie:run, and lint:fix do not publish dependency
views; explicitly regenerate and publish source-generator dependencies with:
devenv tasks run buck2:editor:materializePublish only requested consumers (JSON package paths), or omit the environment
variable to reconcile changes since origin/main. Automatic selection uses the pnpm
lockfile importer graph, including transitive workspace-dependent consumers. Global
dependency inputs or unproven ownership fail closed to the complete authority with a diagnostic.
EDITOR_VIEW_PACKAGES='["packages/@overeng/notion-core"]' devenv tasks run buck2:editor:publishThe default never substitutes a whole-workspace publication for an empty change set. Every automated consumer selects its own scoped publisher. Aggregate source-test chains preserve each package's own publication prerequisite; their shared harness publisher covers only the selected generator/module-script views, not the union of source-test packages. The full operation is manual only and currently exceeds its 300-second deadline; verification optimization is tracked in #1915:
devenv tasks run buck2:editor:publish:allEach authority/bootstrap/publication invocation has a 300-second total deadline (plus a 5-second forced-kill grace), including Buck builds, filesystem work and lock waits. A separate supervisor owns the publication session and always escalates to a group-wide kill after the grace, even if the authority already exited. Fingerprint admission closes on termination. Expiry prints a deadline diagnostic and fails nonzero; partial publication is never reported as success. This bounds shared-lane occupancy well below the 53-minute TT-148 incident. Both view preparations and fingerprint subprocesses are limited to four workers, matching the native host-wide walk cap. Only immutable Nix-store inputs are memoized, keyed by the tool and complete fingerprint arguments; mutable Buck outputs are always re-proven. Phase diagnostics are written as work advances, with phase spans on completion, failure, and SIGTERM.
devenv tasks run buck2:maintain
# Preview the same repository policy and inspect its complete receipt:
mr store buck-maintain --config ./buck-maintain.json --dry-run --jsonbuck-maintain.json contains neutral defaults for the current checkout: a soft
2 GiB output budget, 24-hour recent-output retention, and a 30-minute idle-daemon
policy. Maintenance uses native Buck clean/kill commands only; the budget is
not a hard disk limit. It does not configure daemon_idle_timeout_s.
By default only the current ST_AGENT owner is eligible, unowned worktrees are
excluded, and no seat or explicit owner configuration means report-only.
Active commands (including LSP) and live Buck clients prevent maintenance.
The legacy scripts/buck2-daemon-reaper.ts entrypoint delegates to the same
runtime; the independent reaper policy and its old flags are removed. Use
--config to configure policy and --dry-run to preview it. See
the command reference
for ownership, blackout windows, native cleanup, and the remaining client-arrival
race between final activity recheck and kill.
devenv tasks run buck2:quickPublish Buck-produced declarations to package dist directories when source-side
tools or editors need them:
devenv tasks run buck2:typescript:materialize-dist# All tests
devenv tasks run test:run
# Single package (e.g., utils, genie)
devenv tasks run test:utils
devenv tasks run test:genie
# Rust interop generator integration tests (Bun)
devenv tasks run buck2:rust:generators:test
# Integration tests (requires NOTION_API_TOKEN for Notion packages)
NOTION_API_TOKEN=secret_xxx devenv tasks run test:integration
# Watch mode
devenv tasks run test:watchThe aggregate starts test:buck2:unit after genie:check, independently of
editor dependency publication. It first prebuilds the selected Vitest collection
products from buck2-test-authority.json, then executes the selected bounded lanes
in the existing single Buck test invocation. The prebuild performs no source tests and
does not cache source reports or coverage verdicts.
After the source suites and bounded verdicts finish, test:run still invokes
the baseline-collection gate. That gate resolves the identical collection targets
with the same local-only host-platform Buck build, so current inputs are checked
even when the products are warm. It then validates the complete filesystem census,
each selected bounded lane's exact inventory, source-task ownership and baseline counts.
Missing or malformed products, coverage drift, failed bounded execution and missing
selected source evidence still fail the aggregate.
genie/ci-workflow/test-platforms.json classifies aggregate source tasks, individual
bounded Buck lanes, and every shared module shell script as Darwin-sensitive or
platform-neutral, with a rationale for each. The required macOS lane sets
EFFECT_UTILS_TEST_PLATFORM=darwin and runs only the Darwin subsets; Linux and an
unset platform run both subsets. Disjointness and completeness are enforced against
the generated Buck authority and discovered module scripts. The complete ownership
authority is retained even when collection products and baseline evidence are scoped.
Editor publication follows the selected source suites and module fixtures rather
than publishing neutral-only package views. macOS still builds and smokes the native
and compiled products to cover Darwin artifacts.
Infrastructure Bun suites outside package source roots run through source tasks
rather than buck2-test-authority.json: genie:buck2:test covers the Buck projection
suite, and buck2:rust:generators:test covers every test under buck2/rust/, including
the interop service and wasm guest packager integration tests. Both tasks participate
in test:run; the platform-neutral Rust generator suite runs in the Linux CI partition,
while the Darwin partition retains only host-sensitive suites.
Buck is the only repository-wide TypeScript check authority:
devenv tasks run buck2:quickThe shared compiler options require erasableSyntaxOnly, so package and fixture
typechecks reject TypeScript constructs requiring runtime transformation, such
as parameter properties, enums, and runtime namespaces, before merge-group
consumer tests. Source exports can therefore use Node's strip-only mode without
TypeScript lowering; unrelated runtime requirements and JSX transforms still apply.
Audit cross-cell Buck provider identity separately:
devenv tasks run buck2:providers:checkGenerated TypeScript package and root aggregate BUCK files record their projection
source, generator, schema version, semantic fingerprint, and regeneration command.
They deliberately do not enumerate the workspace-wide generator inputs: unrelated
package additions must not rewrite package-local headers. Follow the projection source
and its imports for the authoring provenance; the package projection reads the owning
repository's Genie registry to resolve workspace dependencies and nested package exclusions.
The fingerprint hashes the canonical projection data, not an enumerated list of filenames
or the bytes of every source file. Freshness is enforced independently by
devenv tasks run genie:check, which loads the generators and compares their complete
formatted output with the committed files (packages/@overeng/genie/src/core/generation.ts).
The warm genie:run task fingerprint separately covers generator sources, configured
extra input globs, generated bytes, and CLI identity in
nix/devenv-modules/tasks/shared/genie.nix; it does not parse these comments.
Buck action/cache identity continues to come from declared target inputs, dependencies,
and toolchain capabilities; no rule interprets the header as a dependency manifest or
cache key. Rules that explicitly stage a BUCK file still hash its complete bytes.
Consumers needing an always-eligible product manifest should pin ref published, not ref main; see the consumer pin contract.
mkConsumerBuckRoot accepts the named watcherPolicy argument. Its default,
"mutable-checkout", emits file_watcher = watchman and retains fail-closed
Watchman admission for interactive source edits. Roots copied into immutable
Nix builds or filtered, immutable source checks must instead pass:
watcherPolicy = "immutable-input";This emits file_watcher = fs_hash_crawler: declared inputs do not change
during the build, so no Watchman executable or service is required. The
from-source builder uses the same policy mapping. Unknown policies fail Nix
evaluation with a message listing both allowed values; raw watcher-provider
strings are not accepted.
The packaged Prelude explicitly clears RUSTC_WRAPPER and
RUSTC_WORKSPACE_WRAPPER in Reindeer build-script action environments, matching
the Rust toolchain and first-party launcher rules. A local Buck daemon started
inside a Cargo development shell must not introduce ambient sccache selection.
Compiler selection and cache identity remain owned by the declared Buck tools;
inherited sccache settings cannot activate a wrapper when these selectors are empty.
First-party and Reindeer build-script launchers also declare PATH from the
immutable Bash and coreutils capabilities. Bundled Prelude shims invoke Bash
through /usr/bin/env and use dirname/realpath; they must not depend on the
environment of whichever task first started the Buck daemon (aggregate tasks
intentionally expose only Watchman on their own PATH).
TypeScript package projections retain census destinations below nested Buck packages,
but resolve each input through its nearest owning BUCK (or BUCK.genie.ts during
generation). For example, src/main.ts below parent/src/BUCK is staged from
//parent/src:main.ts; only locally owned sources are exported by the parent.
Each nested package must publish the explicit inputs the parent consumes with
export_materialization_inputs, including test modules, snapshots and fixture data.
Its target names escape $ as __dollar__, while staged destinations stay unchanged.
This file-level contract preserves source-granular dependencies instead of introducing
a second, nested-tree materialization interface. Project and runner configuration
remain package-root files; declared projectInputs may reference nested files.
Consumer dependency generators declare the cell that exports patches from each
nested checkout instead of loading that checkout's standalone BUCK files:
renderPnpmPackageTargets({
metadata,
sidecar,
patchSourceCells: { 'repos/effect-utils': 'rules' },
})The buck2-rules package exports the shared pnpm patch registry in its rules
cell. Unmapped patch paths retain same-cell labels; mappings match complete path
components, and the most specific checkout root wins.
Frozen source dependencies use an exact workspace-path-to-target mapping rather than resolving a label beneath an ignored runtime directory:
makePnpmStoreProjection({
metadata,
sidecar,
workspaceTreeTargets: {
'.devenv/pnpm-source-inputs/current/repos/sdk/client': 'pnpm_sources//:sdk_client_package_tree',
},
})The consumer owns that declared package tree and its cell. It must expose the
frozen package bytes named by the lockfile, not a mutable checkout with the same
path suffix. A source cell rooted at .devenv/pnpm-source-inputs can keep its
generated BUCK outside the immutable current generation and assemble sources
with empty_package_view (or package_view for packages with dependencies).
The consumer's Nix source closure must supply the same cell, package bytes, and
target declarations. The root continues to ignore .devenv wholesale. Unmapped
workspace packages retain their conventional same-cell :package_tree labels;
mapped labels participate in the projection fingerprint.
Workspace link: dependencies resolve relative to their importer, or relative
to the lockfile root when pnpm emits them inside a package snapshot. Both forms
reference the same workspace importer and package tree. Links must remain inside
the repository; snapshot links must resolve to a known lockfile importer.
Directory snapshots without their own importer view get a normalized store entry
backed by their declared source tree. Their snapshot dependencies, including
workspace links, remain explicit Buck edges rather than being lost behind a
source-tree reference. Directory snapshots with an importer reuse its workspace
tree and dependency view.
Dependency-view availability is derived from the complete required resolver
context, not just a package's own platform fields. Required native dependencies
retain their edges on supported machine platforms; their owners and importer
views have no javascript_portable configuration. Generation still succeeds,
but selecting an unsupported configuration fails analysis before execution.
Optional native packages retain platform filtering. The normalized store schema
is effect-utils/buck2-pnpm-store/v2; importer platforms lists supported
configurations and variants covers only that set.
Put the effect-utils flake's pinned packages.<system>.buck2 on PATH (or use
its bin/buck2 as BUCK2_BIN). Direct commands, agents and devenv tasks then
share the same cache posture preflight; no separate task or probe command is
required:
buck2 build //your/package:targetShell activation and Buck task preparation publish the realized Nix capabilities
into a stable real .buck2/capabilities cell. Publication is process-locked,
installs immutable generation metadata first, and atomically replaces the
watched defs.bzl last. Ordinary capability changes reach already-running
daemons without a restart. The one-time cell-root symlink migration uses atomic
exchange, then explicitly runs buck2 kill for this worktree's registered
isolation directories: the symlink-to-directory transition changes native watch
topology and requires a fresh daemon. The publisher logs each stop; a persistent
migration marker makes a failed or interrupted stop retryable.
Preparation diagnostics go to stderr, preserving command stdout when callers
capture Buck output paths. The daemon regression starts and shuts down its own
private Watchman service, using a fixture-only global config that permits nice 19;
it does not depend on a host service on Linux or macOS.
The publisher fixture retains assertion failures before cleanup under
${XDG_STATE_HOME:-$HOME/.local/state}/buck2-cache-reports/capability-publisher/
and prints the private evidence directory. Each capture keeps at most five
snapshots: the new capture and the four newest prior evidence directories.
It contains the failed generation observation, copied generation metadata and
publisher JSONs, shell job IDs/PIDs/states without command text, and native PID
ancestry without command arguments or environment.
CAPABILITY_TEST_EVIDENCE_DIR overrides the destination for focused proofs.
Copies are best-effort observations while writers may still run, not an atomic
snapshot or a Nix closure archive; collection errors are recorded explicitly.
Retained generations have indirect Nix GC roots under .buck2/capability-roots.
The publisher keeps the three most recently published generations only when
Buck's state files show no live worktree daemon in any isolation directory.
Live or uncertain daemon state retains all generations; the next daemon-free
publication restores the bound. This protects even idle daemons with cached old
generation references. See the capability publication contract.
Tracked [buck2] file_watcher = watchman also opts into watcher admission, even
without remote-cache configuration. The packaged entrypoint admits the actual
Watchman service and canonical watched root with watchman --no-local watch-project <root> before native daemon startup. An attempt has a 2500 ms
deadline and one retry for a timeout only. Successful root admission is cached
for at most five seconds, scoped to the root, .watchmanconfig, PATH, HOME and
socket environment identity. Un-niced default-service queries allow Watchman
to spawn on demand on Linux and Darwin, including job-local CI runners. Niced
clients use --no-spawn: they may connect to an existing service, but never
create a permanently niced shared daemon. Only a proven-missing default
service (the silent no-spawn client plus an absent computed socket) or
Watchman's own startup refusal is diagnosed as a priority problem: start the
service un-niced with watchman get-sockname outside the gate or provision
the host service, and never relax the shared startup priority limit. Other
niced failures keep their genuine executable or service diagnosis; admission
never falls back to notify.
An explicit WATCHMAN_SOCK also uses --no-spawn on every platform: admission
must reach that owned service, not create a replacement. Missing, unhealthy or incorrectly
rooted Watchman fails with the probe command and remediation; it never selects notify as an
outage fallback. For an ancestor-root mismatch, run watchman watch <root> and
rerun the displayed probe. Enter devenv shell if Watchman is missing from PATH.
Explicit unmanaged local watcher choices take precedence and remove stale
managed watcher settings without disturbing the independent cache overlay.
In particular, immutable Nix source products select fs_hash_crawler: they have
no interactive edit loop, and Watchman's state-directory initialization is not
permitted in the Nix sandbox. Mutable worktrees retain Watchman to avoid hashing
the source tree on each command. Watchman-configured worktrees automatically
transition the selected daemon isolation after successful admission: a missing
provider marker or a changed provider stops only that worktree's registered
daemon with the native --isolation-dir <selected> kill command before startup.
The per-root/isolation marker and crash-released lock live outside Buck's
daemon directory in ~/.buck/file-watcher-admission-v1/; native startup cleans
the daemon directory, not these markers. Matching markers prevent repeated stops,
and other worktrees and isolations are never stopped. Failed stops prevent
startup and do not record successful migration. Maintenance kill, status,
and log commands bypass Watchman admission so diagnosis and shutdown remain
available during an outage.
When GATE_SLOT_CLASS is set, the packaged wrapper owns gated admission and
teardown for the selected project/isolation. On Linux it compares native
buck2 status plus /proc/<buck2d pid>/cgroup with the caller's own cgroup.
Ownership is the nearest gate-slot-*.scope ancestor of the unified cgroup
path: parent, nested action and sibling cgroups inside that scope are reused.
An idle foreign daemon is stopped before the client runs, so its replacement
and local actions inherit the job's lane limits and accounting. A daemon with
a valid unified path outside any gate scope is foreign to a known caller gate
scope. Missing unified membership or an unknown caller scope instead retains
the daemon with a warning, never guessing permission to migrate it.
A foreign daemon with active clients is retained and reused with exactly one
stderr accounting warning naming its foreign cgroup; moving or interrupting
another build/editor client is unsafe.
The selected isolation follows the pinned native CLI/environment default and
plain @file/--flagfile expansion, including nested files relative to the
invocation directory. Python/stdin argfiles, config-backed cell-path fallback
and other unresolved forms fail closed: one warning and no lifecycle status
or kill calls, rather than guessing the unrelated default v2 daemon.
Only Buck arguments before the expanded -- separator determine lifecycle
identity and help/version bypass; executable payload such as -- --help does
not bypass cleanup. Native run also accepts separator-free trailing payload,
which can contain isolation-looking options. Lifecycle resolution conservatively
supports run TARGET [-- payload] with Buck options before run; other run
forms retain daemons with the same fail-closed warning rather than guessing
where Buck options end.
An outer shell installs EXIT/INT/TERM/HUP traps and waits for its native client.
At exit it invokes native buck2 kill only when a fresh status identifies the
selected daemon and reports zero active commands, even if this invocation
started it. Busy status quietly retains the daemon; unavailable/malformed status
warns and never authorizes a kill. Cleanup preserves ordinary numeric exits;
after a wrapper INT/TERM/HUP it restores the default disposition and re-raises
the signal, so parents observe signal termination rather than an explicit
128+N exit. kill, status, and log remain diagnostic/lifecycle commands and
bypass both gated admission and teardown.
Signals already ignored on entry to Bash remain ignored as POSIX requires;
the wrapper does not override that inherited caller policy.
An injected BASH_ENV that replaces Bash's kill builtin with an external
command can instead make Bash translate its self-SIGINT into numeric exit 130
(128+N); the agent command guard is one such environment. Native signal tests
use the packaged interpreter without BASH_ENV and assert default SIGINT
disposition before delivery.
Outside gate-slot, native warm-daemon behavior and the admitted-argument fast path are unchanged. A nested wrapper inherits the outer wrapper's cleanup ownership rather than stopping the daemon beneath its caller. No daemon memory cap or separate daemon unit is installed. At the pinned Buck2 revision, resource control places actions in a daemon-owned reusable cgroup pool; the public client protocol has no per-command caller-cgroup destination. Moving the daemon alone therefore moves local build work out of gate-slot's limits, while a daemon-unit memory cap would cap compiler/test actions too.
Buck's kill RPC has no conditional-idle form. At both start (foreign idle
daemon migration) and exit (idle teardown), a new client can arrive between
the final empty-active-commands status read and buck2 kill, and be interrupted.
Wrapper exit teardown and mr store buck-maintain can both observe the same
idle daemon in that window and send duplicate native kill RPCs; native kill is
not serialized between those independent owners. Either observer can also
race a new client arriving after its last idle check. Maintenance invokes the
native executable, so it does not recursively trigger wrapper teardown.
An already observed active client is never deliberately killed. Reusing a
foreign busy daemon leaves an explicitly logged accounting gap for that
invocation, and retaining a busy daemon at exit may keep its original job scope
alive. Independent idle-daemon maintenance remains the backstop for this
conservative concurrent-client case.
The existing explicit local [buck2] file_watcher = notify choice is retained
for deliberate non-agent use, but is unsafe for agent builds: completed source
writes can race notify's unsynchronized callback buffer and produce stale
copied inputs. Agent workflows require a healthy, correctly rooted Watchman
service instead. No new notify opt-in environment variable is introduced.
Watchman output exclusions are defined by .watchmanconfig; Buck's separate
[project] ignore settings alone do not prune notify's initial registrations.
RE client settings belong in .buckconfig, not invocation overrides. Pinned
Buck ignores [buck2_re_client] values supplied by --config or --config-file.
The entrypoint applies writer credentials/endpoints to the managed
.buckconfig.local block before daemon startup. After changing client endpoints
or credentials, stop the existing daemon with buck2 kill in the same project
and isolation directory; changing config does not rebuild an existing RE client.
The checkout and mkConsumerBuckRoot set
buck2_re_client.max_total_batch_size = 3145728 (3 MiB of blob payload).
Pinned Buck2 counts payload bytes, not protobuf framing or per-blob digests,
when batching uploads. The lower threshold leaves transport headroom under
bazel-remote's 4 MiB gRPC receive limit; larger individual blobs use ByteStream
with the same bounded chunk size. A server capability value of
max_batch_total_size_bytes = 0 does not remove its gRPC message limit.
Standalone pnpm archives use native Buck download_file actions with the
canonical registry URL, reviewed SHA-256 and byte size. Buck verifies bytes and
defers materialization; warm archives need no transfer, while explicit fresh
roots still download registry bytes. Downloads do not read the RE CAS. The
private CAS and verified seeder remain optional infrastructure; there is no
runtime archive-origin selection or automatic fallback. A future mirror or CAS
read path needs a separate decision. Nix's per-digest fixed-output archives and
copy-and-verify projection are unchanged.
Public read-only jobs set
BUCK2_PUBLIC_CACHE_READ_ONLY=1; protected public publishers provide
BUCK2_CACHE_WRITE_BASIC_AUTH. A private host resolves its own
BUCK2_PRIVATE_CACHE_WRITE_AUTH=username:password credential and declares
BUCK2_PRIVATE_CACHE_ADDRESS=grpc://<private-host>:<port>. The pinned entrypoint
converts raw host credentials into BUCK2_PRIVATE_CACHE_WRITE_BASIC_AUTH;
credentials never enter config files. Do not use a publisher credential as a
host credential.
Configured REAPI roots use endpoint admission; an omitted
remote_cache_enabled follows the execution policy's enabled default.
BUCK2_NO_REMOTE_CACHE=1 disables reads and uploads, and public read-only posture
wins over either writer credential. The entrypoint probes REAPI capabilities
with a 900 ms deadline, caches endpoint outcomes for five seconds in the user's
cache directory, and emits a warning on every fail-open invocation. An
unavailable read-only REAPI endpoint selects local execution. Writers still
fail closed on REAPI outages. Outage overrides are invocation-local and do not
change tracked configuration. Archive availability does not participate in
REAPI admission.
Identical healthy read-only invocations reuse a shell fast path within the remaining probe lifetime, avoiding JavaScript startup in warm loops. Its cache key includes config contents, command arguments, working directory and exported environment; writers, config includes and external mode files bypass it.
The probe is an admission snapshot: an endpoint that disappears after a successful probe (including during its five-second cache lifetime) can still fail inside native Buck. Native Buck has no configurable RE connection retry limit or startup local-fallback switch at this pinned revision.
Only audited rules requesting the
cache_hermetic execution constraint may reuse/upload; the default platform
denies both even when root policy allows writes. The complete lane inventory and
current sandbox limits are in the execution spec.
Do not put credentials in tracked configuration.
Validate the generic and JavaScript Buck product import boundaries without realizing repository products:
devenv tasks run nix:buck2-artifact-import:check
devenv tasks run nix:javascript-product-import:checkCLI packaging uses Buck products and the validated Nix import boundary described in workspace tools. Live pnpm workspaces share install policy and source-input algebra; Buck products use immutable dependency archives.
Fixed-source Nix products use NIX_BUILD_CORES for Buck execution (build -j),
Tokio workers (build --config build.num_tokio_workers), and daemon blocking
threads (BUCK2_MAX_BLOCKING_THREADS). An unset or zero Nix budget becomes one,
not the host CPU count. Configuration overrides follow the build subcommand;
only the isolation-directory flag is global.
Local builtins.getFlake calls use git+file:// references so Nix copies only
Git-tracked sources, not ignored build outputs or development state. The shared
test runner sets NIX_FLAKE_REF to that same Git reference.
devenv tasks run lint:check:getflake checks this contract with negative fixtures;
it also runs through nix:check:quick and check:quick. For a standalone check
without shell evaluation, run node --test scripts/lint-getflake.unit.test.mjs
and node scripts/lint-getflake.mjs.
check:all also evaluates every flake output for the host system without
building anything:
devenv tasks run nix:flake:eval# Check formatting + lint
devenv tasks run lint:check
# Auto-fix formatting + lint issues
devenv tasks run lint:fixEach package follows modern ESM conventions:
- Source files in
src/(TypeScript with.tsextension) - Entry point at
src/mod.ts - Compiled output in
dist/(gitignored) - Development exports point to source files
- Published exports point to compiled JavaScript
This monorepo uses:
- bun workspaces for package management
- TypeScript project references for incremental builds
- oxlint + oxfmt for linting and formatting
- Vitest for testing
- Effect for core functionality
See individual package READMEs for package-specific documentation.