Skip to content

v1.3.0

Choose a tag to compare

@github-actions github-actions released this 13 Jul 20:44
· 371 commits to main since this release
5363642

Added

  • vouch console: serve the vendored React web console straight from the
    installed package — a same-origin /proxy bridge (loopback-guarded) to
    vouch serve --transport http backends, reimplementing the vite dev-proxy
    in python. the built SPA is bundled into the wheel as vouch/web/console
    (conditionally, via a hatch build hook), so pip install 'vouch-kb[web]'
    then vouch console needs no node and no repo clone.
  • kb.activity read method (+ vouch activity CLI mirror): audit-log
    activity buckets for dashboards — per-day counts with proposal/decision
    breakdowns, an hour-of-week matrix, and actor/event histograms. windowed
    in viewer-local calendar days (IANA tz or a fixed utc offset), scope-
    filtered like kb.audit.
  • console Dashboard view: 12-month activity calendar, last-30-days bars,
    hour-of-week heatmap, top actors and event mix, driven by kb.activity.
  • kb.synthesize llm backend: llm=true drafts the answer with the
    deployment-configured compile.llm_cmd, grounded in retrieved kb pages
    and approved claims. code still verifies every [id] citation against
    the offered sources — invented ids are stripped, and a draft left with no
    verifiable citation returns an empty answer rather than a guess. the wire
    shape is unchanged plus additive pages and _meta.synthesis_backend
    fields. cli mirror: vouch synthesize --llm; the jsonl/http surface
    already forwarded the flag.
  • console Chat: llm answers activated — the chat asks kb.synthesize with
    llm: true and falls back to deterministic claim synthesis when no
    compile.llm_cmd is configured. page citations open the page drawer, and
    llm answers carry an llm badge next to the confidence grade.
  • session transcript viewer: the console Review view opens the full
    transcript of a captured session — thinking, per-tool call rendering
    with diffs, code blocks, and subagent drill-down — via the new
    kb.session_transcript read method. it locates the raw claude code
    jsonl session file or codex rollout by id, parses it into normalized
    blocks, and degrades to the observation buffer when the raw file is
    gone.
  • review-gated artifact delete: kb.propose_delete files a delete
    proposal for a claim, page, entity, or relation. execution happens only
    through proposals.approve(), which checks the referenced-by matrix,
    removes the file, deindexes it, and records exactly what was removed in
    the decided proposal and audit event.
  • kb.clear_claims / vouch claims-clear: bulk-remove auto-approved
    claims (--auto-only, --before, --dry-run, and a confirm gate) for
    cleaning up capture noise in one pass (#433).
  • session-split summaries: large captured sessions are split into topical
    summary pages by a deployment-configured llm (capture.split in
    config.yaml; the split llm_cmd falls back to compile.llm_cmd),
    each filed as its own pending summary. kb.summarize_session runs the
    pass on demand, kb.list_sessions lists captured sessions for the
    review pipeline, and a filed mechanical summary can be llm-narrated in
    place.
  • codex adapter: vouch install-mcp codex now wires the full tier — a
    toml_merge install strategy for .codex/config.toml, an agents.md
    fenced snippet, skills mirroring the vouch slash commands, and hook
    wiring for automatic session capture. codex session rollouts are
    ingested into review-gated summaries.
  • codex: wired UserPromptSubmit to vouch context-hook for the first
    time, reusing the existing command unmodified — codex's hook
    payload/response shape matches claude-code's exactly. (#425)
  • kb.list_skills / kb.get_skill — agents can enumerate the Claude Code
    slash-command and SKILL.md catalogue visible at <kb_root>/.claude/ and
    ~/.claude/ over MCP, then fetch the full body of one by name (project-local
    entries override user-global on collision). Exposed across MCP (kb_list_skills
    / kb_get_skill), JSONL, and the CLI (vouch list-skills / vouch get-skill).
  • mcp.publish_skills config flag (default true) — gates the skill catalogue
    for "company-brain" deployments where the catalogue itself is sensitive. When
    false, kb.list_skills returns an empty list and kb.get_skill errors with
    permission_denied; the flag is read fresh on every call so flipping it hides
    the catalogue without restarting the server, and is surfaced on
    kb.capabilities.mcp.publish_skills so clients can detect the gate. An
    existing KB with no mcp: block stays default-on (#235).
  • mcp serves a minimal tool profile by default (8 core tools) instead
    of the full method surface; widen with VOUCH_TOOL_PROFILE=standard|full
    or mcp.tool_profile in config.yaml. approve/reject and maintenance
    tools live in standard/full — they stay human/cli actions, not agent
    defaults. the jsonl and cli surfaces are unaffected.
  • per-prompt auto-recall: the claude-code adapter's UserPromptSubmit
    hook (vouch context-hook) injects relevant kb context on every
    prompt, so recall no longer depends on the agent remembering to ask.
  • kb.experts — rank the entities carrying the most matched evidence on
    a free-text topic (count, recency, and citation weightings). read-only;
    answers "who/what does this kb actually know about X" (#315).
  • kb.triage_pending — advisory triage scoring over the pending-review
    queue. scores each pending proposal on fit, citation quality,
    duplication risk, and contradiction risk, then attaches a
    _meta.vouch_triage block to help a reviewer prioritize a long
    kb.list_pending. read-only and advisory only: it never approves,
    rejects, or moves a proposal — a human still decides. degrades to a
    difflib heuristic without the [embeddings] extra. opt-in via
    triage.enabled: true; vouch triage mirrors it on the cli (#322).
  • opt-in cross-encoder rerank of the context pack: enable with
    retrieval.rerank.enabled: true in config.yaml; retrieval.rerank.top_k
    bounds the rerank window. off by default (#436).
  • kb.diff is registered at all four kb.* surface sites (mcp tool,
    jsonl handler, capabilities, cli) instead of cli-only (#327).
  • dual-solve web ui: file-changes tree view in the candidate panes — a compact
    folders-first file tree drives a per-file diff pane, replacing the flat
    changed-files list and the stacked all-files diff. selection is
    per-candidate, so inspecting claude's diff never moves the codex pane.
    (#294)
  • demo: dual-path llm configuration — compile & summarize run through
    session-capture replay or directly against the api via a stdlib shim
    wired as compile.llm_cmd with a byo ANTHROPIC_API_KEY.

Changed

  • retrieval auto/hybrid now fuses embedding + fts5 results via
    reciprocal rank fusion instead of a waterfall (embedding-first,
    fts5-fallback), with near-duplicate suppression over the fused list —
    the highest-scored near-duplicate wins, caller order is preserved for
    the context pack.
  • mcp serves one-line tool descriptions under non-full profiles, keeping
    the default surface cheap in agent context windows.

Fixed

  • audit: log_event serialises appends with a file lock, so concurrent
    writers cannot fork the hash chain (#263).
  • lifecycle.contradict() no longer lets a claim contradict itself. calling
    it with the same claim id on both sides previously wrote a self-loop
    contradicts reference and flipped the claim to contested with no
    actual counterparty; it now raises LifecycleError, mirroring the
    existing guard in supersede().
  • rpc internal errors no longer leak tracebacks over the wire; they log
    server-side and return a clean error envelope.
  • models reject empty text/name/title on claim, entity, and page at
    validation time instead of filing empty artifacts.
  • kb.crystallize retries are idempotent for summary pages — a re-run
    after a partial failure no longer files a duplicate page proposal.
  • session.crystallize: retrying on a session that hasn't been ended rewrote
    the session-<id> summary page with a fresh wall-clock Ended: stamp each
    time (and needlessly re-embedded it), so the "idempotent retry" wasn't. an
    open session now renders a stable marker, so retries produce an identical
    body.
  • claude-code: the UserPromptSubmit context hook computed retrieval but
    never fed the entity-salience reflex (#223) — salience.record_query
    was never called from the hook path, leaving the reflex permanently
    dormant for every claude-code session. OpenClaw's context engine already
    called it correctly; cursor's beforeSubmitPrompt hook cannot accept
    injected context at all, so it is not wired. (#425)
  • vouch search tolerates fts index errors instead of crashing — a
    broken or stale fts table degrades to the substring path (#438).
  • list_pages skips corrupt page files instead of failing the whole
    listing, so one bad yaml no longer takes down every kb-wide caller
    (#360).
  • context: the require_citations gate is computed after the max_chars
    budget is applied, so a claim trimmed out by the budget can no longer
    satisfy (or fail) the citation requirement on the pack (#268).
  • vouch digest --limit now caps the followups-due section like the
    pending, decisions, and stale sections — it previously returned every
    due followup regardless of the limit, contradicting the --limit help.
  • the dual-solve diff renderer dropped added/removed lines whose content
    starts with ++/-- (e.g. an added ++counter line) by treating them as
    +++/--- file headers; the header skip now requires the trailing
    space-and-path form. (#294)
  • compile_kb() could file two page proposals for the same title when the
    LLM's batch drafted the same topic (or same slug, e.g. "Retry Policy" vs
    "retry policy") twice — taken_names was only seeded from on-disk pages
    and pending proposals, never updated as drafts were accepted within the
    batch. Approving the second proposal would silently route through
    update_page() and overwrite the first. (#439)
  • volunteer scoring treats hybrid relevance as rank-relative instead of
    assuming pre-normalized scores.
  • kb.capabilities reads openclaw.compat from package.json instead
    of a stale manifest field (#417).
  • the context hook never raises on a non-dict payload or a missing kb —
    a broken hook environment degrades to no injection instead of failing
    the host prompt.
  • context and lifecycle catch only the exceptions they can handle
    (sqlite errors on fts5 fallback, missing-artifact on citation lookup)
    instead of blanket except Exception.
  • vouch install-mcp <host> (codex toml_merge): a config.toml the minimal
    serializer couldn't faithfully re-emit (a non-BMP string value, a nan/inf
    float) was bucketed as skipped and printed as (already present) with a
    clean Done, so the user believed vouch was wired into codex when it wasn't.
    serializer-failure now lands in a distinct failed bucket, is reported as
    such, and the command exits non-zero — "already installed" and "install
    failed" no longer look the same.
  • vouch install-mcp <host>: a manifest dst that escaped the target tree
    (via .. or an absolute path) is now refused with an AdapterError instead
    of writing outside target (defense in depth for the manifest file writer;
    shipped adapters are unaffected).
  • dual-solve review-ui: the recommendation hint rendered "neither engine
    produced a usable diff" for the entire duration of a still-running job — the
    hint was computed over the not-yet-populated candidate list on every poll.
    it is now omitted until candidates exist.
  • vouch capture ingest-codex: rollout parsing had no size cap and could read
    an oversized (or newline-free blob) rollout whole into memory. the file is
    now bounded to 64 MiB up front, mirroring the byte caps on other untrusted
    reads.

Security

  • kb.register_source_from_path blocks path traversal: the path is
    resolved (following symlinks) and must land inside the kb root before
    reading, with O_NOFOLLOW + fstat closing the toctou window between
    the containment check and the read. previously any file the process
    could access was registrable as a "source" and retrievable via
    kb.cite / kb.list_sources (#421).