feat(init): add --template with a gittensor seed pack - #133
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughThe PR introduces a template-based onboarding system for ChangesTemplate-based onboarding initialization
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
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 unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/vouch/onboarding.py (1)
353-362: ⚡ Quick winAvoid coupling
seed_starter_kb()to the default template's source order.Line 359 assumes the starter source is always the first seeded source. If
defaultever gains another source, this wrapper can return the wrongsource_id. Derive it fromSTARTER_SOURCE_TEXT(or the"starter"source spec) instead of indexingresult.source_ids.♻️ Proposed fix
def seed_starter_kb( store: KBStore, *, approved_by: str = "vouch-init" ) -> StarterSeedResult: """Seed the default starter claim. Thin wrapper over `seed_template`.""" result = seed_template(store, template="default", approved_by=approved_by) + starter_source_id = sha256_hex(STARTER_SOURCE_TEXT.encode("utf-8")) return StarterSeedResult( - source_id=result.source_ids[0], + source_id=starter_source_id, claim_id=STARTER_CLAIM_ID, created_source=result.created_sources > 0, created_claim=result.created_claims > 0, )🤖 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 `@src/vouch/onboarding.py` around lines 353 - 362, seed_starter_kb currently assumes the starter source is the first item in seed_template's result.source_ids which can break if template source order changes; update seed_starter_kb to locate the starter source id by matching the seeded source whose text equals STARTER_SOURCE_TEXT (or the "starter" source spec) from seed_template's returned metadata instead of using result.source_ids[0], keeping the rest of the StarterSeedResult construction (claim_id=STARTER_CLAIM_ID, created_source/created_claim flags) unchanged; reference seed_template, seed_starter_kb, STARTER_CLAIM_ID, STARTER_SOURCE_TEXT, and result.source_ids when making the change.
🤖 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 `@src/vouch/onboarding.py`:
- Around line 71-100: The nested list fields are still mutable which lets
callers mutate shared data (e.g., _GITTENSOR_TAGS, Template.sources/claims,
_SourceSpec.tags, _ClaimSpec.source_keys/_ClaimSpec.tags) and can break
seed_template (KeyError at seed_template line 314); fix by making these
collections immutable: change the dataclass fields in _SourceSpec, _ClaimSpec
and Template from list[...] to tuple[...] (e.g., tags: tuple[str, ...],
source_keys: tuple[str, ...], sources: tuple[_SourceSpec, ...], claims:
tuple[_ClaimSpec, ...]) and replace the shared _GITTENSOR_TAGS list with a
tuple; ensure all Template and spec constructions pass tuples (or wrap existing
lists with tuple(...)) so TEMPLATES contains deeply immutable structures while
keeping the dataclasses frozen.
---
Nitpick comments:
In `@src/vouch/onboarding.py`:
- Around line 353-362: seed_starter_kb currently assumes the starter source is
the first item in seed_template's result.source_ids which can break if template
source order changes; update seed_starter_kb to locate the starter source id by
matching the seeded source whose text equals STARTER_SOURCE_TEXT (or the
"starter" source spec) from seed_template's returned metadata instead of using
result.source_ids[0], keeping the rest of the StarterSeedResult construction
(claim_id=STARTER_CLAIM_ID, created_source/created_claim flags) unchanged;
reference seed_template, seed_starter_kb, STARTER_CLAIM_ID, STARTER_SOURCE_TEXT,
and result.source_ids when making the change.
🪄 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: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 1c0c2482-4c3c-4117-843a-97276f83eb70
📒 Files selected for processing (3)
src/vouch/cli.pysrc/vouch/onboarding.pytests/test_onboarding.py
| @dataclass(frozen=True) | ||
| class _SourceSpec: | ||
| """A source to seed. `key` wires claims to this source within a template.""" | ||
|
|
||
| key: str | ||
| title: str | ||
| text: str | ||
| locator: str | ||
| tags: list[str] = field(default_factory=list) | ||
|
|
||
|
|
||
| @dataclass(frozen=True) | ||
| class _ClaimSpec: | ||
| """A claim to seed, citing one or more sources by their `_SourceSpec.key`.""" | ||
|
|
||
| id: str | ||
| text: str | ||
| type: ClaimType | ||
| status: ClaimStatus | ||
| confidence: float | ||
| source_keys: list[str] | ||
| tags: list[str] = field(default_factory=list) | ||
|
|
||
|
|
||
| @dataclass(frozen=True) | ||
| class Template: | ||
| name: str | ||
| description: str | ||
| sources: list[_SourceSpec] | ||
| claims: list[_ClaimSpec] |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
In Python dataclasses, does @DataClass(frozen=True) prevent mutation of nested list fields, or are list attributes still mutable unless they are replaced with immutable types like tuple?
💡 Result:
In Python dataclasses, the frozen=True parameter does not prevent mutation of nested mutable objects, such as lists or dictionaries [1][2]. When you define a dataclass with frozen=True, the decorator adds setattr and delattr methods to the class that raise a FrozenInstanceError if you attempt to assign a new value to a field or delete one [1][3]. However, this only protects the dataclass instance itself from reassignment at the top level [2]. It does not provide deep immutability [1][3]. If a field contains a mutable object (like a list), you can still modify the contents of that object in place (e.g., using.append or index assignment) because these operations do not involve assigning to the dataclass attribute itself; they merely mutate the object the attribute references [4]. To achieve true immutability for such fields, you must replace the mutable type with an immutable alternative, such as a tuple [4][5].
Citations:
- 1: https://docs.python.org/3/library/dataclasses.html
- 2: https://believemy.com/en/glossaries/python/dataclass
- 3: https://peps.python.org/pep-0557/
- 4: https://dev.to/nasirmustafayev/everything-is-an-object-in-python-and-why-that-matters-5boa
- 5: https://dev.to/om_k_4314/week-3-listsdicts-and-why-datastructures-matter-4n5f
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE="src/vouch/onboarding.py"
# Show the relevant definitions near the template/dataclasses section
nl -ba "$FILE" | sed -n '1,220p' | sed -n '60,180p'
nl -ba "$FILE" | sed -n '180,330p'
# Locate where _GITTENSOR_TAGS and TEMPLATES are defined/used
rg -n "_GITTENSOR_TAGS|TEMPLATES|available_templates\(|seed_template\(|seed_starter_kb\(" "$FILE"
# Show the seed_template and seed_starter_kb implementations (around likely failure line ~314 per comment)
nl -ba "$FILE" | sed -n '280,380p'Repository: vouchdev/vouch
Length of output: 101
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE="src/vouch/onboarding.py"
# Print file with line numbers (using awk)
awk '{print FNR "\t" $0}' "$FILE" | sed -n '1,220p'
awk '{print FNR "\t" $0}' "$FILE" | sed -n '220,420p'
# Targeted searches for the specific concerns
rg -n "_GITTENSOR_TAGS|TEMPLATES|available_templates\(|seed_template\(|seed_starter_kb\(" "$FILE"Repository: vouchdev/vouch
Length of output: 15196
Make the exported template registry deeply immutable.
@dataclass(frozen=True) here only blocks reassigning the dataclass fields; it does not make nested list[...] fields immutable. In src/vouch/onboarding.py, _SourceSpec.tags, _ClaimSpec.source_keys, _ClaimSpec.tags, Template.sources, and Template.claims are mutable lists, and _GITTENSOR_TAGS is a shared mutable list reused across multiple specs. Since TEMPLATES is exported as a mutable dict, a caller can mutate these lists in-place and affect later seed_template() runs; if claim_spec.source_keys no longer matches the written sources, the code can raise a KeyError at line 314 after sources were already stored.
♻️ Proposed direction
-from dataclasses import dataclass, field
+from dataclasses import dataclass
+from types import MappingProxyType
+from typing import Mapping
`@dataclass`(frozen=True)
class _SourceSpec:
@@
- tags: list[str] = field(default_factory=list)
+ tags: tuple[str, ...] = ()
`@dataclass`(frozen=True)
class _ClaimSpec:
@@
- source_keys: list[str]
- tags: list[str] = field(default_factory=list)
+ source_keys: tuple[str, ...]
+ tags: tuple[str, ...] = ()
`@dataclass`(frozen=True)
class Template:
@@
- sources: list[_SourceSpec]
- claims: list[_ClaimSpec]
+ sources: tuple[_SourceSpec, ...]
+ claims: tuple[_ClaimSpec, ...]
-_GITTENSOR_TAGS = ["gittensor", "sn74", "scoring"]
+_GITTENSOR_TAGS = ("gittensor", "sn74", "scoring")
-TEMPLATES: dict[str, Template] = {
+TEMPLATES: Mapping[str, Template] = MappingProxyType({
...
-}
+})🤖 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 `@src/vouch/onboarding.py` around lines 71 - 100, The nested list fields are
still mutable which lets callers mutate shared data (e.g., _GITTENSOR_TAGS,
Template.sources/claims, _SourceSpec.tags,
_ClaimSpec.source_keys/_ClaimSpec.tags) and can break seed_template (KeyError at
seed_template line 314); fix by making these collections immutable: change the
dataclass fields in _SourceSpec, _ClaimSpec and Template from list[...] to
tuple[...] (e.g., tags: tuple[str, ...], source_keys: tuple[str, ...], sources:
tuple[_SourceSpec, ...], claims: tuple[_ClaimSpec, ...]) and replace the shared
_GITTENSOR_TAGS list with a tuple; ensure all Template and spec constructions
pass tuples (or wrap existing lists with tuple(...)) so TEMPLATES contains
deeply immutable structures while keeping the dataclasses frozen.
|
Nice one — the template registry is clean and the gittensor pack covers everything #132 listed. Idempotent re-init, back-compat wrapper kept, good tests (including the A few things before merge:
One question: Overall: 👍 once the CHANGELOG line is in — everything else is minor / a quick gut-check. |
af38494 to
03d176f
Compare
Adds a named-template system to
vouch initso a fresh KB can be seeded for a specific adoption.vouch init --template gittensorseeds cited, approved starter claims about Gittensor SN74 OSS-mining scoring (merged-PR base reward, GitHub-identity verification, code-quality factors, repo allow-list policy, issue-solving multipliers, sybil thresholds, emission split) so teams can adopt vouch as their review-gated decision memory.Templates are a registry in onboarding.py that compose the existing put_source / put_claim primitives — no new method surface, on-disk layout, or object-model change (so no VEP needed). Seeding is idempotent: content-addressed sources and id-keyed claims are never duplicated on re-init.
defaultkeeps the prior single-claim starter; seed_starter_kb is retained as a thin wrapper for back-compat.The seeded gittensor claims are deliberately starter-grade (confidence <= 0.8) and the seed source documents that values should be re-verified and superseded against the live spec via
vouch supersede.Refs #132
What changed
Why
What might break
VEP
Tests
make checkpasses locally (lint + mypy + pytest)CHANGELOG.mdupdated under## [Unreleased]Summary by CodeRabbit
Release Notes
vouch initcommand now supports template selection via a--templateoptiongittensortemplate alongside the default template