Add the canonical policy dotfiles: REPO_POLICIES.md, .editorconfig, .prettierrc, .prettierignore, and extend .gitignore #8

Closed
opened 2026-08-09 03:41:37 +02:00 by clawbot · 6 comments
Collaborator

Problem

REPO_POLICIES.md lists the files every repo must contain at minimum. This
repo is missing four of them, and its .gitignore is missing the mandated
content. All five are verbatim drops of canonical files from the prompts
repo, so this is one cohesive commit.

Missing: REPO_POLICIES.md

Required in the minimum file list. Fetch from
https://git.eeqj.de/sneak/prompts/raw/branch/main/prompts/REPO_POLICIES.md.
It must retain its YAML front matter (title: and
last_modified: YYYY-MM-DD) so it can be kept in sync as policies evolve.

Missing: .editorconfig

"All repos should have an .editorconfig enforcing the project's indentation
settings." Canonical contents:

root = true

[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[Makefile]
indent_style = tab

Missing: .prettierrc and .prettierignore

"Documentation and writing repos (Markdown, HTML, CSS) should also have
.prettierrc and .prettierignore." A Hugo site is exactly that. Canonical
contents:

.prettierrc:

{
    "tabWidth": 4,
    "proseWrap": "always"
}

.prettierignore:

node_modules/
yarn.lock

Note that script/fmt and script/fmt-check already pass --tab-width 4 --prose-wrap always on the command line. Keep those flags — the canonical
scripts duplicate them deliberately so the scripts work standalone when copied
as a template. Adding .prettierrc must not change what make fmt does.

Incomplete: .gitignore

Current contents are Hugo outputs only (/public/, /resources/,
.hugo_build.lock). Policy: ".gitignore should be comprehensive from the
start: OS files (.DS_Store), editor files (.swp, *~), language build
artifacts, and node_modules/", and separately "Never commit secrets. .env
files, credentials, API keys, and private keys must be in .gitignore. No
exceptions."

Append the canonical block, keeping the existing Hugo lines:

# OS
.DS_Store
Thumbs.db

# Editors
*.swp
*.swo
*~
*.bak
.idea/
.vscode/
*.sublime-*

# Node
node_modules/

# Environment / secrets
.env
.env.*
*.pem
*.key

Definition of done

  1. REPO_POLICIES.md exists at the repo root, is byte-identical to the
    upstream canonical copy, and head -5 REPO_POLICIES.md contains
    last_modified:.
  2. .editorconfig, .prettierrc, .prettierignore exist at the repo root
    with exactly the contents quoted above.
  3. .gitignore retains its three existing Hugo lines and gains the canonical
    block above; it contains the literal patterns .env, *.key, and *.pem.
  4. make fmt produces no diff after the change (adding .prettierrc must be a
    no-op against the flags already passed by script/fmt). If it does produce
    a diff, commit the reformat as its own separate commit — formatting churn
    must not be mixed with functional changes.
  5. make check passes and script/cibuild succeeds.
  6. TODO.md is updated in the same commit as the work, per the Workflow block.

Explicitly out of scope — no Hugo equivalent, do not add

Each of the following is either language-specific or not required by any org
standard. Do not create them:

  • go.mod, go.sum, .golangci.yml — Go module and Go linter files; there is
    no Go code here.
  • package.json, yarn.lock — only required for JS repos. script/fmt gets
    prettier via npx --yes prettier@<pinned>, so there is no dependency
    manifest to maintain. Adding one would pull in the whole node/nvm/corepack
    pinning apparatus for a single formatter.
  • pyproject.toml — wrong language.
  • CONTRIBUTING.md, SECURITY.md, .gitattributes, CHANGELOG.md,
    AGENTS.md, root CLAUDE.md, renovate/dependabot config, issue/PR
    templates, CODEOWNERSnone of these appear in any org standard. They
    were checked for explicitly and are not mandated.
  • .claude/ scaffolding — the memory policy states "Repos with no memories yet
    need no .claude/ scaffolding." This repo has none.
  • Per-file license headers / SPDX identifiers — not mandated anywhere.

Ref: REPO_POLICIES.md minimum file list; EXISTING_REPO_CHECKLIST.md.

## Problem `REPO_POLICIES.md` lists the files every repo must contain at minimum. This repo is missing four of them, and its `.gitignore` is missing the mandated content. All five are verbatim drops of canonical files from the `prompts` repo, so this is one cohesive commit. ### Missing: `REPO_POLICIES.md` Required in the minimum file list. Fetch from `https://git.eeqj.de/sneak/prompts/raw/branch/main/prompts/REPO_POLICIES.md`. It must retain its YAML front matter (`title:` and `last_modified: YYYY-MM-DD`) so it can be kept in sync as policies evolve. ### Missing: `.editorconfig` "All repos should have an `.editorconfig` enforcing the project's indentation settings." Canonical contents: ``` root = true [*] indent_style = space indent_size = 4 end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true [Makefile] indent_style = tab ``` ### Missing: `.prettierrc` and `.prettierignore` "Documentation and writing repos (Markdown, HTML, CSS) should also have `.prettierrc` and `.prettierignore`." A Hugo site is exactly that. Canonical contents: `.prettierrc`: ```json { "tabWidth": 4, "proseWrap": "always" } ``` `.prettierignore`: ``` node_modules/ yarn.lock ``` Note that `script/fmt` and `script/fmt-check` already pass `--tab-width 4 --prose-wrap always` on the command line. Keep those flags — the canonical scripts duplicate them deliberately so the scripts work standalone when copied as a template. Adding `.prettierrc` must not change what `make fmt` does. ### Incomplete: `.gitignore` Current contents are Hugo outputs only (`/public/`, `/resources/`, `.hugo_build.lock`). Policy: "`.gitignore` should be comprehensive from the start: OS files (`.DS_Store`), editor files (`.swp`, `*~`), language build artifacts, and `node_modules/`", and separately "Never commit secrets. `.env` files, credentials, API keys, and private keys must be in `.gitignore`. No exceptions." Append the canonical block, keeping the existing Hugo lines: ``` # OS .DS_Store Thumbs.db # Editors *.swp *.swo *~ *.bak .idea/ .vscode/ *.sublime-* # Node node_modules/ # Environment / secrets .env .env.* *.pem *.key ``` ## Definition of done 1. `REPO_POLICIES.md` exists at the repo root, is byte-identical to the upstream canonical copy, and `head -5 REPO_POLICIES.md` contains `last_modified:`. 2. `.editorconfig`, `.prettierrc`, `.prettierignore` exist at the repo root with exactly the contents quoted above. 3. `.gitignore` retains its three existing Hugo lines and gains the canonical block above; it contains the literal patterns `.env`, `*.key`, and `*.pem`. 4. `make fmt` produces no diff after the change (adding `.prettierrc` must be a no-op against the flags already passed by `script/fmt`). If it does produce a diff, commit the reformat as its own separate commit — formatting churn must not be mixed with functional changes. 5. `make check` passes and `script/cibuild` succeeds. 6. `TODO.md` is updated in the same commit as the work, per the Workflow block. ## Explicitly out of scope — no Hugo equivalent, do not add Each of the following is either language-specific or not required by any org standard. Do not create them: - `go.mod`, `go.sum`, `.golangci.yml` — Go module and Go linter files; there is no Go code here. - `package.json`, `yarn.lock` — only required for JS repos. `script/fmt` gets prettier via `npx --yes prettier@<pinned>`, so there is no dependency manifest to maintain. Adding one would pull in the whole node/nvm/corepack pinning apparatus for a single formatter. - `pyproject.toml` — wrong language. - `CONTRIBUTING.md`, `SECURITY.md`, `.gitattributes`, `CHANGELOG.md`, `AGENTS.md`, root `CLAUDE.md`, renovate/dependabot config, issue/PR templates, `CODEOWNERS` — **none of these appear in any org standard.** They were checked for explicitly and are not mandated. - `.claude/` scaffolding — the memory policy states "Repos with no memories yet need no `.claude/` scaffolding." This repo has none. - Per-file license headers / SPDX identifiers — not mandated anywhere. Ref: `REPO_POLICIES.md` minimum file list; `EXISTING_REPO_CHECKLIST.md`.
Author
Collaborator

Additional scope for this issue, found while testing the script/cibuild cache
behaviour for #23.

git status --porcelain in a clean checkout reports:

?? .claude/

.claude/ is agent tooling scaffolding (it holds worktrees/ among other
things). It is in neither .gitignore nor .dockerignore, which has two
consequences:

  1. It can be committed by accident. Anything doing a broad git add picks
    it up. REPO_POLICIES.md forbids git add -A/git add . precisely to
    limit this class of mistake, but the ignore file is the belt to that
    braces.
  2. It is in the Docker build context. The Dockerfile does COPY . . and
    .dockerignore currently lists only .git, public, resources, and
    .hugo_build.lock. So .claude/ — including worktrees/, which can hold
    entire additional checkouts of this repo — gets copied into the image. That
    inflates the context and the image, slows every build, and in the worst case
    copies unrelated in-flight work into a build artifact.

Add .claude/ to both files as part of this issue:

  • .gitignore — alongside the canonical block already specified above.
  • .dockerignore — which should also gain the editor/OS patterns for the same
    reason; there is no value in shipping .DS_Store or .idea/ into the build
    context either.

Updated definition-of-done items for this issue:

  1. .gitignore contains .claude/, and git status --porcelain is empty in a
    clean checkout with agent tooling present.
  2. .dockerignore contains .claude/ and the OS/editor patterns. Verify by
    building and confirming the context size drops (or at minimum that
    .claude/ is absent from the image — docker run --rm <image> ls -a /src
    should not list it).

Note the ordering interaction with #23: until #23 lands, a script/cibuild run
may be served entirely from cache, so a build used to verify item 8 must be run
with the cache defeated or it will prove nothing.

Additional scope for this issue, found while testing the `script/cibuild` cache behaviour for #23. `git status --porcelain` in a clean checkout reports: ``` ?? .claude/ ``` `.claude/` is agent tooling scaffolding (it holds `worktrees/` among other things). It is in **neither `.gitignore` nor `.dockerignore`**, which has two consequences: 1. **It can be committed by accident.** Anything doing a broad `git add` picks it up. `REPO_POLICIES.md` forbids `git add -A`/`git add .` precisely to limit this class of mistake, but the ignore file is the belt to that braces. 2. **It is in the Docker build context.** The `Dockerfile` does `COPY . .` and `.dockerignore` currently lists only `.git`, `public`, `resources`, and `.hugo_build.lock`. So `.claude/` — including `worktrees/`, which can hold entire additional checkouts of this repo — gets copied into the image. That inflates the context and the image, slows every build, and in the worst case copies unrelated in-flight work into a build artifact. Add `.claude/` to both files as part of this issue: - `.gitignore` — alongside the canonical block already specified above. - `.dockerignore` — which should also gain the editor/OS patterns for the same reason; there is no value in shipping `.DS_Store` or `.idea/` into the build context either. Updated definition-of-done items for this issue: 7. `.gitignore` contains `.claude/`, and `git status --porcelain` is empty in a clean checkout with agent tooling present. 8. `.dockerignore` contains `.claude/` and the OS/editor patterns. Verify by building and confirming the context size drops (or at minimum that `.claude/` is absent from the image — `docker run --rm <image> ls -a /src` should not list it). Note the ordering interaction with #23: until #23 lands, a `script/cibuild` run may be served entirely from cache, so a build used to verify item 8 must be run with the cache defeated or it will prove nothing.
Author
Collaborator

Blocked on #23 — do not land the .dockerignore portion of this issue
first.

Adding .claude/ to .dockerignore removes a live source of build-context
churn. .claude/worktrees/ is created and destroyed constantly by tooling, and
that churn intermittently invalidates COPY . ., forcing the RUN make check
layer to actually execute. Excluding it makes Docker's cache stickier and more
consistent — correct in itself, but it removes an accidental safety net while
#23's unearned-green hole is still open. The gate would get quietly weaker,
with nothing in the build output to signal the change.

Required sequencing:

  1. #23 lands first (cache-busting so make check cannot be served from cache).
  2. Then this issue's .dockerignore change.
  3. Then re-verify #23's two-consecutive-runs check, because this change alters
    the cache behaviour that #23 was validated against.

The rest of this issue — REPO_POLICIES.md, .editorconfig, .prettierrc,
.prettierignore, and the .gitignore additions including .claude/ — has no
such dependency and can proceed at any time. If it is convenient to start
this issue before #23 is done, split it: land everything except the
.dockerignore edit, and leave that for a follow-up commit after #23.
Adding
.claude/ to .gitignore is unaffected; only the Docker build context matters
here.

For the record, the fleet-wide version of this warning describes repos with
no .dockerignore at all being accidentally protected because .git churns
in the context. That is not this repo — lora.vegas already excludes .git,
which is why the cache hole reproduces here cleanly. The dependency above is
real but arrives via .claude/, not .git.

**Blocked on #23 — do not land the `.dockerignore` portion of this issue first.** Adding `.claude/` to `.dockerignore` removes a live source of build-context churn. `.claude/worktrees/` is created and destroyed constantly by tooling, and that churn intermittently invalidates `COPY . .`, forcing the `RUN make check` layer to actually execute. Excluding it makes Docker's cache stickier and more consistent — correct in itself, but it removes an accidental safety net while #23's unearned-green hole is still open. The gate would get quietly weaker, with nothing in the build output to signal the change. Required sequencing: 1. #23 lands first (cache-busting so `make check` cannot be served from cache). 2. Then this issue's `.dockerignore` change. 3. Then re-verify #23's two-consecutive-runs check, because this change alters the cache behaviour that #23 was validated against. The rest of this issue — `REPO_POLICIES.md`, `.editorconfig`, `.prettierrc`, `.prettierignore`, and the `.gitignore` additions including `.claude/` — has no such dependency and can proceed at any time. **If it is convenient to start this issue before #23 is done, split it: land everything except the `.dockerignore` edit, and leave that for a follow-up commit after #23.** Adding `.claude/` to `.gitignore` is unaffected; only the Docker build context matters here. For the record, the fleet-wide version of this warning describes repos with **no** `.dockerignore` at all being accidentally protected because `.git` churns in the context. That is not this repo — lora.vegas already excludes `.git`, which is why the cache hole reproduces here cleanly. The dependency above is real but arrives via `.claude/`, not `.git`.
Author
Collaborator

Correction to the .dockerignore work — pattern semantics. This is a
security point, not a tidiness one.

.dockerignore does not use .gitignore semantics. It matches with Go's
filepath.Match rules, extended with **. Two consequences that break the
naive approach:

  • * does not cross /. So *.key matches server.key at the context
    root and does not match certs/server.key.
  • Unprefixed patterns are anchored at the context root. node_modules/
    excludes only a top-level node_modules, not a nested one.

Another repo on the roster proved this empirically by planting files at depth
and watching config/.env, certs/server.key, and nested node_modules all
reach the build context despite patterns that appeared to cover them.

For this repo that matters directly, because the Dockerfile does COPY . .
and the whole point of the secrets patterns is that a stray key or .env must
never be baked into an image. A .dockerignore that silently protects only the
root is worse than an obviously incomplete one, because it reads as complete.

Requirement: every depth-independent pattern in .dockerignore gets a
**/ prefix. So **/.env, **/*.key, **/*.pem, **/node_modules,
**/.DS_Store, **/.claude, and so on. Patterns that genuinely are
root-anchored — public, resources — stay unprefixed, deliberately, since
those are specifically the Hugo output directories at the repo root.

Note this applies only to .dockerignore. .gitignore has different
semantics where an unanchored pattern already matches at any depth, so the
canonical .gitignore block quoted in the issue body is correct as written and
must not be given **/ prefixes.

Added definition-of-done item:

  1. Verify the .dockerignore patterns by planting throwaway files at least two
    directories deep — e.g. a/b/.env, a/b/server.key, a/b/node_modules/x
    — then confirming they are absent from the built image (docker run --rm <image> find /src -name '.env' -o -name '*.key' returns nothing). Delete
    the throwaway files afterwards. Testing only at the repo root does not
    exercise the bug and will produce a false pass.

Tracked upstream as prompts #29.

Combined with the earlier ordering note, the .dockerignore portion of this
issue now has two constraints: it lands after #23, and it must use **/
prefixes verified at depth. The rest of this issue is unaffected and can
proceed independently.

**Correction to the `.dockerignore` work — pattern semantics. This is a security point, not a tidiness one.** `.dockerignore` does **not** use `.gitignore` semantics. It matches with Go's `filepath.Match` rules, extended with `**`. Two consequences that break the naive approach: - `*` does **not** cross `/`. So `*.key` matches `server.key` at the context root and does **not** match `certs/server.key`. - Unprefixed patterns are **anchored at the context root**. `node_modules/` excludes only a top-level `node_modules`, not a nested one. Another repo on the roster proved this empirically by planting files at depth and watching `config/.env`, `certs/server.key`, and nested `node_modules` all reach the build context despite patterns that appeared to cover them. For this repo that matters directly, because the `Dockerfile` does `COPY . .` and the whole point of the secrets patterns is that a stray key or `.env` must never be baked into an image. A `.dockerignore` that silently protects only the root is worse than an obviously incomplete one, because it reads as complete. **Requirement:** every depth-independent pattern in `.dockerignore` gets a `**/` prefix. So `**/.env`, `**/*.key`, `**/*.pem`, `**/node_modules`, `**/.DS_Store`, `**/.claude`, and so on. Patterns that genuinely are root-anchored — `public`, `resources` — stay unprefixed, deliberately, since those are specifically the Hugo output directories at the repo root. Note this applies **only to `.dockerignore`**. `.gitignore` has different semantics where an unanchored pattern already matches at any depth, so the canonical `.gitignore` block quoted in the issue body is correct as written and must **not** be given `**/` prefixes. **Added definition-of-done item:** 9. Verify the `.dockerignore` patterns by planting throwaway files at least two directories deep — e.g. `a/b/.env`, `a/b/server.key`, `a/b/node_modules/x` — then confirming they are absent from the built image (`docker run --rm <image> find /src -name '.env' -o -name '*.key'` returns nothing). Delete the throwaway files afterwards. Testing only at the repo root does not exercise the bug and will produce a false pass. Tracked upstream as `prompts` #29. Combined with the earlier ordering note, the `.dockerignore` portion of this issue now has two constraints: it lands **after** #23, and it must use `**/` prefixes verified at depth. The rest of this issue is unaffected and can proceed independently.
Author
Collaborator

Implementation plan

Branching from current main (ccdedc3), which already contains #23 /
PR #30, so the ordering
constraint from the second comment is satisfied and the .dockerignore change
can land in this same commit rather than a follow-up.

One commit, ... (closes #8):

  1. REPO_POLICIES.mdcurl the raw canonical from prompts verbatim (byte
    copy, not a reflow), front matter intact. Note it lands inside
    script/fmt-check's *.md glob, so it must already satisfy
    --tab-width 4 --prose-wrap always; if it does not, item 4 of the DoD and
    "byte-identical" collide and I will report that rather than reformat it
    silently.
  2. .editorconfig, .prettierrc, .prettierignore — exactly the contents
    quoted in the body.
  3. .gitignore — keep the three Hugo lines, append the canonical block
    verbatim, plus a .claude/ entry. No **/ prefixes here — unanchored
    .gitignore patterns already match at any depth.
  4. .dockerignore — every depth-independent pattern gets **/
    (**/.env, **/.env.*, **/*.key, **/*.pem, **/node_modules,
    **/.DS_Store, **/.claude, editor patterns, ...). public and
    resources stay unprefixed: they are the root Hugo output dirs by
    intention. .git and .hugo_build.lock keep their current form.

Not touched, per the out-of-scope list: LICENSE (that is
#10, still awaiting an owner
decision — the README License section stays as-is), go.mod, package.json,
yarn.lock, CONTRIBUTING.md, SECURITY.md, .gitattributes,
CHANGELOG.md, AGENTS.md, root agent-memory file, renovate/dependabot,
.claude/ scaffolding.

Verification

  • Depth-planted .dockerignore proof (DoD 9): plant a/b/.env,
    a/b/server.key, a/b/node_modules/x and a .claude/ marker, build, then
    docker run --rm <image> find /src -name '.env' -o -name '*.key' and expect
    empty. Root-only testing does not exercise the bug. Throwaways deleted
    after, and I will also confirm the pre-change .dockerignore fails this
    same probe, so the test is shown to have teeth.
  • Re-run #23's proof against the new context (third comment's step 3): two
    consecutive script/cibuild runs on an unchanged tree, both pasted, both
    showing the two Hugo builds plus the prettier line, with RUN script/bootstrap
    still CACHED in the second.
  • make fmt diff-free, make check green, make docker still builds.
  • No docker builder prune in any form — shared host. Cache defeat is scoped
    to --no-cache-filter / a throwaway tag.

TODO.md updated in the same commit. script/bootstrap and deploy.yml are
untouched, so the live deploy path is unaffected and no temporary branch
trigger is needed.

I will also reconcile a wording conflict this introduces: REPO_POLICIES.md
says make check "must not modify any files in the repo", while
script/check's header says "must not modify any tracked files". Both will
be present in the tree; I will call out which is authoritative in the PR rather
than leave them contradicting.

## Implementation plan Branching from current `main` (`ccdedc3`), which already contains #23 / [PR #30](https://git.eeqj.de/sneak/lora.vegas/pulls/30), so the ordering constraint from the second comment is satisfied and the `.dockerignore` change can land in this same commit rather than a follow-up. One commit, `... (closes #8)`: 1. `REPO_POLICIES.md` — `curl` the raw canonical from `prompts` verbatim (byte copy, not a reflow), front matter intact. Note it lands inside `script/fmt-check`'s `*.md` glob, so it must already satisfy `--tab-width 4 --prose-wrap always`; if it does not, item 4 of the DoD and "byte-identical" collide and I will report that rather than reformat it silently. 2. `.editorconfig`, `.prettierrc`, `.prettierignore` — exactly the contents quoted in the body. 3. `.gitignore` — keep the three Hugo lines, append the canonical block verbatim, plus a `.claude/` entry. **No `**/` prefixes here** — unanchored `.gitignore` patterns already match at any depth. 4. `.dockerignore` — every depth-independent pattern gets `**/` (`**/.env`, `**/.env.*`, `**/*.key`, `**/*.pem`, `**/node_modules`, `**/.DS_Store`, `**/.claude`, editor patterns, ...). `public` and `resources` stay unprefixed: they are the root Hugo output dirs by intention. `.git` and `.hugo_build.lock` keep their current form. Not touched, per the out-of-scope list: `LICENSE` (that is [#10](https://git.eeqj.de/sneak/lora.vegas/issues/10), still awaiting an owner decision — the README License section stays as-is), `go.mod`, `package.json`, `yarn.lock`, `CONTRIBUTING.md`, `SECURITY.md`, `.gitattributes`, `CHANGELOG.md`, `AGENTS.md`, root agent-memory file, renovate/dependabot, `.claude/` scaffolding. ### Verification - **Depth-planted `.dockerignore` proof** (DoD 9): plant `a/b/.env`, `a/b/server.key`, `a/b/node_modules/x` and a `.claude/` marker, build, then `docker run --rm <image> find /src -name '.env' -o -name '*.key'` and expect empty. Root-only testing does not exercise the bug. Throwaways deleted after, and I will also confirm the pre-change `.dockerignore` *fails* this same probe, so the test is shown to have teeth. - **Re-run #23's proof against the new context** (third comment's step 3): two consecutive `script/cibuild` runs on an unchanged tree, both pasted, both showing the two Hugo builds plus the prettier line, with `RUN script/bootstrap` still `CACHED` in the second. - `make fmt` diff-free, `make check` green, `make docker` still builds. - No `docker builder prune` in any form — shared host. Cache defeat is scoped to `--no-cache-filter` / a throwaway tag. `TODO.md` updated in the same commit. `script/bootstrap` and `deploy.yml` are untouched, so the live deploy path is unaffected and no temporary branch trigger is needed. I will also reconcile a wording conflict this introduces: `REPO_POLICIES.md` says `make check` "must not modify any files in the repo", while `script/check`'s header says "must not modify any **tracked** files". Both will be present in the tree; I will call out which is authoritative in the PR rather than leave them contradicting.
Author
Collaborator

Done in PR #31 (branch
policy-dotfiles), two commits off ccdedc3.

What was built: REPO_POLICIES.md (byte-identical canonical copy, front
matter intact), .editorconfig, .prettierrc, .prettierignore (canonical
contents), .gitignore extended with the canonical block plus .claude/, and
.dockerignore rewritten with **/-prefixed depth-independent patterns.
LICENSE and the README License section untouched, per the out-of-scope list
and #10. script/bootstrap
and deploy.yml untouched, so the live deploy path is unaffected.

DoD 9 (depth-planted .dockerignore): passes, with a counterfactual so the
test is shown to have teeth. Planted a/b/.env, a/b/server.key,
a/b/deep.pem, a/b/node_modules/x, config/.env, certs/server.key,
.claude/worktrees/marker.txt. With the canonical patterns left unprefixed,
all six depth-planted paths reach /src in the image:

/src/certs/server.key
/src/a/b/node_modules
/src/a/b/deep.pem
/src/a/b/server.key
/src/a/b/.env
/src/config/.env

With the shipped **/ form, docker run --rm lora.vegas find /src -name '.env' -o -name '*.key' -o -name '*.pem' -o -name 'node_modules' -o -name '.claude'
returns nothing, and ls -a /src does not list .claude. The emptied a
directory shell still appears — .dockerignore excludes matching files, and a
directory left empty is still created in the context — but nothing inside it
survived. Throwaways and probe images deleted; no docker builder prune was
run at any point.

Comment 3's step 3 (#23
re-verification):
passes against the new, smaller context. Two consecutive
script/cibuild runs on an unchanged tree; run 2 has COPY . . CACHED and
RUN script/bootstrap CACHED, yet the check layer still executes — two Hugo
builds and All matched files use Prettier code style! in both runs. Full
output is pasted in the PR. A bare docker build . still fails on the
CHECK_EPOCH guard.

