Files
document-haness/.agents/skills/writing-practitioner-guides/SKILL.md
T
DongHyeonkaandClaude Opus 5 024362d096 fix(setup): 실험대를 새로 세워 setup 35편을 밟고 어긋난 명령과 결과를 고친다
기반 가이드 7단계로 실험대를 철거하고 다시 세운 뒤 virtualization setup 9편과
keycloak-session-store 26편을 순서대로 밟았다. 24편은 끝까지, 11편은 되는 데까지
밟았고 밟은 범위를 편마다 적었다.

명령이 못 도는 것을 고쳤다.

- kubectl 을 `kc-lab-1` 에서 치라고 적었는데 그 기계에 kubeconfig 가 없다.
  라벨 639개와 각 편의 「어디서 치는가」를 `[lab host]` 로 옮겼다
- `-o custom-columns=…[0]…` 이 zsh 에서 글로브로 읽혀 안 돈다. 28곳에 따옴표
- busybox `sed` 가 끝 개행을 안 붙여 A-3 의 측정이 언제나 0 이었다
- `--token-file ~/node-token` 뒤에 그 파일을 지우면 k3s agent 가 재부팅을
  못 견딘다. `/etc/rancher/node-token` 으로 옮기는 처방을 재서 넣었다
- 게스트에 없는 도구를 전제로 한 명령 넷 — `conntrack`·`dig`·`strings`·`nginx -v`
- `echo` 와 JWT 헤더가 `"이름" : [ 값 ]` 으로 찍는데 문서는 공백 없이 옮겨 적어
  그 실측으로 만든 grep·sed 가 한 줄도 못 잡는다
- B-0 이 `directAccessGrantsEnabled` 와 계정 완성을 빠뜨려 B-3 이 못 돈다
- D-4·D-4a 가 `test-server` 와 `certbot-renew.*` 를 가리키는데 실제로는
  `kc-lab-edge` 의 `certbot.service` 다
- `virsh setmaxmem --config` 를 `dominfo` 로 판정하면 틀린다. `--inactive` 로
- `LIBVIRT_DEFAULT_URI` 를 rc 에만 넣으면 `ssh host '명령'` 에서 안 먹는다

결과가 조건부인 것을 갈랐다.

- readiness 는 즉시 안 뒤집힌다. A-1·A-2 의 60초 창을 적었다
- 03 의 층 ②③ `301` 은 04 이후의 값이고 그 단계에서는 `404` 다
- A-0 의 로그 필터를 요청 직후에 치면 정반대 결론이 나온다
- A-5 의 한 방향 차단은 잠깐 `1` 이었다 `2` 로 돌아온다

증거는 두 프로젝트의 `evidence/raw/` 에 99벌을 README 와 함께 남겼다. 비밀은
길이만 적었고 화면에 찍힌 토큰은 가렸다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 15:59:42 +09:00

581 lines
25 KiB
Markdown

