Skip to content

Repo true-up: Features own their state, augment official Features, host tasks fixed - #10

Closed
nabil-becker wants to merge 8 commits into
mainfrom
repo-true-up
Closed

nabil-becker wants to merge 8 commits into
mainfrom
repo-true-up

Conversation

@nabil-becker

Copy link
Copy Markdown
Owner

What

The collection becomes an ecosystem: every Feature with state owns it (named volume + post-create hook), augmentation Features sit after the official ones instead of replacing them (claude-code, new git, gh, az), a shared common helper (dcf-persist) backs every hook, and the vendored host tasks get the fixes two consumer repos had to work around (.env values reaching the include, pwsh/claude/homes tasks, --docker-path only where accepted). env_mnt is gone; the checkout is the only thing on disk.

Why

Two repos (the office and DSNP) had started wrapping the collection locally: a dc:* passthrough for the Task 3.45 dotenv bug, a claude-host launcher, host-side folder creation for Claude's home, a git wrapper for worktrees under GIT_DIR, chowns of config dirs. Those are now upstream, generically, and the rules are written down in README "How the pieces fit" and CONTRIBUTING. One deliberate decision: no dependsOn on the official Anthropic Feature (npm-only, unpinned, unverified); ours augments it when listed and installs the verified native binary otherwise.

Verified on real Debian containers via wslc for every Feature touched (install as root, tests as non-root, hooks twice, state persisting across containers, volume/bind/image detection on real mounts). Two bugs found and fixed on the way (set -u trap in the claude-code installer; --docker-path passed to features generate-docs).

