Skip to content

Safe outputs MCP server fails to start on main: setup.sh does not copy memory_schema_contract.cjs (regression from #67439) #67505

Description

@SivaKesava1

Summary

Since 92e400a (#67439, "Add declarative JSON schema validation for memory"), the safe outputs MCP server crashes on startup for every workflow whose setup action is pinned to a main commit at or after that change. The safe outputs bundle that actions/setup/setup.sh stages is missing memory_schema_contract.cjs. The server exits during module loading, registers no tools, and the agent cannot emit safe outputs.

This regression does not depend on the engine or SDK mode. It happens in Start MCP Gateway, before the agent starts.

Impact

  • Affects every workflow compiled against main since 92e400a that configures safe outputs, including current main (9e12379).
  • The setup step still reports success ("Successfully copied 138 safe-outputs files"), so the missing file only shows up when the gateway starts the server.
  • Downstream effects:
    • The agent's safeoutputs CLI commands exit with code 127.
    • Ingest agent output fails with "safeoutputs MCP gateway registered 0 tools during setup".
    • The conclusion job reports an agent failure.

Root cause

#67439 added actions/setup/js/memory_schema_contract.cjs and made two existing modules require it: memory_custom_validation.cjs and ledger_store.cjs. Both modules are listed in SAFE_OUTPUTS_FILES in actions/setup/setup.sh, but memory_schema_contract.cjs was not added to that list.

The safe outputs server runs from ${RUNNER_TEMP}/gh-aw/safeoutputs, which contains only the files in that list (plus the entry point and tool JSON). So the relative require cannot be resolved there.

Require stack from the run logs:

safe_outputs_mcp_server.cjs → safe_outputs_handlers.cjs → memory_custom_validation.cjs → ./memory_schema_contract.cjs (missing)

ledger_store.cjs, which is also in the bundle, has the same unresolved require.

Evidence

Workflow runs

All three runs are in githubnext/gh-aw-routing-sandbox. Their setup action is pinned to github/gh-aw/actions/setup@9e123795f5e522f975e08c7effb62fe8a709f4f1:

All three runs fail in the same sequence:

  1. Start MCP Gateway: the gateway (v0.4.30) health check reports github as running and safeoutputs with status error.
  2. Gateway backend stderr and mcp-logs/safeoutputs.log: the server logs Error: Cannot find module './memory_schema_contract.cjs' with the require stack shown above. The gateway then logs MCP backend connection failed: server=safeoutputs.
  3. Mount MCP servers as CLIs: tools/list returned 0 tools for 'safeoutputs' after 5 retries, then fails fast.
  4. Agent: the safeoutputs commands exit with code 127.
  5. Ingest agent output: fails with "safeoutputs MCP gateway registered 0 tools during setup".

Run 38077047915 also has an unrelated agent-step failure: the SDK driver reports "No GitHub OAuth token or Copilot HMAC key provided". That failure is out of scope for this issue. In all three runs, the safe outputs crash happens before the agent starts.

CI

The existing guard in actions/setup/js/setup_sh_file_lists.test.cjs already detects this gap. The relevant test is "setup.sh SAFE_OUTPUTS_FILES › contains all transitive local dependencies".

  • It fails on main with expected [ 'memory_schema_contract.cjs' ] to deeply equal [] in these CJS runs:
    • Run 38072203232 on the merge commit 92e400a
    • Run 38074915262 on 1118de3
  • On the PR head (74019c6), the CJS workflow run (38069547592) concluded failure without running any jobs, so this guard never ran before merge.

Local reproduction

Using a tree at 9e12379:

  • Staging only what setup.sh places in the safe outputs directory (the SAFE_OUTPUTS_FILES list, the entry point, safe_outputs_tools.json/tools.json, and an empty config.json), then loading safe_outputs_handlers.cjs and ledger_store.cjs, fails with MODULE_NOT_FOUND for ./memory_schema_contract.cjs.
  • Adding only memory_schema_contract.cjs to the staged directory lets both modules load.

Other copy steps checked

I checked every file #67439 touched under actions/setup/js against every place that stages or loads those files:

  • MCP_SCRIPTS_FILES: all transitive local requires are covered, so there is no gap.
  • Main actions directory (${RUNNER_TEMP}/gh-aw/actions): setup.sh copies every non-test .cjs and .json file there, so memory_schema_contract.cjs is present. These consumers load from that directory and are unaffected:
    • push_repo_memory.cjs
    • validate_memory_step.cjs
    • the drive-memory steps emitted by pkg/workflow/drive_memory.go
    • the ledger MCP server, which is launched from the actions directory
  • memory_schema_contract.cjs dependencies: the file has no local requires, so no other transitive files are needed.
  • memory_schema_contract.fixtures.json: only tests use it, so it does not need to be copied into the safe outputs directory.

SAFE_OUTPUTS_FILES is the only list that needs a change.

Proposed fix

Add memory_schema_contract.cjs to SAFE_OUTPUTS_FILES in actions/setup/setup.sh, next to memory_custom_validation.cjs.

No compiler changes are needed. Affected workflows pick up the fix after they are recompiled against a gh-aw ref that includes it.

Regression test

A static check for this class of bug already exists (the test named above). It caught this regression, but it never ran before merge. To prevent a repeat:

  1. Add a runtime bundle-load test next to the existing static check.

    • Stage the safe outputs directory the way setup.sh does. Preferably, run setup.sh itself against a temporary RUNNER_TEMP, so the test exercises the real copy logic instead of a parsed copy of the array.
    • In a fresh Node process, load every bundled .cjs module from that isolated directory without starting the server.
    • Fail on any MODULE_NOT_FOUND.

    On current main, this test fails with exactly the error above and passes once the file is added. Unlike the regex-based static check, it also catches local requires that are not written as a single string literal.

  2. Run the check as a blocking job for every PR that touches actions/setup/js/** or actions/setup/setup.sh. Here the CJS workflow failed on the PR before running any jobs, and the PR merged anyway.

Acceptance criteria

  • "contains all transitive local dependencies" in setup_sh_file_lists.test.cjs passes on main.
  • The new runtime bundle-load test fails without the fix and passes with it.
  • A workflow compiled against the fixed ref shows safeoutputs as running in the gateway health check and registers its tools.

Activity

  1. SivaKesava1 commented on Oct 10, 2026

    @SivaKesava1
    CollaboratorAuthor

    Fixed on main by #67506 (2b5c6d4), which adds memory_schema_contract.cjs to SAFE_OUTPUTS_FILES in actions/setup/setup.sh. The existing setup_sh_file_lists.test.cjs check now passes on main. Closing; #67508 duplicates that fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions