Plan: claude-quickstart Alignment

On this page

Status

Step Description Status

1

Plan file and nav entry

Done (pre-ADR-030)

2

Split security.md into security-baseline.md (Tier 1) + security.md (Tier 2)

Done (pre-ADR-030)

3

Add "Known Agent Biases" and ADR conventions to coding-conventions.md

Done (pre-ADR-030)

4

Add "Never weaken a test" rules to testing.md

Done (pre-ADR-030)

5

Add .config/nextest.toml

Done (pre-ADR-030) — already existed

6

Add architecture.md to .claude/docs/

Done (pre-ADR-030)

7

Rename devstack.md to local-dev.md and align with template

Done (pre-ADR-030)

8

Add .gitattributes for LF enforcement

Done (pre-ADR-030)

9

Add .env.example

Done (pre-ADR-030) — already existed

10

Enhance delivery-protocol.md with architectural recommendations + expanded preflight

Done (pre-ADR-030)

11

Update coding-conventions.md with container runtime, dependency management, and task runner sections

Done (pre-ADR-030)

12

Migrate devstack scripts to cargo xtask

Done (2026-03-21) — MR !52

13

Documentation, commit, push, MR

Done (2026-03-21) — MR !52

Issues: TBD
Branch: feature/quickstart-alignment

Context

The claude-quickstart template (v2026.1) has evolved significantly with new governance standards, testing rules, security tiers, and a cargo xtask task runner mandate. CRAIG adopted some quickstart files earlier (SECURITY.adoc, deny.toml, security.md, check-claude-docs.sh) but the template has since added:

  • Tiered document system (Tier 1 universal/immutable, Tier 2 universal skeleton, Tier 3 mandatory project-specific)

  • security-baseline.md (Tier 1) separate from security.md (Tier 2)

  • Known Agent Biases section in coding conventions

  • Explicit "never weaken a test" rules in testing.md

  • .config/nextest.toml for standardized test profiles

  • architecture.md and local-dev.md mandatory doc templates

  • cargo xtask as the sole task runner (replacing shell scripts)

  • Enhanced delivery protocol with architectural recommendation process

  • .gitattributes, .env.example, .editorconfig standard files

Scope

In scope:

  • All governance doc alignment (Steps 2-11)

  • cargo xtask migration (Step 12) — replacing legacy devstack scripts with Rust-based task runner

  • Standard file additions (.gitattributes, .env.example, .config/nextest.toml)

Out of scope:

  • Tier 1 doc hash enforcement in CI (tracked by scripts/check-claude-docs.sh, already present)

  • .editorconfig (CRAIG already has consistent formatting via cargo fmt + Askama templates)

Steps

Step 1: Plan file and nav entry

Create this plan file and link in nav.adoc under Active.

Step 2: Split security.md into Tier 1 + Tier 2

The quickstart separates security into:

  • security-baseline.md (Tier 1, universal, immutable) — Kerckhoffs’s principle + public visibility enforcement

  • security.md (Tier 2, project-specific) — auth model, input handling, transport, secrets, etc.

Files:

  • .claude/docs/security-baseline.md — NEW, copy from claude-quickstart/.claude/docs/security-baseline.md verbatim (Tier 1, do not edit)

  • .claude/docs/security.md — MODIFY, remove Sections 1-2 (Kerckhoffs/visibility — now in baseline), keep Sections 3-10 (project-specific)

  • .claude/CLAUDE.md — update required reading list to reference both files

Step 3: Add Known Agent Biases and ADR conventions to coding-conventions.md

File: .claude/docs/coding-conventions.md

Add two new sections from the quickstart template:

Known Agent Biases (after Plan Authoring section):

## Known Agent Biases

AI agents trend toward recommending older, heavily-documented tools over newer, better alternatives. When making architectural recommendations, always perform web research for current state of the art (see delivery-protocol.md). Known stale defaults to watch for:

- OpenSSL over rustls (rustls is mandated — see `deny.toml`)
- Selenium/Cypress over Playwright (Playwright is mandated for E2E)
- `reqwest` with `openssl-sys` over `reqwest` with `rustls-tls` feature
- `chrono` over `jiff` or `time` (evaluate current state before choosing)
- Heavyweight ORMs over lightweight query builders
- Class-based or inheritance-heavy patterns over composition and traits

This list is a living document. When you catch an outdated recommendation, add it here.

ADR Conventions (after Known Agent Biases):

## ADR Conventions

Architecture Decision Records document non-obvious architectural choices:

- Location: `docs/modules/ROOT/pages/adrs/` (AsciiDoc format)
- Write an ADR when: choosing a framework, database, protocol, or design pattern that has viable alternatives
- Format: Status, Context, Decision, Consequences
- ADRs are immutable once accepted — supersede with a new ADR, do not edit

Step 4: Add "Never weaken a test" rules to testing.md

File: .claude/docs/testing.md

Add a new section Critical Rules (or merge into existing test philosophy section):

## Critical Rules

1. **Never dismiss test failures as transient** — investigate root cause. Only classify as edge case after thorough analysis.
2. **All checks must pass before push** — fmt, clippy, tests (enforced by hook)
3. **Test results in `test-results/`** — check this directory for failure context before investigating
4. **Never weaken a test to make code pass** — fix the code, not the test. Specifically:
   - Never delete, skip, or `#[ignore]` a test to make CI pass
   - Never loosen assertions (e.g., `assert_eq!` → `assert!`, widening tolerance, removing checks) to accommodate broken code
   - Never change expected values to match wrong output
   - The ONLY reason to modify a test is if the test itself is genuinely incorrect — and that must be explained in the commit message
5. **All test types produce JUnit XML** — unit, integration, and E2E tests all output to `test-results/`

Step 5: Add .config/nextest.toml

File: .config/nextest.toml — NEW

[profile.default]
fail-fast = false
slow-timeout = { period = "60s", terminate-after = 2 }

[profile.integration]
fail-fast = false
slow-timeout = { period = "120s", terminate-after = 2 }
junit = { path = "../../test-results/integration/results.xml" }

[profile.ci]
fail-fast = false
junit = { path = "../../test-results/unit/results.xml" }

Move the existing [profile.integration] configuration from wherever it currently lives (if any) into this file. Update .githooks/pre-push and CI pipeline to reference this config location.

Step 6: Add architecture.md

File: .claude/docs/architecture.md — NEW

Consolidate from existing implementation-guide.adoc, architecture.adoc, and CLAUDE.md into the quickstart template structure:

  • Overview — CCWIS in Rust, OpenStack-style services, 8 API services + BFF + CLI

  • Request Lifecycle — HTTP request → CORS → auth middleware → idempotency → handler → DB → response → event publish

  • Component Hierarchy — workspace tree: 8 crates, 10 services, 1 tool

  • Data Layer — PostgreSQL per-service, sqlx migrations, UUID v7, soft-delete pattern

  • State Management — Stateless services, JWT auth, session cookies in BFF

  • Key Design Decisions — reference existing 10 ADRs

  • Project Structure — directory tree

  • 12-Factor Compliance — document adherence

  • Observability — tracing crate, JSON structured logging, /healthz endpoints, audit log

Register in .claude/CLAUDE.md required reading.

Step 7: Rename devstack.md to local-dev.md

File: .claude/docs/local-dev.md — RENAME from devstack.md

Align with quickstart template structure:

  • Prerequisites — Rust, cargo-nextest, Docker, glab CLI

  • First-Run Setup — clone, hooks, .env, build

  • Running Locallycargo xtask dev start

  • Container Management — devstack commands, port table, health checks

  • Seed Datacraig-seed generator

  • Common Tasks — test, e2e, validate

  • CI vs Local Differences

Update all references to devstack.md across:

  • .claude/CLAUDE.md required reading list

  • .claude/docs/delivery-protocol.md if referenced

  • .claude/docs/testing.md if referenced

  • Any plan files that reference devstack.md

Step 8: Add .gitattributes

File: .gitattributes — MODIFY (already exists for LFS)

Add LF enforcement rules:

# Enforce LF line endings for all text files
* text=auto eol=lf

