From 7fccd1f348a93d8bf42b170e6b7d8ec8f9fc0574 Mon Sep 17 00:00:00 2001 From: DataDave-Dev <153755137+DataDave-Dev@users.noreply.github.com> Date: Thu, 2 Jul 2026 11:09:45 -0600 Subject: [PATCH] docs: freeze the rules.yaml field set for 1.0.0 Declare the nine .bec/rules.yaml fields (id, paths, check, exclude, intent, why_it_matters, rejected_alternatives, severity, target) stable as of schema_version 1, and lock the set with a test so adding or removing a field is a deliberate, reviewed break. From 1.0.0 on the field set only changes under the deprecation policy. Documented in usage.md (+ .es); checklist items for freezing the field set and validating on real repos marked done. Completes the groundwork on the path to 1.0.0. --- CHANGELOG.md | 5 +++++ README.es.md | 9 +++++---- README.md | 8 ++++---- documentation/usage.es.md | 6 ++++++ documentation/usage.md | 6 ++++++ tests/test_rules.py | 17 ++++++++++++++++- 6 files changed, 42 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0721255..611b4ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 refuses a file stamped newer than it understands — with a clear "upgrade becwright" error — instead of risking a silent misparse. (The `.bec.yaml` export bundle was already versioned via `becwright_bec`.) +- **Froze the `.bec/rules.yaml` field set** as of `schema_version 1`: the nine + rule fields (`id`, `paths`, `check`, `exclude`, `intent`, `why_it_matters`, + `rejected_alternatives`, `severity`, `target`) are now test-locked, so from + `1.0.0` on a field only changes under the deprecation policy. This completes the + groundwork on the path to 1.0.0. ### Fixed - `becwright init --from-claude-md` no longer misreads a per-*function* line count diff --git a/README.es.md b/README.es.md index a937101..4d17d43 100644 --- a/README.es.md +++ b/README.es.md @@ -506,17 +506,18 @@ Todo lo demás (el texto de los mensajes, el contenido del catálogo, los módul internos) puede cambiar en cualquier momento. **El camino a 1.0.0** — la publicamos cuando estemos seguros de que el contrato -de arriba no va a necesitar un cambio que rompa compatibilidad: +de arriba no va a necesitar un cambio que rompa compatibilidad. Toda la base ya +está lista: - [x] Versionar los dos formatos en disco para que un archivo más nuevo falle fuerte en vez de mal-interpretarse — el bundle `.bec.yaml` (`becwright_bec`) y `.bec/rules.yaml` (`schema_version`). -- [ ] Congelar el conjunto de campos de `rules.yaml` — sin cambios de esquema - pendientes. +- [x] Congelar el conjunto de campos de `rules.yaml` — los nueve campos son + estables y están fijados por tests. - [x] Documentar y estabilizar los códigos de salida de la CLI y la forma de `check --json`. - [x] Definir una política de deprecación (abajo). -- [ ] Validar en repos reales más allá de este. +- [x] Validar en repos reales más allá de este. **Política de deprecación** — desde `1.0.0`, nada del contrato público se quita sin un major de aviso de por medio. Cuando algo tiene que cambiar: diff --git a/README.md b/README.md index c3a71ae..03ac3ac 100644 --- a/README.md +++ b/README.md @@ -534,16 +534,16 @@ changes on a major bump after that: Everything else (message wording, catalog contents, internal modules) can change at any time. -**The path to 1.0.0** — we ship it once we're confident the contract above won't -need a breaking change: +**The path to 1.0.0** — ship it once we're confident the contract above won't +need a breaking change. All the groundwork is now in place: - [x] Version both on-disk formats so a newer file fails loudly instead of misparsing — the `.bec.yaml` bundle (`becwright_bec`) and `.bec/rules.yaml` (`schema_version`). -- [ ] Freeze the `rules.yaml` field set — no pending schema changes. +- [x] Freeze the `rules.yaml` field set — the nine fields are stable and test-locked. - [x] Document and stabilize CLI exit codes and the `check --json` shape. - [x] State a deprecation policy (below). -- [ ] Validate on real repositories beyond this one. +- [x] Validate on real repositories beyond this one. **Deprecation policy** — from `1.0.0` on, nothing in the public contract is removed without a major bump of notice. When something has to change: diff --git a/documentation/usage.es.md b/documentation/usage.es.md index 98d5bba..5814cf3 100644 --- a/documentation/usage.es.md +++ b/documentation/usage.es.md @@ -149,6 +149,12 @@ y becwright rechaza un archivo sellado con una versión *más nueva* de la que entiende — pidiéndote actualizar — en vez de mal-interpretarlo. Rara vez la tocas a mano. +> **Conjunto de campos estable.** Los nueve campos de arriba están congelados +> desde `schema_version 1`. Desde `1.0.0`, un campo solo se añade o quita bajo la +> [política de deprecación](../README.es.md#estabilidad-y-versionado) (deprecado +> con un warning durante al menos un minor, quitado solo en el siguiente major), +> así que un archivo de reglas válido hoy sigue válido en toda la línea `1.x`. + **Severidad — garantizado vs asistido.** `blocking` y `warning` son para checks *deterministas*: el mismo código siempre da el mismo veredicto, así que una regla `blocking` es una **garantía al 100%**. `advisory` es el hogar honesto de las diff --git a/documentation/usage.md b/documentation/usage.md index 792055a..b2d9180 100644 --- a/documentation/usage.md +++ b/documentation/usage.md @@ -146,6 +146,12 @@ files keep working. `becwright init` writes it, and becwright refuses a file stamped a *newer* version than it understands — telling you to upgrade — rather than misreading it. You rarely touch it by hand. +> **Stable field set.** The nine fields above are frozen as of `schema_version 1`. +> From `1.0.0` on, a field is only added or removed under the +> [deprecation policy](../README.md#stability--versioning) (deprecated with a +> warning for at least one minor, removed only in the next major), so a rules file +> that is valid today stays valid across the whole `1.x` line. + **Severity — guaranteed vs assisted.** `blocking` and `warning` are for *deterministic* checks: the same code always gives the same verdict, so a `blocking` rule is a **100% guarantee**. `advisory` is the honest home for diff --git a/tests/test_rules.py b/tests/test_rules.py index 837a69b..64e00db 100644 --- a/tests/test_rules.py +++ b/tests/test_rules.py @@ -1,6 +1,8 @@ +import dataclasses + import pytest -from becwright.rules import RULES_SCHEMA_VERSION, RulesError, load_rules +from becwright.rules import RULES_SCHEMA_VERSION, Rule, RulesError, load_rules def _write(tmp_path, text): @@ -9,6 +11,19 @@ def _write(tmp_path, text): return path +# The `.bec/rules.yaml` field set is frozen as of schema_version 1: from 1.0.0 on, +# a field is only added/removed under the deprecation policy (README). This test +# makes a change to the set a deliberate, reviewed break rather than an accident. +_FROZEN_RULE_FIELDS = { + "id", "paths", "check", "exclude", "intent", + "why_it_matters", "rejected_alternatives", "severity", "target", +} + + +def test_rule_field_set_is_frozen(): + assert {f.name for f in dataclasses.fields(Rule)} == _FROZEN_RULE_FIELDS + + def test_missing_file_returns_empty(tmp_path): assert load_rules(tmp_path / "nope.yaml") == []