Skip to content

chore(agents): make pre-ci detect changed areas and close the frontend gap - #10405

Merged
pa-lem merged 13 commits into
stablefrom
ple-pre-ci-frontend
Aug 28, 2026
Merged

chore(agents): make pre-ci detect changed areas and close the frontend gap#10405
pa-lem merged 13 commits into
stablefrom
ple-pre-ci-frontend

Conversation

@pa-lem

@pa-lem pa-lem commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Problem

/pre-ci describes itself as running "all locally-executable CI checks", but it ran only part of the frontend gate. It could report all-green while frontend-lint and frontend-tests failed on the PR.

Checked against .github/workflows/ci.yml:

Missing entirely

  • pnpm knip — step 2 of the frontend-lint job
  • pnpm test:coverage — the frontend-tests job (Phase 4 ran only backend.test-unit)
  • frontend/packages/graph tests — a separate step of the same job, outside frontend/app

Wrong variants

  • npx biome check --write . instead of pnpm exec biome ci . — the auto-fix variant, not the check-only one CI asserts
  • npx betterer instead of pnpm exec betterer ci — bare betterer rewrites the snapshot rather than failing on an increase
  • npx / npm used throughout a pnpm workspace

Change

Phase 0 — detect what changed. Diffs against the merge-base with origin/develop (falling back to origin/stable) and includes the working tree, since uncommitted work is about to be pushed too. Paths are classified with the same globs as .github/file-filters.yml, so each area's phases run only when relevant. --all forces every phase.

Phase 3 — complete frontend gate, at CI parity, with each command annotated with the job it mirrors.

Two things worth flagging for reviewers:

  • frontend-lint has no path filter in ci.yml — it runs on every PR. A backend-only change still fails CI if frontend lint is broken. Phase 3A therefore always runs the lint trio regardless of detection.
  • frontend-tests runs a second suite in frontend/packages/graph. It is also absent from the four-command gate documented in frontend/app/AGENTS.md.

The summary table now lists skipped rows explicitly (skipped (no backend changes)) rather than omitting them, so partial coverage is visible rather than reading as a full pass.

Notes

  • No changelog fragment: internal agent tooling, not user-facing.
  • Detection is path-based only — no branch-name logic, so it behaves the same for everyone.

🤖 Generated with Claude Code

Review in cubic

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 1 file

Shadow auto-approve: would not auto-approve because issues were found.

Re-trigger cubic

Comment thread .agents/commands/pre-ci.md Outdated
Comment thread .agents/commands/pre-ci.md Outdated
Comment thread .agents/commands/pre-ci.md Outdated
Comment thread .agents/commands/pre-ci.md Outdated
Comment thread .agents/commands/pre-ci.md Outdated
@saltas888

Copy link
Copy Markdown
Contributor

Would it make sense to point stable?

@pa-lem
pa-lem changed the base branch from develop to stable August 26, 2026 08:18
@pa-lem
pa-lem requested review from a team as code owners August 26, 2026 08:18
@pa-lem
pa-lem requested a review from minitriga August 26, 2026 08:18
@pa-lem
pa-lem marked this pull request as draft August 26, 2026 08:19
@pa-lem
pa-lem removed request for a team and minitriga August 26, 2026 08:19
@pa-lem
pa-lem changed the base branch from stable to develop August 26, 2026 08:20
@pa-lem
pa-lem force-pushed the ple-pre-ci-frontend branch 2 times, most recently from 4fbe926 to cae9f48 Compare August 26, 2026 08:32
@pa-lem
pa-lem changed the base branch from develop to stable August 26, 2026 08:33
@pa-lem
pa-lem marked this pull request as ready for review August 26, 2026 08:35
@pa-lem
pa-lem force-pushed the ple-pre-ci-frontend branch from cae9f48 to 6f8a302 Compare August 26, 2026 12:59

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 1 file (changes from recent commits).

Confidence score: 5/5

  • In .agents/commands/pre-ci.md, the git status --porcelain parsing only handles plain paths; pending renames output as R old -> new would be treated as a literal path and fail to match area globs, potentially skipping a staged rename from the diff. Since this is a build/pre-ci helper with no user-facing impact, it's low risk, but consider using git diff --name-only or splitting on whitespace before the arrow to cover renames.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name=".agents/commands/pre-ci.md">

