feat(truth-resolver): alignment-gating prototype over intent/context/value - #19
Conversation
Hybrid truth-resolver gate (SP2, prototype-first): distill -> overlap (intent/context/value) -> score_value -> Verdict, with the semantic distillation step behind a pluggable Distiller seam (deterministic now, LLM later). Encodes knowledge-integration as a value dimension. Runs and unit-tests with no API key. Doctrine (SP1) and operating-mode binding (SP3) are deferred cycles. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
TDD plan (pytest) for scripts/truth_resolver.py: 6 tasks building dataclasses + Distiller seam, DeterministicDistiller, Jaccard overlap, shared-value-gated value scoring, resolve()+dissent, and a CLI — 23 deterministic tests, no API key, LLMDistiller left as a proven seam. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- main() returns 2 (not a traceback) on missing file / bad JSON / missing keys - add tests for the error paths and for the weights override + partial fallback
|
Linter diff in the way? Review this PR in Change Stack to focus on meaningful changes and expand context only when needed. 📝 WalkthroughWalkthroughAdds a deterministic Truth-Resolver: design, dataclasses and Distiller protocol, deterministic distillation/tokenization, Jaccard overlap and weighted value scoring, resolve logic with dissent reporting, CLI entrypoint, fixtures, and comprehensive pytest coverage. ChangesTruth-Resolver Deterministic Prototype
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/superpowers/specs/2026-06-06-truth-resolver-prototype-design.md`:
- Around line 29-34: The fenced code block showing the pipeline
(Distiller.distill, overlap, score_value, resolve) lacks a language identifier;
update the opening fence to include a language such as "python" (i.e. change ```
to ```python) so tooling and syntax highlighting work correctly while leaving
the block content unchanged.
In `@scripts/truth_resolver.py`:
- Line 18: The DEFAULT_WEIGHTS dict is built with a comprehension
"DEFAULT_WEIGHTS = {d: 1.0 for d in VALUE_DIMENSIONS}"; replace it with the
simpler equivalent using dict.fromkeys by assigning DEFAULT_WEIGHTS =
dict.fromkeys(VALUE_DIMENSIONS, 1.0) to keep identical behavior while making
initialization clearer; update any nearby comments if necessary to reflect the
refactor (refer to DEFAULT_WEIGHTS and VALUE_DIMENSIONS).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 04721df6-4921-4949-b14b-71aa04eb5e0c
📒 Files selected for processing (6)
docs/superpowers/plans/2026-06-06-truth-resolver-prototype.mddocs/superpowers/specs/2026-06-06-truth-resolver-prototype-design.mdscripts/truth_resolver.pytests/fixtures/action_fail.jsontests/fixtures/action_pass.jsontests/test_truth_resolver.py
- spec: add 'text' language to the pipeline code fence (markdownlint MD040) - truth_resolver.py: DEFAULT_WEIGHTS via dict.fromkeys (equivalent, clearer)
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
scripts/truth_resolver.py (2)
112-112:⚠️ Potential issue | 🔴 Critical | ⚡ Quick win
set.intersectioncrashes with a single actor.When
vectorscontains only one element,set.intersection(*[v.value])raisesTypeError: intersection expected at least 1 argument, got 0. The single-actor case is not explicitly ruled out by the design spec, and no validation enforces a minimum of two actors.🐛 Proposed fix matching the pattern from line 72
- shared = set.intersection(*[v.value for v in vectors]) if vectors else set() + shared = vectors[0].value.intersection(*[v.value for v in vectors[1:]]) if vectors else set()🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@scripts/truth_resolver.py` at line 112, The current computation of shared using set.intersection(*[v.value for v in vectors]) fails for a single-element vectors; change it to handle three cases: if vectors is empty return an empty set, if len(vectors) == 1 use set(vectors[0].value), otherwise compute set.intersection(*[v.value for v in vectors]). Update the line that assigns shared (referencing the variables vectors and v.value) accordingly.
131-131:⚠️ Potential issue | 🔴 Critical | ⚡ Quick winSame
set.intersectioncrash risk with a single actor.If
vectorshas one element and a dimension score falls below threshold (edge case),set.intersection(*sets)will crash. Although the normal flow would have single-actor dimension scores at 1.0 (and thus skip this branch), the fragility remains.🐛 Proposed fix matching the safe pattern
- shared = set.intersection(*sets) if sets else set() + shared = sets[0].intersection(*sets[1:]) if sets else set()🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@scripts/truth_resolver.py` at line 131, The intersection call using set.intersection(*sets) is unsafe when `sets` has exactly one element; update the logic in scripts/truth_resolver.py (the block that computes `shared` from `sets` derived from `vectors`) to handle the single-element case explicitly: if `sets` is empty return set(), if it has one element return that element directly, otherwise call set.intersection(*sets); adjust the code around the `shared = set.intersection(*sets) if sets else set()` expression so it uses this safe branching to avoid the crash.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@scripts/truth_resolver.py`:
- Line 112: The current computation of shared using set.intersection(*[v.value
for v in vectors]) fails for a single-element vectors; change it to handle three
cases: if vectors is empty return an empty set, if len(vectors) == 1 use
set(vectors[0].value), otherwise compute set.intersection(*[v.value for v in
vectors]). Update the line that assigns shared (referencing the variables
vectors and v.value) accordingly.
- Line 131: The intersection call using set.intersection(*sets) is unsafe when
`sets` has exactly one element; update the logic in scripts/truth_resolver.py
(the block that computes `shared` from `sets` derived from `vectors`) to handle
the single-element case explicitly: if `sets` is empty return set(), if it has
one element return that element directly, otherwise call
set.intersection(*sets); adjust the code around the `shared =
set.intersection(*sets) if sets else set()` expression so it uses this safe
branching to avoid the crash.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: d670dc7d-6aad-48ef-8f52-a9a17a8d2115
📒 Files selected for processing (2)
docs/superpowers/specs/2026-06-06-truth-resolver-prototype-design.mdscripts/truth_resolver.py
Truth-Resolver prototype: alignment-gating over intent/context/value
Who is submitting this PR? (required)
claude-opus-4-8, 1M context). Implementation/review subagents: dispatched at theopustier; the harness does not surface the exact minor version and the tier selector cannot pin 4.7, so workers most likely ran on the session default Opus 4.8, not 4.7. Disclosed honestly.What problem are you trying to solve?
The framework has gates that purge mutations breaking the
[INTENT] ≡ [CODE OPS] ≡ [VALUE GEN]isomorphism (AAA, Quantum, Visual), but no gate that resolves alignment across the actors involved (user / agent / subagent / element). During this session the orchestrator repeatedly had to judge, ad hoc, whether a proposed action was aligned with the user's intent and net-positive on value (e.g. whether to apply a reviewer's suggestion, whether a fix preserved the doctrine). That judgment was implicit and unrepeatable. This prototype makes it an explicit, inspectable function — the first concrete step toward a "truth resolver" that can gate autonomous action on verified alignment.What does this PR change?
Adds
scripts/truth_resolver.py(and tests + fixtures): a deterministic gate that distills each actor's intent/context/value, scores their multi-set overlap and the action's net value, and returns aVerdict {passed, alignment, value, rationale, dissent}. The one genuinely-semantic step (distillation) is isolated behind a@runtime_checkable DistillerProtocol —DeterministicDistillernow, an LLM distiller a future drop-in (deliberately not implemented; the seam is proven satisfiable by a stub). Also includes the design spec and TDD plan.Is this change appropriate for the core library?
No. This is a fork-specific framework component for the RotarySlider/Autoresearch-Superpowers gate family (siblings:
aaa_quality.py,quantum_gate.py,evolution_gate_template.py). It is general-purpose within this fork's domain but not a general Superpowers core skill. Internal fork PR only.What alternatives did you consider?
Distillerseam so the semantics arrive without a rewrite.Does this PR contain multiple unrelated changes?
No. One component (the truth-resolver) plus its own design spec and plan. The docs and code are a single coherent unit (design → plan → implementation of the same feature).
Existing PRs
scripts/truth_resolver.py. Closest in spirit are the gate PRs feat: MaxOp - AAA Quality V&V Pre-Gate #8 (AAA) and feat: Max Tech - Quantum Cryptography Gate #11 (Quantum), which gate on static checks, not actor alignment.Environment tested
python -m pytest tests/test_truth_resolver.py -q→ 26 passed (Python 3.14.0, pytest 9.0.2).python scripts/truth_resolver.py tests/fixtures/action_pass.json→"passed": true, exit 0;action_fail.json→"passed": false, exit 1; bad path →error: ..., exit 2.AttributeError), then implemented to GREEN. Deterministic — no network, no API key, no LLM call.New harness support (required if this PR adds a new harness)
N/A — no new harness.
Evaluation
N/A for skill evals — this is a framework component, not a behavior-shaping skill. Functional evaluation: 6 red→green TDD cycles (RED proof captured per task), then two independent reviewer passes — a spec-compliance review (re-ran the suite, verified the Jaccard is true multi-set
|∩all|/|∪all|,value > 0strict, noLLMDistiller, zero non-deterministic calls) and a code-quality review (empirically exercised zero/single-actor and empty-dimension edge cases, found unguarded CLI input + an untestedweightsoverride, both since fixed and re-verified at 26 tests).Rigor
Human review
Summary by CodeRabbit
New Features
Documentation
Tests