Checklist

  • Every commit is signed off (Signed-off-by:, DCO) - automatic after task repo:setup
  • version bumped in src/<id>/devcontainer-feature.json (semver)
  • Downloads remain checksum-verified; nothing unverified is piped into a shell
  • install.sh is idempotent and does not assume a remoteUser
  • Tests updated (test/<id>/test.sh, scenarios.json) and task test FEATURE=<id> passes (in this repo's devcontainer or on Linux/macOS) - run as equivalent wslc Debian runs; CI runs the real harness
  • taskfile.yml present and registered via installTaskfile (new Features)
  • task lint passes
  • NOTES.md updated if behaviour or options changed, and task docs run so src/<id>/README.md is current

Not included: .devcontainer/devcontainer-lock.json (stale, from an experiment; left untracked). The repo's own devcontainer enables git and gh only after the first release publishes them.

🤖 Generated with Claude Code

https://claude.ai/code/session_01FBCVdVNMWSkF3PKnDH1UFN

nabil-becker and others added 8 commits October 15, 2026 12:28
Signed-off-by: Nabil Becker <nabil.becker@live.com>
…st tasks fixed

Two consumer repos had to wrap this collection to get what they needed;
this change folds those wrappers back in and sets the ecosystem rules.

Features
- claude-code: augments the official Anthropic Feature when present
  (install: auto/native/none), ships claude-host (resume one session by
  UUID via HOST_SESSION), owns CLAUDE_CONFIG_DIR in a named volume with
  a post-create hook. Fixes a set -u trap bug in the native installer.
- git (new): worktree-aware wrapper that scopes GIT_DIR/GIT_WORK_TREE to
  the checkout (nested worktrees, temp folders, init/clone), post-create
  safe.directory and core.hooksPath, GIT_CONFIG_GLOBAL in a volume.
- gh (new): verified release install when absent, GH_CONFIG_DIR volume,
  git credential helper from gh.
- az (new): augments the official azure-cli Feature, AZURE_CONFIG_DIR
  volume, bicep from PATH.
- common (new): dcf-persist, the shared helper behind every hook;
  vendored into the Features that use it, checked identical by lint.
- coder-cli, argocd: own their login state the same way.
- devcontainer-cli: --docker-path only for subcommands that take it.

Host side (bootstrap)
- devcontainer.yml: the Task 3.45 include env: bug fixed, so .env values
  reach the tasks (no dc:* passthrough needed; dc is an include alias);
  new pwsh, claude and homes tasks; in-container runs branch in the
  template because per-command if: is ignored.
- devcontainer:homes (pwsh + bash twins) creates host folders for repos
  that bind-mount a Feature's state target to the host disk.
- env_mnt removed everywhere: the checkout is the only thing on disk.

Docs: README "How the pieces fit" (the paradigm), CONTRIBUTING
conventions for augmentations, state ownership, vendored helpers and
Taskfile pitfalls. CI matrices and the global scenario cover the new
Features.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FBCVdVNMWSkF3PKnDH1UFN
Signed-off-by: Nabil Becker <nabil.becker@live.com>
…f the official claude

The git hooks_and_safe_all scenario expected safe.directory * to be
reported as added, but the Feature's own postCreateCommand adds it before
the scenario runs, so kept is equally right. The claude-code
augment_official scenario matched "node" in the path of the official
Feature's claude, which the node Feature puts under /usr/local/share/nvm/
current/bin; match nvm or node and require it is not our native binary.
Both passed in the wslc harness only because no hook ran there first.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FBCVdVNMWSkF3PKnDH1UFN
Signed-off-by: Nabil Becker <nabil.becker@live.com>
- .devcontainer/devcontainer.json references every src/<id> Feature as
  ./features/<id>; `task features:stage` copies them there (gitignored)
  as initializeCommand, so unreleased changes are what runs here. The
  checkout's git dir (outside OneDrive) is bind-mounted the way the
  consumer repos do it, with the git Feature's wrapper scoping GIT_DIR.
- Host paths in every example use ${localEnv:USERPROFILE} only: on this
  Windows host both USERPROFILE and HOME are set, so concatenating the
  two doubled the path and failed the first start.
- gh-setup makes the global git config folder usable itself (dcf-persist)
  instead of relying on the git hook having run first; installsAfter may
  only name published Features (documented in CONTRIBUTING).
- post-create.sh reports what the Features set up instead of redoing it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FBCVdVNMWSkF3PKnDH1UFN
Signed-off-by: Nabil Becker <nabil.becker@live.com>
…trapped with it

The devhost Feature ports the housekeeping of the consumer repos into one
installable piece: devhost-run-job with the scribe, secretary, librarian
and tester backs (hook-driven, quiet notices, stakes, guards that undo a
rewrite), devhost-briefing at session start, devhost-costs and the monthly
cost report, devhost-adr, devhost-verify (ledger append-only and shape,
secrets, forbidden words and redacted names, ADR shape, task descriptions,
skill frontmatter) and devhost-init, which scaffolds a repo with LEXICON,
PROCESS, TODO, the ledger and ADR folders, the four skills, the hook block
and a CLAUDE.md include. Job state lives in the Feature's volume; every
path and model is a DEVHOST_* / <JOB>_MODEL setting; no person is named,
the person is "the Operator". Verified on Debian with a stub claude, and
by 35 stdlib unit tests that now run in `task lint` and CI.

This repository adopts it: devhost in its own devcontainer, the scaffold
run inside it, CLAUDE.md written for the collection, the pre-commit guard,
and a seeded TODO.md with what is next (merge or split PR #10, release,
first sign-in and first back runs, consumers' adoption).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FBCVdVNMWSkF3PKnDH1UFN
Signed-off-by: Nabil Becker <nabil.becker@live.com>
CI's shellcheck reports SC2317 (unreachable) for job_claude and redact,
which the sourced job file calls; the host's 0.11 does not.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FBCVdVNMWSkF3PKnDH1UFN
Signed-off-by: Nabil Becker <nabil.becker@live.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FBCVdVNMWSkF3PKnDH1UFN
Signed-off-by: Nabil Becker <nabil.becker@live.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FBCVdVNMWSkF3PKnDH1UFN
Signed-off-by: Nabil Becker <nabil.becker@live.com>
@nabil-becker nabil-becker mentioned this pull request Oct 16, 2026
6 of 8 tasks
nabil-becker added a commit that referenced this pull request Oct 16, 2026
## What

The Features half of the repo true-up, landed before the rest so it can
be released and the true-up can pin released versions.

- **New Features:** `git`, `gh`, `az`, `common`, `devhost`, `kube-state`
(owns `KUBECONFIG` state, the way `gh`/`az` own theirs).
- **Changed:** `claude-code`, `dsc` (verifies the tarball without
api.github.com: pinned digests, then the release page; never installs
unverified), `velero`, `argocd`, `coder-cli`, `devcontainer-cli`.
- **devhost:** one source of `DEVHOST_*` defaults; a non-identifying
engineer handle (`DEVHOST_ENGINEER`, default `operator`); verify refuses
a tracked `.env`; descriptive slug ids for backlog items.
- **Tasks:** `task test` / `test:global` stop with a clear message when
no Docker daemon answers (CI is the test loop).

Built by path-filtering `repo-true-up` (#10) and today's work: only
`src/`, `test/`, `.github/workflows/`, `.gitignore`, and the Feature
parts of README, CONTRIBUTING and the Taskfile. Every commit keeps its
original author and sign-off. The devhost of this repo, bootstrap,
`.githooks`, and the way-of-working records stay in #10 for later.

## Why

Backlog: `kube-state-feature`, `one-devhost-defaults`,
`dsc-without-github-api`, `workstation-feature-tests`, and
`release-collection` (this PR is what gets released). Consumers cannot
pull `git`/`gh`/`az`/`common`/`devhost` until they are published.

## Checklist

- [x] Every commit is signed off (DCO): checked, every sign-off matches
its author
- [x] `version` bumped in `src/<id>/devcontainer-feature.json` (semver)
- [x] Downloads remain checksum-verified; nothing unverified is piped
into a shell
- [ ] `install.sh` is idempotent and does not assume a `remoteUser`:
review
- [ ] Tests updated and `task test FEATURE=<id>` passes: **not run
locally (no Docker in the devhost); CI is the first real run**
- [x] `taskfile.yml` present and registered via `installTaskfile` (new
Features)
- [x] `task lint` passes
- [x] `NOTES.md` updated, `task docs` run (no diff)

**Reviewer notes:** the README "How the pieces fit" section was trimmed
to the Feature parts by an agent, so check its wording. `devhost` is at
1.1.0 although it was never published; reset to 1.0.0 before the release
if you prefer. Agent co-author trailers use `@noreply.invalid` addresses
on purpose (ADR 0002).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Signed-off-by: Nabil Becker <nabil.becker@live.com>
Signed-off-by: devhost agent <devhost-agent@noreply.invalid>
Co-authored-by: Claude Fable 5.1 <claude-fable-5-1@noreply.invalid>
Co-authored-by: devhost agent <devhost-agent@noreply.invalid>
Co-authored-by: Claude Sonnet 5.5 <claude-sonnet-5-5@noreply.invalid>
Co-authored-by: Claude Haiku 4.5 <claude-haiku-4-5@noreply.invalid>
Co-authored-by: Claude Opus 5.5 <claude-opus-5-5@noreply.invalid>
@nabil-becker
nabil-becker deleted the repo-true-up branch October 19, 2026 14:16
nabil-becker added a commit that referenced this pull request Oct 19, 2026
…trapped with it

The devhost Feature ports the housekeeping of the consumer repos into one
installable piece: devhost-run-job with the scribe, secretary, librarian
and tester backs (hook-driven, quiet notices, stakes, guards that undo a
rewrite), devhost-briefing at session start, devhost-costs and the monthly
cost report, devhost-adr, devhost-verify (ledger append-only and shape,
secrets, forbidden words and redacted names, ADR shape, task descriptions,
skill frontmatter) and devhost-init, which scaffolds a repo with LEXICON,
PROCESS, TODO, the ledger and ADR folders, the four skills, the hook block
and a CLAUDE.md include. Job state lives in the Feature's volume; every
path and model is a DEVHOST_* / <JOB>_MODEL setting; no person is named,
the person is "the Operator". Verified on Debian with a stub claude, and
by 35 stdlib unit tests that now run in `task lint` and CI.

This repository adopts it: devhost in its own devcontainer, the scaffold
run inside it, CLAUDE.md written for the collection, the pre-commit guard,
and a seeded TODO.md with what is next (merge or split PR #10, release,
first sign-in and first back runs, consumers' adoption).

Co-Authored-By: Claude Fable 5.1 <claude-fable-5-1@noreply.invalid>
Claude-Session: https://claude.ai/code/session_01FBCVdVNMWSkF3PKnDH1UFN
Signed-off-by: Nabil Becker <nabil.becker@live.com>
Signed-off-by: devhost agent <devhost-agent@noreply.invalid>
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.

2 participants