Skip to content

v0.9.0 — Apply the proven preferences

Choose a tag to compare

@EfeAydinalp EfeAydinalp released this 08 Jul 19:47
· 10 commits to master since this release
7b4882b

vibe-council v0.9.0 — Apply the proven preferences (tighten-only, advisory)

Ready for the v0.9.0 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.9.0 release); the repo now reports 0.9.0. The git tag and the GitHub
Release are still a separate, manual step
— see §"Final release checklist" below and
docs/release-checklist.md.

The first release of the v0.9.x line. Its theme — "Apply the proven; describe the personas; defer
their behavior"
— is the "later" that the whole v0.8.x line was built toward: v0.8.2 defined and
validated
the tighten-only preference schema; v0.9.0 finally applies it, but only the four
mechanically-proven, add-friction-only keys, and only in bounded, advisory, tighten-only ways. The
deterministic trust boundary, the executor, the Workbench, and the council prompt/ranking/synthesis
paths remain completely preference-blind — locked by tests. No named-persona behavior, no prompt
emphasis, 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.9.x was planned (council-backed + Fable architecture)

  • Council-backed planning (docs-only, two vibe review --preset balanced passes):
    v0.9.x-council-debate.md,
    v0.9.x-phase-brief.md, and
    v0.9.x-fable-input.md. The council rejected shipping persona
    behavior
    as premature — the dissent-suppression / viewpoint-bias failure mode is a new risk
    class
    the tighten-only proof machinery does not cover.
  • Fable architecture plan (docs-only, version-line):
    v0.9.x-architecture-plan.md resolved the theme into a two-
    release line — v0.9.0 apply-the-keys (PRs 1–5) and v0.9.1 persona lenses + v0.10.x
    dissent-preservation sketch
    — and a spec/CLI resolution (schema v1's full is a council mode,
    not a --preset value → notice-only; schema v1 stays frozen).

What this release adds — the four proven keys, applied

The clamped reader (PR 1)

  • New effective_suggestions(project_root) → Suggestions in
    backend/preferences.py: pure, read-only, fail-closed. It reuses
    the v0.8.2 validator internals and returns clamped tighten-only values only — raw parsed JSON never
    escapes
    : review_preset_floor is emitted only for a preset strictly above the project baseline
    (so "lower" is inexpressible and premium is unrepresentable), the path fields are re-validated,
    de-duplicated relative-path tuples, and require_usage is a plain bool. Any anomaly (missing /
    invalid / oversized / multiple-block / out-of-root / undecodable block, or any validation error) →
    NEUTRAL. It reads exactly one file (PREFERENCES.md, realpath-inside-root), writes nothing, and
    never reads a .council/profile.* store.

Review/diff preset floor + --no-preferences (PR 2)

  • vibe review and vibe diff resolve their preset through the reader — tighten-only and
    CLI-first
    . Precedence (highest wins): an explicit --preset (CLI always wins) → the new
    --no-preferences escape hatch (baseline; byte-identical to pre-v0.9.0) → a validated preference
    floor (can only raise toward more review, never lower, never premium) → the project
    baseline (DEFAULT_PRESET).
  • Because the baseline is already balanced (the strongest non-premium preset), the observable effect
    is that a default_review_preset: "full" block prints one pinned stderr notice recommending
    vibe full and leaves the preset at the baselinefull is a council mode, not a --preset
    value; nothing is silently reinterpreted. A genuine raise (a future lower baseline) is likewise
    announced.
  • extract / mini / full modes never consult preferences.

Usage-flag warning (PR 3)

  • On vibe review / vibe diff only, when the block sets require_usage_flag: true and --usage is
    absent, a single pinned stderr warning ("pass --usage to see token usage (advisory)"). It
    never adds --usage, never fails, never changes cost/model behavior, and is suppressed by
    --usage, --no-preferences, or an explicit choice.

