CtrlK
BlogDocsLog inGet started
Tessl Logo

canonical/mason

Agent kit for working on canonical/chisel-releases. Cross-agent skills + scripts for authoring and reviewing chisel slice definition files.

81

Quality

85%

Does it follow best practices?

Impact

75%

Average score across 5 eval scenarios

SecuritybySnyk

Low

Low-risk findings worth noting

Overview
Quality
Evals
Security
Files

_slice-conventions.mdskills/chisel-slice-porter/kb/

Slice Naming and Content Conventions

Conventions the chisel-releases reviewers enforce on Slice Definition Files (SDFs). These are not parse errors -- chisel accepts any well-formed slice name -- but a PR that ignores them is rejected.

Grouping

Group by content type for ordinary packages: executables, libraries, config and data. For large runtimes or packages with distinct functional subsets, use a minimum-functional core, a fuller standard, and named subsets as needed. Choose a coherent scheme per SDF and ship only functionality that can be tested. Do not include configuration for a tool that is not sliced, such as a logrotate drop-in without logrotate. Describe what a slice ships, not which application prompted its creation.

Published contents

Preserve the effective contents of published slices. When subdividing a slice, keep its original name and make it depend on the new subslices so existing consumers retain their files. Run _check-diff.py after changing published slices and verify effective contents with before/after cuts. A package leaving an archive requires archive evidence, not a failed lookup.

Canonical Slice Names

Names are convention but reviewers enforce them. The counts below are how many SDFs on ubuntu-26.04 use each name, as a rough signal of how established it is; a name is not wrong for being rare, but a rare one wants a reason.

NameUsed byContents
bins114Executables (plural; use bins not bin). The singular bin is only correct in base-files, whose bin slice builds the /bin and /usr/bin directory tree, not executables
libs404Shared libraries (plural; use libs not lib). Same base-files lib exception -- it makes the /lib and /usr/lib tree
config75Configuration files. Singular -- configs is not used. Break large configs into <purpose>-config (e.g. modprobe-config, tmpfiles-config, pam-config)
scripts29Shell helpers / non-binary executables. Not in bins
data21Static data (templates, tables, arch-independent payload). Not fonts -- those get fonts
headers15/usr/include/.... This is the name -dev packages use, not dev
jars5JVM artefacts
copyright690The deb copyright file, plus any upstream NOTICE / LICENSE / ThirdPartyNotices the package ships. Every SDF has one
fonts15Font files. Every font package uses this, not data
core38Minimum-functional subset. Not "everything". Avoid all -- exactly one SDF uses it (fonts-ubuntu, an umbrella aggregate)
standard24Fuller-featured above core
var6Directories/files under /var/
services12Systemd service files
modules33Loadable modules/plugins
locales1Translation/locale files
tables1Static data tables (dpkg_tables ships /usr/share/dpkg/*table)
chisel1The generated manifest slice; only on base-files (generate: manifest)
udev-rules1udev rules (systemd_udev-rules ships /usr/lib/udev/rules.d/*.rules). The bare name rules is not used
minimal / runtime7 / 5Alternative subset names where core / standard do not fit the package's own vocabulary

When the deb already names <pkg>-core (e.g. fonts-dejavu-core), keep the name verbatim.

There is no license or notice slice convention: upstream NOTICE, LICENSE.txt and ThirdPartyNotices.txt go inside the copyright slice next to the deb copyright file. Do not invent a separate slice for them.

Beyond this table, packages freely coin their own names for functional subsets -- openjdk ships awt, jfr, management; binutils ships assembler, linker, archiver. That is expected. The table covers the names that recur across packages; a package-specific name needs only to describe what it ships.

Path Entry Style

Conventions on how a contents: path is written. Chisel accepts either form; reviewers do not.

  • Multiarch lib glob: *-linux-*, not explicit triples -- /usr/lib/*-linux-*/libnghttp2.so.14*:.
  • Drop the trailing * for single-version sonames: libfoo.so.1:, not libfoo.so.1*:.
  • Version globs pin major.minor only, never the patch: /usr/src/rustc-1.93.*/**, /usr/lib/perl5/*/. A patch-level pin breaks on the next package update.
  • Keep globs narrow. A broad ** or a bare *.pm collides with other packages' paths. Add another path level to scope it (.../perl5/*/auto/DBI/DBI.so:). A path more than one package could own is a red flag -- grep the branch's slices/ before declaring one.
  • No explicit symlink: if the deb ships it. Chisel preserves the deb's own symlinks. Write symlink: only for paths the deb does not ship, e.g. ones a maintainer script creates.
  • Annotate explicit symlinks with a comment: /usr/bin/dotnet: # Symlink to ../lib/dotnet/dotnet.
  • Inline-style for short option maps: /path: {arch: [amd64, arm64]}.
  • Arch list order is a nit, not a gate. Alphabetical reads tidily, but real SDFs (systemd) use a priority order; do not block on it.

File Layout

  • Global essential: at the top of the file, right after package:.
  • Include <pkg>_copyright in the global essential: so every slice ships the package's legal files.
  • The copyright slice last in the slices: block.
  • package: matches the filename stem -- slices/foo.yaml -> package: foo.
  • One SDF per package. Never two packages in one YAML file.

Exclude by Default

A .deb ships files a minimal rootfs never needs. Do not slice these unless a concrete runtime need is proven -- reviewers reject them, and check-slice.py flags them:

ExcludedPathsNotes
man pages/usr/share/man/, /usr/man/never shipped
shell completions/usr/share/bash-completion/, /usr/share/fish/, /usr/share/zsh/, /etc/bash_completion.d/never shipped
docs / changelogs/usr/share/doc/**except the legal files below
doc-base / lintian/usr/share/doc-base/, /usr/share/lintian/packaging metadata, not runtime
examples/usr/share/doc/*/examples/, .../example*covered by the doc rule above

Under /usr/share/doc/<pkg>/, ship only legal files: copyright always, and the upstream legal notices (NOTICE, LICENSE, ThirdPartyNotices, with .txt/.gz variants) where the package carries them for licence compliance -- apache2, aspnetcore, and libaprutil1t64 ship NOTICE. Everything else there (README, changelog, NEWS, examples) is clutter. Shared-copyright packages instead ship /usr/share/doc/<pkg> itself as a symlink to another package's doc dir (gcc/cpp/binutils families); that bare entry is also fine.

README.md

tile.json