LearnNewsExamplesServices
Frontmatter
id16988
titleA dangling ai/deploy/.env symlink makes the unit suite report a false red
stateClosed
labels
bugaitesting
assigneesneo-opus-ada
createdAtAug 11, 2026, 5:35 PM
updatedAtAug 11, 2026, 6:37 PM
githubUrlhttps://github.com/neomjs/neo/issues/16988
authorneo-opus-ada
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtAug 11, 2026, 6:37 PM

A dangling ai/deploy/.env symlink makes the unit suite report a false red

Closed Backlog/active-chunk-15 bugaitesting
neo-opus-ada
neo-opus-ada commented on Aug 11, 2026, 5:35 PM

Context

Surfaced while answering the operator's question of whether dev was red after five merges landed inside ~15 minutes. A full unit run against dev HEAD (10a29b1a79) reported 12856 passed, 1 failed — and the one failure was an artifact of the machine, not of dev.

Live latest-open sweep at 2026-08-11T15:3xZ: checked open issues matching false.red|flake|symlink|prescription|\.env; only #16676 matched and it is a different subject (prescription routing, not the test's file handling). No A2A claim on this scope.

The Problem

deploymentPrescriptionEnvironment.spec.mjs"the rendered file changes what the container is CREATED with" — writes ai/deploy/.env, preserving any existing content:

existed = fs.existsSync(envPath),
backup  = existed ? fs.readFileSync(envPath, 'utf8') : null;
…
fs.writeFileSync(envPath, content);

The deployment-prescription workflow links that path at a per-operator store outside the repo (~/.neo-ai/deployment-prescriptions/active.env). A machine that has run it once carries the symlink whether or not the target survives.

fs.existsSync follows symlinks. So a dangling link reads as absent, which defeats the preserve-and-restore on its own terms: the test records "nothing to back up", then writes through a link that resolves nowhere and fails:

Error: ENOENT: no such file or directory, open '<repo>/ai/deploy/.env'

The failure names the repo path, so it reads as a broken suite rather than a broken link. ai/deploy/.env is untracked and gitignored (.gitignore:113), so CI never carries it — the red is unreproducible anywhere but the affected machine, which is what makes it expensive: it cost a full-suite run plus a tracked-vs-untracked check to attribute, during an incident where the operator had just merged overruling what CI appeared to be saying.

A test that cannot distinguish "this machine cannot host me" from "the code is wrong" makes CI unreadable exactly when reading it matters.

The Architectural Reality

  • test/playwright/unit/ai/services/memory-core/helpers/deploymentPrescriptionEnvironment.spec.mjs — owns the write and its restore.
  • The file already models environment preconditions correctly one line above, via test.skip(!composeConfigAvailable(), …). The shape exists; the symlink case is simply not covered by it.
  • fs.lstatSync is the distinction that resolves it: it describes the link, never its target.

The Fix

Treat a dangling prescription symlink as an environment precondition, the same class as the absent Docker CLI already handled beside it — skip with a reason that names the machine state, rather than failing and blaming the suite.

Acceptance Criteria

  • A dangling ai/deploy/.env symlink skips the write test with a message naming the missing prescription store.
  • A real .env file still runs the test and is preserved and restored byte-for-byte.
  • An absent .env path still runs the test — a clean CI checkout must not be skipped, or the skip would mask real regressions.
  • The predicate is proven non-vacuous across all three states.

Out of Scope

  • The prescription workflow's own symlink lifecycle, and whether a vanished store should be re-created (that is deployment-side, not test-side).
  • The queued/cancelled Tests runs on dev — separate cause, GitHub-side, not this.

Decision Record impact

none — test-environment precondition handling; no production surface, no authority boundary.

Authored by @neo-opus-ada (Ada).

tobiu referenced in commit 728dab1 - "test(deploy): a dangling prescription symlink skips instead of false-failing (#16988) (#16989)" on Aug 11, 2026, 6:37 PM
tobiu closed this issue on Aug 11, 2026, 6:37 PM