Skip to content

feat: answer unnamed governance scopes from an enterprise baseline - #23689

Open
iamwhatever wants to merge 1 commit into
mainfrom
feat/ee-baseline-deny-unnamed
Open

iamwhatever wants to merge 1 commit into
mainfrom
feat/ee-baseline-deny-unnamed

Conversation

@iamwhatever

@iamwhatever iamwhatever commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

Problem / Motivation

Goal: In an enterprise build, a governance scope the remote policy does not name answers its minimal set (or off) instead of being permitted; the oss edition is unchanged.

Today _query_level answers a None control with _PERMIT_NOT_GOVERNED, in every edition. RFC rfc-crew-enterprise-edition.md decision D3 (merged in #23208) says that in an enterprise build a control the remote policy does not name is locked to its minimal set, or off when it has none, through a built-in baseline policy. edition.is_enterprise() exists since #23213; nothing reads it in governance yet.

Why it matters

Without this, an enterprise policy that forgets a scope leaves that scope fully open, which is the opposite of the "off by default" the RFC promises (Design section 3, Migration plan phase 3). Every later enterprise item (local-side narrowing, hardcoded defaults for keyless controls) assumes an unnamed scope is already closed.

Not a goal

  • Local config, env, profile and dashboard readers (the "no local loosening" half of D3). Profiles already only narrow; the config readers are a separate item.
  • The policy URL lock, the login and governance gate, Red-row hardcodes, and controls with no catalog key yet.
  • Fixing the gate's tools/commands classification (see Follow-up).
  • The ceiling is None and profile is None early returns in hook_runtime/governance_gate.py, mcp_gateway/app_call.py and governance_profiles.governance_permits. An enterprise host with no policy at all is the enterprise gate's to refuse (RFC Migration plan phase 2).

What changed (motivation → approach → change)

Goal: an unnamed scope in an enterprise build answers the RFC appendix's minimal set; the remote policy can still widen it.

Approach: fill the POLICY level, not every level. _query_level answers both the policy and the profile level, so turning its None branch into a deny would make a profile that does not name a scope impose the baseline again beneath a remote widening, which D3 forbids ("Remote policy: can widen"). So _query_level keeps permitting None, and resolve asks _policy_level(ceiling, scope) for the policy's control: the remote control when the policy names the scope, else (enterprise only) the baseline control.

  • platform/governance_parts/baseline.py (new, data only): BASELINE_CONTROLS, one raw control per catalog scope, and BASELINE_UNGATED for the two ordinals with the reason each keeps Crew's default. The raw controls go through the same _parse_control a remote policy uses, so the catalog's always_permitted floor applies.
  • platform/governance_parts/evaluator.py: _policy_level / policy_level_control; resolve uses it and prefixes a baseline answer's reason with enterprise baseline:. A scope in neither table (registered at run time) is denied in enterprise. A folders.* query looks up the policy's filesystem.* rule first, since the parser stores it there. No baseline is added for the profile layer alone: gate_decision's alias-group pass asks resolve(None, profile, ..., baseline=False), and a Profile passed in the ceiling slot (governance_profiles.any_configured_profile_governs → may_skip_gate(ref, profile)) gets none.
  • platform/governance.py: may_skip_gate and _ceiling_mentions_mcp_server read policy_level_control instead of ceiling.get, and may_skip_gate no longer returns "skip" for a None ceiling in enterprise. Without this an auto-approved built-in (web_fetch) skips the PreToolUse gate, so the baseline is never asked.
  • platform/governance_parts/tiers.py (added to scope by the conductor, from it_d6f8af58): compose_tier_ladder fills the authority tier's unnamed scopes from the baseline (_with_enterprise_baseline) BEFORE the fold, so the existing tighten-only _intersect_ceilings makes a local tier (env, home, bundled) narrow the baseline and never widen it. Without it a local tier naming a scope the central document leaves out supplied that scope's whole answer, e.g. a home file enabling capabilities.browse. With no central document the top tier is itself local, so _with_enterprise_baseline intersects it with the baseline scope by scope (_compose_controls) instead of filling only its gaps; only a central authority's named scopes replace the baseline. oss returns the authority unchanged (same object). The parsed baseline moved to parsing.baseline_controls so both tiers and evaluator read it.
  • dashboard/handlers/member_dashboard.py: _egress_decision (whether an agent-written page may run script) reads policy_level_control(ceiling, "network.egress"), so an enterprise policy that leaves egress out keeps the page static instead of treating egress as unrestricted.
  • dashboard/handlers/security_governance_policy.py: the policy viewer reads policy_level_control, so an enterprise scope the policy leaves out is reported as governed by its baseline, not "ungoverned".
  • platform/governance.py and dashboard/handlers/security.py facades: baseline joins _OWNERS; manifests updated. .github/black-baseline.txt drops test/test_governance_policy_viewer.py, now black-clean.
  • docs/system-specs/modules/governance.md: new "Enterprise built-in baseline" section, Files and Tests entries. catalog.py: the CAPABILITY-DEFAULT contract notes the enterprise exception.

Baseline per scope (RFC appendix "Minimal set"; everything not listed with a set is off):

Scope Baseline Code identifier
tools off (see below) —
approval_modes normal, trust, trust_reads catalog always_permitted
mcp @kirocrew-core server name in agent.py
filesystem.read ~/workplace/kirocrew-workspace and /Volumes/workplace/kirocrew-workspace (+ /**) config/paths.py _default_workspace_base() + _WORKSPACE_DIR_NAME
agent_backend kiro agent_sdk/backends.py POLICY_ID_KIRO
capabilities.publish enabled, destinations = default publish_provider.DEFAULT_PROVIDER
apps, commands, filesystem.write, network.egress, channels, yolo_duration off (empty allow-set) —
every other capabilities.* enabled: false —
approval_mode, sandbox.min_level ungated: Crew's default ordinals are never item-queried
folders.read / folders.write follow filesystem.* _SCOPE_ALIASES

Scopes covered: all 32 rows of SCOPE_CATALOG (28 in BASELINE_CONTROLS, 2 in BASELINE_UNGATED, and the 2 folders.* aliases, which resolve through filesystem.*).

Not mapped: updates.source ("official source"). It is a carriers.UpdatePins field outside controls, never reaches _query_level, and no official-remote constant exists in code; an empty pin permits any remote. distribution ("Crew's current defaults") is likewise outside controls and keeps its defaults.

Appendix rows whose meaning changed, for a later RFC appendix update:

  • Tools ("read-only tools"): off in this PR. A read-only set (fs_read, glob, grep, from hooks._HOST_READ_ONLY_BUILTIN_TOOLS) could not pass while commands is off (Follow-up), so the baseline does not claim one. Read-only tools wait on the tools/commands classifier fix, a separate follow-up item. With an empty policy every built-in tool is denied.
  • Approval modes ("normal"): means normal + trust + trust_reads (the catalog floor); only yolo is off.
  • Update source ("official source"): not mapped; unchanged behaviour (any remote) until an official remote is named.
  • File read ("inside the workspace"): means Crew's fixed default workspace root, not the configured one, because the configured root comes from KIROCREW_WORKSPACE, the saved workspace_dir file or workspaces[].dir, all local sources D3 says cannot widen. A profile may narrow it to a sub-path; nothing local can move it.

Follow-up: bare tool names are checked against commands. classify_tool_title sends every unprefixed name (and every prose display title) to both commands and tools (tool_calls.py:192), so with commands off a read-only tool such as fs_read is refused by commands, and an allow-mode tools set also refuses a prose title like Searching for foo. Read-only tools cannot pass while commands is off, so the tools baseline is off until that fix lands; the fix then sets it to the read-only set. Tracked as a separate item, not this PR.

Backwards compatibility

Compatible: every new branch is behind edition.is_enterprise(), and the checked-in edition is oss; test_oss_unnamed_scope_is_not_governed and test_oss_auto_approve_is_unchanged pin the oss answers. There is no installed enterprise base (RFC Backward compatibility).

Reader: src/kiro_crew/platform/governance.py:may_skip_gate -- entry: chat|subagent|app -- oss path unchanged (ceiling is None still returns True when not enterprise); test_oss_auto_approve_is_unchanged
Reader: src/kiro_crew/platform/governance_parts/evaluator.py:resolve -- entry: chat|cron|subagent|app|crew page -- oss path reads ceiling.get exactly as before; test_oss_unnamed_scope_is_not_governed

Tests

test/test_governance_enterprise_baseline.py:

  • test_every_catalog_scope_has_a_baseline_entry: fails when a catalog scope is in neither BASELINE_CONTROLS nor BASELINE_UNGATED.
  • test_enterprise_unnamed_scope_answers_the_baseline: table-driven over every catalog scope, with no ceiling and with an empty one; minimal-set items permit, others deny at layer policy with an enterprise baseline reason.
  • test_enterprise_policy_naming_a_scope_answers_and_may_widen: a named scope answers from the remote policy, including past the baseline.
  • test_enterprise_profile_not_naming_a_scope_keeps_the_remote_widening and test_enterprise_profile_narrows_the_baseline.
  • test_enterprise_alias_group_keeps_the_remote_grant_under_a_profile: a ("shell", "execute_bash") group the remote policy permits stays permitted with an unrelated profile bound.
  • test_enterprise_may_skip_gate_asked_about_a_profile_adds_no_baseline.
  • test_governance_policy_viewer.py::test_enterprise_unnamed_scope_reports_the_baseline.
  • Tier fold: test_enterprise_local_curl_deny_stays_denied, test_enterprise_local_write_allowlist_still_narrows_writes, test_enterprise_local_tier_cannot_permit_what_the_baseline_denies (env and home tiers), test_enterprise_local_authority_with_no_central_only_narrows_the_baseline (env, bundled and home as the top tier), test_oss_tier_fold_is_unchanged.
  • test_enterprise_alias_query_finds_the_policy_rule: folders.read answers from a filesystem.read rule.
  • test_dashboard_page_scripts_ceiling.py::test_enterprise_unnamed_egress_is_the_baseline_and_gets_NO_scripts.
  • test_enterprise_auto_approve_cannot_skip_the_gate_for_an_unnamed_scope: may_skip_gate is False for web_fetch, web_search, use_subagent and MCP refs.
  • test_enterprise_scope_with_no_baseline_row_is_denied, test_enterprise_gate_refuses_a_shell_command_with_an_empty_policy.
  • test_oss_unnamed_scope_is_not_governed, test_oss_auto_approve_is_unchanged: oss unchanged (_query_level(None) is _PERMIT_NOT_GOVERNED).

Mutation checks: forcing _policy_level to skip the baseline fails 73 cases; re-adding the baseline to the profile pass and to a Profile ceiling fails both profile tests; reverting the viewer, member-dashboard or alias lines fails its test. Skipping the tier fill fails both local_tier_cannot_permit cases. Treating a local authority like a central one fails all three no-central cases.

Local: the new file plus test_governance_*.py, test_hooks*.py, test_facade*.py, test_governance_parts_facade.py, test_security*.py, test_policy_distribution*.py, test_dashboard_page_scripts_ceiling.py, test_platform_context.py, test_edition*.py and test/integration/test_governance.py pass; flake8, isort, mypy, black gate, comment-history, brand, file-line-cap, docs-lint and the flake-pattern ratchet pass.

Manual verification

N/A — the change is pure evaluator logic with no I/O, covered table-driven over the whole catalog; enterprise builds are not enabled yet.

Related Issues

Refs #23206. RFC: #23208 (D3, Migration plan phase 3). Builds on #23213.

Checklist

  • At most two commits (one is the norm), with a Conventional Commits title (feat|fix|docs|style|refactor|perf|test|chore|ci|build|revert: ...)
  • Existing tests pass and new tests added for new functionality
  • Self-review completed; code follows project style guidelines
  • Documentation updated (if applicable)
  • No secrets, credentials, or internal references in the diff

Contribution License Agreement

Contributions are accepted under the project's Apache-2.0 license; see the Licensing section of CONTRIBUTING.md.

@iamwhatever
iamwhatever requested review from a team and KiroCrewCaptain as code owners October 24, 2026 07:52
@github-actions

github-actions Bot commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

UX Review (Opus 5.5) — ⏭️ skipped

Revision 4f9bc12959b6454a1186f8c48cd135276fa8a560 touches no user-facing surface (no changes under website/ or committed screenshots), so the UX review was skipped. Does not block merge.

@github-actions github-actions Bot added the readiness: checking Automated validation is still running label Oct 24, 2026
@github-actions

github-actions Bot commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

First Principles Review (Opus 5.5) — 🔴 BLOCK

Premise-level review of 4f9bc12959b6454a1186f8c48cd135276fa8a560 — why this exists and whether the shipped surface is the smallest honest version. Updated in place on each push. A BLOCK verdict blocks PR readiness; PASS does not.

First-Principles-Verdict: BLOCK

Product-shape change without an accepted RFC: every governance scope the policy leaves unnamed in an enterprise build changes from permitted to a baseline minimal set or off. The base-commit RFC for this is draft.

Notes

  • Item 3 — inherited: the baseline departs from the draft appendix, which it is meant to follow. Per the description, "Tools ('read-only tools'): off in this PR" and "Approval modes ('normal'): means normal + trust + trust_reads". So the minimal sets ship before anyone has decided them.

What this change ships

Inventory (7 items) — 6 justified

Intent: an enterprise operator wants a scope their policy forgot to come out closed, not open. This is an ADDITION.

  1. Enterprise build: an unnamed scope answers its baseline instead of being permitted — justified
  2. Enterprise build: a scope registered at run time that no table lists is denied — justified
  3. A built-in per-scope baseline table (BASELINE_CONTROLS, BASELINE_UNGATED) — oversized (diverges from appendix rows)
  4. Enterprise build: auto-approved built-ins no longer skip the PreToolUse gate when there is no ceiling — justified
  5. Enterprise build: local policy tiers can only narrow the baseline, never widen it — justified
  6. Enterprise dashboard: agent-written pages stay static when egress is unnamed — justified
  7. Enterprise dashboard: the policy viewer reports unnamed scopes as governed by the baseline — justified

Blockers

product-shape change without accepted RFC: enterprise deny-unnamed and the baseline minimal sets (lens 9)
Trigger: items 1 and 3 change what every user of the enterprise edition gets without choosing. The diff adds "In an enterprise build … it is answered by the built-in baseline policy instead", and the base RFC list reads docs/request-for-change/rfc-crew-enterprise-edition.md:status: draft. The RFC itself says "Status: draft. Nothing is built." The D3 decision written inside a draft does not count as a recorded decision.
Outcome: the enterprise edition's default for all unnamed scopes, and minimal sets that already depart from the appendix, ship with no recorded design decision behind them.
Clears when: an RFC covering enterprise deny-unnamed and its baseline minimal sets is merged on the base as accepted, in-progress, partial or implemented (then push or rebase), or a maintainer posts /ai-review override first-principles 4f9bc12959b6454a1186f8c48cd135276fa8a560 product-shape: <decision>.

[FIRST-PRINCIPLES-REVIEWED] 4f9bc12

Description read

[DESCRIPTION-READ] 98995dc8c19f1c7c841eaea98178da2309b89ed91b89c1ae3e3013b11fd26221

That sha256 names the PR description this verdict read. Recompute it with .github/scripts/pr-description-capture.sh; if it differs, the description changed after this verdict was formed and any finding drawn from the description is unproven.

@github-actions

github-actions Bot commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

Design Review (Opus 5.5) — ✅ PASS

Design-level review of 4f9bc12959b6454a1186f8c48cd135276fa8a560 — updated in place on each push. A BLOCK verdict blocks PR readiness; PASS does not.

Design-Verdict: PASS

Nothing blocks: the change only runs in enterprise builds, oss is unchanged, and filling the baseline at the policy level, not in _query_level, keeps remote widening possible.

Notes

  • The baseline is now filled in two places: tiers._with_enterprise_baseline fills the composed ladder, and evaluator._policy_level fills again at query time. The second fill only matters for ceilings built outside the ladder. If you can, name that case in the docstring, or keep only one fill, so the two cannot drift.
  • With no policy at all, an enterprise host still hits the ceiling is None and profile is None early return in governance_gate. may_skip_gate now refuses the skip, but the gate itself permits the call. The PR lists this under Not a goal (phase 2). Pin it with a test so phase 2 cannot forget it.
  • ## Backwards compatibility falls past the description's truncation point, so the take-away check could not compare against it. The oss path takes nothing away.

[DESIGN-REVIEWED] 4f9bc12

Description read

[DESCRIPTION-READ] ffa874dd5f27fcc7070b43a37693f97f27c5eb0a2a7f49a021d7fd69af65dd97

That sha256 names everything this verdict read: the PR description, plus the 1 evidence file(s) the workflow collected from it and handed this review. It covers that evidence because the media strip replaces every attachment URL with the same placeholder, so an edit swapping one attachment for another would leave the description's captured text identical while what this review judged changed. Recompute it with .github/scripts/pr-description-capture.sh over the same inputs; if it differs, the description or that evidence changed after this verdict was formed and any finding drawn from either is unproven.

@github-actions

github-actions Bot commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

Opus 5.5 Review — ✅ no blocking findings

Reviewed 4f9bc12959b6454a1186f8c48cd135276fa8a560 — this comment is updated in place on each push.

Review details

No findings.

[OPUS-REVIEWED] 4f9bc12

Verdict parsed from the review's SHA-scoped output markers for commit 4f9bc12959b6454a1186f8c48cd135276fa8a560.

False positive or not applicable? A repository writer can comment:
/ai-review override fable 4f9bc12959b6454a1186f8c48cd135276fa8a560 false-positive: <reason, 20 to 500 characters>

@github-actions

github-actions Bot commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

GPT 6.1 Review — ✅ no blocking findings

GPT 6.1 completed its review of 4f9bc12959b6454a1186f8c48cd135276fa8a560 and found no blocking issues.

This comment is updated in place on each push.

Review details

No findings.
[GPT-REVIEWED] 4f9bc12

False positive or not applicable? A repository writer can comment:
/ai-review override gpt 4f9bc12959b6454a1186f8c48cd135276fa8a560 false-positive: <reason, 20 to 500 characters>

@iamwhatever
iamwhatever force-pushed the feat/ee-baseline-deny-unnamed branch from b19536a to 86c3a04 Compare October 24, 2026 08:12
@iamwhatever

Copy link
Copy Markdown
Contributor Author

GPT 6.1 finding on b19536a2, evaluator.py:80 (alias lookup): fixed in 86c3a04b.

Verified in code: parsing._parse_controls stores a folders.* rule under its filesystem.* scope (_SCOPE_ALIASES), and _policy_level looked the raw alias up with ceiling.get(scope), so an enterprise folders.read query missed the remote rule and answered from the baseline. _policy_level now looks the canonical scope up before the baseline answers. test_enterprise_alias_query_finds_the_policy_rule covers filesystem.read and folders.read with the same rule, and it fails with the lookup removed.

The oss path is left byte-identical on purpose (this PR must not change oss), so the profile lookup and the oss alias lookup are unchanged.

@iamwhatever

Copy link
Copy Markdown
Contributor Author

Replies to the advisory notes on b19536a2:

Design note 1 (direct ceiling.controls readers): fixed for the one enforcing reader, in 86c3a04b. member_dashboard._egress_decision decides whether an agent-written page may run script. It read ceiling.controls["network.egress"], so in an enterprise build a policy that left egress out handed pages script while resolve treats egress as off. It now reads policy_level_control. Test: test_enterprise_unnamed_egress_is_the_baseline_and_gets_NO_scripts. The remaining direct readers outside governance_parts/ (git grep -n "\.controls\b" -- 'src/kiro_crew/*.py') are cli_commands_security.py policy show / policy validate, which print what the document itself names, and governance_profiles.py, which composes profiles (out of this PR's scope). governance.assert_governance_floor reads only ordinals, which the baseline leaves ungated.

Design note 2 and First Principles item 2 (read-only tools that cannot pass while commands is off): kept as is by decision. The RFC appendix's minimal set is read-only tools, and the owner chose to ship that value with the gap stated rather than set tools to off. With an empty policy every built-in tool is denied, which is fail-closed, and enterprise builds are not enabled yet. The classification fix (bare tool names are also asked of commands in classify_tool_title) is tracked as its own item; it is in the PR body under Follow-up. When it lands the baseline needs no edit.

First Principles item 1 (RFC status draft): noted. The RFC file merged in #23208 with decisions D1 to D3 recorded by the owner on 2026-10-23. Moving its status is the RFC owner's call and is not part of this PR; nothing here enables an enterprise build.

@iamwhatever
iamwhatever force-pushed the feat/ee-baseline-deny-unnamed branch from 86c3a04 to a42712b Compare October 24, 2026 09:08
@github-actions github-actions Bot added readiness: action required A blocking check or review needs attention and removed readiness: checking Automated validation is still running labels Oct 24, 2026
@iamwhatever

Copy link
Copy Markdown
Contributor Author

Scope change on e1bfed9d, made at the conductor's explicit request (it took over the seam from item it_d6f8af58). I removed one "Not a goal" bullet, the local policy tiers one, because this PR now covers it.

compose_tier_ladder now fills the authority tier's unnamed scopes from the enterprise baseline before the fold (tiers._with_enterprise_baseline). The existing tighten-only _intersect_ceilings then makes a local tier (env, home, bundled) narrow the baseline, never widen it. oss returns the authority as the same object. Tests: test_enterprise_local_curl_deny_stays_denied, test_enterprise_local_write_allowlist_still_narrows_writes, test_enterprise_local_tier_cannot_permit_what_the_baseline_denies (env and home), test_oss_tier_fold_is_unchanged. The Goal and "Why it matters" are unchanged.

@iamwhatever
iamwhatever force-pushed the feat/ee-baseline-deny-unnamed branch from a42712b to 9b356f0 Compare October 24, 2026 09:47
@iamwhatever

Copy link
Copy Markdown
Contributor Author

Correction to the scope-change comment above: the commit is 9b356f01, not e1bfed9d.

@github-actions github-actions Bot added readiness: checking Automated validation is still running and removed readiness: action required A blocking check or review needs attention labels Oct 24, 2026
@iamwhatever
iamwhatever force-pushed the feat/ee-baseline-deny-unnamed branch from 9b356f0 to 97cfd42 Compare October 24, 2026 09:53
@iamwhatever

Copy link
Copy Markdown
Contributor Author

GPT 6.1 finding on a42712b4, baseline.py:45 (the commands baseline rejects the read-only tool floor): accepted as real. Disposition: the tools baseline is now off.

Verified in code: classify_tool_title sends every unprefixed name to both commands and tools (tool_calls.py:192), and gate_decision denies when either denies, so fs_read / glob / grep could never pass beside an off commands.

The owner chose not to change that classification in this PR. It is gate code and has its own follow-up item. So the baseline no longer claims a read-only set it cannot deliver: "tools" is an empty allow-set, the same as commands. The baseline docstring, the governance spec and the PR body say that read-only tools wait on the tools/commands classifier fix. When that lands, the fix sets tools back to the read-only set. Tests: the tools row of test_enterprise_unnamed_scope_answers_the_baseline now expects fs_read, glob and grep to be denied, and test_enterprise_local_tier_cannot_permit_what_the_baseline_denies checks that a local tier cannot grant fs_read.

In an enterprise build a scope the remote policy does not name was
permitted, exactly as in oss. RFC D3 (rfc-crew-enterprise-edition.md)
locks such a scope to its minimal set, or off when it has none.

Add governance_parts/baseline.py, a data table of each catalog scope's
minimal set from the RFC appendix, parsed by the same per-control parser
a remote policy uses. resolve fills the POLICY level from it when the
policy names nothing and the build is enterprise; the profile level is
untouched, so a profile can still only narrow and cannot block a remote
widening. may_skip_gate reads the same lookup, so an auto-approve grant
cannot skip the gate for an unnamed scope. oss is unchanged.
@iamwhatever
iamwhatever force-pushed the feat/ee-baseline-deny-unnamed branch from 97cfd42 to 4f9bc12 Compare October 24, 2026 10:28
@iamwhatever

Copy link
Copy Markdown
Contributor Author

Opus 5.5 finding on 97cfd426, tiers.py:402 (with no central document, a local authority tier replaced the baseline): fixed in 4f9bc129. Verified in code: compose_tier_ladder(None, subordinate) made the local tier present[0], and _with_enterprise_baseline only filled its gaps. Now a non-central authority is intersected with the baseline scope by scope (_compose_controls). Only a central authority's named scopes replace the baseline. Test: test_enterprise_local_authority_with_no_central_only_narrows_the_baseline (env, bundled and home as the top tier). It fails with the intersection removed.

@github-actions github-actions Bot added readiness: action required A blocking check or review needs attention and removed readiness: checking Automated validation is still running labels Oct 24, 2026

This branch has not been deployed

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

Labels

readiness: action required A blocking check or review needs attention

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant