Skip to content

feat(cli): add unified vera.py CLI orchestrator wired to domain services - #184

Closed
luca-belli wants to merge 22 commits into
refactor/move-rubric-data-into-si-folderfrom
feat/vera-cli
Closed

feat(cli): add unified vera.py CLI orchestrator wired to domain services#184
luca-belli wants to merge 22 commits into
refactor/move-rubric-data-into-si-folderfrom
feat/vera-cli

Conversation

@luca-belli

@luca-belli luca-belli commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator

Summary

This stacked PR adds the Phase 1 unified vera.py command surface on top of #180. It wires generate, judge, score, pool, and pipeline to parser-independent application functions; resume is reserved and fails explicitly until its state/checksum contract is implemented.

Architecture decisions

  • feat/VERA_2.0 is the source of truth for the CLI architecture.
  • A run is configured by either JSON config or command-line flags. --sample is the sole CLI flag permitted alongside --config.
  • vera.py calls domain functions directly. It does not import or dynamically invoke the legacy generate.py or judge.py CLIs.
  • Generation consumes resolved persona files, not rubric manifests. --target resolves persona files from a manifest for generation and retains the manifest for judging.
  • Manifests may omit personas for judge-only use. A generation target without personas fails with an actionable error and never silently falls back to SI defaults.
  • An optional manifest persona-context template is also resolved by --target; when absent, generation uses its normal default.
  • Legacy scripts remain temporary compatibility entry points while migration continues. They are not dependencies of the new CLI and can be deleted separately.

Implementation

  • Adds centralized run configuration models and CLI/config source validation.
  • Adds parser-independent generation, judging, and scoring application functions.
  • Implements target discovery, config-relative path handling, model repeat shorthand, pipeline stage chaining, pooling, and resolved-config output.
  • Documents the runtime wiring and updates unified CLI usage.
  • Adds structural adapter, manifest-resolution, configuration-contract, and domain-service tests.

Validation

  • Full non-live suite before the review fix: 1003 passed, 8 deselected.
  • No-mistakes review found and fixed missing optional persona-context-template propagation in the --target path.
  • The fix passed focused manifest/CLI tests, documentation checks, Ruff formatting, and Ruff linting.

Deferred work

The architecture requires deleting the legacy root CLIs by the end of Phase 1. This PR removes them from the new CLI dependency graph but leaves physical deletion for the remaining migration work.

jgieringer and others added 22 commits June 3, 2026 15:35
RubricConfig.load_bundle() inlined manifest JSON parsing/validation,
which only judge.py could reach. Per the updated Phase 0 scope in
docs/architecture.md, generate.py needs to read the same manifest's
personas list, so the reading/validation logic moves to utils/ (leaf
layer) instead -- generate/ and judge/ must never import each other.
load_bundle() now delegates to utils.rubric_manifest.load_manifest();
behavior is unchanged, covered by the existing load_bundle tests plus
new direct tests for the extracted module.
load_manifest_personas() returned personas entries verbatim instead of
resolving them relative to the manifest's own folder, contradicting
docs/architecture.md's stated rule for manifest paths (the same rule
rubric_file/etc. already follow via RubricConfig.load()). Update
data/rubric_manifest.json's personas entry to the correct
manifest-relative form ("personas.tsv", not "data/personas.tsv") now
that resolution actually happens, and cover both relative and
absolute-path entries with tests.

Caught while reorganizing data/ into per-rubric subfolders on a
downstream branch -- fixing it here instead, since this PR hasn't
merged yet and is where the bug was introduced.
Same shape as load_manifest_personas(): another optional field a rubric
bundle manifest can carry, read by utils/ so both generate/ and judge/
can reach it without importing each other. Unused until a later PR
wires a schema-specific persona context template into generation.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
data/rubric_manifest.json now points at data/persona_context_template.txt
via the new persona_context_template_file field (accessor added in the
prior commit), matching how the personas field was wired into this same
manifest ahead of generate.py's --rubric-manifest flag landing.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
judge.py --rubrics already loads a rubric bundle manifest's rubric
half; generate.py had no way to load the same manifest's personas
half, leaving a manifest's rubric+personas attachment unverified on
the generation side (docs/architecture.md's updated Phase 0 scope).

Add --rubric-manifest to generate.py: resolves the manifest's
personas list via utils.rubric_manifest.load_manifest_personas() and
threads it through ConversationRunner as persona_prompt_path (a new,
previously-hardcoded-to-data/personas.tsv parameter) instead of the
fixed default. Mirrors judge.py's own "first entry wins, warn on
extras" handling for manifests listing more than one persona file.
Also wires --rubric-manifest through run_pipeline.py's generation
step, alongside its existing --rubrics (judging) flag.
The shared data/persona_prompt_template.txt hardcoded the SI backstory
block, so a second rubric schema (e.g. PHQ9) couldn't reuse it with its
own persona fields. Split it into a shared template (stylistic/behavioral
instructions, with a {persona_context} placeholder) and a schema-specific
context template (data/persona_context_template.txt, selected via the
manifest's persona_context_template_file field added in the prior PR).

generate_conversations/utils.py's load_prompts_from_csv() now requires a
persona_context_template_path, formats it against the TSV row first, and
validates upfront that the context template's placeholders all exist as
CSV columns (previously a missing column silently skipped the row with a
printed warning). generate.py resolves this path from --rubric-manifest
the same way it already resolves persona_prompt_path, defaulting to
data/persona_context_template.txt when no manifest is given.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Everything currently in data/ (rubric.tsv, rubric_prompt_beginning.txt,
question_prompt.txt, rubric_manifest.json, personas.tsv) is specific to
the SI rubric -- once a second rubric type (e.g. PHQ9) exists, data/
needs a subfolder per rubric rather than one flat, implicitly-SI set
of files. Move all five into data/SI/ and update every hardcoded
default/reference across generate.py, judge.py, run_pipeline.py,
judge/score.py, judge/score_utils.py, scripts/, README.md, docs, and
tests.
--rubrics/--rubric-manifest require a full manifest path; there's no
way to select a rubric by bare name (e.g. typing "SI" anywhere on the
command line) until --target lands on the future vera.py CLI. Also
documents generate.py --rubric-manifest, which wasn't in the README
at all.
New top-level vera.py implements the CLI surface from
docs/architecture.md and docs/vera-cli-use-cases.md: generate, judge,
score, pool, pipeline, and resume subcommands, sharing a single
FLAG_SPECS registry so -c/-u/-j/--config etc. are defined exactly once
and reused across subcommands.

utils/config_schema.py centralizes the config.json shape (ModelSpec,
GenerationConfig, JudgingConfig, RunConfig, RubricBundleManifest) that
both CLI shorthand and --config/VERA_RUN_CONFIG resolve into, per the
Phase 1 migration plan. Business-logic wiring into the existing
generate/judge engines is left for a follow-up change; each subcommand
validates its inputs, resolves and prints the canonical RunConfig, and
stops.
@luca-belli
luca-belli marked this pull request as draft August 3, 2026 04:39
@luca-belli
luca-belli changed the base branch from main to refactor/move-rubric-data-into-si-folder August 5, 2026 03:08
@luca-belli

Copy link
Copy Markdown
Collaborator Author

Temporarily closing while correcting the stacked branch ancestry after the validation pipeline rebased it onto main. This draft will be reopened on top of #180.

@luca-belli luca-belli closed this Aug 5, 2026
@luca-belli

Copy link
Copy Markdown
Collaborator Author

Replaced by #185 after restoring exact stacked ancestry on #180; GitHub would not reopen this draft after the corrective force-with-lease push.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants