LearnNewsExamplesServices
Frontmatter
id17239
titleSeven build scripts cross the engine→Brain boundary into `ai/`
stateClosed
labels
enhancementairefactoringarchitecturebuild
assigneesneo-opus-vega
createdAtAug 16, 2026, 9:15 PM
updatedAtAug 22, 2026, 1:18 AM
githubUrlhttps://github.com/neomjs/neo/issues/17239
authorneo-opus-grace
commentsCount4
parentIssuenull
subIssues
17256 The engine→Brain boundary needs an enforceable guard before the nine crossings move
17272 Class B of the engine→Brain burndown: five misfiled Brain files leave `buildScripts/`
subIssuesCompleted2
subIssuesTotal2
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtAug 22, 2026, 1:18 AM

Seven build scripts cross the engine→Brain boundary into ai/

Closed Backlog/active-chunk-16 enhancementairefactoringarchitecturebuild
neo-opus-grace
neo-opus-grace commented on Aug 16, 2026, 9:15 PM

Context

Verified 2026-08-16 while measuring repository structure for #17238. neomjs/neo is the engine repository — the engine, its build pipeline, and the published neo.mjs package. ai/ is the Brain: swarm services, MCP servers, daemons. The dependency direction is one-way by design — the Brain may consume the engine; the engine must not consume the Brain.

Seven files under buildScripts/ violate that direction — nine crossings in total — corrected 2026-08-16, see the census note below. All six confirmed at the exact lines:

Class A — engine build/release tooling importing Brain services. These are genuinely engine-side concerns reaching across the boundary:

file:line imports
buildScripts/docs/index/labels.mjs:23 ../../../ai/services/github-workflow/LabelService.mjs
buildScripts/docs/rebuildContentIndexesAndSeo.mjs:10 ../../ai/services/github-workflow/shared/reconcileActiveChunks.mjs
buildScripts/release/publish.mjs:25 {GH_SyncService} from ../../ai/services.host.mjs

Class B — agent-serving scripts misfiled in an engine directory. These are not the engine reaching into the Brain; they are Brain files sitting in buildScripts/util/, and two reach ai/graph/identityRoots.mjs — the identity graph itself, deeper than any Class A target:

file:line imports
buildScripts/util/agentCoAuthorEmails.mjs:1 ../../ai/graph/identityRoots.mjs
buildScripts/util/deriveFleetRoster.mjs:4 ../../ai/graph/identityRoots.mjs
buildScripts/util/agent-preflight.mjs:8 ../../ai/scripts/setup/initServerConfigs.mjs
buildScripts/devCockpit.mjs:223,234,269 ../ai/mcp/server/shared/helpers/localBearer.mjs, ../ai/services/fleet/fleetLaunchContract.mjs — three dynamic await import(...) sites

The two classes share this ticket's AC but not its fix: Class A moves a concern (the work belongs Brain-side), Class B moves a file (the work is already Brain-side and merely misfiled). Independent corroboration that Class B is agent-serving rather than engine code: all three are already classified agent-side by an existing structural audit of engine-directory files.

⚠️ Census correction #2, 2026-08-16 (final: 7 files / 9 crossings). The count went 3 → 6 → 7. The seventh is buildScripts/devCockpit.mjs, which crosses three times via dynamic await import(...) — invisible to any from-anchored sweep, including the directory grep that produced the six. Independently re-measured with a pattern covering from/import/require, both quote styles, and dynamic form: 9 crossings, 7 files, all under buildScripts/.

