Context
During PR #11615 review on head d491a50b52bfa7d298476c8f06c669f5ce33dfa2, the full GitHub unit job passed, but the focused local command for a touched script spec failed before Playwright could discover tests:
npm run test-unit -- test/playwright/unit/ai/scripts/trioWakeCooldown.spec.mjs
Observed failure:
TypeError: Neo.ns is not a function
at ../setup.mjs:73
71 |
72 | if (mockMain) {
> 73 | Neo.ns('Neo.Main', true).setRoute ??= () => {};
| ^
Error: No tests found.Duplicate sweep before filing:
ask_knowledge_base(query='standalone ai scripts specs Neo.ns is not a function setup.mjs mockMain unit test', type='ticket') surfaced #11578 as related setup provenance, but no exact ticket for this focused-run failure.
rg -n "Neo\.ns is not a function|mock main route|test/playwright/setup\.mjs|standalone ai/scripts|trioWakeCooldown|wakeSafetyGate" resources/content/issues resources/content/discussions found #11578 and related script-test history, but no exact follow-up.
gh search issues "Neo.ns is not a function" --repo neomjs/neo --state open|closed returned [].
gh search issues "trioWakeCooldown wakeSafetyGate Neo.ns" --repo neomjs/neo --state closed returned [].
The Problem
Focused unit-test execution for some test/playwright/unit/ai/scripts/*.spec.mjs files can fail at module-load time before test discovery because test/playwright/setup.mjs now calls Neo.ns(...) for the default mockMain path, while the focused spec has not imported the core augmentation that defines Neo.ns.
This hides a real verification gap:
- Reviewers following
/unit-test and /pr-review are instructed to run the specific changed test file.
- The full suite can pass because another test in the same worker ordering has already loaded the core augmentation.
- A focused command can fail with
No tests found, making it hard to distinguish a PR regression from test-harness setup debt.
The Architectural Reality
Relevant surfaces:
test/playwright/setup.mjs:72-73 default mockMain path calls Neo.ns('Neo.Main', true).
git blame -L 72,73 test/playwright/setup.mjs points to commit bcd86117de from #11578 (feat(test): mock main route and local storage in setup (#11578)).
test/playwright/unit/ai/scripts/trioWakeCooldown.spec.mjs already called setup() on origin/dev; PR #11615 only changed the test signal identity values, not the setup shape.
rg -n "setup\(|src/core/_export|Neo.ns" test/playwright/unit/ai/scripts test/playwright/setup.mjs shows multiple script specs call setup(), while only some explicitly import src/core/_export.mjs.
/unit-test currently states that Playwright unit tests must import src/core/_export.mjs because Neo.mjs alone does not include utilities like Neo.ns.
The Fix
Pick the narrowest substrate-correct repair after checking sibling patterns:
- Either make
test/playwright/setup.mjs robust when Neo.ns has not been installed yet, without masking real class-system initialization errors; or
- Add the canonical core-augmentation import to affected
test/playwright/unit/ai/scripts/*.spec.mjs files that call setup() before using setup-provided Neo.ns mocks.
The implementation should preserve #11578's mockMain/local-storage behavior while making focused spec execution deterministic.
Acceptance Criteria
Out of Scope
- Reworking the full Playwright unit-test harness.
- Changing
trioWakeCooldown.mjs runtime behavior.
- Reopening #11578; that ticket delivered the original setup mock surface, while this ticket is the focused-run regression that surfaced afterward.
Avoided Traps
- Do not rely on worker-order side effects. A focused file must pass without a prior spec importing core augmentation first.
- Do not paper over setup errors by disabling
mockMain globally. Some tests intentionally need the default route mock introduced by #11578.
- Do not broaden to all ai/scripts runtime behavior. This is a Playwright setup/import determinism issue.
Related
- Related setup provenance: #11578 / PR #11579
- Surfaced during PR review: #11615
- Unit-test rule source:
.agents/skills/unit-test/references/unit-test.md import-core-augmentation mandate
Handoff Retrieval Hints
Search for Neo.ns is not a function setup.mjs trioWakeCooldown wakeSafetyGate mockMain focused unit test.
Context
During PR #11615 review on head
d491a50b52bfa7d298476c8f06c669f5ce33dfa2, the full GitHubunitjob passed, but the focused local command for a touched script spec failed before Playwright could discover tests:npm run test-unit -- test/playwright/unit/ai/scripts/trioWakeCooldown.spec.mjsObserved failure:
TypeError: Neo.ns is not a function at ../setup.mjs:73 71 | 72 | if (mockMain) { > 73 | Neo.ns('Neo.Main', true).setRoute ??= () => {}; | ^ Error: No tests found.Duplicate sweep before filing:
ask_knowledge_base(query='standalone ai scripts specs Neo.ns is not a function setup.mjs mockMain unit test', type='ticket')surfaced #11578 as related setup provenance, but no exact ticket for this focused-run failure.rg -n "Neo\.ns is not a function|mock main route|test/playwright/setup\.mjs|standalone ai/scripts|trioWakeCooldown|wakeSafetyGate" resources/content/issues resources/content/discussionsfound #11578 and related script-test history, but no exact follow-up.gh search issues "Neo.ns is not a function" --repo neomjs/neo --state open|closedreturned[].gh search issues "trioWakeCooldown wakeSafetyGate Neo.ns" --repo neomjs/neo --state closedreturned[].The Problem
Focused unit-test execution for some
test/playwright/unit/ai/scripts/*.spec.mjsfiles can fail at module-load time before test discovery becausetest/playwright/setup.mjsnow callsNeo.ns(...)for the defaultmockMainpath, while the focused spec has not imported the core augmentation that definesNeo.ns.This hides a real verification gap:
/unit-testand/pr-revieware instructed to run the specific changed test file.No tests found, making it hard to distinguish a PR regression from test-harness setup debt.The Architectural Reality
Relevant surfaces:
test/playwright/setup.mjs:72-73defaultmockMainpath callsNeo.ns('Neo.Main', true).git blame -L 72,73 test/playwright/setup.mjspoints to commitbcd86117defrom #11578 (feat(test): mock main route and local storage in setup (#11578)).test/playwright/unit/ai/scripts/trioWakeCooldown.spec.mjsalready calledsetup()onorigin/dev; PR #11615 only changed the test signal identity values, not the setup shape.rg -n "setup\(|src/core/_export|Neo.ns" test/playwright/unit/ai/scripts test/playwright/setup.mjsshows multiple script specs callsetup(), while only some explicitly importsrc/core/_export.mjs./unit-testcurrently states that Playwright unit tests must importsrc/core/_export.mjsbecauseNeo.mjsalone does not include utilities likeNeo.ns.The Fix
Pick the narrowest substrate-correct repair after checking sibling patterns:
test/playwright/setup.mjsrobust whenNeo.nshas not been installed yet, without masking real class-system initialization errors; ortest/playwright/unit/ai/scripts/*.spec.mjsfiles that callsetup()before using setup-providedNeo.nsmocks.The implementation should preserve #11578's mockMain/local-storage behavior while making focused spec execution deterministic.
Acceptance Criteria
test/playwright/unit/ai/scripts/trioWakeCooldown.spec.mjs.test/playwright/unit/ai/scripts/wakeSafetyGate.spec.mjsor the ticket documents why that sibling is not affected after root-cause analysis.test/playwright/unit/ai/scripts/*.spec.mjsidentifies allsetup()consumers that rely onNeo.nsavailability and either fixes or explicitly excludes them.mockMainstill providesNeo.Main.setRoute, and opt-out withmockMain: falsestill works.Out of Scope
trioWakeCooldown.mjsruntime behavior.Avoided Traps
mockMainglobally. Some tests intentionally need the default route mock introduced by #11578.Related
.agents/skills/unit-test/references/unit-test.mdimport-core-augmentation mandateHandoff Retrieval Hints
Search for
Neo.ns is not a function setup.mjs trioWakeCooldown wakeSafetyGate mockMain focused unit test.