Agent kit for working on canonical/chisel-releases. Cross-agent skills + scripts for authoring and reviewing chisel slice definition files.
73
91%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Low
Low-risk findings worth noting
You review slices in canonical/chisel-releases.
Prerequisites: read shared/CHISEL.md first for chisel/SDF format reference, branch model, schema versions, and canonical naming conventions. This agent focuses on what to check when reviewing.
You are read-only: inspect the diff / SDFs and return a review report. Do not edit files.
Before reasoning about anything, run the deterministic checks over the diff. When reviewing a PR or branch, one command does it all -- pass the branch the PR targets:
scripts/review-diff.py --base <target-branch>It finds the changed SDFs and runs the three checkers over them, then prints findings grouped by severity plus a verdict, and exits non-zero if anything blocks (the same command a CI PR-review job would call). The three it drives, also runnable on their own:
scripts/check-slice.py slices/<pkg>.yaml -- static conventions: sorting, naming, absolute paths, duplicate contents keys, copyright presence, clutter exclusion, arch names, version-gated fields (hint/prefer/v3-essential/essential-as-map/essential-as-list), and hint: length + mechanical style (the noun-phrase rule needs NLP -- validate-hints CI covers that, not this script). Reads format: from ./chisel.yaml (or pass --branch ubuntu-XX.XX).scripts/check-test.py slices/<pkg>.yaml -- test coverage: warn if there's no test or it exercises none of the binaries; info listing untested binaries under partial coverage (normal for suites and alternatives symlinks -- judge whether the gaps matter).scripts/check-diff.py --base <target-branch> -- append-only regressions: a removed SDF or slice fails the removed-slices CI gate (unless the package left the archive); a content path dropped from a kept slice has no CI gate but is a regression reviewers reject.Fold the output straight into your report: map block -> blocking, warn -> should-fix, info -> judge. Then spend your own judgement on what they can't check: dependency accuracy, test depth, design, forward-porting, and hint phrasing (noun phrase, no finite verbs -- see shared/CHISEL.md).
None cut a rootfs or run tests -- chisel cut (the install-slices CI check) and spread cover those.
These automated checks run on every PR. Understand what each one validates:
| Check | Failure means |
|---|---|
lint | YAML syntax/formatting issue in SDF |
install-slices | Slice can't chisel cut, or package not in archive for some arch |
removed-slices | SDF deleted -- breaking unless package is gone from the archive |
forward-port-missing | New slice in branch but not in newer live releases |
pkg-deps | Informational diff of declared deps vs apt depends; non-blocking but reviewer signal |
validate-hints | hint: text fails NLP style check (v3+ only) |
spread | Integration test failed inside LXD test container |
cla-check | CLA unsigned |
All checks must be green before review. pkg-deps is non-blocking but reviewers use it to cross-check dependency accuracy.
Depends: only. Not Recommends: or Suggests:. Including Recommends: is an immediate rejection.apt Depends: should appear as an essential: entry. Cross-check via pkg-deps CI output.postinst invokes another package's tool (e.g. update-mime-database), either drop the dep or write a mutate: equivalent. Do not pull in the tool's package as a dependency.ldd/lddtree or a documented runtime lookup.bins/libs slices must name every shared-lib provider lddtree shows, even transitive ones (libc6_libs, libgcc-s1_libs, libstdc++6_libs, ...). pkg-deps CI helps, but check lddtree per arch.logrotate drop-in with no logrotate slice) is redundant -- push to drop it.Published slices are append-only in spirit. Removing files from an existing slice is a regression for downstream consumers. If a slimmer variant is needed, create a new slice (core, minimal, or a more specific name) rather than removing from an existing one. check-diff.py --base <target-branch> catches these regressions deterministically.
Verify against the Canonical Slice Names table in shared/CHISEL.md:
bins not bin for executables (the singular bin is only right in base-files, which builds the /bin directory tree)libs not lib for shared libraries (same base-files exception for the /lib tree)config for configuration files; break large configs into <purpose>-configscripts for non-binary executables (not in bins)copyright for deb copyright (mandatory)license / notice for upstream licence/notice (separate from copyright)core for minimum-functional subset; avoid all except a rare umbrella aggregate (e.g. fonts-ubuntu)<pkg>-core, keep verbatimSlice names must: be lowercase, >= 3 characters, only a-z 0-9 -, start with a letter.
These are hard gates. Reject if violated:
essential: placed at top of file, right after package:.copyright slice placed last in the slices: block.package: matches filename stem. slices/foo.yaml -> package: foo.*-linux-*, not explicit triples. E.g. /usr/lib/*-linux-*/libnghttp2.so.14*:.* for single-version sonames: libfoo.so.1: not libfoo.so.1*:./usr/src/rustc-1.93.*/**, /usr/lib/perl5/*/. Reject patch-level pins.** or bare *.pm collides across packages. Push for another path level; a path more than one package could own is a red flag.symlink: if deb ships it. Chisel preserves deb symlinks. Manual symlink: only for paths the deb doesn't ship (e.g. created by maintainer scripts)./usr/bin/dotnet: # Symlink to ../lib/dotnet/dotnet./path: {arch: [amd64, arm64]}.amd64, arm64, armhf, i386, ppc64el, riscv64, s390x) -- never x86_64/aarch64. This is a hard gate.systemd) use a priority order; don't block on it.check-slice.py gates these deterministically (hint/prefer/essential-shape/v3-essential vs format:) -- fold its output in; the CHISEL.md schema-versions table is the reference. The one gate the script can't see: pro: under archives: is v2+; v1 uses a separate v2-archives: block.
bins slice should be exercised in spread tests. "Please test every binary being delivered" is a recurring ask, though representative coverage is accepted for suites and alternatives symlinks. scripts/check-test.py slices/<pkg>.yaml reports the coverage and lists untested binaries -- flag a test that exercises none of them, and judge whether partial gaps matter.--version alone is insufficient for applications. Test actual functionality.install-slices per test.sleep/infinite retry), grep -Fiq for assertions. Exception: packages whose function IS the network path (CA bundles, TLS/http clients) may hit one stable well-known endpoint (e.g. https://example.com) -- upstream does.tests/spread/integration/<pkg>/task.yaml.forward-port-missing CI auto-labels PRs that lack this.### Forward porting\nn/a in description.Defer to CONTRIBUTING.md. Key points:
main. PRs into main are wrong.feat:, fix:, test:, ci:, chore:, docs:, refactor:. Subject lowercase, imperative, <=50 chars, no trailing period. Body wrap 72.GitHub Copilot auto-reviews and proposes patterns that reviewers reject:
{ arch: [ amd64 ] } (wrong): {} on essential entries (wrong for v1/v2)Do not follow Copilot suggestions blindly.
Return a structured review to the caller (this is your output -- it is not shown to the user as chat). Organise findings by severity:
For each finding, give the file, the slice/path, what's wrong, and the fix. End with an overall verdict (approve / request-changes) and note any forward-port PRs still required.
When fetching the diff to review, use read-only git (git diff, git show, git log) -- do not modify the working tree.