<violation number="1" location=".agents/commands/pre-ci.md:45">
P3: The porcelain `cut -c4-` parsing does not handle pending renames: `git status --porcelain` reports them as `R  <old> -> <new>`, which becomes the literal path `old -> new` and matches no area glob, so a staged-but-uncommitted rename can be classified as 'no changes'. Use `git status --porcelain -z` NUL parsing or split rename lines on ' -> ' to capture both paths.</violation>
</file>

Shadow auto-approve: would not auto-approve because issues were found.

Re-trigger cubic

Comment thread .agents/commands/pre-ci.md Outdated
Comment thread .agents/commands/pre-ci.md Outdated
Comment thread .agents/commands/pre-ci.md Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 1 file (changes from recent commits).

Shadow auto-approve: would not auto-approve because issues were found.

Re-trigger cubic

Comment thread .agents/commands/pre-ci.md Outdated
Comment thread .agents/commands/pre-ci.md

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 1 file (changes from recent commits).

Shadow auto-approve: would not auto-approve because issues were found.
Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread .agents/commands/pre-ci.md Outdated
Comment thread .agents/commands/pre-ci.md Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 1 file (changes from recent commits).

Shadow auto-approve: would not auto-approve because issues were found.
Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread .agents/commands/pre-ci.md Outdated
pa-lem and others added 4 commits August 27, 2026 11:00
…d gap

Scope the pre-ci checks to the areas actually touched, and bring the frontend
side up to full parity with ci.yml.

- Add a Phase 0 detection step whose area globs mirror the `<area>_all` lists in
  .github/file-filters.yml, so local gating matches the `files-changed` outputs
  CI branches on.
- Always run the frontend lint trio: the `frontend-lint` job has no path filter,
  so a backend-only change still fails CI when frontend lint is broken.
- Cover the frontend checks that were missing entirely: `knip`, `betterer ci`,
  the `@infrahub/graph` package suite, and the three generated-artifact
  validations (openapi types, graphql types, error catalogue bindings), each
  gated on the same narrow filter as its CI job rather than the whole frontend
  area.
- Correct the CI job names in the summary table: there is no `backend-lint` job
  (ty runs in `python-lint`), JSON schema validation is `json-schema` not
  `openapi-schema`, docs.lint maps to `markdown-lint` and
  `validate-documentation-style` rather than `documentation`, and the lockfile
  check lives in uv-check.yml.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…pre-ci

Address the open cubic review threads.

- Add a `yaml` area and a Phase 2C running `uv run yamllint -s .`, the exact
  command CI's `yaml-lint` job runs. That job fires on any `**/*.{yml,yaml}`
  change, so a yaml-only edit previously passed pre-ci all-green and could
  still fail CI.
- Split `**/*.py` out of the `backend` area into its own `python` area gating
  only the lint phases. `python-lint` fires on `backend || python`, but
  `backend-tests-unit`, `graphql-schema` and `json-schema` gate on `backend`
  alone, so a change to `models/` or a root script no longer drags in the slow
  backend phases.
- Unwrap `git status`'s rename form in the Phase 0 detection snippet, which
  otherwise yields the literal path `old -> new` and matches no area.
- Correct the 4B rationale: `.yamllint.yml` ignores `.venv`, so the reason to
  call `backend.lint` directly is that `invoke lint` bypasses the area gating,
  not a vendored-package failure. Drop `python_testcontainers/**` from the
  backend row - it is in `e2e_all`, not `backend_all`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ase ref

Address the second round of cubic review threads.

- Add a `testcontainers` area and Phase 5.2 running
  `uv run --directory python_testcontainers pytest --rootdir=. -c pyproject.toml
  -vs tests`, mirroring the `backend-testcontainers-unit` job. That suite was
  never covered: `backend.test-unit` runs `backend/tests/unit` only, and
  `python_testcontainers` is a separate uv project. The job also fires on any
  `.github/workflows/*.yml`, not just `ci.yml`.
- Fix Phase 0 base-ref selection. Both `develop` and `stable` exist, so
  preferring `develop` unconditionally diffed a stable-based branch against a
  merge base tens of commits back - on this branch it reported 28 changed files
  instead of 4, marking every area as changed. Pick whichever candidate leaves
  HEAD fewest commits ahead instead.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…o pre-ci

Address the third round of cubic review threads.

