Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions .claude/architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Architecture

Architectural decisions require operator approval before implementation.
ADRs log to `.logs/decisions/architecture.jsonl` (see `.claude/history.md`).

This repo is a **skill package**, not a networked application. There is no service
topology, API surface, datastore, or inter-service communication. Most generic
architecture concerns (API style, idempotency keys, cross-service clients, shared
databases) are **N/A**. The "architecture" here is the contract between the skill,
the `Vagrantfile`, the provisioning scripts, and the VM they produce.

---

## Core Design Principles
- **General-purpose, not project-specific.** `scripts/setup.sh` installs only a baseline (system deps, Docker, Go, mage, optional KVM). Consumer projects layer their own provisioning on top. Adding project-specific tooling to the base scripts is rejected.
- **Idempotent provisioning.** Every provisioning step must be safe to re-run; `vagrant provision` must converge to the same state. Guard installs with capability checks (`command -v ...`).
- **Disposable by design.** The VM holds no durable state. `vagrant destroy -f` is the recovery path. The host repo is rsynced in (read copy at `/project`), never mutated by the VM.
- **No host privilege.** All sudo/privileged operations happen inside the VM; the agent never needs host-level sudo.
- **Multi-provider parity.** The `Vagrantfile` supports Parallels, libvirt, and VirtualBox so the skill works across macOS, Linux, and Windows/WSL2. Provider-specific knobs live in their own provider blocks.

---

## Boundaries / Contracts
- **Skill ↔ host:** `SKILL.md` frontmatter declares `allowed-tools` and required bins (`metadata.openclaw.requires`). Honor these — do not assume tools outside the declared set.
- **Vagrantfile ↔ scripts:** the provisioner is invoked from the `Vagrantfile`; keep the host/guest path contract (`/project`) and env-var interface (`VM_CPUS`, `VM_MEMORY`, `PROJECT_SRC`) stable.
- **Tests ↔ behavior:** test boundary = behavior boundary. A behavior change must come with a bats assertion. Unit suites must not require a VM; integration/e2e suites may.

---

## Anti-Patterns (refuse these)
- Project-specific tooling baked into the general-purpose `scripts/setup.sh`.
- Non-idempotent provisioning (unconditional installs, appends without guards).
- Persisting state in the VM that survives `vagrant destroy` and is relied upon.
- Provider lock-in: a change that works on one provider and silently breaks the others.
- "Temporary" workarounds without an expiry date and an owner.
- Secrets in scripts, the `Vagrantfile`, source control, or CI variables.

---

## Decision Logging
Log to `.logs/decisions/architecture.jsonl`:
```json
{"id":"arch-001","date":"YYYY-MM-DD","decision":"...","rationale":"...","alternatives":"...","references":["https://..."]}
```

---

## Reference Architectures
When citing patterns, prefer primary sources:
- Vagrant official docs (developer.hashicorp.com/vagrant).
- Agent Skills standard documentation and the `skills-ref` validator.
- Provider docs: libvirt, VirtualBox, Parallels.
Cite the exact URL in `.logs/references/architecture.jsonl`.
47 changes: 47 additions & 0 deletions .claude/history.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# History — Decision and Reference Logging

All significant decisions and citable references log to disk as JSONL.
One JSON object per line. No prose, no markdown, no commentary inside the JSON.

---

## Decisions

**Location:** `.logs/decisions/<topic>.jsonl`

**Format:**
```json
{"id":"<topic>-NNN","date":"YYYY-MM-DD","decision":"One-sentence statement of what was decided","rationale":"Why","alternatives":"What was considered and rejected, and why","references":["https://..."]}
```

**Rules:**
- ID prefix matches the topic filename. IDs increment sequentially. Check the last entry before writing a new one.
- One decision per line. No embedded newlines — keep the file `jq -c` parseable.
- Log the decision before or immediately after acting on it. Not "later."
- Architectural decisions require operator approval before the log entry is written.

**What counts as a decision worth logging:**
- A choice between two or more viable options.
- A constraint, assumption, or non-obvious workaround being encoded.
- A tool, framework, library, or service being adopted or rejected.
- A scope boundary being set or changed.
- Any one-way-door action.

Routine code edits, typo fixes, and pure refactors do not require log entries.

---

## References

**Location:** `.logs/references/<topic>.jsonl`

