Skip to content
Merged
6 changes: 6 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ commit metadata does not. CODEOWNERS routes reviews but does not grant access.
see `docs/guides/development/contributing.md`.
- **Required local PR/push-readiness gate:** `bun run ci:preflight` (exact stages
and focused debugging commands are documented in `docs/ci.md`).
- **Eve build boundary:** web builds and hosted admin previews emit unqualified
Eve artifacts without sandbox provisioning. Production services retain full
prewarming; use `bun run --cwd packages/eve-runtime build:full` in the approved
target environment for full qualification. Follow the
[build runbook](docs/guides/development/build-runbook.md#eve-artifacts-and-qualification)
and keep Release Off until the separate launch requirements are met.
- **Production E2E:** `bun run test:e2e:production-gate` is the bounded
release gate required for `production`; broader `bun run test:e2e` remains useful
for local feature validation.
Expand Down
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,13 @@ behavior; its source-owner amendments remain proposed.

Use the per-app `dev:*` scripts when you only need one surface, or `bun run dev` / `bun run dev:all` when you need several (see root `package.json`).

`bun run build` and the `build:<app>` commands compile Eve dependency artifacts
without provisioning sandboxes. Hosted admin previews use the same unqualified
artifact mode and leave Eve Release Off. Standalone Eve and production service
builds retain full qualification; see the
[build runbook](docs/guides/development/build-runbook.md#eve-artifacts-and-qualification)
before treating any preview as launch evidence.

### AI Agent Guidance System

Agent-oriented docs live under `docs/ai/`:
Expand Down
8 changes: 7 additions & 1 deletion apps/admin/eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
import { nextjsConfig } from "@asym/eslint-config/nextjs.mjs";

export default nextjsConfig;
export default [
...nextjsConfig,
{
// withEve emits deployment bundles here, not authored app/runtime source.
ignores: [".eve/vercel-services/**", ".vercel/output/**"],
},
];
1 change: 1 addition & 0 deletions apps/admin/next.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,5 @@ const sentryConfig = withSentryConfig(

export default withEve(sentryConfig, {
eveRoot: `${WORKSPACE_ROOT}/packages/eve-runtime`,
eveBuildCommand: "bun run build:service",
Comment thread
cobmojo marked this conversation as resolved.
Resolved
Comment thread
cobmojo marked this conversation as resolved.
Resolved
});
37 changes: 36 additions & 1 deletion docs/guides/development/build-runbook.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,47 @@ This runbook defines the canonical build workflow for the Bun + Turborepo monore

Notes:

- Internal packages define `build` scripts as `tsc --noEmit` (type-check only, no JavaScript emit).
- Most shared packages define `build` as `tsc --noEmit` (type-check only). Eve
emits runtime artifacts; its qualification boundary is described below.
- Example: `bunx turbo run build --filter=@asym/ui` now executes the `@asym/ui` package build task.
- Turbo `build` caching tracks app artifacts (`.next/**`) and package/typecheck artifacts (`dist/**`, `*.tsbuildinfo`).
- Cache output globs in `turbo.json` must never be able to match a package's own `node_modules`. Use package-relative globs (`*.tsbuildinfo`, `dist/*.tsbuildinfo`), not recursive ones (`**/*.tsbuildinfo`), and keep the `"!node_modules/**"` guard in `build.outputs` / `typecheck.outputs`. See [Turbo cache restore replaces workspace symlinks](#turbo-cache-restore-replaces-workspace-symlinks).
- For troubleshooting, use Turbo filters directly: `bunx turbo run build --filter=@asym/<package>`.

## Eve artifacts and qualification

The generic web build planner sets `CORE_EVE_BUILD_MODE=artifacts` for its
children. Eve 0.25.1 then compiles with `--skip-sandbox-prewarm`; this applies to
both dependency and app phases without changing Turbo's dependency order.
Admin uses `bun run build:service` through the supported `withEve` build-command
option. This stable command selects artifact mode only when it executes on a
hosted preview. Production services retain the full SDK build, even when web
dependencies were compiled in artifact mode. The decision happens at service
execution because the SDK preserves previously generated service commands when
the same checkout builds another target.

These are **unqualified Release-Off artifacts**. They can expose the deployed
candidate for inspection, but do not prove a sandbox template exists or permit
autonomous effects. Auth, governance, policy, audit and release admission remain
unchanged. The bundled Vercel runtime refuses a missing sandbox template; preview
health or web smoke success is not sandbox qualification.

- `bun run --cwd packages/eve-runtime build` defaults to the full SDK build when
`CORE_EVE_BUILD_MODE` is unset. Unknown modes fail before the SDK starts.
- `bun run --cwd packages/eve-runtime build:artifacts` explicitly compiles only.
- `bun run --cwd packages/eve-runtime build:full` always selects the full SDK
build, including Vercel sandbox prewarming in a Vercel-targeted environment.

Turbo hashes the mode and does not cache the Eve `build` task. An artifact build
or an earlier prewarm cannot be replayed as new provider qualification. A local
non-Vercel build remains local compilation under the SDK's own behavior.

Before release, run full qualification in the correctly configured, authorized
target environment and collect the exact target-bound evidence required by the
[Eve launch runbook](../operations/eve-launch.md). Missing credentials, unavailable
governance, Release Off, or a denied prewarm remain qualification blockers. Do
not enable release to make CI pass or count artifact compilation as that proof.

## Environment profiles

## 1) Default local profile (CI-equivalent)
Expand Down
9 changes: 9 additions & 0 deletions docs/guides/operations/eve-launch.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@ Do not copy credential values into the manifest. The panel must show **Runtime
target: Configured** and **Release: Off**. If the governance state changes,
produce a new manifest against the new state version.

Hosted web previews compile Eve artifacts without sandbox prewarming so this
Release-Off inspection can occur. These outputs are unqualified: a healthy web
preview or Eve health endpoint is not proof of sandbox availability or release
readiness. Before activation, full runtime/sandbox qualification and all evidence
below are still required for the exact target. Use the full build described in
the [build runbook](../development/build-runbook.md#eve-artifacts-and-qualification);
if credentials or governance deny prewarming, report that qualification blocker.
Never activate Eve or relax its policy merely to make a build pass.

## 2. Collect launch evidence while release is off

Build one `eve-launch-manifest-v1` JSON document using the schema exported by
Expand Down
3 changes: 3 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,9 @@ const eslintConfig = defineConfig([
ignores: [
".next/**",
"**/.next/**",
// SDK-generated admin service bundles; authored Eve/app code stays linted.
"apps/admin/.eve/vercel-services/**",
"apps/admin/.vercel/output/**",
"out/**",
"**/out/**",
"build/**",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Design

The web build planner passes `CORE_EVE_BUILD_MODE=artifacts` to its child
commands while retaining Turbo's dependency graph. The Eve workspace build
dispatcher defaults to full compilation/prewarming and rejects unknown modes.
Explicit `build:artifacts` and `build:full` commands remain available.

Admin's existing `withEve` integration uses one stable `build:service` command.
That dispatcher selects artifact mode only when it executes on a hosted preview.
The SDK preserves existing generated service commands, so choosing the mode only
when generating config could carry a preview skip into a later production build.
Service execution ignores the generic web artifact variable; production and
ordinary standalone commands retain the SDK's full build. A production target
overrides a conflicting preview environment marker.

Turbo hashes the mode. The Eve build task does not cache provider qualification:
an artifact build or a prior successful prewarm cannot stand in for a fresh
required full build. All auth, governance, sandbox and release code is unchanged.

Admin's generated `.eve/vercel-services` and `.vercel/output` bundles are excluded
from authored-source linting and data-boundary scans. Regression coverage checks
the exact output paths and confirms admin app/config and Eve agent/runtime source
remain checked. Actual scanner CLI fixtures reject raw database imports in
authored admin files, neighboring `.eve`/`.vercel` files, and another app's
same-named directory; retired CRM markers in authored Eve runtime still fail.

Installed Eve 0.25.1 source shows that skipping prewarm still emits app and
workflow functions. Its bundled Vercel runtime refuses a missing template rather
than prewarming it on demand. An isolated SDK fixture verified generated service
output and health without credentials or network access. Actual Core validation
must additionally exercise the package dispatcher and generated service.

Release-Off previews are unqualified artifacts. Later full sandbox/runtime
qualification and target-bound launch evidence remain required. If governance
denies that qualification, the denial remains a blocker; this change supplies no
alternate authorization path. No API, database, migration or runtime policy
change is part of this repair.
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Separate Eve preview artifacts from runtime qualification

Tracking issue: [AL-1913](https://github.com/Asymmetric-al/core/issues/1913).

## Why

Admin preview builds traverse the Eve workspace dependency and then build the
generated `withEve` service. Both invoke sandbox prewarming, which correctly
refuses unavailable or Release-Off governance. This prevents the deployed,
Release-Off candidate required by the launch runbook from being inspected.

## What changes

- Give generic web builds an explicit Eve artifact mode and use Eve 0.25.1's
supported `--skip-sandbox-prewarm` option for hosted preview services.
- Preserve ordinary standalone and production service builds with prewarming.
- Keep artifact mode distinct in build caching and describe its unqualified
status in the build and launch runbooks.

## Scope and boundaries

This changes build orchestration only. It does not activate Eve, change any
governance/effect admission, authorize provisioning, supply credentials, or
qualify a preview for release. A passing preview is not sandbox or launch proof.

## Capability

- `eve-runtime-foundation`: separate compilation from runtime qualification.

## Rollback

Revert this focused change to restore full prewarming on web builds. The
existing fail-closed preview build failure returns; no data migration is needed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
## ADDED Requirements

### Requirement: Web Build Artifacts Are Separate From Eve Runtime Qualification

Generic web builds MUST compile their Eve dependency without provisioning a
sandbox. Hosted preview Eve services MUST support the same explicit artifact
mode. These outputs MUST be treated as unqualified Release-Off previews and MUST
NOT activate Eve, change effect admission, or satisfy sandbox/launch evidence.
Build caches MUST distinguish artifact mode and MUST NOT reuse a cached result
as full sandbox qualification. Ordinary standalone and production service builds
MUST retain the full SDK prewarm path and propagate its failures.
Authored-source verification MUST exclude only the SDK's exact generated service
and deployment output directories, while retaining checks on authored code and
same-named directories outside those paths.

#### Scenario: A Release-Off preview compiles without provisioning

- **GIVEN** the web preview requires Eve service output but release is off
- **WHEN** the web dependency and generated preview service are built
- **THEN** complete app/workflow artifacts are emitted without sandbox prewarm
- **AND** existing runtime governance continues to deny unauthorized effects
- **AND** a successful preview is not represented as full Eve qualification

#### Scenario: Full qualification remains mandatory

- **GIVEN** an artifact build succeeded without a qualified sandbox template
- **WHEN** a standalone full build or production service build runs
- **THEN** the normal SDK prewarm path still runs and any denial fails the build
- **AND** artifact or prior cache success cannot substitute for that qualification
- **AND** full runtime verification and target-bound launch evidence remain
required before any authorized release activation

#### Scenario: Generated service output is reused for another target

- **GIVEN** a checkout generated an Eve service during a preview build
- **WHEN** that service command executes for a production target
- **THEN** it selects full SDK qualification using the current target
- **AND** neither stale preview configuration nor an inherited web artifact
variable can skip prewarming

#### Scenario: Generated server bundles coexist with authored app source

- **GIVEN** the SDK emitted admin `.eve/vercel-services` or `.vercel/output` bundles
- **WHEN** lint and data-boundary verification run after the build
- **THEN** they exclude those generated bundles without classifying server dependencies as authored browser imports
- **AND** forbidden database imports or retired CRM references in authored source still fail verification
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
## 1. Reproduce and specify

- [x] 1.1 Trace the preview failure and installed SDK build/service paths.
- [x] 1.2 Verify isolated SDK artifacts without credentials or network access.
- [x] 1.3 Add failing web-planner and preview-service regression tests.

## 2. Implement and validate

- [x] 2.1 Add explicit artifact orchestration while retaining full qualification.
- [x] 2.2 Bind cache behavior to mode and document the qualification boundary.
- [x] 2.3 Pass focused tests, formatting, lint/typecheck and strict OpenSpec checks.
- [x] 2.4 Verify actual Core artifacts and full-build denial in isolation.
- [ ] 2.5 Complete independent review, canonical preflight and required preview CI.
5 changes: 4 additions & 1 deletion packages/eve-runtime/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@
"./launch-watchdog": "./src/launch/watchdog.ts"
},
"scripts": {
"build": "eve build",
"build": "node scripts/build.mjs",
"build:artifacts": "eve build --skip-sandbox-prewarm",
"build:full": "eve build",
"build:service": "node scripts/build.mjs --service",
Comment thread
cobmojo marked this conversation as resolved.
Resolved
"eval": "eve eval smoke specialists --strict --max-concurrency 1",
"info": "eve info",
"lint": "eslint agent evals src",
Expand Down
65 changes: 65 additions & 0 deletions packages/eve-runtime/scripts/build.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { spawnSync } from "node:child_process";
import { createRequire } from "node:module";
import path from "node:path";
import { fileURLToPath } from "node:url";

const require = createRequire(import.meta.url);
const EVE_BINARY = path.join(
path.dirname(require.resolve("eve/package.json")),
"bin/eve.js",
);
const PACKAGE_ROOT = fileURLToPath(new URL("..", import.meta.url));

export function runEveBuild({
environment = process.env,
args = [],
service = false,
spawn = spawnSync,
} = {}) {
// Generated Vercel service config can survive a later build in this checkout.
// Decide from the service's current target, never from a saved preview command
// or the artifact mode inherited from the generic web dependency build.
const hostedPreview =
environment.VERCEL === "1" &&
environment.VERCEL_ENV === "preview" &&
environment.VERCEL_TARGET_ENV !== "production";
Comment thread
cobmojo marked this conversation as resolved.
Resolved
const mode = service
? hostedPreview
? "artifacts"
: "full"
: (environment.CORE_EVE_BUILD_MODE ?? "full");
Comment thread
cobmojo marked this conversation as resolved.
Resolved
Comment thread
cobmojo marked this conversation as resolved.
Resolved
if (mode !== "full" && mode !== "artifacts") {
throw new Error("CORE_EVE_BUILD_MODE must be full or artifacts.");
}

const buildArgs = [EVE_BINARY, "build"];
if (mode === "artifacts") {
console.log("Eve artifact build: sandbox qualification is still required.");
buildArgs.push("--skip-sandbox-prewarm");
}
buildArgs.push(...args);
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved

const result = spawn(process.execPath, buildArgs, {
cwd: PACKAGE_ROOT,
env: environment,
shell: false,
stdio: "inherit",
});
if (result.error) throw result.error;
return result.status ?? 1;
}

if (
process.argv[1] &&
path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)
) {
try {
const args = process.argv.slice(2);
const service = args[0] === "--service";
if (service) args.shift();
process.exitCode = runEveBuild({ args, service });
} catch (error) {
console.error(error instanceof Error ? error.message : error);
process.exitCode = 1;
}
}
1 change: 1 addition & 0 deletions packages/eve-runtime/turbo.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"extends": ["//"],
"tasks": {
"build": {
"cache": false,
"outputs": []
},
"typecheck": {
Expand Down
14 changes: 8 additions & 6 deletions scripts/verify/ci-build.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,13 @@ function createRunWithCiEnvStep(label, command, args) {
}

function createBuildStep(label, command, args, { strict = false } = {}) {
// Web dependency compilation is not authorization to provision Eve sandboxes.
const env = { CORE_EVE_BUILD_MODE: "artifacts" };
if (strict) {
return { label, command, args };
return { label, command, args, env };
}

return createRunWithCiEnvStep(label, command, args);
return { ...createRunWithCiEnvStep(label, command, args), env };
}

export function getSharedPackageBuildSteps({
Expand Down Expand Up @@ -185,12 +187,12 @@ export function getRequestedApps(args = [], apps = NEXT_APPS) {
return [requestedApp];
}

function run(command, args, label) {
function run(command, args, label, environment) {
console.log(`==> CI build: ${label}`);
const result = spawnSync(command, args, {
cwd: REPO_ROOT,
stdio: "inherit",
env: process.env,
env: { ...process.env, ...environment },
});

if (result.error) {
Expand Down Expand Up @@ -315,7 +317,7 @@ function main(args = process.argv.slice(2)) {
apps: requestedApps,
})) {
clearStaleNextLocks();
run(step.command, step.args, step.label);
run(step.command, step.args, step.label, step.env);
clearStaleNextLocks();
}

Expand All @@ -327,7 +329,7 @@ function main(args = process.argv.slice(2)) {
// scripts/repair-workspace-links.mjs.
repairAndLogWorkspaceLinks();
clearStaleNextLocks();
run(step.command, step.args, step.label);
run(step.command, step.args, step.label, step.env);
clearStaleNextLocks();
}

Expand Down
Loading
Loading