[!IMPORTANT]
[PROVISIONAL_UNGRADUATED: D#17886]
Implementation is paused. Continued physical-consumer measurement changed this ticket's root premise twice; Discussion #17886 now owns divergence and the public path contract. This ticket is the reserved implementation landing pad only after graduation.
Context
Neo applications need to find one public workspace/mount root, then resolve applications, Main, workers, themes, resources, and package assets beneath or relative to it. Current configuration exposes basePath, appPath, mainPath, and workerBasePath, but merged source uses five different anchors to interpret them.
The latest deployment evidence resolves an earlier false dichotomy in this body: the application mount and public workspace root coincide by construction in the measured deployment because the whole workspace is served at <mount>/. The direct /apps/<app>/ route is a development convenience where they diverge. The defect is therefore not yet proven to require a second configurable root. The open fork is whether to formalize and normalize existing basePath, add a distinct workspace URL, retain owner-relative paths, use explicit per-surface URLs, or generate a manifest.
Evidence was gathered on merged dev at df05ec3854 from source, build output, historical issues, and peer-trusted physical-consumer traces. The consumer identity is private; only redacted topology and URLs appear here.
Five Measured Resolution Families
| Surface |
Current derivation |
Source coordinate |
Observed result |
| Source-mode theme CSS |
document URL after basePath.substring(6) plus ../../dist/<environment>/ |
src/main/addon/Stylesheet.mjs:72-89, :99-105 |
direct route requests /apps/dist/development/css/**; mounted route happens to request /dist/development/css/** |
| Worker entries |
workerBasePath + fileName from page config |
src/worker/Manager.mjs:236-243 |
works when config already carries the mount-aware worker URL |
| Application entry |
App-worker module URL plus hard-coded ../../${appPath} |
src/worker/App.mjs:378-388 |
external generators compensate with parent segments tied to package depth |
| Main entry |
MicroLoader.mjs module URL plus free-form mainPath |
src/MicroLoader.mjs:1-4; appworker generator :73-78 |
copied loader at <mount>/src/ plus baked ../main.js requests <mount>/main.js, losing dist/development/ |
| Bundled theme CSS |
document URL after deleting six characters from basePath |
Stylesheet.mjs:52-55, :77-78, :103-105 |
absolute mount is truncated into a tail such as udio/; Font Awesome and five global sheets 404, leaving a live App worker behind a black page |
The fifth specimen proves the severity boundary: bundled Main and all three core workers load from the dist tree, then stylesheet loading alone prevents the shell from mounting.
Source-of-Authority Conflict
learn/guides/advanced/BuildArchitecture.md defines basePath as the physical depth from an application folder back to project root and shows it changing after relocation into dist/<environment>/.
src/DefaultConfig.mjs documents basePath as the path to the Neo.mjs directory, which is not the same thing for an installed consumer.
- Dist appworker configs generate
basePath, mainPath, and workerBasePath independently from output depth.
src/MicroLoader.mjs imports mainPath relative to its own module URL; source and copied consumer loaders can therefore give the same config different meaning.
This conflict is why the previous body's proposed workspaceBasePath is withdrawn rather than implemented.
Provisional Contract Ledger
| Target Surface |
Current Authority |
Unresolved Contract Fork |
Graduation Evidence |
Neo.config.basePath |
DefaultConfig; app configs; build generators |
formalize as public workspace root vs. preserve legacy/package meaning behind a new workspace URL |
compatibility census + exact URL matrix |
Neo.config.appPath |
App worker; app generators |
workspace-root logical identity vs. worker-relative path/absolute override |
native + bundled app load at shallow/nested depths |
Neo.config.mainPath / MicroLoader |
loader module URL; build generators |
workspace-root logical identity vs. explicitly loader-relative path |
copied/source loader matrix; red control dropping environment segment |
Neo.config.workerBasePath |
Main-thread Worker creation |
derived workspace path vs. explicit per-realm override |
worker URLs in dedicated/shared modes |
| theme/resource URLs |
Stylesheet; createStyleSheet; environment branches |
root + environment asset identity vs. generated manifest/per-surface URL |
global/class/Font Awesome 200s in all environments |
| app/dist generators |
app creation + appworker webpack configs |
emit invariant logical identities vs. environment-relative physical paths |
generated-config read-back tests |
dist/esm config generation |
buildScripts/build/esmodules.mjs#minifyFile |
preserve absolute basePath without parent-prefixing; derive workerBasePath for the ESM output tree rather than the source mount |
physical generated-config read-back + worker URL requests (DC_kwDODSospM4BFeP2) |
dist/esm installed-package import transform |
buildScripts/build/esmodules.mjs#regexImport; app scaffold output |
rewrite installed-package specifiers for every emitted quote form, or replace regex ownership with an AST transform; no compatibility dist/esm/node_modules tree |
scaffold single-quote control reaches /dist/esm/node_modules/neo.mjs/** 404 only after config isolation (DC_kwDODSospM4BFeP2) |
Newly Measured ESM Prerequisites — Owned Here, Still Provisional
The physical four-environment fixture in D#17886 found two independent dist/esm build-output defects at dev@f1d3ed2840:
- An absolute source
basePath: '/mount/' becomes ../..//mount/, while generated workerBasePath becomes /mount/src/worker/ and drops the dist/esm output segment. Main loads, but App/Data/VDom worker URLs 404.
- After a served-config-only isolation fixes those URLs, scaffolded single-quoted imports still point at
../../../node_modules/neo.mjs/src/**. The ESM build flattens Engine modules to dist/esm/src/**, but regexImport matches only double quotes/backticks, so the first View dependency 404s beneath dist/esm/node_modules/neo.mjs/**.
These are prerequisites of this ticket’s all-environment URL contract, not separate shadow work and not gate-6 path-derivation controls. They remain provisional until D#17886 graduates and the ADR + full Contract Ledger are rewritten together. The positive fixture must repair them; compatibility symlinks would invalidate the evidence.
Evidence: DC_kwDODSospM4BFeP2; peer separation/custody audit DC_kwDODSospM4BFeQF.
Code-Ready Gate
Eventual Runtime Evidence Floor
Decision Record impact
REQUIRED — this changes or formally defines the public cross-environment path contract.
Out of Scope
- Reorganizing a consumer repository or its server.
- Data/Canvas/Task bundle reach; that architecture continues in D#1881.
- Changing Webpack
publicPath: 'auto' without a graduated option requiring it.
- Consumer-local loader patches before the Engine contract settles.
Related
Related: D#17886, #9586, #6725, #3173, #2180, #1876, #15383
Origin Session ID: a63227a3-7e65-4384-ba2c-89a2fb98ec7b
Retrieval Hint: five path anchors basePath mainPath workerBasePath appPath Stylesheet substring absolute mount
Update 2026-08-31: Folded the two measured dist/esm generator defects into this provisional landing pad so D#17886 is not their shadow tracker. No implementation authorization or graduation claim; ADR + complete ledger rewrite remain gated.
Context
Neo applications need to find one public workspace/mount root, then resolve applications, Main, workers, themes, resources, and package assets beneath or relative to it. Current configuration exposes
basePath,appPath,mainPath, andworkerBasePath, but merged source uses five different anchors to interpret them.The latest deployment evidence resolves an earlier false dichotomy in this body: the application mount and public workspace root coincide by construction in the measured deployment because the whole workspace is served at
<mount>/. The direct/apps/<app>/route is a development convenience where they diverge. The defect is therefore not yet proven to require a second configurable root. The open fork is whether to formalize and normalize existingbasePath, add a distinct workspace URL, retain owner-relative paths, use explicit per-surface URLs, or generate a manifest.Evidence was gathered on merged
devatdf05ec3854from source, build output, historical issues, and peer-trusted physical-consumer traces. The consumer identity is private; only redacted topology and URLs appear here.Five Measured Resolution Families
basePath.substring(6)plus../../dist/<environment>/src/main/addon/Stylesheet.mjs:72-89,:99-105/apps/dist/development/css/**; mounted route happens to request/dist/development/css/**workerBasePath + fileNamefrom page configsrc/worker/Manager.mjs:236-243../../${appPath}src/worker/App.mjs:378-388MicroLoader.mjsmodule URL plus free-formmainPathsrc/MicroLoader.mjs:1-4; appworker generator:73-78<mount>/src/plus baked../main.jsrequests<mount>/main.js, losingdist/development/basePathStylesheet.mjs:52-55,:77-78,:103-105udio/; Font Awesome and five global sheets 404, leaving a live App worker behind a black pageThe fifth specimen proves the severity boundary: bundled Main and all three core workers load from the dist tree, then stylesheet loading alone prevents the shell from mounting.
Source-of-Authority Conflict
learn/guides/advanced/BuildArchitecture.mddefinesbasePathas the physical depth from an application folder back to project root and shows it changing after relocation intodist/<environment>/.src/DefaultConfig.mjsdocumentsbasePathas the path to the Neo.mjs directory, which is not the same thing for an installed consumer.basePath,mainPath, andworkerBasePathindependently from output depth.src/MicroLoader.mjsimportsmainPathrelative to its own module URL; source and copied consumer loaders can therefore give the same config different meaning.This conflict is why the previous body's proposed
workspaceBasePathis withdrawn rather than implemented.Provisional Contract Ledger
Neo.config.basePathDefaultConfig; app configs; build generatorsNeo.config.appPathNeo.config.mainPath/MicroLoaderNeo.config.workerBasePathStylesheet;createStyleSheet; environment branchesdist/esmconfig generationbuildScripts/build/esmodules.mjs#minifyFilebasePathwithout parent-prefixing; deriveworkerBasePathfor the ESM output tree rather than the source mountDC_kwDODSospM4BFeP2)dist/esminstalled-package import transformbuildScripts/build/esmodules.mjs#regexImport; app scaffold outputdist/esm/node_modulestree/dist/esm/node_modules/neo.mjs/**404 only after config isolation (DC_kwDODSospM4BFeP2)Newly Measured ESM Prerequisites — Owned Here, Still Provisional
The physical four-environment fixture in D#17886 found two independent
dist/esmbuild-output defects atdev@f1d3ed2840:basePath: '/mount/'becomes../..//mount/, while generatedworkerBasePathbecomes/mount/src/worker/and drops thedist/esmoutput segment. Main loads, but App/Data/VDom worker URLs 404.../../../node_modules/neo.mjs/src/**. The ESM build flattens Engine modules todist/esm/src/**, butregexImportmatches only double quotes/backticks, so the first View dependency 404s beneathdist/esm/node_modules/neo.mjs/**.These are prerequisites of this ticket’s all-environment URL contract, not separate shadow work and not gate-6 path-derivation controls. They remain provisional until D#17886 graduates and the ADR + full Contract Ledger are rewritten together. The positive fixture must repair them; compatibility symlinks would invalidate the evidence.
Evidence:
DC_kwDODSospM4BFeP2; peer separation/custody auditDC_kwDODSospM4BFeQF.Code-Ready Gate
[DIVERGENCE_FOLDED @ <comment-id>].STEP_BACKsweep.[PROVISIONAL_UNGRADUATED]marker is removed only after graduation.Eventual Runtime Evidence Floor
/belongs to another application.development,dist/esm,dist/development, anddist/production.appPathvalues receive explicit bounded migration behavior.undefinedpromise rejections.Decision Record impact
REQUIRED— this changes or formally defines the public cross-environment path contract.Out of Scope
publicPath: 'auto'without a graduated option requiring it.Related
Related: D#17886, #9586, #6725, #3173, #2180, #1876, #15383
Origin Session ID:
a63227a3-7e65-4384-ba2c-89a2fb98ec7bRetrieval Hint:
five path anchors basePath mainPath workerBasePath appPath Stylesheet substring absolute mount