修复 AGC 确定性 E2E 与 master 合并后的运行链路
Project CI / Backend tests (pull_request) Failing after 11s
Project CI / Frontend tests (pull_request) Successful in 2m59s
Project CI / Repository checks (pull_request) Failing after 21s
Project CI / Native shell tests (pull_request) Failing after 16m26s

合并 master 后 isolated AppData 配置改为私有副本,避免 Windows 安全校验拒绝硬链接。
只读 runner 状态命令显式配置 config dir,避免误读为 runner 未启用。
为 debug 构建增加仅 E2E 显式开启的确定性 Provider 路由开关,并补充回归测试。
兼容 Windows 对私有副本权限位的校验差异。
This commit is contained in:
2026-09-03 15:59:19 +08:00
parent f86a1320f6
commit e34d797336
5 changed files with 43 additions and 9 deletions
@@ -1948,6 +1948,7 @@ async function runE2e(options) {
...process.env,
NO_COLOR: '1',
[platformSessionFixtureEnv]: fixturePath,
GENARRATIVE_AGC_DEBUG_PROVIDER_E2E: '1',
}),
);
childReport = parseChildReport(childResult);
@@ -773,7 +773,8 @@ export async function prepareIsolatedSuiteAppData({
isScopedAgentsSuite() ||
isProjectSkillSuite() ||
isParallelReadSuite() ||
isSupervisorSwarmSuite()
isSupervisorSwarmSuite() ||
isSupervisorAutonomousPlayableLaneDefenseSuite()
? 'private-copy'
: 'hardlink';
try {
@@ -796,7 +797,7 @@ export async function prepareIsolatedSuiteAppData({
storageMode === 'private-copy' &&
(linkedMetadata.dev !== source.metadata.dev ||
linkedMetadata.ino !== source.metadata.ino) &&
(linkedMetadata.mode & 0o077) === 0;
(process.platform === 'win32' || (linkedMetadata.mode & 0o077) === 0);
const hardlinkValid =
storageMode === 'hardlink' &&
linkedMetadata.dev === source.metadata.dev &&
@@ -1976,7 +1977,7 @@ export async function verifyIsolatedSuiteConfigLinksUnchanged() {
linkedMetadata.ino === link.linkedIno &&
(linkedMetadata.dev !== sourceMetadata.dev ||
linkedMetadata.ino !== sourceMetadata.ino) &&
(linkedMetadata.mode & 0o077) === 0
(process.platform === 'win32' || (linkedMetadata.mode & 0o077) === 0)
: linkedMetadata.dev === link.dev && linkedMetadata.ino === link.ino;
const sourceMetadataStable =
sourceMetadata.mode === link.sourceMode &&
@@ -3446,18 +3446,33 @@ pub(crate) fn migrate_legacy_game_creator_agent_mode(path: &Path) -> Result<(),
/// Returns whether a real AGC build must use the authenticated API Server
/// proxy instead of any persisted provider credentials.
///
/// Debug and release binaries intentionally share this decision. The only
/// exception is the Rust unit-test build, where existing tests may install an
/// explicit loopback provider fixture; that fixture is never compiled into a
/// shipped binary and is not a runtime fallback.
/// Debug and release binaries intentionally share this decision. The two
/// exceptions are the Rust unit-test build and the explicitly env-gated debug
/// deterministic-provider E2E; their loopback fixtures are never compiled into
/// or enabled inside a shipped release binary.
pub(crate) fn game_creator_official_llm_route_locked() -> bool {
game_creator_official_llm_route_locked_for_build(cfg!(test))
!debug_provider_e2e_route_unlocked()
&& game_creator_official_llm_route_locked_for_build(cfg!(test))
}
pub(crate) fn game_creator_official_llm_route_locked_for_build(is_test_build: bool) -> bool {
!is_test_build
}
fn debug_provider_e2e_route_unlocked() -> bool {
debug_provider_e2e_route_unlocked_for_build(
cfg!(debug_assertions),
std::env::var_os("GENARRATIVE_AGC_DEBUG_PROVIDER_E2E").as_deref(),
)
}
pub(crate) fn debug_provider_e2e_route_unlocked_for_build(
debug_assertions: bool,
value: Option<&std::ffi::OsStr>,
) -> bool {
debug_assertions && value == Some(std::ffi::OsStr::new("1"))
}
pub(crate) fn lock_game_creator_app_config_to_official_route(config: &mut GameCreatorAppConfig) {
if !game_creator_official_llm_route_locked() {
return;
@@ -2316,7 +2316,7 @@ fn main() {
app_log!("agent.runner.failed: {error}");
std::process::exit(1);
}
if command.requires_external_agent_runner() {
if command.requires_external_agent_runner() || command.is_read_only_status() {
let configured = if command.is_read_only_status() {
configure_external_agent_runner_read_only(&config_dir)
} else {
@@ -330,6 +330,23 @@ fn official_llm_route_is_locked_for_debug_and_release_platform_builds() {
assert!(!game_creator_official_llm_route_locked_for_build(true));
}
#[test]
fn debug_provider_e2e_flag_only_unlocks_debug_platform_build() {
assert!(debug_provider_e2e_route_unlocked_for_build(
true,
Some(std::ffi::OsStr::new("1"))
));
assert!(!debug_provider_e2e_route_unlocked_for_build(
false,
Some(std::ffi::OsStr::new("1"))
));
assert!(!debug_provider_e2e_route_unlocked_for_build(
true,
Some(std::ffi::OsStr::new("0"))
));
assert!(!debug_provider_e2e_route_unlocked_for_build(true, None));
}
#[test]
fn codex_app_server_requires_responses_route_and_disables_native_web_search() {
let mut llm = GameCreatorLlmConfig::default();