Two DoD conflicts surfaced, neither resolved silently:

  1. The canonical REPO_POLICIES.md is not clean under this repo's prettier
    settings — prettier@3.4.2 inserts a blank line before a nested list that
    follows a paragraph, in five places — so DoD 1 (byte-identical) and DoD 4
    (make fmt diff-free) cannot both hold. Resolved as DoD 4 anticipates:
    commit 1 adds the byte-identical copy, commit 2 is the five-blank-line
    reformat on its own. Syncing that back upstream is now a Future Step.
  2. REPO_POLICIES.md says make check "must not modify any files in the
    repo"; script/check's header says "must not modify any tracked files".
    make check writes public/ and .hugo_build.lock, both gitignored, so
    git status --porcelain is empty but files are created. script/check's
    wording is the accurate one; the policy sentence is unsatisfiable for any
    repo whose check builds artifacts. Called out in the PR for a decision
    rather than patched locally, since the canonical copy should not diverge.

make fmt is a no-op at HEAD, make check is green and leaves the tree
clean, make docker builds. TODO.md updated in the functional commit.

Done in [PR #31](https://git.eeqj.de/sneak/lora.vegas/pulls/31) (branch `policy-dotfiles`), two commits off `ccdedc3`. **What was built:** `REPO_POLICIES.md` (byte-identical canonical copy, front matter intact), `.editorconfig`, `.prettierrc`, `.prettierignore` (canonical contents), `.gitignore` extended with the canonical block plus `.claude/`, and `.dockerignore` rewritten with `**/`-prefixed depth-independent patterns. `LICENSE` and the README License section untouched, per the out-of-scope list and [#10](https://git.eeqj.de/sneak/lora.vegas/issues/10). `script/bootstrap` and `deploy.yml` untouched, so the live deploy path is unaffected. **DoD 9 (depth-planted `.dockerignore`):** passes, with a counterfactual so the test is shown to have teeth. Planted `a/b/.env`, `a/b/server.key`, `a/b/deep.pem`, `a/b/node_modules/x`, `config/.env`, `certs/server.key`, `.claude/worktrees/marker.txt`. With the canonical patterns left unprefixed, all six depth-planted paths reach `/src` in the image: ``` /src/certs/server.key /src/a/b/node_modules /src/a/b/deep.pem /src/a/b/server.key /src/a/b/.env /src/config/.env ``` With the shipped `**/` form, `docker run --rm lora.vegas find /src -name '.env' -o -name '*.key' -o -name '*.pem' -o -name 'node_modules' -o -name '.claude'` returns nothing, and `ls -a /src` does not list `.claude`. The emptied `a` directory shell still appears — `.dockerignore` excludes matching files, and a directory left empty is still created in the context — but nothing inside it survived. Throwaways and probe images deleted; no `docker builder prune` was run at any point. **Comment 3's step 3 ([#23](https://git.eeqj.de/sneak/lora.vegas/issues/23) re-verification):** passes against the new, smaller context. Two consecutive `script/cibuild` runs on an unchanged tree; run 2 has `COPY . .` `CACHED` and `RUN script/bootstrap` `CACHED`, yet the check layer still executes — two Hugo builds and `All matched files use Prettier code style!` in both runs. Full output is pasted in the PR. A bare `docker build .` still fails on the `CHECK_EPOCH` guard. **Two DoD conflicts surfaced, neither resolved silently:** 1. The canonical `REPO_POLICIES.md` is not clean under this repo's prettier settings — prettier@3.4.2 inserts a blank line before a nested list that follows a paragraph, in five places — so DoD 1 (byte-identical) and DoD 4 (`make fmt` diff-free) cannot both hold. Resolved as DoD 4 anticipates: commit 1 adds the byte-identical copy, commit 2 is the five-blank-line reformat on its own. Syncing that back upstream is now a Future Step. 2. `REPO_POLICIES.md` says `make check` "must not modify any files in the repo"; `script/check`'s header says "must not modify any **tracked** files". `make check` writes `public/` and `.hugo_build.lock`, both gitignored, so `git status --porcelain` is empty but files are created. `script/check`'s wording is the accurate one; the policy sentence is unsatisfiable for any repo whose check builds artifacts. Called out in the PR for a decision rather than patched locally, since the canonical copy should not diverge. `make fmt` is a no-op at `HEAD`, `make check` is green and leaves the tree clean, `make docker` builds. `TODO.md` updated in the functional commit.
Author
Collaborator

Two defects in the canonical upstream files, found while implementing this.
Recording here because they affect every repo that syncs them and I have no
write access to prompts. @sneak — these want fixing at source.

1. prompts/prompts/REPO_POLICIES.md is not prettier-clean. prettier@3.4.2
with the shared settings (tab width 4, proseWrap: always) wants a blank line
before a nested list following a paragraph, in five places. So any repo that
both commits the canonical file byte-identical and runs prettier over its
own markdown in make check has two requirements that cannot both hold. PR #31
handles it by splitting into a byte-identical commit plus a reformat commit,
but every future sync into any repo re-introduces the conflict. Fix: reformat
the file upstream with the shared settings; downstream copies then become
straight byte syncs.

2. REPO_POLICIES.md and the canonical script/check contradict each
other.
The policy says make check "must not modify any files in the repo";
script/check's header says "must not modify any tracked files". The
policy version is unsatisfiable for any repo whose check builds artifacts —
this one writes public/ and .hugo_build.lock, both gitignored. It also
cannot be used as a literal compliance probe, since it would fail every repo
that builds anything. Fix: change the policy line to "tracked files", matching
script/check.

PR #31 treats script/check as authoritative locally and deliberately does
not patch the committed canonical copy — diverging it downstream would
defeat the purpose of committing it. That is the right call, but it leaves this
repo carrying a canonical file that contradicts a canonical script until
upstream is fixed.

Neither blocks PR #31.

**Two defects in the canonical upstream files, found while implementing this.** Recording here because they affect every repo that syncs them and I have no write access to `prompts`. @sneak — these want fixing at source. **1. `prompts/prompts/REPO_POLICIES.md` is not prettier-clean.** prettier@3.4.2 with the shared settings (tab width 4, `proseWrap: always`) wants a blank line before a nested list following a paragraph, in five places. So any repo that both commits the canonical file byte-identical **and** runs prettier over its own markdown in `make check` has two requirements that cannot both hold. PR #31 handles it by splitting into a byte-identical commit plus a reformat commit, but every future sync into any repo re-introduces the conflict. Fix: reformat the file upstream with the shared settings; downstream copies then become straight byte syncs. **2. `REPO_POLICIES.md` and the canonical `script/check` contradict each other.** The policy says `make check` "must not modify any files in the repo"; `script/check`'s header says "must not modify any **tracked** files". The policy version is unsatisfiable for any repo whose check builds artifacts — this one writes `public/` and `.hugo_build.lock`, both gitignored. It also cannot be used as a literal compliance probe, since it would fail every repo that builds anything. Fix: change the policy line to "tracked files", matching `script/check`. PR #31 treats `script/check` as authoritative locally and deliberately does **not** patch the committed canonical copy — diverging it downstream would defeat the purpose of committing it. That is the right call, but it leaves this repo carrying a canonical file that contradicts a canonical script until upstream is fixed. Neither blocks PR #31.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/lora.vegas#8