CLAUDE.md
Rama main · réplica de lectura del repositorio original.
# Cairn
**Cairn is an AI-native artifact-sharing service** — a pastebin / gist / requestbin
for the agent era. Humans post from the CLI and web; agents read, create, comment,
and react over MCP. Every artifact gets a short shareable URL with provenance,
reactions, comments, and a TTL. See [docs/DESIGN.md](docs/DESIGN.md) for the full
product design brief.
## Architecture Context
- Architecture Decision Records are in docs/adrs/
- Specifications are in docs/openspec/specs/
- The product design brief is in docs/DESIGN.md
This project follows **spec-driven development** (the `sdd` plugin). Read the ADRs
and specs before proposing structural changes. When implementing code governed by a
spec, leave a governing comment: `// Governing: ADR-XXXX (desc), SPEC-XXXX REQ "…"`.
### SDD Configuration
#### Tracker
- **Type**: github
- **Owner**: joestump
- **Repo**: cairn
#### Branch Conventions
- **Enabled**: true
- **Prefix**: feature
- **Epic Prefix**: epic
- **Slug Max Length**: 50
#### PR Conventions
- **Enabled**: true
- **Close Keyword**: Closes
- **Ref Keyword**: Part of
- **Include Spec Reference**: true
## Shell rules for scripts and CI
**Never pipe a command whose exit status you depend on.** A pipeline's status is
the *last* stage's, so `set -e` walks straight past a failure:
```bash
set -euo pipefail
git push origin main | tail -3 # status is tail's: 0, even on a 403
echo "pushed" # ...so this runs anyway
```
This is not hypothetical. In a single session it reported a **403-denied `git
push` as a successfully created repository**, made a failed `git rebase` look
like it had succeeded, and elsewhere reported a deploy as `exit 0` while it
converged nothing. Every time, the output *looked* right — which is precisely
what makes it expensive: the failure is silent and downstream steps keep going.
Use one of these instead:
```bash
some-command # simplest: don't pipe it
some-command > /tmp/out.log 2>&1 || { tail -20 /tmp/out.log; exit 1; }
set -o pipefail # pipeline fails if ANY stage does
```
### Before you reach for `PIPESTATUS`, read this
**`${PIPESTATUS[0]}` is bash. zsh names the array `pipestatus` and 1-indexes
it**, so on zsh the bash spelling expands to an **empty string** — not an error,
not a status:
```bash
some-command | tail -5
rc=${PIPESTATUS[0]} # bash: the real status. zsh: "" — silently nothing
[ "$rc" -ne 0 ] && ... # zsh: errors on an empty operand, or never fires
```
That is the same defect one layer down: **the fix for a masked exit code
silently produces no exit code at all.** It happened in this repo — a script
printed `lint exit=` with nothing after the `=`, and the surrounding "Passed"
output was read as success. Reaching for `PIPESTATUS` from bash muscle memory
on a zsh login shell reintroduces the original bug while looking like the cure.
If you need a specific stage's status portably, don't: restructure so the
command you care about isn't in a pipeline.
One more: **`set -o pipefail` is bash/zsh only.** `sh` on Debian and Ubuntu is
dash, where it is an error — in an Ansible `shell:` task set
`executable: /bin/bash` before relying on it.
The same reasoning applies to any check: **a test that cannot distinguish
"the thing is absent" from "I could not measure it" reports success either way.**
See `scripts/verify-cli-artifact.sh`, whose binary gate carries a positive
control for exactly this reason.
### A broken test is not a false test — it falls through to `else`
`[ ... ]` does not return "false" when the *expression itself* is invalid. It
**errors**, and inside an `if` that error lands in the `else` branch:
```bash
if [ "$a" \> "$b" ]; then # zsh: "condition expected: >" — the test ERRORS
echo "a is newer"
else
echo "b is newer" # ...so this runs, asserting the inverse
fi
```
This happened in this repo while dating the release chain against a tag. The
comparison was invalid, the `else` fired, and the script printed a fluent,
plausible, **exactly inverted** conclusion — which was nearly reported as fact.
That makes it the worst member of this family. A masked exit code or an empty
grep at least *looks* suspicious. A confident wrong verdict does not.
**Validate a comparison against known inputs before trusting it on unknown
ones**, the same way the binary gate proves it can see before it reports
absence:
```bash
later() { [ "$(printf '%s\n%s\n' "$1" "$2" | sort | tail -1)" = "$1" ] && [ "$1" != "$2" ]; }
later 2026-09-12 2026-07-15 && echo YES || echo NO # expect YES
later 2026-07-15 2026-09-12 && echo YES || echo NO # expect NO
later 2026-09-12 2026-09-12 && echo YES || echo NO # expect NO
```
### `\s`, `\S` and `\d` are GNU extensions, and BSD fails them silently
macOS `grep -E` does not support them. The pattern does not error; it simply
**matches nothing**:
```bash
git grep -nE '^\s*var\s+version' # macOS: zero hits, even where it exists
git grep -nE '^[[:space:]]*var[[:space:]]+version' # portable
```
This cost a wrong diagnosis here: two probes came back empty, the emptiness was
blamed on the git pathspec, and the real cause was `\s`. A positive control
found it — the same query shape matched a string known to be present, which
proved the method worked and the pattern did not.
Use POSIX classes, `-F` for fixed strings, or `grep -P` where it exists.
### Never print a conclusion you have not checked the data against
Guard text like `(empty above = free to claim)` or `(nothing listed = only X
changed)` prints unconditionally, so the moment the list is non-empty it
asserts the opposite of what is on screen. This shipped four times in one
session, once directly above a list of thirteen counter-examples.
Compute the claim from the data instead of narrating it:
```bash
n=$(some-command | wc -l | tr -d ' ')
if [ "$n" -eq 0 ]; then echo "none found"; else echo "$n found:"; some-command; fi
```