Skip to content

Known scars, and how to get past them

Before this: Vibe or spec, and when settled which session type fits the work in front of you.

This is a lookup surface, not a lesson. Every entry below is one symptom, one cause, one fix, in that order, so you can scan for the symptom you are actually looking at. If gator verify
Offline Gatekeeper test runner that evaluates constraint suites and cases before any cluster exists.
is what sent you here, work the triage order first.

  1. Confirm the suite count. A full run reports 14 suites; a smaller number means the path you passed never resolved to all of them, and the assertion you care about was skipped rather than failed.
  2. Re-read the failing case name. It names the suite directory and the case file, which is where the assertion lives, not where the rule lives.
  3. Open the case object. The YAML under infrastructure/gatekeeper/tests/ is the exact input the rule was evaluated against.
  4. Open the constraint match scope. The match block under infrastructure/gatekeeper/constraints/ decides whether your object was ever in scope, and an out-of-scope object produces no violations at all.

Symptom: the CLI reports 3.22.0 while the vendored Gatekeeper
OPA Gatekeeper — Kubernetes admission controller that evaluates ConstraintTemplates against cluster objects.
chart says 3.21.1, which reads like a broken install.

Cause: the CLI pin is the GATOR_VERSION default in scripts/install-gator.sh, and the chart carries its own version and appVersion in infrastructure/gatekeeper/base/vendored/chart/gatekeeper/Chart.yaml.

Fix: keep the pinned CLI rather than downgrading it, and read Install the toolchain for why the mismatch is expected.

Symptom: the scaffold is blocked and the hook message names one manifest along with the conflicting minAvailable and replicas values it found.

Cause: minAvailable: 1 is only valid once replicas is 2 or greater, and the rule is encoded twice, in .kiro/steering/ and in .kiro/hooks/validate-app-scaffold.kiro.hook.

Fix: raise replicas to 2 or greater in both overlays, or drop the PodDisruptionBudget
PodDisruptionBudget — limits voluntary disruptions; the factory scar requires replicas >= 2 when minAvailable is 1.
.

Symptom: account IDs 111122223333 and 444455556666 and region ap-southeast-2 appear throughout the trees, and nothing complains locally.

Cause: those are documentation placeholders carried through .kiro/steering/ so the trees build without real accounts; 111122223333 stands for dev (dev-eks-1) and 444455556666 for prod (prod-eks-1).

Fix: substitute your own account IDs and region, then re-run the offline builds before anything touches IAM
AWS Identity and Access Management — you still shrink roles to least privilege; the factory does not invent that judgement.
or ECR
Amazon Elastic Container Registry — image registry used when the factory retags or pulls app images.
.

Symptom: the run exits without executing a single case and reports a test count of zero.

Cause: the path you passed does not resolve to any suite.yaml under infrastructure/gatekeeper/tests/<name>/.

Fix: rerun gator verify against a path that resolves to all 14 suites, and confirm the reported suite count is 14.

Symptom: a case fails with a reported expected violation count that differs from the actual count, while the constraint itself behaves exactly as designed.

Cause: the asserted count in the sibling pass.yaml or fail.yaml case object does not match the number of violations the ConstraintTemplate rule produces for that object.

Fix: reconcile the asserted count with the rule output, then rerun to a zero exit code.

A constraint match scope excludes the reviewed object

Section titled “A constraint match scope excludes the reviewed object”

Symptom: a fail.yaml object produces zero violations, so the negative case passes without ever exercising the rule it exists to prove.

Cause: the match scope in infrastructure/gatekeeper/constraints/<name>/constraint.yaml excludes the reviewed object’s kind or namespace.

Fix: align that match scope with the case object and confirm the fail case now reports at least one violation.

One consolidated page is the choice here, and the alternative it beat was an inline callout wherever each scar bites: a note about the version pin on the install page, a note about the PDB rule beside the generated PodDisruptionBudget, a note about placeholders next to every account ID. That reads better on first pass and rots on the second, because six copies of an explanation drift until they contradict each other and nobody knows which one is current. It is the same reason the version skew is explained once on Install the toolchain and only summarised here: one authority, one place to correct.

The cost of that choice, stated rather than hidden, is a page you have to remember exists. And the gotcha this page owes about itself: nothing in continuous integration verifies that a file quoted on these pages still matches the file it was copied from. The fidelity check needs a clone of the factory repo to compare against, and it skips with a notice when there is none, so a quoted block that drifted upstream stays green until a human notices. Treat every quoted block as dated, and follow its link when the detail matters.

Next: Evidence checklist collects what Labs A-C actually proved.