Parent
#11837 — Sub 5 of Epic #11831 (External-user configurability audit). PR #11946 shipped AC1-AC3 invariant tests + AC4 audit-time verification, but AC5 (npx-neo-app workspace safety under missing-Neo-substrate conditions) was deferred because it requires runtime workspace-spawning — too heavy for unit-test scope.
The Problem
Sub 5 AC5 requires: "running daemons from a fresh npx-neo-app workspace must not error on missing Neo-team substrate (identityRoots entries, etc.); features that require it MUST disable cleanly with a clear log."
PR #11946 verified at audit-time that the existing daemon code routes deployment-aware enable flags through resolveDeploymentEnabled / resolveCloudOnlyEnabled helpers (Orchestrator.mjs:347-351) — but did NOT exercise the fresh-workspace boot path. There's no test that proves:
- A daemon spawned in a fresh npx-neo-app workspace boots without erroring on missing
ai/graph/identityRoots.mjs entries (the SwarmHeartbeatService identity-resolver path, for example).
- Missing Neo-team-substrate features (swarm-heartbeat target resolution, etc.) downgrade gracefully with operator-visible log lines rather than throwing.
- The cloud-deployment profile (
AiConfig.orchestrator.deploymentMode: 'cloud') is the safe-default for the AC5 fresh-workspace scenario.
The Architectural Reality
External users (forks, npx-neo-app workspace consumers, cloud tenants) do NOT have:
- Pre-populated
ai/graph/identityRoots.mjs entries for Neo-team handles
- The gitignored
ai/config.mjs runtime config (only the template ships)
- Pre-existing
.neo-ai-data/ substrate directories
- Operator-specific git remote / branch setup
The Sub-5 ACs assume external users CAN run daemons with the cloud-deployment-profile default disabling Neo-team-only features. AC5 is the test that proves this assumption empirically.
The Fix
Add an integration test under test/playwright/integration/ai/daemons/ that:
- Creates a temporary fresh workspace directory mimicking npx-neo-app output (just
package.json + ai/config.template.mjs + no ai/config.mjs + empty ai/graph/identityRoots.mjs)
- Spawns the orchestrator daemon entry point (
ai/daemons/orchestrator/daemon.mjs) with NEO_AI_DEPLOYMENT_MODE=cloud
- Asserts the daemon boots without erroring within a reasonable timeout
- Inspects the log output for any features that require Neo-team substrate — verifies they emit clear "feature disabled because " log lines rather than throwing
Acceptance Criteria
Out of Scope
- AC1-AC3 invariant tests (already shipped via PR #11946 /
Orchestrator.externalConfig.spec.mjs)
- AC4 static usage trace (already documented in PR #11946 body)
- Fixing any failures the test surfaces (file as separate sub-tickets if discovered)
Authority
PR #11946 review body committed to filing this follow-up. Original Sub 5 (#11837) scope explicitly enumerated AC5 as a runtime contract.
Authored by: [Claude Opus 4.7] (Claude Code)
Parent
#11837 — Sub 5 of Epic #11831 (External-user configurability audit). PR #11946 shipped AC1-AC3 invariant tests + AC4 audit-time verification, but AC5 (npx-neo-app workspace safety under missing-Neo-substrate conditions) was deferred because it requires runtime workspace-spawning — too heavy for unit-test scope.
The Problem
Sub 5 AC5 requires: "running daemons from a fresh npx-neo-app workspace must not error on missing Neo-team substrate (identityRoots entries, etc.); features that require it MUST disable cleanly with a clear log."
PR #11946 verified at audit-time that the existing daemon code routes deployment-aware enable flags through
resolveDeploymentEnabled/resolveCloudOnlyEnabledhelpers (Orchestrator.mjs:347-351) — but did NOT exercise the fresh-workspace boot path. There's no test that proves:ai/graph/identityRoots.mjsentries (the SwarmHeartbeatService identity-resolver path, for example).AiConfig.orchestrator.deploymentMode: 'cloud') is the safe-default for the AC5 fresh-workspace scenario.The Architectural Reality
External users (forks, npx-neo-app workspace consumers, cloud tenants) do NOT have:
ai/graph/identityRoots.mjsentries for Neo-team handlesai/config.mjsruntime config (only the template ships).neo-ai-data/substrate directoriesThe Sub-5 ACs assume external users CAN run daemons with the cloud-deployment-profile default disabling Neo-team-only features. AC5 is the test that proves this assumption empirically.
The Fix
Add an integration test under
test/playwright/integration/ai/daemons/that:package.json+ai/config.template.mjs+ noai/config.mjs+ emptyai/graph/identityRoots.mjs)ai/daemons/orchestrator/daemon.mjs) withNEO_AI_DEPLOYMENT_MODE=cloudAcceptance Criteria
test/playwright/integration/ai/daemons/(or equivalent integration tier)package.json, no gitignored configs)NEO_AI_DEPLOYMENT_MODE=cloudcompletes without uncaught errorsOut of Scope
Orchestrator.externalConfig.spec.mjs)Authority
PR #11946 review body committed to filing this follow-up. Original Sub 5 (#11837) scope explicitly enumerated AC5 as a runtime contract.
Authored by: [Claude Opus 4.7] (Claude Code)