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
The design for #411, before any code: docs/superpowers/specs/2026-10-30-creation-constraints-design.md. Merging it approves the design; each slice then gets its own sub-issue and PR.
A read-only view opened on a Deployment, ReplicaSet, StatefulSet, DaemonSet, Job or CronJob, through :blocked or Explain workload creation failures. It shows the creation failures recorded for the workload next to the namespace's ResourceQuotas and LimitRanges. It keeps four answers apart: a recorded rejection, a possible current constraint, no standard policy observed, and not established.
its owned ReplicaSets, for a Deployment, or its owned Jobs, for a CronJob;
Events, listed and filtered locally to FailedCreate events matched by UID;
quotas and LimitRanges.
Templates are projected at once, so no literal environment value leaves the run.
Classification relies only on fixed quota and LimitRanger phrasings. A quota is attributed only by the name its message gives. A LimitRange message is attributed to "a LimitRange in this namespace", because LimitRanger messages don't name one. Anything else is shown verbatim, attributed to nothing.
Quantities are shown as written and compared as exact Decimals. Computed amounts keep the limit's unit family and are never rounded.
Evidence:
stale or missing quota status is downgraded with downgrade_stale_status;
"no quota" is said only when the list is conclusive;
Events can only confirm a failure, never rule one out;
recreated workloads and earlier incarnations' events are kept apart.
Delivery:
Q1 core;
Q1 view, with a version-matrix scenario;
Q2: possible constraints, from the template's demand with LimitRange defaults, quota scope applicability and LimitRange checks.
The seven decisions in the spec's "Decisions" section were confirmed by the maintainer. Two changed from the proposal: CronJobs are in scope, and the command is :blocked.
Verification
Documentation only; no code changed. I checked the spec's claims against the code:
parse_quantity in k8s/models.py;
EVENTS and its retention-limited policy in core/api_versions.py;
downgrade_stale_status in core/capability.py;
the event time precedence in k8s/events.py;
Pulse's ReplicaFailure rule in core/pulse_rules.py;
the existing command aliases in ui/command.py.
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. (No behavior changed.)
make check passes locally. (Documentation only; pre-commit hooks ran on commit.)
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.
A read-only view on a Deployment, ReplicaSet, StatefulSet, DaemonSet or Job
showing recorded FailedCreate rejections next to the namespace's
ResourceQuotas and LimitRanges, with exact quantity handling, stale-status
downgrades, and possible constraints in a second slice.
Part of #515
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
Unresolved projection and resource-accounting gaps can miss or falsely report creation constraints, while legacy event handling can lose repetition counts and misorder failures.
This documentation-only PR proposes workload creation-failure explanations for #411, building on the shared capability-aware diagnostic readers and lifecycle. No runtime behavior changes.
Changes:
Defines a read-only workload view combining UID-matched creation failures with namespace quotas and LimitRanges.
Specifies projections, rejection classification, quantity handling, and evidence boundaries.
Splits delivery into Q1 core/view work and Q2 possible-constraint calculations, with testing requirements.
- Keep init containers' order and restartPolicy, and runtimeClassName.
- Count and date older events by deprecatedCount and
deprecatedLastTimestamp.
- Conflicting LimitRange defaults, unknown RuntimeClass overhead and
Pod-level resources per resource leave demand not established or
override it precisely.
- BestEffort follows the Pod's QoS, and StatefulSet claims are a
conditional demand.
Part of #515
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
Unresolved quota-evaluation gaps around admission-assigned defaults, mandatory resource fields, and incomplete usage data can produce incorrect constraint findings or unsupported unconstrained-template conclusions.
No open issues 🎉
4 previously missed issues
In code that hasn't changed since last review
Downgrade conclusions when quota usage entries are missing
Even when status.hard matches spec.hard, a missing status.used entry leaves usage unknown and can cause a status unknown for quota rejection. This rule would leave the observation conclusive without an established value for used + demand. Include incomplete usage maps in the downgrade rule and test matching hard maps with a missing used key.
Treat omitted priority class as unknown for quota applicability
An omitted priorityClassName does not establish that the created Pod has no class: Kubernetes' Priority admission plugin assigns the global-default PriorityClass before quota evaluation. With a default class gold and a PriorityClass In [gold] quota of zero Pods, this predicate would skip the applicable quota and permit the unconstrained-template conclusion. Since PriorityClasses are cluster-scoped and outside these reads, mark applicability and dependent negative conclusions as not established when the template's class is empty.
The compute group explicitly includes hugepages, but Kubernetes' quota validationSet requires fields only for the CPU/memory request and limit keys. A quota on requests.hugepages-2Mi does not require an ordinary Pod to request hugepages, whereas this rule would report a constraint. Enumerate the CPU/memory keys instead of using the display grouping; their mandatory-field checks also need to retain per-container missingness rather than relying solely on aggregate Pod demand.
Preserve omitted versus empty storage class as unknown
When a claim template omits storageClassName, admission can assign an unread default class, so checking only the template's class can miss an exhausted per-class quota. Conditional claim creation does not resolve that unknown class. Preserve absent versus explicitly empty class names, and mark affected per-class checks and dependent unconstrained-template conclusions as not established.
- An incomplete status.used map makes quota status stale.
- A PriorityClass selector with no priorityClassName, and a claim
template that omits storageClassName, are not established: admission
may assign cluster defaults the view does not read.
- Only CPU and memory keys require a field, checked per container.
Part of #515
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot's "previously missed issues" from the e335bda review are addressed in f3eb872:
Missing status.used entries: an incomplete used map now counts as stale status and is downgraded to PARTIAL/STALE_STATUS. The test plan includes matching hard maps with a missing used key.
Omitted priority class: a PriorityClass selector is not established without priorityClassName, because admission may assign a global default the view does not read.
Required quota fields: only requests.cpu, cpu, limits.cpu, requests.memory, memory and limits.memory require a field. The check is per container, so the projection keeps which container lacks what. Hugepages and extended resources are excluded.
Omitted vs. empty storage class: the projection keeps them apart. When the class is omitted, per-class checks and "nothing constrains this template" are not established. An explicitly empty class matches no per-class quota.
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
The quota rule omits the PodLevelResources exemption and must leave results unestablished when admission behavior is unknown to avoid spurious per-container CPU or memory requirements.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Human assessment is needed to evaluate whether propagated ReplicaFailure conditions could misclassify Pod deletion failures as creation failures and admission rejections.
Copilot's 4ea6123 review asked whether a propagated ReplicaFailure condition could turn a Pod deletion failure into a creation failure. It could: the ReplicaSet controller also sets ReplicaFailure with reason FailedDelete. As of 8e0540b, a condition counts only when its status is True and its reason is FailedCreate. The test plan covers FailedCreate, FailedDelete (not shown) and status False.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Human assessment is needed because the specified unconditional stale-status downgrade conflicts with its available-only precondition when quota reads are partial.
Copilot's 8e0540b review pointed out that downgrade_stale_status accepts only an AVAILABLE observation. As of 43dd21e, an AVAILABLE quotas observation is downgraded to PARTIAL/STALE_STATUS, and one that is already PARTIAL (e.g. truncated) keeps its own, already inconclusive basis. Either way the stale quota's rows say "status not yet updated". The test plan covers a stale quota in a truncated list.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Seven unresolved design choices, including workload coverage and namespace-wide Event listing under bounded truncation, require maintainer agreement on scope and evidence tradeoffs before implementation.
- CronJobs are in scope: the view follows a CronJob's own FailedCreate
and its owned Jobs' events.
- The command is :blocked.
- The other five decisions stand as proposed.
Part of #515
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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
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 #515
Summary
The design for #411, before any code:
docs/superpowers/specs/2026-10-30-creation-constraints-design.md. Merging it approves the design; each slice then gets its own sub-issue and PR.A read-only view opened on a Deployment, ReplicaSet, StatefulSet, DaemonSet, Job or CronJob, through
:blockedor Explain workload creation failures. It shows the creation failures recorded for the workload next to the namespace's ResourceQuotas and LimitRanges. It keeps four answers apart: a recorded rejection, a possible current constraint, no standard policy observed, and not established.FailedCreateevents matched by UID;Templates are projected at once, so no literal environment value leaves the run.
Decimals. Computed amounts keep the limit's unit family and are never rounded.downgrade_stale_status;The seven decisions in the spec's "Decisions" section were confirmed by the maintainer. Two changed from the proposal: CronJobs are in scope, and the command is
:blocked.Verification
Documentation only; no code changed. I checked the spec's claims against the code:
parse_quantityink8s/models.py;EVENTSand its retention-limited policy incore/api_versions.py;downgrade_stale_statusincore/capability.py;k8s/events.py;ReplicaFailurerule incore/pulse_rules.py;ui/command.py.Checklist
make checkpasses locally. (Documentation only; pre-commit hooks ran on commit.)and a fail-closed audit entry, and sensitive reads are still masked.