Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 5 additions & 4 deletions README.es.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
6 changes: 6 additions & 0 deletions documentation/usage.es.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions documentation/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
17 changes: 16 additions & 1 deletion tests/test_rules.py
Original file line number Diff line number Diff line change
@@ -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):
Expand All @@ -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") == []

Expand Down
Loading