Skip to content

v0.8.2 — Preference schema and validator

Choose a tag to compare

@EfeAydinalp EfeAydinalp released this 07 Jul 00:59
· 24 commits to master since this release
e684a97

vibe-council v0.8.2 — Preference schema v1 + read-only doctor validator

Ready for the v0.8.2 tag — not yet tagged. The version bump (backend/__init__.py,
pyproject.toml, uv.lock self-version) and the dated CHANGELOG.md section are done
(chore: prepare v0.8.2 release); the repo now reports 0.8.2. The git tag and the GitHub
Release are still a separate, manual step
— see §"Final release checklist" below and
docs/release-checklist.md.

The preference-control slice of the v0.8.x "Solidify the core, local-first" line: a normative,
tighten-only preference schema v1 plus a read-only validator folded into vibe project doctor.
This is the "auditable before executable" gate — the schema is defined and validated but never
applied
. No preference influences any behavior, no council/persona behavior changes, no new
command, no new dependency. Based on and crediting
karpathy/llm-council.

No commercial-clearance claim. License/provenance remains an unresolved "Question 0"
commercial gate; no LICENSE is added.

How v0.8.x was planned (council-backed + Fable architecture)

What this release adds

Preference schema v1 (PR 7)

  • A normative spec — docs/fable/preference-schema-v1.md — and a
    single bounded (≤ 4096-byte) fenced json block in
    docs/context/project/PREFERENCES.md (Markdown stays the source
    of truth; the block is the machine-checkable region).
  • Exactly four tighten-only keys plus the required schema: 1:
    • default_review_preset — enum cheap | balanced | full (a review floor; premium is not in
      the enum and can never be named).
    • extra_sensitive_paths — array of relative path prefixes (additive extra-guarding).
    • never_stage_extra — array of relative paths (additive no-stage extension).
    • require_usage_flag — boolean; only true is meaningful (warn when --usage is absent).
  • Tighten-only by construction: every legal value can only add friction/checks; the schema has
    no vocabulary to loosen a safety/security/no-stage/trust rule, change the Workbench executor/trust
    boundary, add shell/auto-execution/network/hosted behavior, override the review policy, or
    hide/suppress dissenting council opinions.
  • Council personas (Cost Skeptic, Security Guardian, Product Strategist, Local-first Guardian,
    UX/User Advocate, Risk Officer, Commercialization Lens) are documented as an illustrative, future
    v0.9.x direction
    — curated presets of these tighten-only values, never a policy override. They are
    not v1 fields and are not applied.

Read-only preference validator in vibe project doctor (PR 8, full review)

  • New pure module backend/preferences.py validates the schema v1 block
    and returns findings only (Finding(level, message) — never parsed settings; parse helpers are
    private). It is read-only (reads exactly one file), writes nothing, creates no .council/, and
    never reads a .council/profile.* store.
  • vibe project doctor gains an advisory Preferences (machine-readable, advisory): section:
    a valid block → [ok ], a missing block → informational [note] (prose-only is fine), an
    invalid block → [warn] with the reason and "ignored (not applied to anything)".
  • READY/NOT-READY and exit code are unchanged — a missing or invalid block is never a doctor
    failure (failure stays reserved for missing required docs + dangerous staged files).
  • Hardening (fail-closed on any anomaly): first/only fenced ```json block, 4096-byte cap,
    stdlib json.loads only (no jsonschema/pydantic/YAML/TOML), key allowlist, strict per-key
    types, relative-path checks (reject absolute / drive-letter / .. / backslash / non-string;
    traversal detected across both separators), empty-array + duplicate warnings, missing/unknown
    schema version rejected (a JSON true rejected as non-integer), realpath-inside-project-root
    symlink defense
    (generic warn, no content/target leak), UTF-8-only (UnicodeDecodeError → clean
    warn).
  • The module exposes findings, not settings: a test asserts no module outside the doctor path
    imports backend.preferences
    , so a parsed value can never be wired into behavior.

Safety posture — unchanged from v0.8.1

  • No preference application and no council/persona behavior application — the schema is
    validated into a report, never routed into any command's logic. Application is deferred to v0.9.x.
  • No local .council/profile.* store, no preference applier, no named-persona runtime.
  • No guide/context-export behavior change — those stay pointer-only (never inline the block).
  • No Workbench trust-boundary/executor/proposal/importer/panel change, no command-allowlist growth.
  • No model/provider/API call, no vector DB / database / hosted stack, no network/LAN/mobile
    surface, no new dependency (stdlib-only; the only uv.lock change is the vibe-council
    self-version line). Redaction lint stays 0 critical (30 warnings); context check and MCP health
    stay 21/21.

Explicit non-goals (deferred, not started in this release)

No named persona runtime · no UI/dashboard persona controls · no local .council/profile.* store · no
preference applier · no Workbench/executor/trust changes · no hosted / network / LAN / mobile mode · no
vector DB / database stack · no /council real command. v0.8.2 is the schema + read-only validator
infrastructure only.

Release checklist (must be clean before tagging)

  • uv run python -m unittest discover -s tests -t . is green (919 tests).
  • uv run python -m backend.cli --version prints vibe-council 0.8.2.
  • vibe lint --redaction reports 0 critical (30 warnings, expected).
  • vibe decisions lint passes.
  • vibe project doctor reports READY and shows the Preferences (machine-readable, advisory):
    section.
  • vibe context check scores 21/21.
  • vibe mcp inspect --context --health scores 21/21.
  • uv sync produces no uv.lock diff beyond the intentional self-version sync in this PR.
  • No .council/ artifact (incl. .council/runtime/payloads/ and .council/profile.*)
    staged/committed; no root CLAUDE.md/AGENTS.md/FABLE.md; no private/local plan file staged.

Final release checklist (manual steps, after this PR merges)

These are not automated by this PR — a maintainer performs them once the checklist above is clean
on master:

  • Merge this PR (chore: prepare v0.8.2 release) into master.
  • On the merged master, re-confirm: tests green, vibe --version reports vibe-council 0.8.2,
    redaction lint 0 critical (30 warnings), decisions lint passes, vibe project doctor READY,
    context check 21/21, MCP health 21/21, and uv sync shows no drift.
  • Verify git status --short and the merged diff carry no private/local artifacts
    (.council/, .council/profile.*, the two untracked private plan files, .env/.venv//data/,
    secrets, generated packs/exports, root CLAUDE.md/AGENTS.md/FABLE.md).
  • Create an annotated git tag: git tag -a v0.8.2 -m "vibe-council v0.8.2" on the merge
    commit, then git push origin v0.8.2.
  • Create the GitHub Release for v0.8.2 manually, using this document
    (docs/releases/v0.8.2.md) as the release-notes body.

Known limitations

  • Validate-only. The validator reports on the block; nothing applies it. A valid block
    changes no behavior — that is deliberate (application is v0.9.x behind its own reviewed design).
  • Personas are documentation. The named council personas are an illustrative future direction, not
    defined, selected, or applied here.
  • No hosted/team/mobile/voice — deferred to later phases.

Next after v0.8.2

Cut the v0.8.2 tag/GitHub Release, closing the v0.8.x "Solidify the core, local-first" line
(v0.8.0 launcher, v0.8.1 vault polish, v0.8.2 preference schema + validator). The next version-line
architecture moment is v0.9.x — preference application (letting validated preferences influence a
command, and the council-persona model): a Fable architecture pass over council-produced planning, then
Opus/Sonnet implementation. Preference application, a .council/profile.* store, named
personas/persona UX, mobile/LAN/voice, and hosted/team all stay deferred behind their own gated designs.