Doctor staged-path advisories (PR 3)

  • vibe project doctor emits advisory [warn] lines in its staged-file section when a staged path
    equals/prefixes a declared never_stage_extra / extra_sensitive_paths entry — naming the preference
    key (never its configured value / raw JSON), volume-capped at 10 lines plus a roll-up.
    Advisory only: READY/NOT-READY, exit code, and the [FAIL] dangerous-staged set are byte-stable;
    a missing/invalid block leaves doctor behavior unchanged. It does not change staging, git, or the
    no-stage guard.

Isolation lock-in (PR 4)

  • tests/test_preferences_isolation.py locks the boundary:
    an allowlist-first static scan (the backend.preferences importer set is exactly {cli.py};
    effective_suggestions is referenced only in {preferences.py, cli.py}; an explicit forbidden-
    surface list — all workbench_*, council.py, openrouter.py/providers.py, guards.py, mcp_*,
    context_pack.py — imports none of it), a behavioral byte-identity check (the deterministic trust
    evaluation and the dry-run executor are identical with and without a maximal valid block), pointer-
    only guide/context-export tripwires, doctor READY stability, and a pack-21/21-with-block check.

Safety posture

  • Advisory / tighten-only only. Every preference effect can only add friction/warnings — never
    enforce, never block, never fail a command, never lower a preset, never select premium, never
    auto-add --usage, never change staging/git. An explicit --preset/--usage (or --no-preferences)
    always wins.
  • Preference-blind trust surface. The guard, executor, Workbench, proposal/importer/panel, and the
    council prompt / ranking / synthesis paths never read preferences (proven by static scan +
    byte-identity tests). Guide / context-export stay pointer-only. No .council/profile.* store.
  • Raw JSON never escapes the reader; all preference-driven text is stderr-only and pinned.
  • 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 behavior · no prompt emphasis · no ranking/synthesis influence · no persona schema
objects or persona validator (v0.9.1 documents the review lenses as prose; v0.10.x is the persona-
behavior line behind a dissent-preservation framework) · no UI/dashboard · no .council/profile.*
local store · no Workbench trust-boundary/executor change · no command-allowlist growth · no hosted /
network / LAN / mobile mode · no vector DB / database stack · no /council real command. v0.9.0 applies
the four proven keys, advisory/tighten-only, and nothing more.

Release checklist (must be clean before tagging)

  • uv run python -m unittest discover -s tests -t . is green (990 tests).
  • uv run python -m backend.cli --version prints vibe-council 0.9.0.
  • 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.9.0 release) into master.
  • On the merged master, re-confirm: tests green, vibe --version reports vibe-council 0.9.0,
    redaction lint 0 critical (30 warnings), decisions lint passes, vibe project doctor READY (with
    the preferences advisory section), 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.9.0 -m "vibe-council v0.9.0" on the merge
    commit, then git push origin v0.9.0.
  • Create the GitHub Release for v0.9.0 manually, using this document
    (docs/releases/v0.9.0.md) as the release-notes body.

Known limitations

  • Small observable delta by design. With the balanced baseline, the preset floor is notice-only
    (no preset actually changes); v0.9.0's deeper value is the application pattern (single clamped
    consumption point, fixed precedence, byte-identity guarantees) that later work reuses.
  • Preferences are advisory. Nothing here enforces or blocks; an explicit CLI flag always wins.
  • Personas are not applied. Named council personas remain a future direction (v0.9.1 documents them
    as prose review lenses; v0.10.x is the behavior line).
  • No hosted/team/mobile/voice — deferred to later phases.

Next after v0.9.0

Cut the v0.9.0 tag/GitHub Release, then continue the v0.9.x line per
v0.9.x-architecture-plan.md: v0.9.1 — the council review
lenses
as pure documentation (Security Guardian, Cost Skeptic, Local-first Guardian + stubs; no
schema, no behavior) plus the v0.10.x dissent-preservation design sketch and a v0.9.0 dogfood pass.
Persona behavior, a .council/profile.* store, named-persona UX, mobile/LAN/voice, and hosted/team
all stay deferred behind their own gated designs.