---
name: writing-practitioner-guides
description: Use when writing hands-on guides, runbooks, troubleshooting docs, lab walkthroughs, or validation procedures that a human will execute themselves in a terminal over SSH. Symptoms that this applies - the reader is expected to type the commands, the doc teaches how to read a system rather than reporting a result, or a draft contains python -c, embedded JSON parsing, one-liners nobody types by hand, or a config file or YAML authored with printf/echo >>/heredoc instead of an editor.
---
# Writing Practitioner Guides
## Overview
**Optimize for human operation, not command compactness.**
A guide is not a script. The reader types each command, reads its raw output,
and decides what to do next. Commands that are efficient for an agent to run
once are often useless for a human learning to read a system.
The failure this prevents: an agent writes `curl … | python3 -c 'import json…'`
because it produces a clean answer in one call. The reader gets the answer and
learns nothing about the tool they will need at 3am.
## The boundary
Three tiers. Pick the lowest one that fits.
```
interactive command → short pipeline → saved script file
```
| Tier | When | Form |
|---|---|---|
| **interactive** | reading state, one question | `kubectl get pods`, `ss -lntp`, `journalctl -u nginx -n 50` |
| **short pipeline** | filtering that a person would actually type | `ps aux \| grep java`, `… \| jq .status`, `for p in a b; do … done` |
| **saved script** | it has become a program | write the file with an editor, then run it |
**Move to a saved script when any of these is true:**
- multiple branches (`if`) or nested loops
- combining several requests and computing across them
- non-trivial JSON transformation
- you cannot tell what it does by reading it once
- it will be run again later
For a saved script, the guide says to open an editor, shows the code as a
**separate file listing** (not a terminal command), then shows the run command.
```bash
vim scripts/check_sessions.py
```
```python
# file: scripts/check_sessions.py
...
```
```bash
python3 scripts/check_sessions.py
```
Terminal command ≠ program source. Never blur them with a heredoc.
## Files the reader has to understand before changing them
The tiers above stop at the saved script. The same split reaches further: **any
file whose content the reader must read and understand to change it is written
in an editor, not assembled by a shell one-liner.** Config files and YAML are
that kind of file.
> **조회·진단·실행은 CLI를 적극 사용하고, 사람이 내용을 이해하면서 작성해야 하는 설정 파일은
> 에디터를 사용한다.**
| Reading or acting on the system → CLI | Authoring a file a human must understand → editor |
|---|---|
| CPU flags → `grep /proc/cpuinfo`, `lscpu` | cloud-init YAML → `nano kc-lab-1.yaml` |
| service state → `systemctl status` | systemd unit → `sudo nano /etc/systemd/system/x.service` |
| VM state → `virsh list --all` | `nginx.conf``sudo nano /etc/nginx/nginx.conf` |
| network → `ip addr`, `virsh net-list --all` | `~/.bashrc``nano ~/.bashrc` |
| logs → `journalctl -u x` | Kubernetes manifest → `nano deploy.yaml` |
| fetch / copy → `curl`, `cp`, `scp` | a script → `nano x.sh``chmod +x x.sh``./x.sh` |
| create a VM → `virt-install` | |
### This rule is not "replace sed with nano"
> 단순히 **「`sed`를 `nano`로 바꿔라」**라고 하면 안 됩니다. 그러면 모든 shell 명령을 기계적으로
> 에디터 작업으로 바꿀 가능성이 큽니다.
The trigger is the *file-authoring step*, not the appearance of a shell tool.
| Kind | Examples | Verdict |
|---|---|---|
| what an operator types by hand | `virsh`, `systemctl`, `ssh`, `curl`, `virt-install` | keep |
| reading / diagnosing | `grep`, `lsmod`, `cat`, `stat`, `groups` | keep |
| shell tricks that author a file | `printf >`, `echo >>`, `cat <<EOF`, `python3 -c`, `ssh '… cat > …'` | rewrite as an editor step |
A pipe is not the problem. A 12-line `virt-install` is not the problem —
creating the VM *is* that command's purpose, so the CLI is the right way to show
it. `sed` is fine for a query or a throwaway substitution; it is wrong as the
default interface for editing config, because what the reader will actually do
during an incident is open the file and read what is in it.
### Rewrite: `~/.bashrc`
```bash
# before
echo 'export LIBVIRT_DEFAULT_URI=qemu:///system' >> ~/.bashrc
virsh uri
```
```bash
# after
nano ~/.bashrc
```
```text
export LIBVIRT_DEFAULT_URI=qemu:///system
```
```bash
source ~/.bashrc
virsh uri
```
Two reasons, and the second is the one that gets forgotten:
1. The reader sees the chain — file → variable → reload this shell → `virsh`
now resolves that URI. `echo >>` produces only the end state.
2. **`echo >>` is not idempotent.** Someone who walks the guide a second time
appends the same line again. Opening the file shows what is already there.
### Rewrite: cloud-init meta-data
```bash
# before
printf 'instance-id: kc-lab-1-%s\nlocal-hostname: kc-lab-1\n' "$(date +%s)" > meta-kc-lab-1
```
```bash
# after
nano meta-kc-lab-1
```
```yaml
instance-id: kc-lab-1-20260912
local-hostname: kc-lab-1
```
> `instance-id`는 이전 cloud-init 실행과 다른 인스턴스로 인식시키기 위해 이전 값과 겹치지 않게
> 지정한다.
The `printf` form makes the reader decode `%s`, `\n`, `$(...)`, `date +%s` and
`>` before reaching the two keys the page is about. A document teaching
cloud-init should not be teaching shell `printf`. The editor form also gives the
one line about `instance-id` a place to sit, right where it is typed.
### Rewrite: a file on a remote host
```bash
# before
ssh donghyeon@192.168.122.11 'umask 077; cat > ~/kc-lab-2.yaml' < kc-lab-2.yaml
ssh donghyeon@192.168.122.11 'cloud-init schema -c ~/kc-lab-2.yaml; rm -f ~/kc-lab-2.yaml'
```
```bash
# after
scp kc-lab-2.yaml donghyeon@192.168.122.11:~/
ssh donghyeon@192.168.122.11
```
then, on the guest:
```bash
chmod 600 ~/kc-lab-2.yaml
cloud-init schema -c ~/kc-lab-2.yaml
rm ~/kc-lab-2.yaml
```
The first line asked the reader to hold SSH, redirection, `umask`, file creation
and local stdin at once. The rewrite uses more commands and puts fewer things in
each: **one action, one command.** In a guide someone is learning from, that
trade is the right way round.
One more rewrite belongs to this rule — replacing a `python3 -c` YAML check with
the format's own validator. It sits in **Command priority** below, where the
ranking it changes lives.
## Command priority
| Rank | Reach for | Examples |
|---|---|---|
| 1 | the system's own CLI | `kubectl`, `systemctl`, `psql`, `redis-cli`, `docker compose` |
| 2 | standard OS tools | `ps`, `ss`, `lsof`, `free`, `top`, `dmesg` |
| 3 | network / protocol tools | `curl`, `dig`, `openssl`, `nc`, `tcpdump` |
| 4 | short Unix combinators | `grep`, `jq`, `awk`, `head`, `tail`, `less`, `watch` |
| — | **avoid** | python/node heredocs, `python -c` that *processes data*, giant awk programs, pipelines built to produce one tidy answer |
**The line is doing-the-work vs checking-a-fact, not the language.**
```bash
# not fine — this is data processing the native tool should do
curl -s "$URL" | python3 -c '
import json,sys
for r in json.load(sys.stdin)["data"]["result"]:
print(r["metric"]["pod"], r["value"][1])'
```
That one iterates, reshapes, and formats. `jq`, or the tool's own
output flag, does that — and when neither is installed, say so and show the
raw output instead of writing a parser.
`grep`, `jq`, `awk`, and a one-line `for` are what practitioners type. Do not
ban them. Ban the ones written for the *agent's* convenience.
### Validate with the format's own checker first
Checking a fact is allowed — but a hand-rolled syntax check is the *last*
resort, not the default. If the domain ships a command that validates this file,
that command is the step. Drop to a one-line syntax check only when nothing
validates the format.
```bash
# before — checks that it parses as YAML, and nothing else
python3 -c 'import yaml,sys; yaml.safe_load(open("kc-lab-1.yaml")); print("YAML OK")'
# after — the domain's own validator: schema, keys, and deprecations too
cloud-init schema -c ~/kc-lab-2.yaml
```
Same rank elsewhere: `nginx -t`, `sshd -t`, `systemd-analyze verify x.service`,
`kubectl apply --dry-run=server -f deploy.yaml`, `terraform validate`,
`docker compose config`. Each one is also the command the reader will reach for
when the service refuses to start, which a `python3 -c` line never becomes.
### Two shapes of the same tool
Most tools have a *reading* form and a *value-extracting* form. Pick by what
the reader does next with the output.
| The reader will… | Form | Example |
|---|---|---|
| **look at the response** and judge | reading form | `curl -I <url>` · `curl -v <url>` |
| **compare or count the value** across runs or hosts | extracting form | `curl -s -o /dev/null -w '%{http_code}\n' <url>` |
The extracting form hides everything except the field you chose. Use it only
when that field *is* the answer — a status code you will compare before and
after an injection, or a number you will repeat 900 times. When the reader is
still figuring out what is wrong, they need the headers and the TLS handshake,
not `200`.
Same split elsewhere: `kubectl get` (read) vs `-o jsonpath=` (extract),
`systemctl status` (read) vs `systemctl show -p X --value` (extract),
`psql` interactive (read) vs `psql -tAc` (extract).
**Show the reading form first at least once per tool.** A reader who has only
ever seen `-w '%{http_code}'` cannot debug a TLS error.
## Progressive narrowing
Never jump to the precise command. Show the widening-to-narrowing path the
reader will actually walk.
```
list / status → detail / describe → logs → targeted inspection
```
```bash
kubectl get pods # what is there
kubectl get pods -o wide # where, and on which node
kubectl describe pod api-7c874-8m2js # why is this one unhappy
kubectl logs api-7c874-8m2js # what did it say
kubectl logs api-7c874-8m2js --previous # what did it say before it died
```
**Observe before filtering.** Show the raw output at least once before piping
it. A reader who has never seen `ss -lntp` output needs to see it whole.
## Mutation ordering
```
observe → diagnose → reproduce → mutate
```
`rm`, `kill`, `delete`, `UPDATE`, restart, config change do not appear in the
diagnosis phase. If a step changes state, say what it changes and how to undo it.
## Shape of one step
Four elements, in this order. A command with no interpretation is not a step.
```
무엇을 확인하는가 one line — the question this answers
$ command the command, short
어디를 봐야 하는가 which field/line in the output matters
이 결과가 의미하는 것 what it tells you, and what to do next
```
Show the real output. If it was measured, quote it verbatim; if it is
illustrative, say so.
### When the step changes state
The four elements above are the shape of a step that **reads**. A step that
**changes state** needs a different one — otherwise the why, the failure
symptoms and the special cases all pile into the same paragraph:
> 정보 밀도는 높은데 **처음 따라 하는 사람의 시선 이동이 어렵습니다.**
```
목적 → 행동(번호 매긴 명령) → 예상 결과 → 왜 필요한가 → 문제가 생기면
```
```text
### 4. libvirt 기본 연결을 system으로 설정한다
목적
virsh가 사용자 세션이 아니라 시스템 libvirt에 연결되도록 한다.
1. 설정 파일을 연다.
$ nano ~/.bashrc
2. 다음 줄을 추가한다.
export LIBVIRT_DEFAULT_URI=qemu:///system
3. 저장한 설정을 현재 셸에 반영한다.
$ source ~/.bashrc
4. 확인한다.
$ virsh uri
예상 결과
qemu:///system
왜 필요한가
qemu:///session과 qemu:///system은 서로 다른 libvirt 연결이다.
VM을 system 쪽에 만들고 virsh가 session 쪽을 보고 있으면
VM을 만들었는데도 목록에서 찾지 못할 수 있다.
문제가 생기면
$ virsh uri
부터 확인한다.
```
**A step that only reads takes the first shape; a step that changes state takes
this one.** Same headings every time, so the reader's eye lands in the same
place on step 11 as on step 1.
## Verify before publishing
Every command in a guide must have been run, or be marked as unverified.
**Check that the tools you reach for are actually installed on the machine
the reader will be on** — `jq` and `yamllint` are absent more often than you
expect, and a guide that assumes them sends the reader to install things
mid-diagnosis.
Two failures this catches, both real:
- `kubectl get endpoints` — deprecated since v1.33, prints a warning
- `kubectl exec keycloak-0 -- curl …` — the image has no curl, exit 127
A guide that teaches a stale or failing command makes the reader doubt their
own environment.
## No placeholders
`<token>` puts the value outside the document. Give the command that produces
it. For secrets, confirm existence or length — never print the value.
```bash
TOKEN=$(ssh node1 'sudo cat /var/lib/rancher/k3s/server/node-token')
echo "${#TOKEN} chars"
```
One exception: a value an earlier step already printed on screen, which the
reader carries into a later step in a different shell — a session id, a realm
UUID. The producing command is already in the document, so the value is not
outside it. Write that slot as `{{NAME}}` (uppercase, digits, underscore), and
say in the prose above the block which step printed it.
Not `${NAME}` — guides use `$TOKEN`, `$SID` and friends as real shell
variables, and a reader who reads a placeholder as one will paste it unchanged.
`{{ }}` is not shell syntax, so pasting it fails where the reader can see it.
## The reader cannot see what is not on screen
Everything below came out of reading 35 finished guides in one pass. Each rule
names the accident that produced it. None of them is a style preference — in
every case the guide passed every other rule in this file and still handed the
reader a wrong answer that looked right.
### A value copied into a container is a snapshot, not a reference
`kubectl run --env="K0=$K0"`, `docker run -e`, cloud-init user-data: each bakes
the string as it was at that moment. From then on two spellings mean different
things, and they differ by two characters:
```bash
exec pod -- sh -c '...$K0...' # the value baked into the pod
exec pod -- sh -c '...'"$K0"'...' # the value in the shell typing this
```
**They agree until something restarts.** In one guide a `rollout restart` changed
the pod IP, and a later step still read the baked copy; the request went to an
address that no longer existed, and the failure it produced was a `500` — which
was also that step's expected result. The screen looked correct.
So: when a step replaces the thing a baked value points at — a pod IP, a node
address, a lease — say in that step which spelling the next commands use.
Prefer recreating the container. If state inside it forbids that, show the
live-read form and add one line saying why it differs from the block above.
**Distance is not the test.** A variable defined 700 lines up can be safe, and
one defined nine lines up can be stale. Ask what happened in between.
### A step that only works inside a window says when, not just what
The four-part shape above — what / command / where to look / what it means —
has no *when*. Several steps read correctly only during a restart, only while a
rule is installed, only within sixty seconds. Read late, they do not error;
they print a different, plausible number.
Name the command that opens the window and the one that closes it, and say
**what the reader sees if they type it after it closed** — that is what most
readers will actually get.
### A check must be able to fail
For every line that says "이렇게 나오면 통과", state what would print the same
thing while the condition is false. Three real cases:
- `virsh list --all` used to prove a group membership took effect — it connects
to the per-user URI, which works with no group at all
- a `postmaster.pid` path checked on a fixed node, when the volume may be on the
other one — "no such file" passes either way
- `source ~/.bashrc` on a host whose login shell is zsh — true in that shell,
gone at next login, and the symptom surfaces one guide later
If the check passes when the step was skipped — because it reads a different
scope, host or shell than the step wrote to — it is not a check. Put the scope
in the command, or write one line naming the failure this check cannot see.
### Never ship a command the guide knows is wrong
Three guides printed a command and told the reader, in prose underneath, to
edit it before typing. Prose is not a guard. The worst of them was a **valid**
assignment:
```bash
OLDID=980ee9b7-... # ← copy from the output above
```
Paste it and `OLDID` holds the literal string, and the `delete` two lines later
runs. Every other hardcoded value in those guides failed loudly — `(0 rows)`,
`(nil)`. This one succeeded at the wrong thing.
If prose under a block says "replace X first", the block already says it — or
says `{{X}}`, which is not shell syntax and fails where the reader can see it.
### One block, one machine
A code block is the reader's copy unit. When the machine changes, the block
ends, even when the commands form one logical step. Splitting the explanation
in prose does not help: they copy the block.
And a machine label tells the reader *where* a block runs — it does not put
them there. When consecutive blocks carry different labels, the transition is
its own step with its own command (`ssh host`, `exit`, "open a second
terminal"). Count them per guide: entries and exits must balance. A
verification section that runs somewhere else needs both.
### A shell function defined mid-guide is worse than all three tiers
It leaves no file, so the reader cannot re-read it. It dies with the shell, so
a new window silently breaks every later step. `unset` does not reach it.
One guide defined `R()` on line 188 and used it through line 617 — a one-letter
name for `kubectl -n … exec deploy/redis -- redis-cli`. At the point of use
the reader cannot see what command they are running.
If something is repeated often enough to want a name, make it a script file
with that name. If it must be a function, define it in the same block as its
first use, name it for what it does (`redis`, not `R`), and restate the
definition at the top of any later section more than a screen away.
### Names the reader must already have
A host alias, a directory, a volume, a file that no earlier step created is not
a placeholder — it is an assumption, and the placeholder rule above does not
catch it. Four guides in one set ran entirely on `ssh kc-lab-1` with no stanza
anywhere that creates it; the second guide hits it on its first command.
Show the command that creates it, or name the guide that owns it, in the prose
above the first block that uses it.
### Walk the guide twice
`echo >>` is one case of a larger rule. Anything created under a fixed name — a
pod, a volume, a DHCP reservation, a namespace — says what the second run
prints and how to clear it first. `--rm` only removes on clean exit; Ctrl+C
leaves the pod and the next run dies on `AlreadyExists`.
And anything that destroys and recreates a host says what identity changes with
it — SSH host keys, MAC-bound leases, certificates — and what that breaks the
next time the reader connects.
### The output block belongs to the command above it
If it came from a wider `grep`, an extra `uniq -c`, or a `sed` that rewrote
names, show that command too or say so on the line before. Readers compare
their screen to yours character by character; a silent edit makes them hunt for
a fault that is not there.
### Context selectors are read as a set
`-n`, `--context`, `-h`, `-U`. One guide's `kubectl exec` was missing
`-n keycloak-lab` while the eight commands around it had it. On its own the
line looks fine; next to its neighbours it is obviously running somewhere else.
Read them as a column, not line by line.
### When the same action has several forms, one of them is the step
One guide gave three ways to kill a backend and marked none of them. Show the
step; put the rest under a heading that says they are alternatives. Leaving the
reader to choose asks them to weigh a trade-off the guide has not explained yet.
### A fixed output path makes a block single-use
"Change the variable and run it again" is incomplete when the block writes to a
fixed file: the second run overwrites the first run's baseline, silently, and
the comparison two sections later has nothing to compare against. Name the
output path among the things to change.
### Run the remedy you prescribe
A guide diagnosed lexical sorting and prescribed `sort -g`. Every line in that
file began with the same `200`, so `sort -g` compared equal and fell through to
byte order — its output was identical to plain `sort`. The fix the guide
offered did not fix anything, and the sentence "miss this and you misread the
maximum" stayed true after following it.
## Rationalization table
| Excuse | Reality |
|---|---|
| "The pipeline gives a clean answer" | The reader needs to read the raw output, not your summary of it |
| "python -c is shorter than explaining" | It is shorter for you. The reader learns nothing and cannot adapt it |
| "jq/awk are also programming" | They are what practitioners type. The line is *program vs command*, not *language* |
| "I'll show the efficient way" | Efficient for one run. This doc is for someone learning to read the system |
| "The reader can copy-paste it" | Copy-paste is not the goal. Knowing where to look is |
| "I verified the logic mentally" | Run it. Two commands in a recent guide were wrong and both looked right |
| "It's obvious what this output means" | Then write the one line. If it is obvious it costs nothing |
| "`-w '%{http_code}'` is precise" | Precise about one field. The reader debugging TLS needs `-v`, not `200` |
| "It's fewer commands" | Fewer for you to type. The reader cannot tell which action they are in the middle of |
| "The file ends up the same either way" | Only on the first run. `echo >>` appends again every time someone repeats the guide |
| "So I should use nano for everything" | No. The trigger is authoring a file the reader must understand. `grep`, `virsh`, a long `virt-install` stay as they are |
| "`python3 -c` only checks syntax" | Then it misses the schema. If the format has a validator — `cloud-init schema`, `nginx -t`, `--dry-run` — that is the step |
| "The prose right under it says to change that value" | The reader copies the block. Prose is not a guard — put `{{NAME}}` in the block |
| "The variable is defined earlier in the same shell" | Ask what restarted in between. A pod IP baked at line 877 was stale by line 764 |
| "The label says which machine it runs on" | A label says where, not how to get there. The transition is its own step |
| "It's the same command, just shorter" | A one-letter function hides the command at the exact moment the reader needs to read it |
| "The check passed" | Ask what it would print if the step had been skipped. Three checks in one set passed either way |
## Red flags — stop and rewrite
- `python3 -c` or a `<<'PY'` heredoc inside a guide
- JSON parsed with a language runtime instead of `jq` or the tool's own `-o`
- a pipeline whose purpose you cannot state in one clause
- a command with no "what to look at" line under it
- `delete`/`kill`/`restart` before any observation step
- `<placeholder>` with no command that produces it
- output shown that you never actually ran
- only the extracting form of a tool appears, never the reading form
- a config file or YAML built with `printf >`, `echo >>`, or `cat <<EOF`
- one line stacking connect + redirect + file creation (`ssh host 'cat > f' < f`)
- `python3 -c` checking syntax when the format has its own validator
- a step that appends, so walking the guide twice appends the line twice
- prose under a block telling the reader to edit the command before typing it
- a block whose machine label differs from the one above, with no command between
- a one- or two-letter shell function, or any function defined far from its use
- a host alias, directory or volume that no step in any guide creates
- `--rm` with no line saying what a Ctrl+C leaves behind
- a "통과" line that would print the same thing if the step had been skipped
- a step that reads correctly only during a window, with no word about the window
- a remedy you have not run against the data that made you prescribe it
## References
Per-technology command vocabulary — what practitioners reach for first, not
an encyclopedia. Load only the one you need.
- [kubernetes.md](references/kubernetes.md)
- [linux-systemd.md](references/linux-systemd.md)
- [networking-tls.md](references/networking-tls.md)
- [datastores.md](references/datastores.md)