You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Show a workload's creation failures next to its namespace's quotas and LimitRanges (#411 Q1, view) - #526
The view half of slice Q1 of #411, built on the core run from #524. The plan is docs/superpowers/plans/2026-10-30-creation-constraints-view.md.
:blocked, or Explain workload creation failures in the Action Palette, opens a read-only view on the selected Deployment, ReplicaSet, StatefulSet, DaemonSet, Job or CronJob. No default key is bound.
The header shows the workload and its controller's counters, and each source gets one line from the shared renderer.
Recorded creation failures: how often and when each was last recorded, and what it says. A quota is attributed only by the name the message gives, and flagged "no longer present" or "not in the quotas read". A LimitRange message is attributed to "a LimitRange in this namespace". Anything else is "other rejection".
ResourceQuotas: grouped values shown verbatim (used X / hard Y), marked "at its limit" or "status not yet updated", with scopes.
LimitRanges: each constraint.
Notes: rejections are dated individually while policies are as read now; recreated and absent workloads, and earlier incarnations, are said. "No recorded failure" is never a conclusion, because Events expire. "No ResourceQuota" and "No LimitRange" appear only from a conclusive list, and the notes switch to "the list is stale" as the view ages.
Enter opens a failure's subject, a quota or a LimitRange in its table, in the run's epoch.
Controller (ui/creation_constraints_controller.py): follows the :consumers controller. One exclusive worker runs under a run token; a stale result is dropped; availability reasons are given; the context switch cancels the group; a failed worker is reported.
Wiring: the command and router, palette availability, the context-switch cancel, worker-failure reporting, and __main__.
Version matrix: a korvid-matrix-quota namespace with a pods: "0" quota, a LimitRange and a Deployment. Its scenario waits for the ReplicaSet's recorded rejection and checks it is read next to the policies, without the template's literal reaching the report. The creation_* modules and k8s/events.py join the workflow's path filters.
Docs:docs/tui.md ("Workload creation failures"), docs/keybindings.md, docs/kubernetes-support.md and the unreleased notes.
Verification
Tests were written first for the screen and for each wiring step:
tests/ui/test_creation_constraints_screen.py: 25 tests covering rows, attribution, markers, notes, keys, literal text and ageing.
tests/ui/test_creation_constraints_controller.py: availability, the read set, late results, navigation and cancellation.
tests/ui/test_creation_constraints_workflow.py: from :deployments, :blocked and Enter lead to the ReplicaSet; the wrong view says what to open; a failed run is reported.
Router, action-policy, coordinator and worker-failure tests.
The controller was written before its tests. To check its branches anyway, I mutation-checked it; the screen was mutation-checked too. The helper now runs the unmutated tests first and refuses to report on a failing baseline. Every mutation was caught, except one equivalent guard (child is not None: a target without a child kind never has a children observation).
Local gate, using the venv's tools behind the corporate mirror:
scripts/check_source_size.py, ruff check src tests, ruff format --check src tests, mypy (285 files) and tach check all passed.
pytest -n 8: 15218 passed, 41 skipped, 1 failed. The failure is the known local-only test_device_login_prefixes::test_the_measured_release_is_the_installed_one: the venv has litellm 1.100.3 and can't re-sync behind the mirror.
The version-matrix scenario skips locally because there is no kind cluster; the matrix workflow runs it on this PR.
Checklist
This closes an accepted issue in this repository that is assigned to me.
Tests cover the change, written to fail first where behavior changed.
make check passes locally.
User-facing docs and the README match the change, or nothing user-facing changed.
No security invariant is weakened: writes still need a keystroke approval
and a fail-closed audit entry, and sensitive reads are still masked.
ui/widgets/creation_constraints_screen.py renders a CreationReport: the
workload and its counters, one S6 line per source, recorded failures with
their classification, quotas with grouped values, limit and stale markers
and scopes, LimitRanges, and notes on what is not established. Enter
returns where a row leads. evidence_text gains elapsed_text for the
failures' ages.
Part of #525
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
ui/creation_constraints_controller.py runs explain_creation in one
exclusive worker under a run token, opens the view only while the token,
the view, scope and selection are current and no dialog is open, and
opens a row's object in its table in the run's epoch. The shared fake UI
surface now records whether a worker is exclusive.
Part of #525
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The command and its palette entry Explain workload creation failures reach
the controller through the router; the palette greys it out with the
controller's own reason; a context switch cancels its worker group; and a
failed run is reported instead of crashing the app.
Part of #525
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
A namespace whose quota admits no Pod, a LimitRange, and a Deployment: the
scenario waits for the ReplicaSet's recorded rejection and checks it is
read next to the quota and LimitRange, without the template's literal
environment value reaching the report.
Part of #525
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
The screen presents unreadable constraint and quota data as confirmed absences, misattributes child-workload events, and leaves time-dependent table cells stale during refresh.
Adds the read-only :blocked view for workload creation failures, building on the core diagnostics from #524. This delivers the view portion of #411 through #525, placing recorded rejections alongside namespace quotas and LimitRanges.
Changes:
Adds the diagnostic screen, controller, command and palette entry, with context-safe navigation and worker handling.
Adds UI coverage and a Kubernetes version-matrix quota-rejection scenario.
Documents the command, evidence boundaries and supported scenario.
File
Description
tests/version_matrix/test_scenarios.py
Checks recorded quota rejection alongside namespace policies.
tests/version_matrix/fixtures.yaml
Adds a quota-blocked Deployment and LimitRange.
tests/ui/test_worker_failures.py
Checks diagnostic worker failure reporting.
tests/ui/test_session_timeline_controller.py
Records worker exclusivity in the shared fake.
tests/ui/test_evidence_text.py
Tests elapsed-time formatting.
tests/ui/test_creation_constraints_workflow.py
Covers command-to-screen navigation and failures.
tests/ui/test_creation_constraints_screen.py
Covers rendering, attribution, navigation and ageing.
…rent
- A quota or LimitRange the projection could not read in full shows
'constraints could not be read' instead of 'no hard limits' or 'no
constraints'.
- The earlier-incarnations note covers the workload and its ReplicaSets or
Jobs, whose own UIDs can change.
- The refresh timer re-renders the table's time-dependent cells too:
failure ages, and whether a quota missing from the list is gone or just
not read.
Part of #525
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Navigation can open the wrong resource table when custom API aliases collide, and multiline admission-denial messages are truncated by one-line table rows.
No open issues 🎉
2 previously missed issues
In code that hasn't changed since last review
Preserve API group when resolving failure destinations
The destination drops the workload's API group and uses its plural as a view alias. If a custom API wins the replicasets or jobs alias, Enter opens that foreign table rather than the native failure subject; jump_to_object looks up the supplied alias directly, and the UID guard cannot correct the wrong resource type. Preserve the group/plural identity and resolve it through resolve_resource and canonical_resource_alias before navigating, as WorkspaceController.drill_into already does.
Allow multiline rejection messages to display fully
_failure_row preserves rejection messages verbatim, including newlines, but DataTable.add_row defaults to a one-line row. A multiline admission denial therefore displays only its first line; horizontal scrolling cannot reveal the remaining lines, and Enter opens the workload rather than the full message. Use automatic row height so the complete rejection remains readable, and cover a multiline message in the screen tests.
- A Destination carries the API group; the controller resolves it with
resolve_resource and canonical_resource_alias, so a custom API holding
the replicasets or jobs alias cannot receive the navigation, and an
undiscovered resource is reported instead of opened.
- Data rows grow to fit a multiline rejection message.
Part of #525
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot's two "previously missed" issues from the 9a18c16 review are addressed in 1e43e43, each with a failing test first:
API group on navigation:Destination now carries group and resource instead of a view alias. The controller resolves it with resolve_resource and canonical_resource_alias, as WorkspaceController.drill_into does. A custom API that won the replicasets alias can no longer receive the navigation; it goes to replicasets.apps. A resource the session has not discovered is reported in a warning instead of opened. Tests: test_a_destination_is_opened_under_its_own_api_group_not_a_colliding_alias and test_a_destination_this_session_does_not_serve_is_said_not_opened.
Multiline messages: data rows are added with height=None, so a multiline rejection message is shown in full. Test: test_a_multiline_message_is_shown_in_full (a three-line message gives a three-line row).
A quota with matching spec and status hard limits but an unparsable status.used value has stale=False and Usage.NOT_ESTABLISHED. This branch renders the same blank note as BELOW, hiding that the comparison could not be made. Add an explicit comparison-not-established marker after the stale-status check so unknown usage stays distinct from usage below the limit.
- No recorded failure names Events and conditions only when the workload
and its children were read, and conditions only for Deployments and
ReplicaSets; otherwise it names Events and says the rest is not
established.
- A quota resource whose comparison is not established is marked so,
never left blank like usage below the limit.
- The multiline test checks the message text, the workflow fake checks the
name and namespace read, and a test type error is fixed.
Part of #525
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot's "previously missed" issue from the 1e43e43 review is addressed in 60c34bb. A quota resource whose comparison is Usage.NOT_ESTABLISHED but whose status is current, such as an unparsable used value, is now marked "not established" instead of being left blank like usage below the limit. Test: test_an_unestablished_comparison_is_marked_not_left_blank.
The same commit fixes the pre-commit and test (3.11) failures on 1e43e43: a mypy error in my new test, which passed a tuple where Coordinate is required.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
area: uiTextual application, screens, widgets, and interaction designenhancementNew feature or request
2 participants
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #525
Summary
The view half of slice Q1 of #411, built on the core run from #524. The plan is
docs/superpowers/plans/2026-10-30-creation-constraints-view.md.:blocked, or Explain workload creation failures in the Action Palette, opens a read-only view on the selected Deployment, ReplicaSet, StatefulSet, DaemonSet, Job or CronJob. No default key is bound.ui/widgets/creation_constraints_screen.py):used X / hard Y), marked "at its limit" or "status not yet updated", with scopes.ui/creation_constraints_controller.py): follows the:consumerscontroller. One exclusive worker runs under a run token; a stale result is dropped; availability reasons are given; the context switch cancels the group; a failed worker is reported.__main__.korvid-matrix-quotanamespace with apods: "0"quota, a LimitRange and a Deployment. Its scenario waits for the ReplicaSet's recorded rejection and checks it is read next to the policies, without the template's literal reaching the report. Thecreation_*modules andk8s/events.pyjoin the workflow's path filters.docs/tui.md("Workload creation failures"),docs/keybindings.md,docs/kubernetes-support.mdand the unreleased notes.Verification
tests/ui/test_creation_constraints_screen.py: 25 tests covering rows, attribution, markers, notes, keys, literal text and ageing.tests/ui/test_creation_constraints_controller.py: availability, the read set, late results, navigation and cancellation.tests/ui/test_creation_constraints_workflow.py: from:deployments,:blockedand Enter lead to the ReplicaSet; the wrong view says what to open; a failed run is reported.child is not None: a target without a child kind never has a children observation).scripts/check_source_size.py,ruff check src tests,ruff format --check src tests,mypy(285 files) andtach checkall passed.pytest -n 8: 15218 passed, 41 skipped, 1 failed. The failure is the known local-onlytest_device_login_prefixes::test_the_measured_release_is_the_installed_one: the venv has litellm 1.100.3 and can't re-sync behind the mirror.Checklist
make checkpasses locally.and a fail-closed audit entry, and sensitive reads are still masked.