swarm repositories / source
aboutsummaryrefslogtreecommitdiff
path: root/docs/bootstrap-fresh.md
blob: 2db3ccc53dfb203cc30e58a4536d03e9e0cf547a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# Fresh Bootstrap

Use this surface when the target repo is blank or when you are setting up Rust linting from scratch.

## Goal

Install the `rust-starter` lint posture cleanly:

- target `AGENTS.md` links to the canonical Rust style doctrine
- root `Cargo.toml` owns lint levels
- every crate inherits workspace lint policy
- the latest system Rust toolchain is used instead of a hardcoded starter version
- project-local `.cargo/config.toml` routes Cargo output to `/data/main/cargo-target/<project-slug>`
- `clippy.toml` stays tiny and only carries structured config
- the runner stays thin and reads canonicalization and verification command vectors plus the source-file cap from workspace metadata instead of restating policy

## Inputs To Set Deliberately

Before copying the template, decide:

- actual workspace members
- package naming
- license policy
- active system Rust toolchain from `rustc --version` and `cargo --version`
- whether the target should record a `rust-version`; if so, derive it from the active system `rustc`
- Cargo target-dir slug under `/data/main/cargo-target`, normally the target repo directory name
- whether tests should allow `expect`, `unwrap`, or `panic`
- whether the repo is library-heavy enough to keep rustdoc linting in the fast gate or only the deep gate
- whether unsafe Rust is forbidden or tightly-governed
- whether the default `3000`-line source-file cap should stay as-is or be tightened for this repo
- how to merge the Rust style doctrine link into any existing target `AGENTS.md` guidance

## Files To Start From

Use these as the concrete baseline:

- [docs/rust-style-doctrine.md](/home/main/programming/projects/rust_starter/docs/rust-style-doctrine.md)
- [template/fresh/AGENTS.md](/home/main/programming/projects/rust_starter/template/fresh/AGENTS.md)
- [template/fresh/.cargo/config.toml](/home/main/programming/projects/rust_starter/template/fresh/.cargo/config.toml)
- [template/fresh/Cargo.toml](/home/main/programming/projects/rust_starter/template/fresh/Cargo.toml)
- [template/fresh/rust-toolchain.toml](/home/main/programming/projects/rust_starter/template/fresh/rust-toolchain.toml)
- [template/fresh/clippy.toml](/home/main/programming/projects/rust_starter/template/fresh/clippy.toml)
- [template/fresh/check.py](/home/main/programming/projects/rust_starter/template/fresh/check.py)
- [template/fresh/crates/app/Cargo.toml](/home/main/programming/projects/rust_starter/template/fresh/crates/app/Cargo.toml)
- [template/fresh/crates/app/src/main.rs](/home/main/programming/projects/rust_starter/template/fresh/crates/app/src/main.rs)

Do not copy them mechanically. Replace the placeholder members, names, license, and Cargo target-dir slug. Do not copy a Rust version from the starter; inspect the active system toolchain.

## Sequence

### 1. Initialize Git for an empty target

If the target directory is empty and is not already inside a Git worktree, run
`git init` before copying template files. The starter assumes normal versioned
Rust work; beginning from an unversioned empty directory is gratuitous entropy.

### 2. Seed `AGENTS.md`

Create or adapt the target repo's `AGENTS.md` so it links to
[docs/rust-style-doctrine.md](/home/main/programming/projects/rust_starter/docs/rust-style-doctrine.md).
Use [template/fresh/AGENTS.md](/home/main/programming/projects/rust_starter/template/fresh/AGENTS.md)
as the starting point for a blank repo. If the target already has instructions,
merge the link without erasing local rules.

The point is inheritance: future agents entering the repo must encounter the
Rust style doctrine without knowing this bootstrap skill exists.

### 3. Write the root manifest

Start from the template root manifest and adapt:

- workspace member list
- package metadata
- repo-wide Clippy carve-outs

If the target records `workspace.package.rust-version`, derive it from the
active system `rustc --version`; do not invent a minimum supported Rust version
from memory and do not paste one from this starter.

Keep the command vectors in `[workspace.metadata.rust-starter]` even if you later wrap them with a different local runner.

The fresh template exports an ordered `canonicalize_commands` pipeline. Keep it repo-owned in the root manifest and make the default `check` path run it automatically before the verification gate so humans and agents do not need to remember a separate pre-pass.

Also keep the source-file cap in `[workspace.metadata.rust-starter.source_files]`. The starter default is a hard `3000`-line limit across `*.rs` files. Tighten it if the repo already has sharper discipline.

### 4. Install project-local Cargo target config

Create or adapt the target repo's `.cargo/config.toml` before running Cargo commands:

```toml
[build]
target-dir = "/data/main/cargo-target/<project-slug>"
```

