What you're trying to do
ROADMAP.md's 1.4 milestone: "Good synthesized answers can be filed back as
page proposals — gated by review like every other write." kb.synthesize
(src/vouch/synthesize.py) produces exactly that shape today — citation-
bearing prose traceable to approved claims, with a confidence grade — but
there's no way to turn a good answer into a page without manually copying
the text into a separate kb.propose_page call and re-typing the cited
claim ids.
What you've tried
kb.synthesize returns {query, answer, claims, pages, gaps, _meta} —
everything needed to file a page proposal (title-worthy prose, the
cited claim ids for the page's claims field) is already computed, just
not wired to propose_page.
kb.compile/vouch compile files page proposals too, but from an
LLM-drafted topic sweep over the whole corpus, not from answering one
specific query on demand.
Suggested shape
kb.synthesize(..., file_as_page: bool = False, page_title: str | None = None) — when file_as_page=True, file the answer back as a PAGE
proposal via the existing propose_page, citing the same claim ids the
answer already cites. Still fully gated: propose_page files a pending
proposal, never approves anything, identical to every other write path.
Skip filing (not an error) when the answer is empty or cites nothing — an
uncited "answer" is the KB saying it doesn't know, not knowledge worth
filing. Report the outcome in the result via page_proposal_id (None
when skipped or filing failed) and page_proposal_skipped_reason.
Registered the same way as every other opt-in kb.synthesize parameter,
on all four surfaces (MCP, JSONL, CLI vouch synthesize --file-as-page).
Compatibility considerations
Purely additive and opt-in — file_as_page defaults to False, so every
existing caller (and the result shape it gets back) is unchanged. No VEP:
no object model, on-disk layout, or kb.* method signature removal —
propose_page and the review gate itself are untouched; this only adds a
new way to reach the existing, already-reviewed write path.
Alternatives
A separate kb.synthesize_and_propose method — rejected in favor of a
flag on the existing method: the answer computation is identical either
way, and a second method would just be kb.synthesize plus a
propose_page call a caller could already make by hand (which is
precisely the friction this closes).
What you're trying to do
ROADMAP.md's 1.4 milestone: "Good synthesized answers can be filed back as
page proposals — gated by review like every other write."
kb.synthesize(
src/vouch/synthesize.py) produces exactly that shape today — citation-bearing prose traceable to approved claims, with a confidence grade — but
there's no way to turn a good answer into a page without manually copying
the text into a separate
kb.propose_pagecall and re-typing the citedclaim ids.
What you've tried
kb.synthesizereturns{query, answer, claims, pages, gaps, _meta}—everything needed to file a page proposal (title-worthy prose, the
cited claim ids for the page's
claimsfield) is already computed, justnot wired to
propose_page.kb.compile/vouch compilefiles page proposals too, but from anLLM-drafted topic sweep over the whole corpus, not from answering one
specific query on demand.
Suggested shape
kb.synthesize(..., file_as_page: bool = False, page_title: str | None = None)— whenfile_as_page=True, file the answer back as aPAGEproposal via the existing
propose_page, citing the same claim ids theanswer already cites. Still fully gated:
propose_pagefiles a pendingproposal, never approves anything, identical to every other write path.
Skip filing (not an error) when the answer is empty or cites nothing — an
uncited "answer" is the KB saying it doesn't know, not knowledge worth
filing. Report the outcome in the result via
page_proposal_id(Nonewhen skipped or filing failed) and
page_proposal_skipped_reason.Registered the same way as every other opt-in
kb.synthesizeparameter,on all four surfaces (MCP, JSONL, CLI
vouch synthesize --file-as-page).Compatibility considerations
Purely additive and opt-in —
file_as_pagedefaults toFalse, so everyexisting caller (and the result shape it gets back) is unchanged. No VEP:
no object model, on-disk layout, or
kb.*method signature removal —propose_pageand the review gate itself are untouched; this only adds anew way to reach the existing, already-reviewed write path.
Alternatives
A separate
kb.synthesize_and_proposemethod — rejected in favor of aflag on the existing method: the answer computation is identical either
way, and a second method would just be
kb.synthesizeplus apropose_pagecall a caller could already make by hand (which isprecisely the friction this closes).