- The Phase 0 pipeline called `git rev-list`, `sort`, `head`, `cut` and `sed`,
  none of them in `allowed-tools`, so the documented detection could not run
  without extra authorization. Rewrite it to use only `git rev-parse`,
  `git merge-base`, `git diff`, `git ls-files` and `sort`: base selection now
  compares the two merge bases with `--is-ancestor` instead of counting
  commits, and uncommitted work comes from `git diff HEAD` plus `git ls-files
  --others` instead of parsing `git status --porcelain`. `--no-renames` keeps
  both sides of a rename so the area that lost the file is still flagged.
- Add `uv run ty check .` to Phase 2B. CI's `python-lint` job runs it on the
  `python` filter, but ty was only reachable through Phase 4B `backend.lint`,
  which the `python` area does not enable - so a `models/` or root-script
  change cleared pre-ci and still failed CI. 4B now advertises mypy as what it
  adds.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The previous commit claimed Phase 1B made CI's `ruff format --check` step
redundant. It does not: `uv run invoke format` reformats only `tasks`,
`models`, `utilities`, `python_testcontainers` and `backend`, while
`python-lint` runs `ruff format --check --diff --exclude python_sdk .` over the
whole repo. An unformatted file under `development/`, `tests/` or the repo root
cleared pre-ci and still failed CI - the same coverage gap already documented
one step earlier for `ruff check`.

Add the whole-repo format check as its own Phase 2B step.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@pa-lem
pa-lem force-pushed the ple-pre-ci-frontend branch from fee04b7 to 85c0c04 Compare August 27, 2026 09:00

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 1 file

Shadow auto-approve: would not auto-approve because issues were found.

Re-trigger cubic

Comment thread .agents/commands/pre-ci.md Outdated
Comment thread .agents/commands/pre-ci.md Outdated
Comment thread .agents/commands/pre-ci.md Outdated
…n area

Address the fourth round of cubic review threads.

- Add a `schema` area (`schema/**`) enabling Phase 4D. The phase guard already
  read "if backend or schema/** changed" and the note called that deliberately
  stricter than CI, but Phase 0 classified paths into six areas and none of
  them was schema - a schema-only change detected nothing and 4D could never
  fire.
- Guard every base ref, not just `origin/develop`. On a fork or a remote
  carrying only one of the two branches, the unguarded
  `git merge-base HEAD origin/stable` aborted the block and left `MERGE_BASE`
  empty, silently detecting nothing instead of degrading to the documented
  all-areas fallback. The loop now handles both refs the same way and falls
  through when neither resolves.
- Fetch `stable` and `develop` before comparing merge bases. Stale refs move a
  merge base backwards, which usually just over-detects, but between two
  candidates a stale ref can flip the choice and narrow the diff instead. Warn
  and treat the run as best-effort if the fetch fails.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 1 file (changes from recent commits).

Shadow auto-approve: would not auto-approve because issues were found.
Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread .agents/commands/pre-ci.md
Four rounds of review fixes each left a paragraph of rationale behind, and the
justification had grown longer than the instructions it justified.

Collapse it: Phase 0's four explanatory paragraphs become one "do not simplify
this" bullet list, Phase 2B's per-step essays become a single note covering
steps 2-4, and every phase keeps its command, its gate and the trap worth
naming - `biome ci` not `check --write`, `betterer ci` not bare, 3A always
runs, `--no-renames`, the separate uv project behind 5.2.

No command, gate or summary row changes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 issues found across 1 file (changes from recent commits).

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Shadow auto-approve: would auto-approve. Updates the pre-ci agent command to detect changed areas and add frontend lint/test checks at CI parity. Pure internal developer tooling documentation with no production, security, or contract impact.

Re-trigger cubic

@polmichel polmichel left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a great idea 👍
Have you tried to use /pruning-residues skill on this skill? When I've run it locally it offers me to trim/condense a number of items.

Comment thread .agents/commands/pre-ci.md Outdated
…script

Phase 0 was a shell block that picked a base ref by comparing merge bases,
plus five bullets defending each of its lines. Replace it with the instruction
itself: find the areas this branch touched relative to whichever long-lived
branch it forked from, and include anything uncertain. `release-*` bases now
work without extending a script.

Also prune the commentary the review loop deposited across the rest of the
file — restated rationale, "easy to miss" framing, and defences of choices
against alternatives no longer present.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 1 file (changes from recent commits).

Shadow auto-approve: would not auto-approve because issues were found.
Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread .agents/commands/pre-ci.md Outdated
Verified every command and job name in the file against .github/workflows/ci.yml
and .github/file-filters.yml:

- `--fast` claimed to skip ty, but `ty check .` now runs in Phase 2B, before the
  --fast stop point. Only mypy is skipped.
- The area table claimed each row was a verbatim `<area>_all` list. Two rows are
  deliberate deviations (`python` narrower, `schema` has no CI filter); say so
  instead of over-claiming parity.
- `docs.validate` mirrors `validate-generated-documentation`, which fires on
  `python || documentation` — the reference docs are generated from Python source.
  Gate 4C.2 accordingly.
- `infrahub-testcontainers-uv-check` had no local mirror; add the second
  `uv lock --check` for the python_testcontainers project.
- Summary table named a workflow file, not a job: `uv-check (uv-check.yml)` is
  really `infrahub-uv-check` plus `infrahub-testcontainers-uv-check`.
- backend enables Phase 5.1, not all of Phase 5 (5.2 is the testcontainers suite).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 1 file (changes from recent commits).

Shadow auto-approve: would not auto-approve because issues were found.
Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread .agents/commands/pre-ci.md
4C.2 was gated on the `python` area alone, but that area is written as "any
*other* `**/*.py`" so `backend/foo.py` lands in `backend` and never reached it.
CI's `python` filter is `**/*.py` including `backend/**`, so a backend-only
Python change fires `validate-generated-documentation` while pre-ci reported
all-clear. `backend.validate-generated` does not cover the reference docs — it
diffs `core/schema/generated`, `protocols.py` and the SDK submodule, never
`docs/` — so nothing else caught it. Enable 4C.2 for `backend` too.

Phase 0 asked for "both sides of a rename" without saying how, and the
allowed-tools list offered `git status`, whose `R  old -> new` collapses into a
single unmatched path. Name the three collection commands and the
`--no-renames` requirement, and drop `git status` from allowed-tools.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 1 file (changes from recent commits).

Shadow auto-approve: would not auto-approve because issues were found.
Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread .agents/commands/pre-ci.md Outdated
The note claimed `git status --porcelain` collapses `R old -> new` into one path
that matches no area. It does not: the entry carries both paths. That claim was
true only of the `cut -c4-` pipeline it was originally written about, which
yields the literal string `old -> new`; the premise went away when the pipeline
did.

Justify `--no-renames` by what it actually prevents — verified against a real
rename, `git diff --name-only HEAD` reports only the new path — and drop the
`git status` aside, which no longer has a tool in allowed-tools to warn about.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 issues found across 1 file (changes from recent commits).

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Shadow auto-approve: would auto-approve. Updates the pre-ci agent command definition to detect changed areas and run frontend lint/test checks at CI parity. Pure internal developer tooling; no production, security, data, or contract impact.

Re-trigger cubic

Three rounds of review left justifications aimed at the reviewer rather than at
the agent that runs this command: proof that the 4C.2 gap was real, a defence of
which areas diverge from CI's filters, and two rebuttals of "isn't this step
redundant?". Each rule they argue for is already stated by a phase gate or an
area row, so the argument is noise to whoever reads this next.

Gating, commands and job names are untouched. Also drops the now-unused
`Bash(sort:*)` permission — Phase 0 no longer shows a pipeline.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 1 file (changes from recent commits).

Shadow auto-approve: would not auto-approve because issues were found.
Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread .agents/commands/pre-ci.md Outdated
The previous commit cut the caveat but left the absolute claim it qualified:
"local gating matches the files-changed outputs CI branches on" is false for two
rows. `backend_all` carries no `schema/**` entry, so graphql-schema and
json-schema never fire on a schema-only change and Phase 4D exists only behind
the local `schema` area; `python` is narrower than CI's `**/*.py` on purpose.

An agent told to match CI would resolve the contradiction by deleting the schema
area or widening python — both regressions. Mark the two rows as intentional
instead, in one line rather than the paragraph that was cut.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 issues found across 1 file (changes from recent commits).

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Shadow auto-approve: would auto-approve. Updates the internal pre-ci agent command to detect changed areas and run frontend checks at CI parity; delta since prior approval is documentation wording cleanup only. Developer tooling; no production, security, data, or contract impact.

Re-trigger cubic

@polmichel polmichel left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool improvement 👍

@pa-lem
pa-lem merged commit decf073 into stable Aug 28, 2026
44 checks passed
@pa-lem
pa-lem deleted the ple-pre-ci-frontend branch August 28, 2026 12:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants