dev-ci 0.9.0

CI workflow generator and GitHub Action for the dev-* verification suite. Generates calibrated CI pipelines and runs the suite end-to-end on pull requests.
Documentation
# dev-ci — Project Specification (REPS)

> Rust Engineering Project Specification.
> Normative language follows RFC 2119.

## 1. Purpose

`dev-ci` MUST provide two capabilities:

1. **Generation** — produce CI workflow files for popular platforms
   from a structured Rust API and a CLI front-end.
2. **Execution** — run the full `dev-*` verification suite end-to-end
   inside a CI job, emitting `dev-report::MultiReport` for programmatic
   consumption (planned for a later 0.9.x release).

Output MUST be machine-readable. AI agents and CI gates MUST be able
to consume the result and decide accept / reject / retry / escalate
without parsing free-form logs.

## 2. Scope

This crate MUST provide:

- A `Target` enum naming supported CI platforms.
- A `Generator` builder with the full standard surface: workflow name,
  branches filter, OS matrix, cache toggle, workspace flag, features
  list, no-default and all-features build steps, sibling path-dep
  cloning, `clippy`, `fmt`, `docs`, and `msrv` jobs.
- A `PathDep` value capturing the `(name, repo_url)` pair for a sibling
  path-dependency.
- A CLI binary (`dev-ci`) wrapping the library for terminal use. The
  CLI surface MUST cover every builder method.

This crate MAY provide later:

- GitLab CI YAML output.
- Buildkite YAML output.
- CircleCI YAML output.
- A GitHub Action distribution that wraps the runtime side (runs the
  full dev-* suite end-to-end and uploads SARIF).
- PR comment posting via GitHub API.

This crate MUST NOT:

- Replace the underlying CI runners. It generates configuration; it
  does not host runners.
- Encode opinions specific to one organization. Templates MUST be
  parametric.
- Embed credentials. All authentication is handled by the CI
  platform's standard mechanisms.

## 3. Determinism

A given `Generator` configuration MUST produce byte-identical YAML
across runs and across machines. No clock reads, no random IDs.
Iteration over user-supplied lists (branches, matrix OS, path-deps)
MUST follow insertion order. This is required for diff-based review
of CI changes.

Two calls to `generate()` on the same `Generator` instance MUST
return equal strings.

## 4. Target platforms

`Target::GitHubActions` MUST emit:

- `name`, `on`, `env` headers.
- One `test` job by default. The `test` job MUST be a matrix job
  with `fail-fast: false` and the configured OS list.
- Optional jobs for `clippy`, `fmt`, `docs`, `msrv` as configured.
- All `actions/checkout` references at `v5` or later (Node 24-compatible).
- `Swatinem/rust-cache@v2` after the toolchain setup, when caching is
  enabled (the default).
- When path-deps are declared, a `Check out sibling crates (path deps)`
  step immediately after the checkout step that emits
  `git clone --depth 1 <url> ../<name>` lines for each declared
  `PathDep`.

Other targets (GitLab, Buildkite, CircleCI) MUST be feature-gated or
fully optional dependencies in any future release.

## 5. Integration with dev-report

When the runtime execution side ships (planned for a later 0.9.x
release), the runner MUST emit a `dev-report::MultiReport` aggregating
every producer it invoked. The report SHOULD be:

- Written to disk at a configurable path.
- Uploaded as a CI artifact.
- Optionally converted to SARIF for the GitHub Security tab.

## 6. CLI contract

The `dev-ci` binary MUST expose every builder method through CLI flags.
The exit code MUST be:

- `0` on successful generation.
- non-zero with a single-line `dev-ci: <message>` error on stderr for
  malformed arguments, invalid `--path-dep` syntax, missing required
  fields (e.g. `--with msrv` without `--msrv`), or filesystem failures.

The CLI MUST support writing to stdout (`--print` or `--output -`) as
well as to a file. When writing to a file, parent directories MUST be
created as needed.

## 7. Stability

Through `0.9.x`, the public Rust API MAY shift between minor versions
but generated YAML for a given configuration MUST remain stable across
patch releases. The `1.0` release pins the Rust API; YAML output is
treated as versioned data and continues to evolve through minor
releases beyond 1.0.