**Format:**
```json
{"id":"ref-NNN","date":"YYYY-MM-DD","category":"official_docs|standard|article|repo|paper","title":"...","url":"...","relevance":"why this source supports the claim"}
```

**Rules:**
- Cite every external claim. No unverifiable statistics, no "studies show…" without a link.
- Primary authorities: official vendor docs, NIST, CIS, SLSA, DORA, OWASP, official RFCs.
- Not citations: Medium posts, Stack Overflow answers, LLM outputs, screenshots without a URL.
- If a source cannot be validated, state that explicitly. Do not pretend it was validated.
55 changes: 55 additions & 0 deletions .claude/language.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Language Conventions

`[FILL IN]` marks a gap. Treat as "ask the operator," not a guess.

This repo has no compiled application code. The active languages are Ruby (the
`Vagrantfile`) and Bash (the provisioning/verification scripts). Correctness is
validated by syntax checks, shellcheck, and bats-core suites — there is no unit
test framework beyond bats and no coverage tooling.

For each active language, this file records:
1. Pinned version and how it is pinned.
2. Formatter and config location.
3. Linter and config location.
4. Test / validation approach.

---

## Active Languages

### Bash
- Version target: bash 5.x (Ubuntu 24.04 guest; macOS/Linux hosts).
- Scope: `scripts/setup.sh`, `scripts/verify.sh`, inline provisioning in `Vagrantfile`, and `examples/*/test/e2e.bats` helpers.
- Formatter: none. Match existing style (4-space indent, aligned comment banners).
- Linter: `shellcheck` — `make lint` runs `shellcheck scripts/setup.sh scripts/verify.sh`. Must be clean.
- Style: `set -euo pipefail` in every script. Quote all expansions. No `eval`. All scripts must be **idempotent** (`vagrant provision` re-runs safely).
- Validation: bats-core suites assert structure and behavior (`test/scripts.bats`).

### Ruby (Vagrantfile only)
- Version: Ruby 3.3 in CI (`ruby/setup-ruby@v1`). No `.ruby-version` file pinned in repo; the runtime Ruby is whatever Vagrant bundles when the skill is used.
- Scope: `Vagrantfile` and `examples/*/Vagrantfile`. No application Ruby, no gems beyond Vagrant plugins (e.g. vagrant-libvirt).
- Formatter: none.
- Linter / validation: `ruby -c <Vagrantfile>` (`make lint` runs `ruby -c Vagrantfile`). Must report `Syntax OK`.
- Validation: `test/vagrantfile.bats` checks required configuration (box, synced_folder, providers).

---

## Skill Definition (Markdown + YAML frontmatter)
- `SKILL.md` is validated against the Agent Skills standard. The validator requires the skill directory to be named `vagrant`, so the `validate-skill` CI job copies the checkout to `/tmp/vagrant` first: `mkdir -p /tmp/vagrant && cp -r ./* ./.* /tmp/vagrant/ 2>/dev/null; npx --yes skills-ref validate /tmp/vagrant`. Running it directly from the `vagrant-skill` checkout fails on the directory-name check.
- `test/skill.bats` asserts frontmatter fields and structure.
- Keep `SKILL.md`, the `Vagrantfile`, and the bats suites in sync when behavior changes.

---

## Tests (bats-core)
- Unit (no VM): `test/scripts.bats`, `test/skill.bats`, `test/vagrantfile.bats` — run by `make test` (alias `test-unit`).
- Integration (boots a real VM, requires Vagrant + provider): `test/integration.bats` — run by `make test-integration`.
- End-to-end examples: `examples/<name>/test/e2e.bats` — boot the example VM, run bats, tear down (`vagrant destroy -f`). bats exits non-zero on any failure.
- No coverage threshold is enforced; correctness is asserted by the bats suites passing.

---

## Cross-Cutting Rules
- No language rule overrides the linter. Fix the config or script, not by suppressing the check.
- `Vagrantfile` is committed; `.vagrant/` and `node_modules/` are gitignored and never committed.
- Changing skill behavior requires updating `SKILL.md` and the matching bats suite in the same change.
69 changes: 69 additions & 0 deletions .claude/sourcecontrol.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Source Control

---

## Repository
- Host: GitHub — `github.com/daax-dev/vagrant-skill`
- Default branch: `main`
- All work lands via PR. No direct commits to main.

---

