feat(proposer): keel assets propose — screen an LLM asset shortlist, admit nothing - #153
Merged
Conversation
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…steps Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… nothing Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…hyphenated-asset rejection, stronger writes-nothing test
- Single source of truth for the zero-bar failure-tag suppression: add
DATA_DERIVED_FAILURES to keel/compliance/screen.py (it owns the tags) and have
both keel/cli.py's `_DATA_DERIVED_FAILURES` and keel/proposer.py import it
instead of each defining its own copy, plus a pin test asserting the set
matches screen_asset's real output.
- Reject an asset code containing non-alphanumeric characters (e.g. "sol-usd")
at schema validation: `_history_product` and the gate key off
product.split("-")[0], but the report's on_allowlist/attested labels keyed off
the full string would silently disagree with what was actually screened.
- Strengthen test_propose_writes_nothing to assert the full
repo.get_asset_attestations() == [] on a freshly reopened DB handle, so a
stray write to any asset/table would be caught, not just the one candidate
proposed.
- Add coverage: human output includes the DISCLAIMER footer; a non-dict
candidate entry lands in `invalid` with a clear reason instead of crashing.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Implements roadmap direction #3, slice (A):
keel assets propose --from <shortlist.json>— a read-only candidate source that ingests an externally-produced LLM asset shortlist and routes each candidate through the existing, unmodified_screen_productadmission gate.Follows
docs/superpowers/specs/2026-07-24-llm-asset-proposer-design.mdanddocs/superpowers/plans/2026-07-24-llm-asset-proposer.md.Design — outside-first hybrid
The LLM + web-search scouting happens outside keel (operator / Claude + firecrawl skills produce the JSON shortlist). keel owns only the deterministic, testable half:
validate → screen → report.keel/proposer.py—parse_proposal(schema + per-candidate validation),build_proposal_report(routes each candidate through an injectedscreen_fn),render_proposal_report(human) +report_to_jsonable(--json). It does not importkeel.cli(no cycle); the CLI passes the real_screen_productas the gate.assets proposecommand incli.py, besideassets screen/assets holdings.Guarantees (verified by an independent review — by construction, not just by test)
Repositorymethod.screen_asset/ScreenPolicy/_screen_productare byte-unchanged.assets proposeandassets screenreturn the identical verdict for the same asset (test assertsADMITon both sides). Becauseattestation=Nonefails closed, a freshly-scouted assetREJECTs until a human attests it and data is fetched — the proposer surfaces candidates, it never admits them.shariah_hypothesiscan't influence admission.build_proposal_reportpasses only(repo, product, quote)to the gate; the hypothesis is rendered as an explicitUNVERIFIED (never used for admission)hint and can never become an attestation.Out of scope (per spec)
No embedded LLM/web API, no new dependency, no second secret, no proposal-audit table, no allowlist mutation. Strategy-proposal (B) and insights/veto (C) are separate future specs.
Tests
+29 tests (
1629 → 1658), ruff clean.keel/proposer.pyunit tests (schema, builder, renderers, JSON) + CLI integration tests (same-gate equivalence, admits-nothing [reopens the DB],--jsonvalidity, hypothesis-never-admits, citation-required, hyphenated-asset rejection, non-dict entry, disclaimer on human path).Review
Built TDD (Sonnet) from the plan, independently reviewed by a fresh-context Opus agent → mergeable-as-is. The 4 hardening items it raised are included: single-sourced
DATA_DERIVED_FAILURESinscreen.py(with a pin test so a tag rename breaks a test rather than silently disabling suppression), alphanumeric-asset validation, a stronger writes-nothing test, and two coverage tests.🤖 Generated with Claude Code