Skip to content

Commit 9f7ac17

Browse files
authored
ci: block Vale tooling paths from main + mirror spec dev-only narrative (#69)
## Summary Repositions the Vale prose-check stack (`styles/`, `.vale.ini`, `scripts/prose-check.sh`) as dev-only contributor tooling, mirroring `agentnative-spec` PR #45 (ed066b6). This is the evergreen half: workflow guard, doc reference updates, and dev-direct exception note. The actual file deletions on `main` happen in a follow-up performed directly on the `release/v0.5.0` branch so that one release cycle removes the files from `main`; from then on the workflow guard keeps them out. Bundles two small release-doc polish items that surfaced during the same review pass: a guarded-path leak-check entry in `RELEASES-PREFLIGHT.md`, and a version-neutral rename of `CLAUDE.md` § "Scorecard v0.5 Fields" to § "Scorecard JSON fields" so the heading stops aging out as schema versions move. ## Changelog ### Changed - `.github/workflows/guard-main-docs.yml`: pass `extra_paths: 'styles/,.vale.ini,scripts/prose-check.sh'` to the reusable guard workflow. Future PRs to `main` that add or modify those paths fail the check. Mirrors the path values used by `agentnative-spec`. - `BRAND.md`: refreshed verbatim from `agentnative-spec` to pick up the "narrative is authoritative for both the why and the what" reframing and the `(dev-only)` annotation on the Vale-rule-pack column of the Channel-artifacts table. As a vendored mirror, BRAND.md should match the spec word for word. - `PRODUCT.md`: Inheritance and Register sections retune to "authoritative voice contract" framing; explicitly names the rule pack as dev-only tooling that does not ship to `main`. Removes the dead `styles/brand/README.md` / `styles/brand/*.yml` / `styles/config/vocabularies/cli/` links. - `AGENTS.md`: rewrites the "Voice and prose rules" section to drop the `scripts/prose-check.sh` invocation example and the rule-pack vendoring prose; mirrors the spec's AGENTS.md voice-contract paragraph. - `scripts/SYNCS.md`: drops the `sync-prose-tooling.sh` row from the upstream sync table, the matching mermaid arrow, and the Reference section entry. - `RELEASES.md`: prose-scrubbing intro no longer promises a future vendoring; explicitly names the spec checkout as the Vale config source. - `CLAUDE.md`: § "Scorecard v0.5 Fields" renamed to § "Scorecard JSON fields"; the cross-link in `RELEASES-PREFLIGHT.md` updates to match. ### Added - `RELEASES.md` gains a `### Dev-direct exception` subsection under Daily development, mirroring the spec's same insertion point and content. Names the two path categories (engineering docs and prose-check stack) that may be committed directly to `dev` without a feature branch. - `RELEASES-PREFLIGHT.md` gains a "Release mechanics sanity" item that runs the same guarded-path leak check `RELEASES.md` step 4 runs, so operators catch leaks before the release PR opens. Points at the new `RELEASES.md` § Cherry-pick conflicts on guarded paths subsection for resolution. ## Type of Change - [x] `ci`: CI/CD configuration changes ## Related Issues/Stories - Story: n/a - Issue: n/a - Architecture: Mirrors `agentnative-spec` PR #45 (ed066b6) "feat(prose-check): move stack to dev-only". The spec's follow-up release PR (#46, 20b9deb) performed the corresponding file deletions on `main`; this repo's equivalent deletions happen on `release/v0.5.0` after this PR merges. - Related PRs: agentnative-spec#45, agentnative-spec#46 ## Testing - [x] All tests passing **Test Summary:** - `cargo test`: 793 passed, 2 ignored. - `cargo build`: clean. - `bash scripts/prose-check.sh --vale-only` on dev: stack still present, runs as expected. ## Files Modified **Modified:** - `.github/workflows/guard-main-docs.yml` - `AGENTS.md`, `BRAND.md`, `CLAUDE.md`, `PRODUCT.md`, `RELEASES.md`, `RELEASES-PREFLIGHT.md`, `scripts/SYNCS.md` **Created:** - None. **Renamed:** - None. **Deleted:** - None on this branch. The actual prose-check stack deletions (`.vale.ini`, `styles/`, `scripts/prose-check.sh`, plus the orphaned helpers `scripts/sync-prose-tooling.sh`, `scripts/test-prose-check.mjs`, `scripts/generate-pack-readme.mjs`) ship on the release branch. ## Breaking Changes - [x] No breaking changes ## Deployment Notes - [x] No special deployment steps required
1 parent 1e140ee commit 9f7ac17

8 files changed

Lines changed: 65 additions & 51 deletions

File tree

.github/workflows/guard-main-docs.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,5 @@ permissions:
1515
jobs:
1616
guard-docs:
1717
uses: brettdavies/.github/.github/workflows/guard-main-docs.yml@main
18+
with:
19+
extra_paths: 'styles/,.vale.ini,scripts/prose-check.sh'

AGENTS.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -173,10 +173,9 @@ behavior.
173173

174174
User-facing prose follows the **linter channel** rules in [`PRODUCT.md`](PRODUCT.md). Short version: second-person
175175
imperative, no RFC 2119 keywords in error messages, no marketing voice, errors name "what failed / why / what to do."
176-
Run `bash scripts/prose-check.sh --vale-only` before changing markdown to surface findings; warnings are informational,
177-
blocking findings need a fix. The rule packs (`styles/brand/`) and the brand vocab (`styles/config/vocabularies/brand/`)
178-
are vendored from `agentnative-spec` via `scripts/sync-prose-tooling.sh`; CLI-specific terms live in
179-
`styles/config/vocabularies/cli/`.
176+
`BRAND.md` and `PRODUCT.md` are the authoritative voice contract. The Vale rule pack maintained in `agentnative-spec`
177+
(mirrored onto this repo's `dev` branch) encodes the literal phrases for enforcement on contributor PRs against `dev`;
178+
the pack and `scripts/prose-check.sh` are dev-only tooling and do not ship to `main`.
180179

181180
## Testing
182181

BRAND.md

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,8 @@ Two first-class consumers across all channels:
4242

4343
## Universal anti-patterns
4444

45-
These bans apply across every channel. The narrative below explains *why* each category is banned; the executable
46-
contract for *what* is banned lives in [`styles/brand/README.md`](styles/brand/README.md), generated from the Vale rule
47-
pack at `styles/brand/*.yml`.
45+
These bans apply across every channel. The narrative below is authoritative for both the *why* and the *what*; a Vale
46+
rule pack on the `dev` branch encodes the literal phrases for enforcement on contributor PRs (dev-only tooling).
4847

4948
- **No marketing register.** First-person belief and recommendation framings are out. The standard speaks in the third
5049
person about contracts, not in the first person about beliefs.
@@ -57,8 +56,7 @@ pack at `styles/brand/*.yml`.
5756
## Voice anchors: concrete examples
5857

5958
The ✓ column shows the contract voice. The ✗ column names the category of failure rather than reproducing literal banned
60-
phrases. Those live in [`styles/brand/README.md`](styles/brand/README.md). The category labels describe the shape of the
61-
failure each ✓ phrasing replaces.
59+
phrases. The category labels describe the shape of the failure each ✓ phrasing replaces.
6260

6361
|||
6462
| ------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
@@ -82,16 +80,15 @@ The shared identity above applies to every channel. Each channel adds register a
8280

8381
Each channel's repo carries its own narrow stack on top of this universal `BRAND.md`. The canonical layout:
8482

85-
| Channel | `PRODUCT.md` location | Deep tier-3 | Vale rule pack | How `BRAND.md` arrives |
86-
| ------------ | ----------------------------------------------- | ------------------------------------------------------ | -------------- | ------------------------------- |
87-
| Spec | `agentnative-spec/PRODUCT.md` | `principles/`, `docs/architecture/`, `docs/decisions/` | `styles/spec/` | (origin: this repo) |
88-
| Site | `agentnative-site/PRODUCT.md` | `DESIGN.md` (root) | (none yet) | `scripts/sync-prose-tooling.sh` |
89-
| CLI (`anc`) | `agentnative-cli/PRODUCT.md` (when warranted) | `src/` (Rust source IS the artifact) | (planned) | `scripts/sync-prose-tooling.sh` |
90-
| Skill bundle | `agentnative-skill/PRODUCT.md` (when warranted) | `bundle/` | (planned) | `scripts/sync-prose-tooling.sh` |
83+
| Channel | `PRODUCT.md` location | Deep tier-3 | Vale rule pack | How `BRAND.md` arrives |
84+
| ------------ | ------------------------------ | ------------------------------------------------------ | ------------------------- | ------------------------------- |
85+
| Spec | `agentnative-spec/PRODUCT.md` | `principles/`, `docs/architecture/`, `docs/decisions/` | `styles/spec/` (dev-only) | (originthis repo) |
86+
| Site | `agentnative-site/PRODUCT.md` | `DESIGN.md` (root) | (none yet) | `scripts/sync-prose-tooling.sh` |
87+
| CLI (`anc`) | `agentnative-cli/PRODUCT.md` | `src/` (Rust source IS the artifact) | (planned) | `scripts/sync-prose-tooling.sh` |
88+
| Skill bundle | `agentnative-skill/PRODUCT.md` | `bundle/` | (planned) | `scripts/sync-prose-tooling.sh` |
9189

92-
A channel earns its `PRODUCT.md` when channel-specific decisions (visual system, error rubric, instructional voice,
93-
etc.) accumulate enough that the universal `BRAND.md` cannot carry them. The spec and site channels have crossed that
94-
threshold today.
90+
Every channel has earned a `PRODUCT.md` today: each holds channel-specific decisions (visual system, error rubric,
91+
instructional voice, etc.) that the universal `BRAND.md` cannot carry.
9592

9693
**Convention: deep tier-3 artifacts live at the repo root, not in `docs/`.** The site channel's `DESIGN.md` sits at
9794
`agentnative-site/DESIGN.md` (not `docs/DESIGN.md`) so the `/impeccable` skill loader and human readers find it without
@@ -100,6 +97,11 @@ artifacts and historical plans live under `docs/`.
10097

10198
## Sync
10299

103-
This document is the source of truth. The site syncs it via `scripts/sync-spec.sh` alongside `principles/*.md`,
104-
`VERSION`, and `CHANGELOG.md`. The skill bundle and linter sync similarly when they grow brand-aware artifacts. A PR
105-
that changes `BRAND.md` flags whether channel sync is needed; channel repos pick up the change in a follow-on PR.
100+
This document is the source of truth. Each consumer channel (`agentnative-site`, `agentnative-cli`, `agentnative-skill`)
101+
vendors a copy via its own `scripts/sync-prose-tooling.sh`, decoupled from `scripts/sync-spec.sh` (which vendors
102+
`principles/p*-*.md`, `VERSION`, and `CHANGELOG.md` into each consumer's `spec/`). The split exists because brand prose
103+
and the principle contract release on different cadences.
104+
105+
`sync-prose-tooling.sh` tracks this repo's `main` HEAD, not tagged releases. Prose tooling is shared infrastructure
106+
across channels, not pinned per-version. Edits land here first; consumer repos pick up the change in a follow-on commit
107+
(batched into a release branch or maintenance PR).

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ either source.
139139
Regenerate whenever you add a requirement, change an audit's `covers()`, or rename an audit ID. The regeneration is a
140140
deliberate commit, not a build-time artifact; the matrix is citable from outside this repo.
141141

142-
## Scorecard v0.5 Fields
142+
## Scorecard JSON fields
143143

144144
`src/scorecard/mod.rs` emits `schema_version: "0.5"`. The schema evolves additively during the `0.x` pre-launch window;
145145
consumers feature-detect each addition rather than pinning exact shape. Cumulative history:

PRODUCT.md

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@ Read that first.
88

99
The linter channel sits in a three-tier waterfall. Each tier owns a different concern; nothing duplicates.
1010

11-
1. **Universal, [`BRAND.md`](BRAND.md).** Shared identity, voice anchor, audiences, universal anti-patterns. Vendored
12-
from `agentnative-spec` via [`scripts/sync-prose-tooling.sh`](scripts/sync-prose-tooling.sh).
11+
1. **Universal, [`BRAND.md`](BRAND.md).** Shared identity, voice anchor, audiences, universal anti-patterns. The
12+
authoritative copy lives in `agentnative-spec`; a vendored mirror sits on this repo's `dev` branch.
1313
2. **Channel delta, this file (`PRODUCT.md`).** Second-person imperative register, the three-part error shape (what
1414
failed, why, what to do next), 80-column help-text discipline, neutral diagnostics, stdout/stderr separation. The
15-
narrative companion to the executable Vale rule pack at [`styles/brand/`](styles/brand/) plus the CLI-local
16-
vocabulary at [`styles/config/vocabularies/cli/`](styles/config/vocabularies/cli/).
15+
authoritative voice contract for the linter channel; the Vale rule pack maintained in `agentnative-spec` (mirrored to
16+
`dev` here) enforces the literal phrases on contributor PRs against `dev`. The pack is dev-only tooling and does not
17+
ship to `main`.
1718
3. **Implementation, `src/`.** The Rust source for `anc`. Behavioral audits executed against compiled binaries; the
1819
principle registry codegen'd from `src/principles/spec/` (vendored from `agentnative-spec` via
1920
[`scripts/sync-spec.sh`](scripts/sync-spec.sh)).
@@ -44,9 +45,9 @@ on without re-reading.
4445

4546
## Register
4647

47-
The narrative below describes the linter channel's voice rules; the executable contract for the literal phrases lives in
48-
[`styles/brand/README.md`](styles/brand/README.md), generated from the Vale rule pack at `styles/brand/*.yml`, plus the
49-
CLI-local vocabulary at [`styles/config/vocabularies/cli/`](styles/config/vocabularies/cli/).
48+
The narrative below is the authoritative voice contract for the linter channel. The Vale rule pack maintained in
49+
`agentnative-spec` (mirrored to `dev` here) encodes the literal phrases for enforcement on contributor PRs; the pack is
50+
dev-only tooling and does not ship to `main`.
5051

5152
- **Second-person imperative IS the register.** "Run `anc audit`", "Set `--audit-profile human-tui`", "Pipe the output
5253
to `jq`". This is the linter channel's defining departure from the spec channel: the spec describes contracts in
@@ -80,9 +81,9 @@ These extend the universal bans in [`BRAND.md`](BRAND.md):
8081
- **Mixing structured output and diagnostic prose on the same stream.** `anc audit --output json` writes JSON to stdout;
8182
diagnostics go to stderr. Mixing them strands consumers who pipe stdout into `jq` and get a parse error from a banner.
8283
The prose shape (verb + artifact) is the same on either stream; the stream choice is the load-bearing part.
83-
- **Color codes in the prose itself.** Vale and prose-check operate on content, not formatting. ANSI escapes belong in
84-
the rendering layer, never in the source `&str` literal. The literal `"\x1b[31merror\x1b[0m"` is content rot; a
85-
separate `colorize(level, "error")` is the right shape.
84+
- **Color codes in the prose itself.** Prose lives in source strings, not in formatting. ANSI escapes belong in the
85+
rendering layer, never in the source `&str` literal. The literal `"\x1b[31merror\x1b[0m"` is content rot; a separate
86+
`colorize(level, "error")` is the right shape.
8687
- **Marketing voice in CLI surface.** "blazing-fast", "elegant", "powerful", "delightful". All banned. Describe what
8788
`anc` does, never how it feels to use. The brand vocab's `MarketingRegister` pack fires on this set; the per-channel
8889
rule is that the entire CLI surface inherits it, not just the README.

RELEASES-PREFLIGHT.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ These items duplicate steps in `RELEASES.md` deliberately: easy to skip, expensi
8484
- [ ] `rust-toolchain.toml` last bumped ≥7 days ago (supply-chain quarantine). If a bump landed inside the window, hold
8585
or revert it before tagging.
8686
- [ ] No unmerged dependency advisories from `cargo deny check advisories`.
87+
- [ ] Leak check: `git diff origin/main..HEAD --name-only | grep -E
88+
'^(docs/plans|docs/brainstorms|docs/ideation|docs/reviews|docs/solutions|\.context)'` returns nothing. If cherry-picks
89+
pulled in guarded paths via rename detection, resolve per `RELEASES.md` § Cherry-pick conflicts on guarded paths.
8790

8891
### Post-tag verification
8992

@@ -104,4 +107,4 @@ Run immediately after the tag push triggers `release.yml`.
104107

105108
- [`RELEASES.md`](./RELEASES.md): operational runbook this checklist gates.
106109
- [`RELEASES-RATIONALE.md`](./RELEASES-RATIONALE.md): release-flow rationale.
107-
- [`CLAUDE.md`](./CLAUDE.md) § Scorecard v0.5 Fields: consumer-facing JSON contract reference.
110+
- [`CLAUDE.md`](./CLAUDE.md) § Scorecard JSON fields: consumer-facing JSON contract reference.

RELEASES.md

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,18 @@ gh pr create --base dev --title "feat(scope): what changed"
3737
- **PR body**: follow `.github/pull_request_template.md`. See [§ PR body](#pr-body).
3838
- **PR body prose scrub**: see [§ Prose scrubbing](#prose-scrubbing).
3939

40+
### Dev-direct exception
41+
42+
Paths that live only on `dev` and never ship to `main` can be committed directly to `dev` without a feature branch or
43+
PR. The `guard-main-docs` workflow blocks them from `main` PRs regardless. The exception applies to:
44+
45+
- Engineering docs: `docs/brainstorms/`, `docs/ideation/`, `docs/plans/`, `docs/research/`, `docs/reviews/`,
46+
`docs/solutions/`, and anything under `.context/`.
47+
- Prose-check stack: `styles/`, `.vale.ini`, `scripts/prose-check.sh`.
48+
49+
The standard feature → PR → squash-merge flow remains required for everything else, including consumer-facing markdown
50+
(README, AGENTS, CONTRIBUTING, CHANGELOG, in-repo runbooks).
51+
4052
## PR body
4153

4254
Every PR (feature, fix, docs, release) uses `.github/pull_request_template.md` verbatim. Six sections, no inventions:
@@ -221,8 +233,8 @@ Three release-flow artifacts live outside any automated prose check and need a m
221233

222234
The canonical Vale + LanguageTool rule packs and orchestrator behavior live in the spec repo at
223235
[`~/dev/agentnative-spec/docs/architecture/voice-enforcement.md`](../agentnative-spec/docs/architecture/voice-enforcement.md).
224-
Until those packs are vendored into this repo (a deferred follow-up expected to extend `scripts/sync-spec.sh`), point
225-
Vale at the spec checkout via `--config`.
236+
This repo's `main` branch does not ship a local copy; point Vale at the spec checkout via `--config` (see the example
237+
below).
226238

227239
```bash
228240
# 1. Save the artifact to /tmp/.

0 commit comments

Comments
 (0)