Skip to content

Workflow status is tracked in GitHub: https://github.com/emulebb/emulebb/issues/141. This local document is retained as an engineering spec/evidence record.

CI-051 - Move generated workspace outputs outside repos and worktrees

Summary

Move generated build artifacts, test artifacts, reports, logs, package staging, caches, transient profiles, runtime harness state, and release-campaign evidence out of the source workspace. The source workspace should stay focused on repos\ and managed app worktrees under workspaces\workspace\app\.

The intended shape is a single external output root owned by emulebb-build:

%EMULEBB_OUTPUT_ROOT%
  builds\
  logs\
  reports\
  artifacts\
  packages\
  release\
  cache\
  tmp\
  profiles\
  tools\

Local default should be outside EMULEBB_WORKSPACE_ROOT, for example a sibling directory such as <workspace-parent>\emulebb-output. CI should use a runner-local temporary output root and upload artifacts from there.

Current Problem

Generated output is currently concentrated under workspaces\workspace\state, but source-adjacent paths still collect build or runtime output:

  • workspaces\workspace\state\... for build logs, release state, package staging, certification, release campaigns, test reports, test artifacts, caches, tools, and transient harness profiles
  • workspaces\workspace\artifacts and workspaces\workspace\logs
  • root-level legacy state and ad hoc root logs
  • app worktree build output under srchybrid\x64 and srchybrid\ARM64
  • test repo output such as repos\emulebb-build-tests\build and legacy reports
  • tooling-local generated docs/cache output under .local

This makes cleanup expensive, obscures source/worktree dirtiness, increases path-length pressure, and makes it too easy for test evidence or package staging to be treated as workspace-owned content.

Target Contract

  • Add one output-root resolver to emulebb-build.
  • Support both EMULEBB_OUTPUT_ROOT and a CLI --output-root override.
  • Expose typed layout paths for output categories instead of reconstructing workspace_root\state in scripts.
  • Keep durable workspace topology, manifests, and app worktrees inside EMULEBB_WORKSPACE_ROOT.
  • Write generated output only under the resolved output root.
  • Keep compatibility reads for old locations during one transition window.
  • Add validation gates that fail when new generated output appears under source repos or app worktrees.

Migration Plan

1. Add One Output Root Contract

Add a resolved output root to the workspace layout/config layer:

  • EMULEBB_OUTPUT_ROOT
  • --output-root
  • default outside EMULEBB_WORKSPACE_ROOT

Expose typed roots such as:

  • layout.output_root
  • layout.output_build_root
  • layout.output_logs_root
  • layout.output_reports_root
  • layout.output_artifacts_root
  • layout.output_release_root
  • layout.output_cache_root
  • layout.output_tmp_root
  • layout.output_profiles_root
  • layout.output_tools_root

2. Preserve Workspace Manifest, Move Generated State

Keep these durable workspace files and worktrees where they are:

  • workspaces\workspace\deps.json
  • workspaces\workspace\app\...

Move generated state from:

  • workspaces\workspace\state
  • workspaces\workspace\artifacts
  • workspaces\workspace\logs
  • root-level legacy state

to the external output root.

3. Move MSBuild Outputs Out Of App Worktrees

Update emulebb-build MSBuild invocations to pass external OutDir and IntDir for routine app builds, not only release packaging:

%EMULEBB_OUTPUT_ROOT%\builds\app\<variant>\<platform>\<config>\bin\
%EMULEBB_OUTPUT_ROOT%\builds\app\<variant>\<platform>\<config>\obj\

Update harness executable resolution to consume the external build output unless an explicit --app-exe is supplied.

4. Move Test Builds And Harness Output

Move test outputs from source-adjacent paths to:

%EMULEBB_OUTPUT_ROOT%\builds\tests\...
%EMULEBB_OUTPUT_ROOT%\artifacts\tests\...
%EMULEBB_OUTPUT_ROOT%\reports\tests\...