## Branch Naming
- Feature: `feature/<short-topic>`
- Bug fix: `fix/<short-topic>`
- Docs: `docs/<short-topic>`
- Chore / tooling: `chore/<short-topic>`
- Release: `release/vX.Y.Z` and version bumps `bump-X.Y.Z` (existing convention in this repo).
- Claude Code sessions: harness-assigned name (e.g., `claude/<task>-<id>`). Do not rename mid-session.
- Lowercase, hyphen-separated. Keep names short.

---

## Commits
- Imperative mood, present tense: "add X", not "added X" or "adds X".
- Subject line ≤ 72 characters.
- Body explains the **why**. The diff shows the what.
- One logical change per commit. Mixed-purpose commits get rejected at review.
- Do not amend a commit that has already been pushed unless explicitly asked.

---

## Pull Requests
- Open a PR as soon as the branch has a meaningful commit. Draft is fine.
- PR title = leading commit subject line.
- PR body must include:
- Problem statement (link the GitHub Issue when one exists).
- Approach taken and alternatives considered.
- Test evidence (commands run, output — at minimum `make lint && make test`).
- Which model produced and which model validated (if AI-assisted).
- Never merge your own PR unless explicitly authorized by the operator.
- Squash-merge by default unless the branch history is intentionally curated.

---

## Worktrees
- Long-running parallel work uses `git worktree` rather than branch-switching in place.
- Worktree paths live outside the primary checkout (e.g., `/tmp/<repo>-<branch>`).
- Worktrees are disposable. Clean them up when the branch lands (`git worktree remove`).

---

## What Never Gets Committed
- Secrets, tokens, keys, connection strings, npm publish tokens.
- `.env` files with live values.
- VM state (`.vagrant/`) and `node_modules/` — both gitignored.
- IDE / OS noise (`.DS_Store`, `Thumbs.db`) — already in `.gitignore`.

---

## Destructive Operations
- Force-push to a shared branch requires explicit operator authorization.
- `git reset --hard`, branch deletion, and history rewrites require confirmation when recovery is uncertain.
- Treat destructive git operations as high-risk: pause, verify the target, get confirmation.

---

## Tags and Releases
- Tag scheme: semver `vX.Y.Z`, matching `package.json` `version` (currently 0.7.x).
- Release flow: version-bump branch (`bump-X.Y.Z`) → PR → publish via `.github/workflows/publish.yml` to npm + ClawHub.
37 changes: 37 additions & 0 deletions .claude/stack.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Stack

`[FILL IN]` marks an undefined entry. Treat as "ask the operator," not a guess.
Only document what is confirmed and deployable today.

This repo is a **skill package**, not a running service. There is no persistence,
messaging, auth, observability, or cloud-compute tier — those sections are omitted
deliberately. The "runtime" is the contributor toolchain plus the VM the skill provisions.

---

## Skill Format
- Agent Skills standard: `SKILL.md` with YAML frontmatter (`name`, `description`, `license`, `compatibility`, `allowed-tools`, `metadata`).
- Validated by the `validate-skill` CI job. The validator requires the skill dir to be named `vagrant`, so CI copies the checkout to `/tmp/vagrant` before validating: `mkdir -p /tmp/vagrant && cp -r ./* ./.* /tmp/vagrant/ 2>/dev/null; npx --yes skills-ref validate /tmp/vagrant`.
- Consumed as a Claude Code skill (`/vagrant`) and an OpenClaw skill (`metadata.openclaw` declares required bins).

## Contributor Toolchain
- Ruby — `Vagrantfile` is Ruby; validated via `ruby -c`. CI pins Ruby 3.3 (`ruby/setup-ruby@v1`). No application Ruby code, no gems beyond Vagrant plugins.
- Bash — `scripts/setup.sh`, `scripts/verify.sh`; linted with shellcheck.
- bats-core — test runner for `test/*.bats` and `examples/*/test/e2e.bats`.
- Vagrant CLI + a provider — required only to run integration/e2e tests and to use the skill. Providers: Parallels (macOS Apple Silicon), libvirt (Linux, nested KVM), VirtualBox (cross-platform). Base box `bento/ubuntu-24.04`.

## Provisioned VM (what the skill installs)
- Ubuntu 24.04, full sudo, Docker CE, Go, mage, optional nested KVM. See `references/vm-contents.md` for the authoritative inventory.
- Configurable via env vars before `vagrant up`: `VM_CPUS` (default 4), `VM_MEMORY` (default 4096 MB), `PROJECT_SRC`.

## Build / Package
- npm package `@daax-dev/vagrant-skill`; Node engine `>=22.14.0`. `package.json` `files`: `SKILL.md`, `Vagrantfile`, `scripts/`, `references/`, `LICENSE`. `publishConfig.access: public`.
- npm `scripts` proxy to make: `lint`, `test`, `test:integration`, `test:all`.
- CI: GitHub Actions — `.github/workflows/ci.yml` runs `lint` → (`test`, `validate-skill`) on push/PR to `main`. Release/publish via `.github/workflows/publish.yml`.
- Artifact registries: npm (public) and ClawHub (per `package.json` keywords / publish workflow).

## Explicitly Not in Stack
List rejected tools and the reason. Prevents re-proposal.
- Project-specific provisioning inside `scripts/setup.sh` — this is a general-purpose skill; consumers add their own tooling on top.
- Docker Desktop — the skill deliberately provides Docker CE inside a VM to avoid Docker Desktop's commercial-license constraints (see `examples/mac-docker-compose/`).
- Application databases / services — out of scope; this repo ships configuration and scripts, not a deployed app.
52 changes: 52 additions & 0 deletions .claude/workflow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Workflow

## Planning
- A plan is required for any non-trivial change.
- Trivial: typo fix, single-line config update, obvious rename. Everything else requires a plan.
- Write the plan down — in the PR description, task system, or `.logs/decisions/`. Plans held only in chat do not count.
- Present trade-offs as facts: option, cost, risk, reversibility. The operator decides; the agent executes.
- Do not start coding until the plan is approved.

---

## Execution Discipline
- State assumptions that affect implementation. If the request has multiple plausible readings, ask before editing.
- Smallest change that satisfies the verified goal. No speculative features, abstractions, or config.
- Touch only what the task requires. No adjacent cleanup or drive-by refactors. Every changed line traces to the request or its validation.
- Remove only the orphans your change created; leave pre-existing dead code (mention it, don't delete).
- Define a verifiable goal before coding. Add or update tests when behavior changes (bats suites under `test/`).
- This is a general-purpose skill: keep `scripts/setup.sh` free of project-specific tooling. All scripts stay idempotent and shellcheck-clean.

---

## Work Intake
Tasks originate from (check in this order):
1. GitHub Issues — `github.com/daax-dev/vagrant-skill/issues` (active; bug reports drive fixes and PRs).
2. Direct request from operator.

Identify the source before starting. If the same task appears in multiple systems, ask which is canonical.

---

## Model Selection
- Match model capability to task complexity. Do not waste large models on small tasks.
- Code with one model; validate with a model from a **different provider where possible** (e.g., produced by Claude/Anthropic, validated by Codex/OpenAI, or vice versa). Prefer cross-provider; a different model from the same provider is the fallback; same model is last resort. Record both — producer and validator — in the PR description, and note if cross-provider was not possible.
- Call out when a task requires a paid API call. State the cost estimate before incurring it.

---

## Communication
- Report blockers immediately. No silent workarounds.
- Surface uncertainty. State confidence level. No claims of certainty without a validated primary source.
- Objective language. No first-person pronouns. No apologies.

---

## Definition of Done
A task is done only when:
- [ ] Lint and unit tests pass: `make lint && make test` (matches CI: shellcheck + `ruby -c` + bats unit suites). When a Vagrant provider is available and VM behavior changed, also run `make test-integration` (or `make test-all`).
- [ ] Skill changes validate against the Agent Skills standard. The validator requires the skill directory to be named `vagrant`, so run the CI flow (the `validate-skill` job) rather than invoking it from the `vagrant-skill` checkout root: `mkdir -p /tmp/vagrant && cp -r ./* ./.* /tmp/vagrant/ 2>/dev/null; npx --yes skills-ref validate /tmp/vagrant`.
- [ ] PR opened with problem statement, approach, and test evidence.
- [ ] Non-trivial decisions logged in `.logs/decisions/` per `.claude/history.md`.
- [ ] Validation pass by a separate model — cross-provider (Claude ↔ Codex) where possible — recorded in the PR description as `Validation:` producer model + validator model + verdict (note if cross-provider was not possible).
- [ ] Task system of record updated to done with link to PR/commit.
Loading
Loading