Move model alias/multiplier propagation from step env to activation artifact file#34837
Move model alias/multiplier propagation from step env to activation artifact file#34837Copilot wants to merge 12 commits into
Conversation
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
|
🧪 Test Quality Sentinel completed test quality analysis. |
|
✅ PR Code Quality Reviewer completed the code quality review. |
|
✅ Design Decision Gate 🏗️ completed the design decision gate check. No ADR enforcement needed: PR #34837 does not have the 'implementation' label and has only 10 new lines (≤100) in default business logic directories. |
|
🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅ |
There was a problem hiding this comment.
Pull request overview
This PR moves model alias/multiplier propagation from step environment variables to a file-based flow rooted in the activation artifact, reducing compiled log/env churn and making downstream jobs read a consistent materialized payload from disk.
Changes:
- Activation job now writes
/tmp/gh-aw/model_multipliers.json(built-in multipliers merged withGH_AW_INFO_TOKEN_WEIGHTS) and uploads it in the activation artifact. - Runtime ET logic (
effective_tokens.cjs) now resolves multipliers in order: merged file →GH_AW_MODEL_MULTIPLIERSenv fallback → built-inmodel_multipliers.json. - Setup no longer exports the large
GH_AW_MODEL_MULTIPLIERSJSON intoGITHUB_ENV; tests and golden fixtures are updated accordingly.
Show a summary per file
| File | Description |
|---|---|
| pkg/workflow/compiler_activation_job_builder.go | Upload activation artifact now includes /tmp/gh-aw/model_multipliers.json. |
| actions/setup/setup.sh | Removes exporting GH_AW_MODEL_MULTIPLIERS into job env. |
| actions/setup/js/generate_aw_info.cjs | Writes merged multipliers file into /tmp/gh-aw/ during activation. |
| actions/setup/js/generate_aw_info.test.cjs | Adds coverage for merged multipliers file creation and override merge behavior. |
| actions/setup/js/effective_tokens.cjs | Adds file/env/built-in precedence for multipliers resolution. |
| actions/setup/js/effective_tokens.test.cjs | Updates tests to reflect new precedence (including built-in fallback). |
| actions/setup/js/parse_mcp_gateway_log.cjs | Updates doc comment for ET multiplier data source. |
| pkg/workflow/testdata/TestWasmGolden_CompileFixtures/with-imports.golden | Golden updated to include the new artifact path. |
| pkg/workflow/testdata/TestWasmGolden_CompileFixtures/smoke-copilot.golden | Golden updated to include the new artifact path. |
| pkg/workflow/testdata/TestWasmGolden_CompileFixtures/playwright-cli-mode.golden | Golden updated to include the new artifact path. |
| pkg/workflow/testdata/TestWasmGolden_CompileFixtures/basic-copilot.golden | Golden updated to include the new artifact path. |
| pkg/workflow/testdata/TestWasmGolden_AllEngines/pi.golden | Golden updated to include the new artifact path. |
| pkg/workflow/testdata/TestWasmGolden_AllEngines/gemini.golden | Golden updated to include the new artifact path. |
| pkg/workflow/testdata/TestWasmGolden_AllEngines/copilot.golden | Golden updated to include the new artifact path. |
| pkg/workflow/testdata/TestWasmGolden_AllEngines/codex.golden | Golden updated to include the new artifact path. |
| pkg/workflow/testdata/TestWasmGolden_AllEngines/claude.golden | Golden updated to include the new artifact path. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 16/16 changed files
- Comments generated: 3
| if (Object.prototype.hasOwnProperty.call(process.env, "GH_AW_MODEL_MULTIPLIERS")) { | ||
| const raw = process.env.GH_AW_MODEL_MULTIPLIERS; | ||
| if (raw && raw.trim()) { | ||
| const parsedFromEnv = parseMultipliersJSON(raw); | ||
| if (parsedFromEnv) { | ||
| _parsedMultipliers = parsedFromEnv; | ||
| return _parsedMultipliers; | ||
| } | ||
| } | ||
| _parsedMultipliers = null; | ||
| return null; | ||
| } |
| beforeEach(() => { | ||
| _resetCache(); | ||
| if (fs.existsSync(MERGED_MULTIPLIERS_PATH)) { | ||
| fs.unlinkSync(MERGED_MULTIPLIERS_PATH); | ||
| } |
| * Parses token-usage.jsonl content and returns an aggregated summary. | ||
| * Computes effective tokens (ET) per model using the GH_AW_MODEL_MULTIPLIERS env var. | ||
| * Computes effective tokens (ET) per model using merged/built-in model multipliers data. | ||
| * @param {string} jsonlContent - The token-usage.jsonl file content |
🧪 Test Quality Sentinel Report✅ Test Quality Score: 90/100 — Excellent
📊 Metrics & Test Classification (3 tests analyzed)
Test Classification Details
Language SupportTests analyzed:
Verdict
📖 Understanding Test ClassificationsDesign Tests (High Value) verify what the system does:
Implementation Tests (Low Value) verify how the system does it:
Goal: Shift toward tests that describe the system's behavioral contract — the promises it makes to its users and collaborators.
|
There was a problem hiding this comment.
Skills-Based Review 🧠
Applied /zoom-out, /improve-codebase-architecture, and /tdd — commenting with non-blocking suggestions.
📋 Key Themes & Highlights
Key Themes
- Lookup precedence edge case: When
GH_AW_MODEL_MULTIPLIERSis present but empty/invalid, the built-in file tier is silently skipped. This may be intentional but diverges from the documented 3-tier spec and is untested. - Scoping inconsistency:
parseTokenWeightsFromEnvandwriteMergedModelMultipliersare defined insidemain()whilegetPlainObjectOrEmptylives at module scope — inconsistent placement for large, reusable helpers. - Duplicate plain-object guard:
isPlainObjectineffective_tokens.cjsandgetPlainObjectOrEmptyingenerate_aw_info.cjsimplement identical logic — good candidate for a shared utility. - Minor: JSDoc cast in
getPlainObjectOrEmptyis missing parentheses around the expression.
Positive Highlights
- ✅ Solid architectural move — file-based artifact propagation is cleaner than injecting large JSON blobs into job environment variables.
- ✅ Compatibility fallback retained for
GH_AW_MODEL_MULTIPLIERS— smooth migration path for any existing consumers. - ✅ Good test additions in
generate_aw_info.test.cjscovering the merge/write path and custom override case. - ✅
isPlainObjectandparseMultipliersFile/parseMultipliersJSONextraction improves readability ineffective_tokens.cjs. - ✅ All golden files updated, confirming the compiler change is reflected end-to-end.
🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · sonnet46 1.5M
| return _parsedMultipliers; | ||
| } | ||
| } | ||
| _parsedMultipliers = null; |
There was a problem hiding this comment.
[/zoom-out] Silent null-return when env var is present but invalid skips the built-in file fallback.
If GH_AW_MODEL_MULTIPLIERS is set to "" or contains invalid JSON, the function returns null without attempting the built-in file. This differs from the documented 3-tier lookup — tier 3 (built-in file) is unreachable whenever the env var key exists, even with an unusable value.
💡 Suggested fix
Continue to the next tier on invalid/empty value:
if (Object.prototype.hasOwnProperty.call(process.env, "GH_AW_MODEL_MULTIPLIERS")) {
const raw = process.env.GH_AW_MODEL_MULTIPLIERS;
if (raw && raw.trim()) {
const parsedFromEnv = parseMultipliersJSON(raw);
if (parsedFromEnv) {
_parsedMultipliers = parsedFromEnv;
return _parsedMultipliers;
}
// invalid JSON — fall through to built-in
}
// env var present but empty — fall through to built-in
}Alternatively, document explicitly that a set-but-invalid env var intentionally blocks the built-in tier.
|
|
||
| test("returns 1.0 when env var is not set", () => { | ||
| test("falls back to built-in multipliers when env var is not set", () => { | ||
| _resetCache(); |
There was a problem hiding this comment.
[/tdd] Missing edge-case test: env var present but invalid, merged file absent — should verify which multipliers (built-in or none) are returned.
The test on line 130 renames the old 'returns 1.0 when env var is not set' case but doesn't add a complementary test for when the env var is set but contains invalid JSON (and the merged file doesn't exist).
💡 Suggested test
test("returns null (no built-in fallback) when GH_AW_MODEL_MULTIPLIERS is set to invalid JSON", () => {
_resetCache();
process.env.GH_AW_MODEL_MULTIPLIERS = "not-json";
// merged file already absent (cleaned in beforeEach)
expect(getModelMultiplier("claude-opus-4.5")).toBe(1.0); // or toBeGreaterThan(1.0) if built-in should still apply
});This pins the intended behaviour so it can't silently regress.
|
|
||
| // Write to /tmp/gh-aw directory to avoid inclusion in PR | ||
| fs.mkdirSync(TMP_GH_AW_PATH, { recursive: true }); | ||
| writeMergedModelMultipliers(core, tokenWeights); |
There was a problem hiding this comment.
[/improve-codebase-architecture] writeMergedModelMultipliers is called before its declaration (relies on JS function hoisting) and is nested inside main() alongside parseTokenWeightsFromEnv.
Defining large helper functions inside an async top-level function makes the module harder to navigate — readers expect to see them near top-of-file or at module level, not buried after several hundred lines of main(). Both helpers have no closure state and could trivially be lifted to module scope.
💡 Suggested refactor
Move parseTokenWeightsFromEnv and writeMergedModelMultipliers to module scope (outside main), the same way getPlainObjectOrEmpty is already defined at module level. The call in main stays the same; only the function definition moves.
| /** | ||
| * @param {unknown} value | ||
| * @returns {Record<string, unknown>} | ||
| */ |
There was a problem hiding this comment.
[/improve-codebase-architecture] getPlainObjectOrEmpty duplicates the plain-object guard already extracted as isPlainObject in effective_tokens.cjs.
Both files now implement the same value !== null && typeof value === 'object' && !Array.isArray(value) pattern independently. A shared utils.cjs or object_utils.cjs module would prevent this drift.
💡 Suggested approach
Extract to a shared file, e.g. actions/setup/js/object_utils.cjs:
/** `@param` {unknown} v `@returns` {v is Record<string, unknown>} */
function isPlainObject(v) {
return v !== null && typeof v === "object" && !Array.isArray(v);
}
/** `@param` {unknown} v `@returns` {Record<string, unknown>} */
function toPlainObjectOrEmpty(v) {
return isPlainObject(v) ? /** `@type` {Record<string, unknown>} */ (v) : {};
}
module.exports = { isPlainObject, toPlainObjectOrEmpty };Both files can then require the shared helpers.
| module.exports = { main }; | ||
|
|
||
| /** | ||
| * @param {unknown} value |
There was a problem hiding this comment.
[/improve-codebase-architecture] JSDoc cast is missing parentheses — /** @type */ value instead of /** @type */ (value).
The standard JSDoc type-assertion form requires wrapping the expression in parentheses: /** @type {T} */ (expr). Without parens, some type checkers and linters misparse the annotation.
💡 Fix
// Before
return /** `@type` {Record<string, unknown>} */ value;
// After
return /** `@type` {Record<string, unknown>} */ (value);There was a problem hiding this comment.
REQUEST_CHANGES — 1 high + 3 medium issues found across the ET/multiplier refactor.
### Issues summary
High
Number(mult)inparseMultipliersJSONstoresNaNwithout aNumber.isFiniteguard; any non-numeric value in a multipliers file silently poisons ET calculations for that model.
Medium
getMultipliersData(): whenGH_AW_MODEL_MULTIPLIERSis set but empty or invalid, the function returnsnulland skips the built-in file. The three-tier fallback described in the PR collapses to two for anyone with the env var exported (even empty).getPlainObjectOrEmpty: JSDoc cast/**@type{T} */ valueis missing parentheses — the assertion has no effect and the inferred return type remainsunknown.writeMergedModelMultipliers:fs.writeFileSyncis unguarded; a write failure propagates as an uncaught exception with nocore.setFaileddiagnostic, unlike the read paths above it.
Overall direction (activation-artifact file over env-var injection) is sound. Fix the Number.isFinite guard and the env-var fallback logic before merging.
🔎 Code quality review by PR Code Quality Reviewer · sonnet46 2.8M
| multipliers[model.toLowerCase()] = Number(mult); | ||
| if (isPlainObject(parsed.multipliers)) { | ||
| for (const [model, mult] of Object.entries(parsed.multipliers)) { | ||
| multipliers[model.toLowerCase()] = Number(mult); |
There was a problem hiding this comment.
Number(mult) stores NaN without validation, silently corrupting multiplier lookups.
Any non-numeric multiplier value (string, object, null) becomes NaN in the map. Downstream getModelMultiplier() returns NaN, causing all ET calculations for that model to silently produce NaN instead of falling back to 1.0.
💡 Suggested fix
const numMult = Number(mult);
if (Number.isFinite(numMult)) {
multipliers[model.toLowerCase()] = numMult;
}This is the same guard already applied to token_class_weights entries a few lines above — consistent and cheap.
| } | ||
| } | ||
| _parsedMultipliers = null; | ||
| return null; |
There was a problem hiding this comment.
When GH_AW_MODEL_MULTIPLIERS is set but empty or invalid, the built-in file fallback is silently skipped.
The hasOwnProperty guard at line 56 treats any presence of the env var — including GH_AW_MODEL_MULTIPLIERS="" or invalid JSON — as an explicit override: it sets _parsedMultipliers = null and returns without reaching the built-in file path. A caller that exports the env var as empty (e.g. from a template) will get null multipliers permanently, even though model_multipliers.json is right there.
💡 Suggested fix
Fall through to the built-in when the env var is present but not parseable:
if (Object.prototype.hasOwnProperty.call(process.env, "GH_AW_MODEL_MULTIPLIERS")) {
const raw = process.env.GH_AW_MODEL_MULTIPLIERS;
if (raw && raw.trim()) {
const parsedFromEnv = parseMultipliersJSON(raw);
if (parsedFromEnv) {
_parsedMultipliers = parsedFromEnv;
return _parsedMultipliers;
}
}
// env var present but empty/invalid — fall through to built-in
}Only cache null after all three sources have been exhausted.
| */ | ||
| function getPlainObjectOrEmpty(value) { | ||
| if (value && typeof value === "object" && !Array.isArray(value)) { | ||
| return /** @type {Record<string, unknown>} */ value; |
There was a problem hiding this comment.
Incorrect JSDoc cast syntax — type assertion has no effect without parentheses.
/** @type {T} */ value is a comment before an expression; it does not cast in JSDoc/TypeScript. Without parentheses, the type annotation is silently ignored and the return type is inferred as unknown, defeating the @returns {Record<string, unknown>} contract.
💡 Suggested fix
return /** `@type` {Record<string, unknown>} */ (value);The parentheses are required for JSDoc type-casts to be recognized by TypeScript and type-aware editors.
| }; | ||
|
|
||
| const mergedPath = `${TMP_GH_AW_PATH}/model_multipliers.json`; | ||
| fs.writeFileSync(mergedPath, JSON.stringify(merged, null, 2)); |
There was a problem hiding this comment.
fs.writeFileSync failure is unhandled and will crash the activation job step with a raw stack trace.
The read paths above have try/catch + core.warning, but the write does not. A disk-full or unexpected permission error will propagate as an uncaught exception from inside main, failing the step with no actionable diagnostic.
💡 Suggested fix
try {
fs.writeFileSync(mergedPath, JSON.stringify(merged, null, 2));
core.info(`Generated merged model multipliers at: ${mergedPath}`);
} catch (error) {
core.setFailed(`Failed to write merged model multipliers: ${String(error)}`);
}There was a problem hiding this comment.
Smoke reply test. Me answer old review thread with tiny footprint.
Warning
Firewall blocked 6 domains
The following domains were blocked by the firewall during workflow execution:
accounts.google.comandroid.clients.google.comclients2.google.comcontentautofill.googleapis.comsafebrowsingohttpgateway.googleapis.comwww.google.com
To allow these domains, add them to the
network.allowedlist in your workflow frontmatter:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
📰 BREAKING: Report filed by Smoke Copilot · gpt55 4M
|
@copilot review ALL comments and review comments. Respond with resolution and resolve review comments. |
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Addressed all three review threads in b94fd19:
|
|
@copilot update compiler to stop online the full model info in env variables. Only needed if workflow has custom models |
|
🚀 Smoke Gemini MISSION COMPLETE! Gemini has spoken. ✨ |
|
|
|
✨ The prophecy is fulfilled... Smoke Codex has completed its mystical journey. The stars align. 🌟 Caution agentic threat detected |
This comment has been minimized.
This comment has been minimized.
Agent Container Tool Check (Corrected)
Result: 12/12 tools available ✅ — PASS
|
Smoke Test Results\n- GitHub MCP Testing: ✅\n- Web Fetch Testing: ✅\n- File Writing Testing: ✅\n- Bash Tool Testing: ✅\n- Build gh-aw: ❌\n\nOverall status: FAILWarning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "localhost"See Network Configuration for more information.
|
|
Caution agentic threat detected Comment MemoryNote This comment is managed by comment memory.It stores persistent context for this thread in the code block at the top of this comment. Warning Firewall blocked 6 domainsThe following domains were blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
|
|
@copilot the awf config should be constructed from this file, not inlined JSON |
|
Smoke bot here. Me tap rock. Test smoke go poof. 🪨🔥 Warning Firewall blocked 6 domainsThe following domains were blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
|
|
Smoke Copilot 26431767340: FAIL Warning Firewall blocked 6 domainsThe following domains were blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
|
Comment MemoryNote This comment is managed by comment memory.It stores persistent context for this thread in the code block at the top of this comment. Warning Firewall blocked 6 domainsThe following domains were blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
|
There was a problem hiding this comment.
Smoke review done. Me leave non-blocking notes.
Warning
Firewall blocked 6 domains
The following domains were blocked by the firewall during workflow execution:
accounts.google.comandroid.clients.google.comclients2.google.comcontentautofill.googleapis.comsafebrowsingohttpgateway.googleapis.comwww.google.com
To allow these domains, add them to the
network.allowedlist in your workflow frontmatter:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
📰 BREAKING: Report filed by Smoke Copilot · gpt55 4M
| include-hidden-files: true | ||
| path: | | ||
| /tmp/gh-aw/aw_info.json | ||
| /tmp/gh-aw/model_multipliers.json |
There was a problem hiding this comment.
Smoke review note: new artifact path show good. Me check line can take review comment.
| include-hidden-files: true | ||
| path: | | ||
| /tmp/gh-aw/aw_info.json | ||
| /tmp/gh-aw/model_multipliers.json |
There was a problem hiding this comment.
Same artifact path here too. Smoke test says locked workflow carries model file.
|
📰 VERDICT: Smoke Copilot has concluded. All systems operational. This is a developing story. 🎤 |
|
Smoke Test: Claude — Run 26431767267 Core (#1–13): ✅✅✅✅✅✅✅✅✅✅✅✅✅ Overall: ✅ PASS Warning Firewall blocked 6 domainsThe following domains were blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
|
There was a problem hiding this comment.
💥 Automated smoke test review - all systems nominal!
Warning
Firewall blocked 6 domains
The following domains were blocked by the firewall during workflow execution:
accounts.google.comandroid.clients.google.comclients2.google.comcontentautofill.googleapis.comsafebrowsingohttpgateway.googleapis.comwww.google.com
To allow these domains, add them to the
network.allowedlist in your workflow frontmatter:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
💥 [THE END] — Illustrated by Smoke Claude · opus47 6.5M
| if data.EngineConfig != nil && data.EngineConfig.TokenWeights != nil { | ||
| // Embed custom token weights only when custom model multipliers are configured. | ||
| // This avoids emitting large model payload env values when workflows only customize | ||
| // token-class weights. |
There was a problem hiding this comment.
Nice guard — gating on len(Multipliers) > 0 keeps the env payload lean when only token-class weights are customized. 👍
| // This avoids emitting large model payload env values when workflows only customize | ||
| // token-class weights. | ||
| if data.EngineConfig != nil && data.EngineConfig.TokenWeights != nil && len(data.EngineConfig.TokenWeights.Multipliers) > 0 { | ||
| if tokenWeightsJSON, err := json.Marshal(data.EngineConfig.TokenWeights); err == nil { |
There was a problem hiding this comment.
Consider whether a nil Multipliers map should be normalized at config-load time so this conditional stays close to the data definition. Optional nit.
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Implemented in 9389877 (with core change in 7eeda42). AWF config generation now avoids inlining custom model multipliers in JSON and instead merges |
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Done in 1bb6eaf. I moved the inline Python model-multiplier merge logic to |
|
pr-sous-chef:
|
The compiler currently pushes merged model data through step environment variables, which bloats compiled logs and creates churn. This change shifts model multiplier/alias propagation to a file-based flow rooted in the activation artifact, so downstream jobs read the same materialized payload from disk.
Activation job now materializes merged model data
generate_aw_info.cjsnow builds/tmp/gh-aw/model_multipliers.jsonby merging:actions/setup/js/model_multipliers.json)engine.token-weights(GH_AW_INFO_TOKEN_WEIGHTS)/tmp/gh-aw/model_multipliers.json.Runtime ET/model logic now reads from artifact-backed file
effective_tokens.cjsnow resolves multipliers in deterministic order:/tmp/gh-aw/model_multipliers.json(activation artifact payload)GH_AW_MODEL_MULTIPLIERS(compatibility fallback)model_multipliers.jsonin setup scriptsSetup no longer injects large model JSON into job env
GH_AW_MODEL_MULTIPLIERSexport block fromactions/setup/setup.sh.Readability hardening in JS merge/parse paths
✨ PR Review Safe Output Test - Run 26431767267
Warning
Firewall blocked 6 domains
The following domains were blocked by the firewall during workflow execution:
accounts.google.comandroid.clients.google.comclients2.google.comcontentautofill.googleapis.comsafebrowsingohttpgateway.googleapis.comwww.google.comSee Network Configuration for more information.