# Existing LFS rules
docs/modules/ROOT/images/screenshots/*.png filter=lfs diff=lfs merge=lfs -text

This eliminates the CRLF warnings on every commit (Windows Git Bash issue).

Step 9: Add .env.example

File: .env.example — NEW

Document all required environment variables with placeholder values:

# CRAIG Development Environment
# Copy to .env and fill in values

# Service ports (defaults shown — only override if port conflict)
# CRAIG_RULES__PORT=8001
# CRAIG_CASES__PORT=8002
# CRAIG_PLACEMENT__PORT=8003
# CRAIG_EXCHANGE__PORT=8004
# CRAIG_FINANCIAL__PORT=8005
# CRAIG_REPORTING__PORT=8006
# CRAIG_SECURITY__PORT=8007
# CRAIG_INTAKE__PORT=8008
# CRAIG_WEB__PORT=8080

# Keycloak (devstack defaults)
# CRAIG_WEB__OIDC_ISSUER=http://host.docker.internal:8180/realms/craig
# CRAIG_WEB__KEYCLOAK_CLIENT_ID=craig-ui

# Session (MUST change in production)
CRAIG_WEB__SESSION_SECRET=change-me-in-production-use-64-random-chars

# CORS (restrict in production)
# CRAIG_RULES__CORS_ORIGINS=*

# Seed data
CRAIG_SEED=42
CRAIG_FAMILIES=12

Add .env to .gitignore if not already present.

Step 10: Enhance delivery-protocol.md

File: .claude/docs/delivery-protocol.md

Add Architectural Recommendations section (from quickstart):

## Architectural Recommendations

Before recommending a new dependency, framework, library, or architectural pattern:

1. **Research current state of the art** — search crates.io, official docs, and recent release notes. Do not rely on training data alone.
2. **Identify at least 3 alternatives** — including the option you are inclined toward.
3. **Compare on**: maintenance activity (last release date, commit frequency), community adoption, security posture, alignment with existing project conventions (pure Rust, musl-compatible, AGPL-compatible license).
4. **Present the comparison** to the user before proceeding — do not unilaterally choose.
5. **Document the decision** in an ADR if it introduces a new architectural choice.

AI agents trend toward recommending older, heavily-documented tools over newer, better alternatives because training data favors established projects. This process exists to counteract that bias.

Expand preflight checklist to match quickstart (add mandatory docs check, CLAUDE.md filled in, commit signing).

Move Bug Discovery section here from git-workflow.md (quickstart puts it in delivery-protocol).

Step 11: Update coding-conventions.md with container, dependency, and task runner sections

File: .claude/docs/coding-conventions.md

Add sections from quickstart:

Container Runtime (after Docker & DevStack):

## Container Runtime

- **Alpine is mandatory** for all container images (build and runtime stages)
- Build stage: `rust:1.94-alpine` (current), runtime stage: `alpine:latest`
- All images must run as non-root user, include HEALTHCHECK, use multi-stage builds
- `.dockerignore` excludes `target/`, `.git/`, `node_modules/`
- Alpine uses musl — use `rustls` (not `openssl`) for TLS. The `openssl` crate is banned in `deny.toml`.

Dependency Management (after Rust & Cargo):

## Dependency Management

- Use latest stable versions. Pin to non-latest only with documented reason.
- Workspace-level dependency management (`[workspace.dependencies]`)
- `cargo deny` for license allowlist (AGPL-compatible), duplicate detection, advisory DB
- `cargo audit` in CI (blocking)
- Monthly dependency review: `cargo update` + full test verification

Task Runner (new, or replace Docker & DevStack):

## Task Runner

- **`cargo xtask` is the mandatory task runner** for all project automation
- No shell scripts for project automation — use xtask instead
- Standard subcommands: `dev`, `test`, `e2e`, `validate`, `check-docs`
- Project-specific: `seed`, `screenshots`
This section documents the target state. Step 12 implements it.

Step 12: Migrate devstack scripts to cargo xtask

This is the largest step. Create a xtask/ workspace member that replaces the legacy devstack scripts.

Files:

  • xtask/Cargo.toml — NEW workspace member

  • xtask/src/main.rs — clap CLI with subcommands

  • xtask/src/cmd/dev.rs — Docker lifecycle (start, stop, clean, status, logs)

  • xtask/src/cmd/test.rs — Test runner (fmt + clippy + nextest)

  • xtask/src/cmd/e2e.rs — E2E runner (ensures containers running, runs Playwright)

  • xtask/src/cmd/validate.rs — Pre-push validation (signing, docs, SPDX, fmt, clippy, nextest, docker build)

  • xtask/src/cmd/check_docs.rs — Tier 1 doc drift detection (replaces scripts/check-claude-docs.sh)

  • xtask/src/cmd/seed.rs — Seed generator wrapper

  • xtask/src/cmd/screenshots.rs — Screenshot capture wrapper

  • xtask/src/docker.rs — Docker compose wrapper (subprocess calls)

  • Cargo.toml — add xtask to workspace members

  • .githooks/pre-push — replace shell commands with cargo xtask validate

The xtask binary wraps the same Docker Compose operations in cross-platform Rust. Key behaviors:

  • cargo xtask dev start — build and start all containers

  • cargo xtask dev stop — stop containers, preserve data

  • cargo xtask dev clean --confirm — stop + wipe volumes

  • cargo xtask dev status — show service health

  • cargo xtask e2e — start containers if needed, run Playwright via Docker

  • cargo xtask test — fmt + clippy + nextest

  • cargo xtask validate — full pre-push battery

  • cargo xtask seed — run craig-seed with default args

  • cargo xtask screenshots — run Playwright screenshot project

Dependencies: clap, anyhow, which (for finding Docker binary).

After xtask is working:

  • Delete legacy devstack scripts (already done)

  • Delete scripts/check-claude-docs.sh (replaced by cargo xtask check-docs)

  • Update all documentation references

Step 13: Documentation, commit, push, MR

  • CHANGELOG.adoc — entry under Unreleased

  • .claude/CLAUDE.md — update required reading list

  • All plan references to legacy devstack scripts → cargo xtask

  • Verify all new files build and pass

  • This plan — status to Complete

Files Touched

File Change

.claude/docs/security-baseline.md

NEW: Tier 1 universal (Kerckhoffs + visibility)

.claude/docs/security.md

MODIFY: remove Sections 1-2, keep project-specific

.claude/docs/coding-conventions.md

ADD: agent biases, ADRs, containers, deps, task runner

.claude/docs/testing.md

ADD: critical rules, never-weaken-test

.claude/docs/architecture.md

NEW: system architecture consolidated doc

.claude/docs/local-dev.md

RENAME from devstack.md + align with template

.claude/docs/delivery-protocol.md

ADD: architectural recommendations, expanded preflight

.claude/CLAUDE.md

UPDATE: required reading list

.config/nextest.toml

NEW: test profiles with slow-timeout

.gitattributes

MODIFY: add LF enforcement

.env.example

NEW: documented env vars

xtask/

NEW: cargo xtask workspace member (8 source files)

Cargo.toml

ADD: xtask to workspace members

.githooks/pre-push

MODIFY: delegate to cargo xtask validate

devstack.ps1

DELETED (replaced by xtask)

devstack.sh

DELETED (replaced by xtask)

scripts/check-claude-docs.sh

DELETE (replaced by xtask)

Verification

  1. cargo xtask --help — prints available subcommands

  2. cargo xtask validate — runs full pre-push battery

  3. cargo xtask dev start — starts devstack, all services healthy

  4. cargo xtask e2e — runs E2E tests, all pass

  5. cargo xtask test — runs unit + integration tests

  6. cargo xtask check-docs — validates Tier 1 docs

  7. All existing E2E tests pass (127+)

  8. Pre-push hook works via xtask

Documentation Updates

  • CHANGELOG.adoc

  • .claude/CLAUDE.md — required reading, phase status

  • All plan files referencing legacy devstack scripts → cargo xtask

  • docs/modules/ROOT/pages/devstack.adoc — update commands to xtask

  • CONTRIBUTING.adoc — update commands to xtask

  • README.adoc — update quick start commands

Edit this page · latest