src/** is clean — zero crossings, re-verified with the same comprehensive pattern. Its one apparent hit, src/worker/App.mjs:779 → import('../ai/Client.mjs'), resolves from src/worker/ to src/ai/ — the engine loading its own Neural Link socket, not a boundary crossing. src/ai/ itself imports nothing outside src/ (0 hits), so the socket carries no Brain coupling at all.

⚠️ Census correction, 2026-08-16. This ticket originally said "three exact sites" in its title and body. It was six. The original three came from an external structural review; I verified those three at their exact lines and stopped, never running a sweep of my own over the directory — I confirmed a set someone else handed me instead of enumerating the real one. Caught by @neo-opus-ada running this ticket's own AC-1 as written ("grep over the whole directory, not only the three named files") rather than as a formality. The failure mode that AC prevents, stated plainly: with "three" in the title, a reviewer checks three, finds them fixed, and approves while buildScripts/ still imports ai/ in three places — a green that means nothing.

The Problem

This is not a hypothetical layering complaint — it is the only thing making the engine's build pipeline depend on the agent OS existing.

src/** itself is clean: a grep for relative imports from src/ into ai/ or apps/ returns zero. The engine's runtime respects the boundary completely. Only its build and release tooling crosses, and it crosses into the one tree that is furthest from it.

The practical consequence is concrete rather than aesthetic: buildScripts/release/publish.mjs is the script that performs the atomic dev → main release commit. It cannot run without ai/services.host.mjs. Releasing the engine therefore requires the agent OS to be present and importable — a coupling nobody chose and nothing documents.

The same class in the opposite direction is #17237 (Neo.util.Env publishing a Brain-internal parser as public engine API). Together they suggest the boundary is eroding from both sides while src/** stays clean.

The Architectural Reality

The honest reading of what these three scripts are: they are content-sync and release plumbing, and content sync is produced by the swarm and merely rendered by the portal. rebuildContentIndexesAndSeo.mjs derives indexes over resources/content/**, which the Data Sync pipeline writes. labels.mjs pages GitHub labels. publish.mjs reaches for GH_SyncService.

None of these is engine-build work that happens to need a helper. All three are agent-side concerns sitting in an engine directory.

That points at the fix. There are two shapes and they are not equal:

  • Promote ai/services/github-workflow/** into a shared bucket — makes the import legal by redefining the boundary. Preserves the current file layout, but it means the engine's build tooling permanently depends on a shared tier that exists only to host this.
  • Move the three scripts to the Brain — makes the import legal by putting the code where its concern already lives, and lets the swarm own content sync end to end.

The second is the honest reading and the recommended shape. It also leaves the engine's build pipeline able to run with ai/ absent, which is the property that actually matters.

The Fix

Relocate the three scripts (or the concern they carry) to Brain-side ownership so that no file under buildScripts/ imports from ai/. Destination validated via structural-pre-flight at pickup — buildScripts/ai/** is the existing sibling precedent for agent-serving build tooling and is the likely home, but the choice is made against the tree, not asserted here.

The release path needs care: publish.mjs is invoked by the release workflow, so its relocation must keep the release entry point working. That is the one sequencing constraint in this ticket.

Decision Record impact

amends ADR 0004 §3.4 (updated 2026-08-21 at pickup — the original none said no ADR defines this boundary; the boundary itself has none, but ADR 0004 §3.4 RECORDS the release-cut composition this ticket changes (publish.mjs calling runFullSync in-process). The severance PR amends that section to the two-command composition; caught by @neo-gpt'''s PR #17506 round-1 RA-3.)

Acceptance Criteria

  • No file under buildScripts/ imports from ai/ — verified by grep over the whole directory, not only the six named files. This AC is the one that found the undercount; run it as a sweep, never as a spot-check of the table above.
  • The three concerns retain their behavior; the docs/index, content-index/SEO, and release paths all still run from their entry points.
  • buildScripts/release/publish.mjs's replacement is reachable from the release workflow, and the workflow is updated in the same PR if its path changed.
  • The engine's build pipeline is demonstrated to run with ai/ unavailable — the property this ticket exists to restore. A mutation control: the check fails if the import is reintroduced.
  • Destination recorded on this ticket, with the sibling precedent that justified it.

Out of Scope

  • The reverse-direction violation (#17237) — same boundary, separate owner, separate fix.
  • Any repository split. This ticket is worth landing whether or not any extraction ever happens; it is a precondition, not a consequence.
  • Redefining the engine↔Brain contract in an ADR.

Avoided Traps

  • Making the import legal by widening the boundary. A shared bucket that exists solely to legalize three imports moves the violation into the definitions rather than removing it.
  • Treating this as cosmetic. The falsifiable consequence is that engine release tooling cannot run without the agent OS. That is checkable, and it is the AC.

Related

#17237 (same boundary, opposite direction) · #17238 (repository structure; this is a precondition for any extraction) · ADR 0029

Live latest-open sweep: latest 20 open issues checked 2026-08-16T19:14:37Z; no equivalent. A2A in-flight claim sweep: 30 most recent messages, newest 2026-08-16T14:10Z; no claim on this scope. Structure-map gate: npm run --silent ai:structure-map -- --files --loc executed this session.

Origin Session ID: b17338dd-b474-494f-b08c-683044de2ddb Retrieval Hint: "engine buildScripts import ai/services directional boundary violation publish.mjs"

tobiu referenced in commit eace3d1 - "feat(build): the engine → Brain boundary becomes enforceable, nine crossings baselined (#17257) on Aug 17, 2026, 10:35 AM
tobiu referenced in commit 7aed270 - "chore(ai): the misfiled Brain files leave the engine directory (#17239) (#17273) on Aug 17, 2026, 11:14 AM
tobiu referenced in commit 2e67c4d - "fix: the engine's build pipeline runs with the Brain absent (#17239) (#17506) on Aug 22, 2026, 1:18 AM
tobiu closed this issue on Aug 22, 2026, 1:18 AM