feat: wire lens into research prompts (closes R38) - #6
Merged
Merged
Conversation
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
Closes backlog item R38 ("lens-axis") per
docs/REVIEW_2026-07.md/docs/ROADMAP.md.lens(an angle-of-attack instruction likeskeptic/opportunity/first_principles/practical, injected as the first line of a model's prompt) has worked for chat jobs sincecouncil/worker.py'sPerspectiveWorker.answer()— but was inert for research jobs:council/researcher.py'sResearchWorker.lensfield existed and was threaded through, but nothing ever read it when building the findings-generation prompt.This wires it in:
ResearchWorker._draft()now computesLENSES.get(self.lens, LENSES["neutral"])(same fallback patternworker.pyalready uses) and injects it as the first instruction bullet, alongside the existing role/vantage/citation bullets. Query planning (_plan_queries/_refine_queries) is untouched — lens shapes only the final synthesis, matchingworker.py's own scope (it doesn't lens the question either).docs/GLOSSARY.md's Lens entry gets a one-clause addition noting this now applies uniformly acrosspw askandpw research/network research jobs, since that's what the generic phrasing already implied.Backward compatibility
council/local.pyis intentionally untouched. It hardcodeslens="independent analyst"for single-playerpw research— not a key incouncil.worker.LENSES— soLENSES.get(self.lens, LENSES["neutral"])safely falls through to the neutral instruction for it, exactly as it already does for any other unknown lens string. This is verified by a dedicated regression test rather than "fixed" inlocal.py.Testing
New
tests/test_researcher_lens.py:_draft()'s prompt carriesLENSES["skeptic"]'s text whenlens="skeptic"._draft()'s prompt carriesLENSES["neutral"]'s text with the default lens.lens="independent analyst"(the exact stringcouncil/local.pyhardcodes) does not raise and falls back to the neutral instruction text — the regression guarantee forlocal.py.Full verification (all green):
python -m py_compile council/researcher.py tests/test_researcher_lens.pyruff check .→ All checks passed!pytest tests/ -q→ 510 passed, 1 skipped (511 collected total, including the 3 new tests; the 1 skip is pre-existing/unrelated)Touched only
council/researcher.py,tests/test_researcher_lens.py(new),docs/GLOSSARY.md— no changes tocouncil/local.py,council/worker.py, or anything else.🤖 Generated with Claude Code