lacs-project / lacs-project/sysknife
Story coverage map: 64 Ubuntu and cross-family actions have no story, clustered into takeable pieces
- Dominant language
- Rust
- Stars
- 12
- Forks
- 19
- Avg merge
- 18h 57m
- Merged PRs (30d)
- 116
Description
64 of the 164 Ubuntu-and-cross-family actions are named by no story at all, and 98 of them are named by no story that runs on Ubuntu. This issue is the map, so the work can be taken one cluster at a time.
## Derivation
```bash
python3 - <<'PY'
import re, glob
from collections import Counter
rows = re.findall(r'^\| `([A-Za-z0-9_]+)` \|.*?\| (All|Ubuntu|Fedora) \|',
open('docs/action-reference.md').read(), re.M)
U = {n for n, d in rows if d in ('All', 'Ubuntu')}
named = set()
for f in glob.glob('tests/e2e/stories/*.sh'):
named |= set(re.findall(r'"([A-Za-z0-9_]+)"', open(f, errors='replace').read()))
ub = [f for f in glob.glob('tests/e2e/stories/*.sh')
if re.search(r'^# Story \d+ \([^)]*ubuntu[^)]*\)', open(f, errors='replace').read(), re.M)]
named_ub = set()
for f in ub:
named_ub |= set(re.findall(r'"([A-Za-z0-9_]+)"', open(f, errors='replace').read()))
print('|U| =', len(U), 'uncovered =', len(U - named), 'not on ubuntu =', len(U - named_ub))
PY
|U| = 164 uncovered = 64 not on ubuntu = 98
```
Catalogue split: 189 tabled rows, `All` 97, `Ubuntu` 67, `Fedora` 25. 79 story files carry an `ubuntu` header tag.
Two honest caveats. This counts an action as covered when its name appears as a quoted literal anywhere in a story, which over-counts: `ConfigureWifi`, `GrubSetKargs` and `SetLocale` appear only inside "must not confuse with" comments. And 34 Ubuntu-and-`All` actions are covered only by stories 1 to 54, the atomic family, which no recorded Ubuntu run includes, so `AptListUpgradable`, a Debian-only action, has its sole coverage in a Fedora-family story.
## Clusters, each one a reasonable PR
Ubuntu-family exclusive, highest priority:
- **fail2ban** (4): tracked separately in #219
- **GRUB kargs** (1): `GrubSetKargs`
Cross-family (`All`):
- **sysctl and auditd** (5): `GetSysctl`, `SetSysctl`, `GetAuditRules`, `AddAuditRule`, `RemoveAuditRule`
- **PAM policy and lockout** (6): `GetPasswordAging`, `SetPasswordAging`, `SetPasswordPolicy`, `SetAccountLockout`, `LockUserAccount`, `UnlockUserAccount`
- **Scoped sudoers.d** (3): `GetSudoGrants`, `GrantSudoAccess`, `RevokeSudoAccess`
- **Groups** (2): `CreateGroup`, `DeleteGroup`
- **Mounts and swap** (5): `GetMounts`, `AddMount`, `RemoveMount`, `AddSwap`, `RemoveSwap`
- **LVM** (4): `GetLvmReport`, `CreateLogicalVolume`, `ExtendLogicalVolume`, `CreateLvSnapshot`
- **Log management** (5): `GetLogrotateStatus`, `ConfigureLogRotation`, `RemoveLogRotation`, `ConfigureRemoteSyslog`, `RemoveRemoteSyslog`
- **Journald and diagnostics** (3): `GetJournalLog`, `VacuumJournal`, `CollectDiagnostics`
- **Container lifecycle** (4): `CreateContainer`, `StartContainer`, `StopContainer`, `RemoveContainer`
- **Flatpak remotes and info** (4): `ListFlatpakRemotes`, `AddFlatpakRemote`, `RemoveFlatpakRemote`, `GetFlatpakAppInfo`
- **Toolbox** (2): `ListToolboxes`, `RemoveToolbox`
- **certbot and ACME** (3): `GetCertificates`, `ObtainCertificate`, `RenewCertificates`
- **DNS, wifi, sockets** (4): `ResolvectlStatus`, `ResolvectlSetDns`, `ConfigureWifi`, `GetListeningPorts`
- **systemd extras** (4): `UnmaskService`, `CreateScheduledJob`, `GetServiceResourceLimits`, `SetServiceResourceLimits`
- **Time and locale** (3): `GetDateTime`, `SetNtp`, `SetLocale`
- **Singletons** (2): `SetSshdOption`, `SignalProcess`
## How to take one
Pick a cluster, write one story per action, and record on Ubuntu the way the current 79 run:
```bash
UBUNTU_RELEASE=noble ./tests/e2e/ubuntu-vm.sh
```
Then commit the cassette and its replay twin so the suite still runs offline. `run-stories.sh` accepts story numbers, so you can record only yours. Any of the seven `*_API_KEY` variables the runner recognises works; no credentials are needed from the maintainer.
The header decides the family and a wrong one fails silently, so use `# Story (ubuntu, ): ` and check that `bash tests/e2e/run-stories.sh --metadata` puts your story in the `ubuntu` family. Next free id is 134.
Start with a read-only cluster if this is your first story. `GetMounts`, `GetSysctl` and `GetListeningPorts` need no approval receipt and exercise the whole chain.
## Worth fixing alongside
Nothing compares the story set against the action catalogue, which is why this drifted unnoticed. The derivation above is small enough to become a gate, and it would keep the number in #229 honest at the same time.
## Difficulty
`medium` per cluster. The harness and the pattern exist; the work is writing intents and recording a clean pass.
## Getting started
[CONTRIBUTING.md](https://github.com/lacs-project/sysknife/blob/main/CONTRIBUTING.md) has the build and test commands, and its E2E section covers the VM harness. No CLA and no copyright waiver. The project is MIT.
Contributor guide
Assessment
This issue has not been assessed yet.