Skip to content

refactor(dockerfile): drop speculative dpkg-owner branch from pebble removal - #88

Open
sbp-bvanb wants to merge 19 commits into
mainfrom
fix/pebble-rm
Open

sbp-bvanb wants to merge 19 commits into
mainfrom
fix/pebble-rm

Conversation

@sbp-bvanb

@sbp-bvanb sbp-bvanb commented Sep 25, 2026 •

Copy link
Copy Markdown
Collaborator

Closes #65

Replaces the pebble layer's dpkg-owner/purge branch with ! dpkg -S /usr/bin/pebble >/dev/null 2>&1 && rm -f /usr/bin/pebble and drops the comment sentence justifying the purge branch. There's no purge path any more: if a future base image packages pebble, the build fails at this layer, so handling it becomes a deliberate decision.

No openspec/specs or tests reference the purge-if-owned behaviour.

🤖 Generated with Claude Code

Part of stack A (GitHub stack #102): bottom of the stack, based on main.

Comment thread Dockerfile Outdated
&& if [ -n "$owner" ]; then apt-get purge -y "$owner"; else rm -f /usr/bin/pebble; fi \
&& ! test -e /usr/bin/pebble
# since no rebuild against a patched stdlib exists yet.
RUN rm -f /usr/bin/pebble && ! test -e /usr/bin/pebble

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rm -f also removes a file that a package owns, and dpkg keeps listing it afterwards, so ! test -e can't catch a future packaged pebble. Shall we fail on the owner instead? It stays a one-liner, and a packaged pebble becomes a deliberate decision:

Suggested change
RUN rm -f /usr/bin/pebble && ! test -e /usr/bin/pebble
RUN ! dpkg -S /usr/bin/pebble >/dev/null 2>&1 && rm -f /usr/bin/pebble

The PR body's "fails the build loudly" line would need the same update.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, rm -f made the ! test -e check a no-op. Applied your one-liner in fff7fb1 and updated the PR body to match.

@sbp-bvanb
sbp-bvanb removed this pull request from stack #102 September 26, 2026 21:59
sbp-bvanb and others added 16 commits September 29, 2026 11:24
README is the project's front door and a ~35-minute read: 458 lines, 8,537
words, with a 3,246-character bullet at README.md:276 and a threat model
averaging 107 words per line.

The part that makes this a spec change rather than a docs commit is invisible
until you grep for it. Nine scenarios across four capabilities locate this
prose by section name -- `claude-docker/README.md` § Threat model, "the
preinstalled-CLI list at the top of ...". Moving the prose makes them false,
and openspec/specs/ is generated on archive and may not be hand-edited.

The deltas reword those scenarios to be location-independent rather than
repointing each at a new docs/ file. Every one of them was always a claim
about what the documentation says; the filename was incidental precision that
made prose layout a spec-level concern. Location-independent wording means the
next reorganisation needs no spec change at all.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…removal

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
README keeps what a new user needs to get running -- intro, install, the GHCR
path, container runtime, usage, the credential opt-in table, session flags --
plus Specs and License, and gains a four-line Documentation index. The
remaining ~7,000 words move to docs/auth.md, docs/security.md,
docs/maintenance.md and docs/workflows.md, grouped by audience rather than by
topic adjacency, at 1,400-2,200 words each.

The credential opt-in table stays in README deliberately: it is the most
cross-referenced reference in the file and it is what people come back for.

This is a relocation, not a rewrite. A normalised diff against the old README
-- link targets and heading levels collapsed -- shows exactly two changed
prose lines, both directional words that stopped being true once the text
moved. The 3,246-character runtime code-fetch bullet and the 2,184-character
hardening paragraph land in docs/security.md unchanged; rewriting them in the
same commit would cost the reviewer the ability to confirm by inspection that
nothing else was smuggled in.

Every moved heading keeps its exact text, so every anchor slug survives; only
the file in front of the # changes. 23 intra-README anchors become cross-file
links, 12 repo-relative links inside the moved text gain a ../ prefix, and
AGENTS.md and CONTRIBUTING.md are repointed off README.md#threat-model.

run.sh's --help heredoc shipped a section title to the terminal and now names
docs/auth.md. Three comments describing README by content follow their prose.

ci.yml's link check stops being advisory. That was defensible when every link
was intra-README and a break was a few hundred lines from its target; with 23
links crossing a file boundary, the way you break one is by renaming a heading
in a file you were not looking at, and an advisory check nobody reads is a
check that does not exist. Verified clean against main before the split, so
the gate starts green. Markdownlint stays advisory -- there is no config in
the repo, so it runs at defaults and MD013 fires on nearly every prose line.

Closes #76

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Making the step blocking surfaced that it had never checked anything. lychee
v0.24 turned include_fragments from a bool into an enum
(none|anchor-only|text-only|full), so `include_fragments = true` is a config
parse error and lychee exited 3 before reading a single file. Under
continue-on-error that looked exactly like a pass.

anchor-only is what bare `--include-fragments` in ci.yml resolves to, and no
link in this repo uses a text fragment.

Also pin lycheeVersion. The action's default for that input floats while the
action itself is SHA-pinned, which is how a tool-side enum change landed here
in the first place. Survivable while the step was advisory; a red build on an
unrelated PR now that it gates.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
lychee's include/exclude are regexes matched against the links, not globs
matched against the files, so `include = ["*.md"]` is an invalid regex --
"repetition operator missing expression". File selection is the path argument
in ci.yml plus exclude_path.

Same root cause as the include_fragments bool: the config has never been
loaded, so nothing it says has ever been tested.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Replace the repo's own lychee step in ci.yml with the shared lint-links
testing-type (mcvs-general-action v0.7.1). lychee.toml keeps it offline
and out of the archive.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#108 rewrote the note in README after this branch had already moved it,
so the rebase kept the old PINS_UPDATER_TOKEN text in the moved copy.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every other paragraph in docs/ is one line. Line joins only; word diff
is empty.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
"Workflows" already means GitHub Actions here, and host config parity,
file ownership and extending the image are not workflows. Anchors are
unchanged; only the file name in front of the # moves.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Install and Usage already come first on main (lines 12 and 74); the
proposal claimed a reader had to scroll past the reference material to
reach them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The container runs Claude, so the Terraform, uvx pipenv and worktree
repair steps now say Claude runs them (or you type `! …`).

Terraform, checked against the tfenv v3.2.2 source: TFENV_AUTO_INSTALL
defaults to true (lib/tfenv-exec.sh), so the first terraform call
installs the .terraform-version version and `tfenv install` is not a
step. required_version in *.tf is only read via the min-required or
latest-allowed keyword (libexec/tfenv-resolve-version).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Closes #113, pulled into this PR as suggested in review, on top of the
verbatim move.

- Runtime code-fetch becomes a list of the fetchers (npx, pnpm dlx,
  uvx, tfenv, Go) with each one's risk. Its build-time pin sentence
  repeated the hardening paragraph, so it folds in there; the
  nodejs/task apt-repo detail it alone carried moves with it.
- The hardening paragraph becomes three short lists: Not applied first
  (what a reviewer needs most, previously its last sentence), then
  Applied at runtime and Applied at build time.
- The image-scanning section's "npm audit signatures check above"
  pointed at README text that now lives in docs/maintenance.md; link it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
sbp-bvanb and others added 3 commits September 29, 2026 14:14
docs: split the readme into a quickstart plus docs/
The applied / not-applied lists followed the last threat-model bullet
with nothing introducing them. The tfenv version in auth.md would go
stale at the next pin bump; the auto-install default is what matters.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
rm -f also removes a package-owned file, so the old ! test -e check
could never fail. Checking dpkg -S first makes a packaged pebble a
build failure, per review.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dockerfile: pebble layer branches on a dpkg owner its own comment says does not exist

2 participants