Update emule_test_harness.paths and scripts\harness-cli-common.py so get_test_artifacts_root, get_test_reports_root, and get_test_binary_path derive from the external output root.

5. Move Release And Package Staging

Move package and release evidence from workspace_root\state to:

%EMULEBB_OUTPUT_ROOT%\packages\build
%EMULEBB_OUTPUT_ROOT%\release
%EMULEBB_OUTPUT_ROOT%\reports\release-campaigns
%EMULEBB_OUTPUT_ROOT%\reports\certification

Release package contents must remain clean and self-contained; this item only changes staging and evidence locations.

6. Move Caches And Downloaded Tool Payloads

Move cache-like and downloaded-tool paths to:

%EMULEBB_OUTPUT_ROOT%\cache\test-tools
%EMULEBB_OUTPUT_ROOT%\tools
%EMULEBB_OUTPUT_ROOT%\cache\dep-updates
%EMULEBB_OUTPUT_ROOT%\cache\tooling

Tooling .local may remain as a fallback only when no output root is available.

7. Add Compatibility Window

For one transition window:

  • read old paths if present
  • write only to new paths
  • print warnings when old workspace-local generated paths are detected
  • provide an explicit cleanup command for legacy output
  • never silently delete historical evidence

8. Add Validation Gates

Validation should fail if generated output appears under:

  • repos\**
  • workspaces\workspace\app\**
  • workspaces\workspace\state\**
  • workspaces\workspace\artifacts\**
  • workspaces\workspace\logs\**

Allow only explicit source, manifest, policy, or tracked documentation exceptions.

9. Update CI

CI should set:

EMULEBB_OUTPUT_ROOT=$RUNNER_TEMP/emulebb-output

Artifact upload paths should target:

  • $EMULEBB_OUTPUT_ROOT/reports/**
  • $EMULEBB_OUTPUT_ROOT/artifacts/**
  • $EMULEBB_OUTPUT_ROOT/logs/**
  • $EMULEBB_OUTPUT_ROOT/release/**

10. Update Documentation

Update workspace policy and developer docs to state:

  • repos\ is source only
  • workspaces\workspace\app\ is worktrees only
  • generated output belongs under EMULEBB_OUTPUT_ROOT
  • all build, test, validation, package, certification, and release-campaign commands still go through repos\emulebb-build

Scope Constraints

  • Do not move or rename app worktrees.
  • Do not move workspaces\workspace\deps.json.
  • Do not move source repos or change repo topology.
  • Do not weaken release package cleanliness checks.
  • Do not require machine-specific absolute paths in tracked docs or scripts.
  • Do not break explicit --app-exe or explicit harness --artifacts-dir overrides, but reject Windows temp paths for durable outcomes.

Acceptance Criteria

  • [ ] emulebb-build resolves a single external output root from EMULEBB_OUTPUT_ROOT, --output-root, or a safe default outside EMULEBB_WORKSPACE_ROOT.
  • [ ] Build logs, MSBuild binary logs, and build recaps write under the external output root.
  • [ ] Routine app build OutDir and IntDir write outside app worktrees.
  • [ ] Test binaries, test artifacts, and test reports write outside source repos and app worktrees.
  • [ ] Release package staging, release assets, release-campaign runs, and certification reports write under the external output root.
  • [ ] Downloaded test tools, dependency caches, and tooling caches write under external cache/tool roots.
  • [ ] CI uploads artifacts from EMULEBB_OUTPUT_ROOT paths.
  • [ ] Validation fails on new generated output under source repos, workspaces\workspace\app, or legacy workspace-local state roots.
  • [ ] Transition warnings explain legacy paths and point to an explicit cleanup command.
  • [ ] Workspace policy and developer docs describe the new output-root contract.

Validation

  • python -m pytest tests -q in repos\emulebb-build
  • python -m pytest tests\python -q in repos\emulebb-build-tests
  • python -m emule_workspace validate
  • Debug and Release x64 app builds with external output root
  • Release x64 package proof with external output root
  • One representative live E2E or smoke run with reports and artifacts published from the external output root