Use the target repo directory name as the default slug. If two repos share a
directory basename, append a short path hash or another stable disambiguator.
The point is a clean, checked-in per-repo target directory under the global
Cargo target volume, not a source-tree `target/` directory and not command-line
`--target-dir` folklore.

This is a repo-local ratchet. Do not mutate user-global Cargo config during
bootstrap; if a repo has not opted in yet, the developer's global Cargo config
remains the fallback.

If `.cargo/config.toml` already exists, merge the `[build] target-dir` value
without overwriting unrelated Cargo configuration.

### 5. Use the latest system Rust toolchain

Inspect `rustc --version` and `cargo --version` early, before deciding whether a
lint is noisy or broken. Lint output is part of the toolchain contract, and the
contract here is the latest Rust toolchain already selected by the system.

The template `rust-toolchain.toml` deliberately avoids a numbered channel. Do
not replace it with a remembered version. If the target repo needs a rustup
override, use the active system toolchain; if the target environment does not
use rustup, omit the file rather than fabricating a pin.

### 6. Make every crate inherit lint policy

Each member crate must contain:

```toml
[lints]
workspace = true
```

Do not rely on memory or convention here; add it explicitly.

### 7. Add `clippy.toml` only if it carries real configuration

The default template only relaxes `expect`, `unwrap`, and `panic` inside tests. If the target repo does not want that, delete the file instead of leaving inert config behind.

Do not move global allow/deny policy into `clippy.toml`.

### 8. Add a thin runner

The template `check.py` is intentionally small. It reads canonicalization and verification commands plus the source-file policy from workspace metadata, enforces the file cap, and then runs the Rust commands.

Default runner shape:

- `check`: enforce the file cap, run canonicalization, then verify formatting, lint, and tests
- `verify`: enforce the file cap without mutating files; this is the non-writing CI-friendly path
- `deep`: `check` plus docs
- `fix` / `canon`: canonicalization only

If the target repo already prefers another orchestration surface, keep that surface only if it remains policy-thin:

- okay: `xtask`, `just`, shell wrapper, CI job that calls the canonical commands
- not okay: restating dozens of `-A` and `-D` flags in scripts

If the repo has checked-in generated Rust that should not count against the cap, express that with explicit `exclude` patterns under `[workspace.metadata.rust-starter.source_files]` instead of weakening the global limit.

### 9. Keep the deep gate opt-in

The template only installs the fast gate. Add the deeper posture when the repo is mature enough:

- `cargo hack clippy --workspace --all-targets --feature-powerset`
- `cargo hack test --workspace --feature-powerset`
- `cargo doc --workspace --all-features --no-deps`
- `cargo deny check`
- optionally `cargo nextest` and `cargo semver-checks`

## Do Not Do These

- do not use `--no-deps` as the workspace-wide Clippy default
- do not enable `clippy::restriction` wholesale
- do not enable `clippy::nursery` wholesale
- do not duplicate lint policy in scripts, CI, and editor config
- do not pass `--target-dir` from runners, CI, or command vectors; use `.cargo/config.toml`
- do not change user-global Cargo config as part of bootstrapping a target repo
- do not hardcode a Rust version from the starter or from memory

## Acceptance Checklist

- root `Cargo.toml` contains `[workspace.lints.rust]`, `[workspace.lints.rustdoc]`, and `[workspace.lints.clippy]`
- target `AGENTS.md` links to [docs/rust-style-doctrine.md](/home/main/programming/projects/rust_starter/docs/rust-style-doctrine.md)
- target `.cargo/config.toml` contains `[build] target-dir = "/data/main/cargo-target/<project-slug>"`
- fresh bootstraps in an empty target directory start with `git init`
- root `Cargo.toml` owns warning-fatality policy, e.g. `warnings = "deny"` under `[workspace.lints.rust]`, rather than hiding it in runner flags
- root `Cargo.toml` preserves the global wildcard/glob carve-outs; compact `*` imports are intentionally allowed for token economy
- root `Cargo.toml` contains canonical command vectors in `[workspace.metadata.rust-starter]`
- root `Cargo.toml` contains an ordered `canonicalize_commands` pipeline in `[workspace.metadata.rust-starter]`
- root `Cargo.toml` contains `[workspace.metadata.rust-starter.source_files]` with an intentional `max_lines` value
- each member crate opts into `[lints] workspace = true`
- the target uses the latest system Rust toolchain; any `rust-version` value is derived from the active system `rustc`
- `clippy.toml` is either tiny and justified or absent
- the default `check` path canonicalizes before verification, and a non-mutating `verify` path exists for CI or drift detection
- no runner or CI file duplicates the Clippy allowlist
- no runner, CI file, or manifest-owned command vector passes `--target-dir`

Read [docs/rust-linting-proposal.md](/home/main/programming/projects/rust_starter/docs/rust-linting-proposal.md) only when you need rationale or policy nuance.