Test#366
Conversation
scaffold typed page and entity proposals from the page-kind registry so authors get correctly-shaped drafts through the normal review gate. Co-authored-by: Cursor <cursoragent@cursor.com>
catch invalid yaml in --field and interactive prompts, gate citation-required kinds before filing, unify dry-run json id key, and move new command tests into test_cli.py. Co-authored-by: Cursor <cursoragent@cursor.com>
the old openclaw.plugin.json spoke a manifest dialect current openclaw no longer parses: installs of the linked repo failed before load (the loader hard-requires id + configSchema, routes any dir containing an openclaw.plugin.json away from the bundle path, and needs a package.json openclaw.extensions pointer to find the entry module). every old-dialect field the manifest relied on — mcpServers, contracts, family, shared_deps, openclaw.* — is silently ignored by the current parser. rewrite the packaging for the current contract, verified against a real openclaw 2026.6.11 install: * openclaw.plugin.json: id + json-schema configSchema + kind: context-engine + version (synced with pyproject) + skills as SKILL.md directories under adapters/openclaw/skills/ (mirrored from the claude-code commands; a sync test keeps them identical). the kb.* mcp server moves to deployment config (openclaw mcp add). * package.json (new, loader-facing only): openclaw.extensions entry pointer + openclaw.compat.pluginApi floor. * engine id renamed vouch-context -> vouch to equal the plugin id: the installer auto-binds plugins.slots.contextEngine to the plugin id while resolveContextEngine looks the slot value up by engine id, so distinct ids quarantined the engine and silently fell back to openclaw's legacy engine. * vouch openclaw-rpc: json-serialize datetimes in wire payloads. contextPack.generated_at crashed json.dumps on every assemble that found a kb — found by running a live agent turn against the linked plugin, where openclaw quarantined the engine for the process. * tests: manifest sync tests rewritten for the new dialect (id alignment, three-way version sync, publishable skill dirs, dead dialect fields rejected); new tier-2 e2e (tests/test_openclaw_plugin_load_real.py, skipped without the openclaw cli) links the repo into an isolated profile and asserts import, engine registration, slot auto-bind, skill publication, and a clean plugins doctor; new stdio round-trip regression test for the datetime fix. verified live: plugins install --link of this repo, inspect --runtime (imported, loaded, contextEngineIds ["vouch"]), four skills ready, plugins doctor clean, and a full embedded agent turn where assemble() ran against a real kb with zero context-engine quarantines.
93f5836 made storage.list_sources() skip artifacts it cannot parse so one corrupt file no longer crashes bulk listings, and pinned utf-8 so a non-utf-8 locale no longer mis-decodes healthy files into mojibake at read time. the skip leaves a gap for files that really are corrupt on disk: a hand edit or an external writer under a mismatched locale can land a raw control character pyyaml rejects, and such a meta then vanishes from the lint sweep with only a log warning while any claim citing the source is misreported as broken_citation. lint now loads source metas per-file like _load_claims_for_lint does for claims: a meta that fails to parse becomes an unreadable_source error finding with a repair hint, and the source id (its directory name) still counts as present so citation checks point at the actual problem instead of a phantom missing source.
# Conflicts: # CHANGELOG.md # openclaw.plugin.json
…refs Docs/remove gittensor template refs
fix(openclaw): repackage plugin for the 2026.6 loader dialect
fix(health): surface unreadable source metas as lint findings
new remember-across-sessions tutorial told through prompts typed into the claude code window, with real captured transcripts: monday's session fixes a staging bug and proposes what it learned over mcp; the sessionstart hook injects the approved claims into tuesday's fresh session, which answers a pr-review question in 2 turns citing the incident and its regression test, while the same question without vouch is slower and generic. includes a measured a/b benchmark on the fix task (4 verified headless runs per arm, claude-sonnet-5): 17% faster, 32% fewer turns, 31% fewer output tokens, 18% cheaper with the ~260-token recall digest injected. adds the tutorial to the index.
feat(cli): add vouch new scaffold command
1. Add 8 new CLI commands for reading and listing approved artifacts
(read-{claim,page,entity,relation}, list-{claims,pages,entities,relations})
2. Document self-approval prevention in getting-started guide with
config option for local testing (approver_role: trusted-agent)
3. Parameterize jsonl-quickstart test to support dynamic method count
4. Complete decision-log example with 5 approved decisions and full KB
Fixes discovered during end-to-end installation testing.
the relation model uses source/relation/target but the list-relations command was incorrectly trying to access from_id/relation_type/to_id. this caused mypy errors that failed the ci type-check step.
fix: add CLI read/list, docs, fix test, complete example
link the @vouch_dev x account from the badge row so the project's social presence is discoverable from the readme.
declares record kinds (contact, org, project-record, meeting-notes, followup, decision-record, voice) as ordinary page_kinds config so both gates validate them, and seeds a cited, approved guide page describing the conventions. merging into config.yaml is additive: operator-declared kinds win, and when the file has no page_kinds key the block is appended textually so comments survive. idempotent via stable artifact ids.
…stry templates layer on top of the starter seed instead of replacing it, so an init'd kb always carries the walkthrough basics. click.Choice keeps the flag self-documenting and rejects unknown names before any i/o.
the natural-language layer for a team-memory kb lives host-side as prompts: ask answers only with citations, remember registers the user's words as a source then proposes claims citing it, record files entity + typed-page pairs, followup files dated commitments. every flow terminates at kb_propose_* — none may call kb_approve. registered in the claude-code install manifest (T3) and the plugin skills array.
typed record kinds put their structure in page frontmatter; this adds one shared filter vocabulary over it — kind equality, field equality, and inclusive ordered bounds (numbers, iso dates) — as a viewport over store.list_pages(). deliberately not a query language: anything richer belongs in the caller. same kb.list_pages method, new optional params, plus a human mirror: vouch pages --kind followup --before due_at=...
…e followups an operator returning to a kb reconstructs "what needs me" from several commands; vouch digest folds them into one glance — pending proposals oldest-first, decisions in the window (from the decided/ records), stale claims behind the count metrics already reports, and open followup pages whose due_at has arrived. strictly a viewport: composes list_proposals, list_claims, list_pages and metrics.compute, writes nothing, logs no audit event. registered at all four surfaces as kb.digest plus a /vouch-standup slash command that narrates it.
yaml parses a bare due_at: 2026-07-01 as a date object — from the cli --meta parser and from every frontmatter disk round-trip — so a type: string schema field either rejects the natural spelling at propose time or, worse, fails re-validation at approve time for a page that validated when proposed. treat date/datetime as string-compatible scalars; genuinely wrong types still fail.
one page covering the template, the record conventions, frontmatter queries, the digest cron loop, and the slash commands — plus the honest constraint that the review queue is the bottleneck by design.
evidence intake for web content: fetch the exact bytes once, register them content-addressed, and let claims cite the immutable snapshot id so the evidence a reviewer approved against survives the live page drifting. conservative defaults for the first outbound network call in the intake path: http/https only, every redirect hop re-validated, hosts must resolve to public addresses, 2mib body cap, raw bytes only. fetched_at and final_url recorded in source metadata; audit event source.fetch. never imports proposals — sources are evidence, not knowledge.
each new .md/.txt file in the folder is registered as a content-addressed source and rolled into exactly one pending page proposal citing it — the capture.finalize shape with a dropped file as the trigger instead of a hook payload. content-hash seen-state sidecar makes re-runs idempotent; edited files re-propose. --watch is a bounded stdlib poll, no daemon. reads go through read_under_root, and an ast test pins that the module never imports an approve path.
the gate only works if a human notices it has work. vouch notify sweep evaluates the pending queue against config-declared webhooks — new proposals, a backlog crossing its threshold, proposals aged past a cutoff — and posts a small json envelope (optionally hmac-signed, secrets via the env: convention serve.bearer_token uses). delivery is best-effort and idempotent per (event, proposal); state lives in the derived state.db so losing it can only re-notify. read-and-notify only: no path here proposes, approves, or edits. protected page kinds tighten the gate the one direction invariants welcome: a kind with protected: true is exempt from the trusted-agent self-approval opt-out, so policy-bearing pages (voice, decision records — both marked in the company-brain template) always need a reviewer other than the proposer.
the nl layer lives host-side as prompt files, so the strongest deterministic guarantee is textual: every brain command must keep its explicit never-approve instruction, every manifest skills path must exist, and an ast walk pins that fetch/inbox/notify have no import or attribute path to approve(). plus docs and changelog for the intake and notification features.
docs(readme): add x social link badge
the queue used to show 27 proposals all titled "session summary: <project> (<uuid>)" — unreviewable at a glance. the sessionend hook payload already carries transcript_path, so finalize now lifts the human's first genuine prompt from the transcript (pure extraction — host wrapper messages skipped, no model involved, capture's no-llm rule holds) and titles the proposal "session: <prompt excerpt>", with the prompt quoted in a new body section. without a transcript the title falls back to what changed: "session <date>: web, docs — 9 file(s)". the uuid stays in the body for traceability.
resolve openclaw.plugin.json to the 2026.6 loader dialect: id/kind/ version plus a single json-schema configSchema, skills as directories. publish the five company-brain commands as adapters/openclaw/skills/<name>/SKILL.md and extend the manifest test's skill list to all nine. bump package.json to 1.1.0 so the version lockstep test holds against pyproject. repoint the decision-log screenshot shots at claims that exist in the reworked example fixture and re-render the svgs.
ruff flagged the two host-wrapper transcript entries at over 100 columns (e501); reformat only, no behaviour change.
feat: company brain — typed records, digest, intake, notify, readable captures
vouch compile hands the live approved claims to a deployment-configured llm command (compile.llm_cmd in config.yaml), parses the drafted topic pages, and files the survivors as pending page proposals by the wiki-compiler actor. never calls approve() — the review gate is the ingest review. every citation is verified mechanically before filing: listed claim ids must exist and be live, inline [claim: …] markers must be backed by a listed claim, wikilinks must resolve against existing pages plus the surviving batch (drops cascade to a fixpoint so a dangling link never ships), and a title that collides with an existing page or a pending draft is dropped — approve() routes colliding page ids through update_page, so an unchecked collision would silently overwrite on approval. re-running compile is idempotent against its own pending drafts. the review-ui queue gets a compile wiki button (shown once llm_cmd is configured): posts land the drafts in the same queue, one compile runs at a time per kb, failures surface as a notice, and each run appends a compile.run audit event attributed to whoever triggered it. subprocess i/o is explicit utf-8 (the default follows the locale and mojibakes or crashes on latin-1 hosts), the llm runs in a throwaway cwd so a cli that discovers per-project hooks cannot fire this project's capture pipeline mid-compile, and a malformed compile: stanza degrades to defaults instead of 500ing the queue that reads it per render.
local clients (vouch-ui) run against vouch serve and can only reach features advertised on the kb.* wire, so compile joins the method surface: kb_compile mcp tool, kb.compile jsonl handler, and the capabilities METHODS entry — test_capabilities enforces the parity. the cli command already existed, completing the four registration sites. semantics are unchanged from the compile module: the call blocks while the deployment-configured llm drafts (same shape as a summarize call), files survivors as pending page proposals by the wiki-compiler actor, attributes the run to the calling agent in the compile.run audit event, and never approves. compileerror surfaces as a clean caller-visible error envelope rather than internal_error.
110-second walkthrough recorded live against a throwaway demo kb: auto capture, one-click llm summary, the review gate, vouch compile turning approved claims into cited topic pages, and the real vouch recall digest closing the loop. 720p/3.4mb in docs/, poster frame links to it from the readme. demo content is generic placeholder data only.
approve and reject stamp decided_at with wall-clock time while the digest window tests anchor to a fixed NOW; once real time passed NOW + 1 day, test_build_window_excludes_old_decisions started failing because fresh decisions now land inside the "future" window. pin datetime.now in vouch.proposals to NOW for the fixture so decisions are deterministic relative to the window under test.
Feat/compile
a config max_pages: 0 (or --max-pages 0) made cap <= 0, so every draft was dropped with "over max_pages=0" after the LLM run was already spent. raise CompileError up front instead of silently producing nothing.
the unlabeled fence trips markdownlint MD040.
Fix/compile review followup
the decision-log-search svg committed with the merge was rendered in an environment whose search fell back to the substring backend, so ci's fresh render (fts5 with match highlights) never matched it. re-rendered from a clean python 3.12 venv with a fresh editable install — the same shape ci builds — so the committed bytes agree with what the matrix renders.
…env" This reverts commit 54ae30a.
github renders no inline player for repo-committed mp4s, so the how-it-works poster becomes a 3x-speed animated gif preview (6.4mb, 720px, 10fps) that plays right in the readme and clicks through to the full video with audio. the unused poster jpg is removed; the committed mp4 stays as-is (already 720p/3.4mb, faststart). trims 145 lines of duplication: the running-the-tests section (contributing.md territory), the long gittensor walkthrough (the top callout + docs/gittensor.md cover it), the full cli dump (vouch --help / vouch capabilities), the trust-metadata deep-dive (spec.md), and the what-ships-today table. also drops the stale "per-runtime adapter templates not yet shipped" line — adapters/ ships them.
docs(readme): embed an animated demo preview and cut redundancy
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (4)
📒 Files selected for processing (91)
📝 WalkthroughWalkthroughThis PR adds several new vouch KB capabilities: ChangesCore feature and packaging changes
Estimated code review effort: 4 (Complex) | ~75 minutes Sequence Diagram(s)sequenceDiagram
participant CLI as vouch compile
participant Compile as compile.compile_kb
participant LLM as configured llm_cmd
participant Store as KBStore
CLI->>Compile: compile_kb(actor, dry_run)
Compile->>Store: build_prompt(claims, pages)
Compile->>LLM: run_llm(prompt)
LLM-->>Compile: draft JSON
Compile->>Compile: validate drafts, resolve wikilinks
Compile->>Store: propose_page for surviving drafts
Compile->>Store: audit compile.run event
Compile-->>CLI: CompileReport
sequenceDiagram
participant Browser
participant WebServer as web/server.py
participant CompileMod as compile.compile_kb
participant Store as KBStore
Browser->>WebServer: POST /compile
WebServer->>WebServer: acquire compile_lock
WebServer->>CompileMod: compile_kb(triggered_by)
CompileMod->>Store: propose_page / audit log
CompileMod-->>WebServer: CompileReport
WebServer-->>Browser: redirect with compiled/dropped counts
Possibly related issues
Possibly related PRs
Suggested labels: ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
What changed
Why
What might break
VEP
Tests
make checkpasses locally (lint + mypy + pytest)CHANGELOG.mdupdated under## [Unreleased]Summary by CodeRabbit
New Features
Documentation
Bug Fixes