Skip to content

feat(analysis): bind Pareto candidate-K selection to an analysis-run profile - #409

Draft
seonghobae wants to merge 1 commit into
mainfrom
feat/pareto-candidate-k-analysis-run-gap-004
Draft

feat(analysis): bind Pareto candidate-K selection to an analysis-run profile#409
seonghobae wants to merge 1 commit into
mainfrom
feat/pareto-candidate-k-analysis-run-gap-004

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Summary

GAP-004 leftover / ADR 0053. Bind existing model_selection::select_candidate_k and selected_k_root_mean_square_error to a cutoff-safe pareto_candidate_k_v1 analysis-run profile (tepp.pareto_candidate_k.v1).

  • Invokes the Pareto-filtered statistical front already on protected main. Does not reimplement dominance or RMSE.
  • Artifact carries selected K, candidate/statistical counts, known-truth K, selected-K RMSE, and inference status pareto_statistical_front_not_fitted_schwarz_sampler.
  • LLM-vote-only sets and empty candidate sets fail closed. Snapshot/profile/cutoff mismatch fails closed, including reuse of fitted_candidate_k_v1, joint_posterior_draws_v1, and trsl_topic_lineage_v1.

Not Schwarz fitted candidate-K (#404 / ADR 0049). Not interpreter/verifier (#405 / ADR 0050). Not topic activity/dormancy (#407 / ADR 0051). Not joint Gauss-Newton Laplace draws (#408 / ADR 0052). Not a Bayesian sampler. Not GPU. Not topic birth/split/merge. Not implemented-main.

Distinct from live slices

Does not duplicate #408 (joint posterior Laplace draws), #407 (topic activity), #406 (wait CLI), #405 (interpreter/verifier), #404 (fitted candidate-K), #403 (retry-lineage CLI), #398 (membership-posterior ICC), #376 (ESEM/DSEM), #374 (Rubin), #372 (CWC), #389 (irregular event-time), #364 (TDT/CHRONOS), #356/#358/#359 (GAP-003A), #351 (Leiden), or Driver p.16 std-family micro-PRs.

Verification

  • cargo test -p analysis_engine
  • cargo clippy -p analysis_engine --all-targets -- -D warnings
  • python3 scripts/validate_documentation.py

Merge gate

Two independent current-head APPROVEs required. Author/bot COMMENTED is not independent APPROVE. Exact-head Checks on this SHA only. Predecessor Checks do not transfer. Do not self-approve. Do not merge without two independent approvals.


Devin Review

…profile

GAP-004 leftover / ADR 0053. Bind existing model_selection::select_candidate_k
and selected_k_root_mean_square_error to cutoff-safe pareto_candidate_k_v1.
LLM votes cannot define the numerical optimum. Not Schwarz fitted selection,
not joint Laplace draws, not a Bayesian sampler, and not implemented-main.
@coderabbitai

coderabbitai Bot commented Aug 31, 2026

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 20 minutes.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 95e9bac9-ee24-4b2b-b858-45a335b58fda

📥 Commits

Reviewing files that changed from the base of the PR and between 1bc02f5 and 7f24e43.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (9)
  • CHANGELOG.md
  • crates/analysis_engine/Cargo.toml
  • crates/analysis_engine/src/lib.rs
  • crates/analysis_engine/src/pareto_candidate_k_artifact.rs
  • crates/analysis_engine/tests/pareto_candidate_k_execution_contract.rs
  • docs/TRACEABILITY.md
  • docs/adr/0053-pareto-candidate-k-analysis-run.md
  • docs/adr/README.md
  • docs/doctoring/pareto-candidate-k-analysis-run.md

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@seonghobae seonghobae left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Operator COMMENT on exact head 7f24e43.

This is not an APPROVE. Author COMMENTED is not an independent review. Ruleset 18156473 still needs two independent current-head APPROVEs from non-author, non-bot reviewers.

Bind is Pareto select_candidate_k / selected-K RMSE as pareto_candidate_k_v1 (ADR 0053). Distinct from Schwarz fitted candidate-K (#404 / ADR 0049), interpreter/verifier (#405 / ADR 0050), topic activity (#407 / ADR 0051), and joint Laplace draws (#408 / ADR 0052). LLM votes cannot define the numerical optimum. Not a Bayesian sampler. Not implemented-main.

Do not self-approve. Do not merge without two independent approvals. Predecessor Checks do not transfer.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 6 potential issues.

Devin Review

return Err(AnalysisEngineError::InvalidEvidence);
}

let selected_k = u64::from(select_candidate_k(input.candidates())?);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Future evidence enters historical selection

With candidates fitted from post-cutoff evidence, select_candidate_k accepts them because the input records no availability provenance. Historical results can therefore use future evidence.

Prompt for agents
Make ParetoCandidateKInput carry validated construction provenance for the exact snapshot and knowledge cutoff, including enough availability information or an eligibility-bound upstream artifact to prove that every diagnostic excludes post-cutoff evidence. In execute_pareto_candidate_k_run, validate that provenance against the request before calling select_candidate_k. Add a test where a candidate built from post-cutoff evidence is rejected.
Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

return Err(AnalysisEngineError::InvalidEvidence);
}

let selected_k = u64::from(select_candidate_k(input.candidates())?);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Unbounded selection can exhaust CPU

With a large candidate vector, select_candidate_k performs quadratic dominance comparisons before enforcing any limit. One run can monopolize CPU and stall the service.

Prompt for agents
Define a defensible maximum candidate count for ParetoCandidateKInput and reject oversized inputs before select_candidate_k performs its quadratic Pareto-front scan. Bound selected_replications as well, enforce limits at construction and execution boundaries, and add boundary tests.
Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +221 to +226
let summary = AnalysisResultSummary::new(
"pareto_candidate_k",
candidate_count,
2,
PARETO_CANDIDATE_K_INFERENCE_STATUS,
)?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Candidate totals masquerade as evidence

AnalysisResultSummary::new records model candidates as evidence units. Clients receive evidence totals unrelated to the source corpus.

Prompt for agents
Carry the cutoff-eligible source evidence count in the validated Pareto input provenance and pass that count as AnalysisResultSummary.evidence_count. Keep candidate_count only in the Pareto artifact. Add an integration assertion where evidence count differs from candidate count.
Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +129 to +140
#[test]
fn mismatched_replications_record_positive_rmse() {
let request = request();
let mismatched = ParetoCandidateKInput::new(
vec![ModelCandidate::statistical(2, -30.0, 8.0).expect("k2")],
vec![4, 4, 4],
2,
);
let execution = execute(&request, &mismatched).expect("rmse");
assert_eq!(execution.artifact.selected_k, 2);
assert!((execution.artifact.selected_k_rmse - 2.0).abs() < f64::EPSILON);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 Recovery evidence remains narrow

Hand-built RMSE examples do not establish the required recovery, bias, convergence, or failure-rate evidence. Verify whether existing studies cover this exact profile.

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +69 to +90
pub struct ParetoCandidateKArtifact {
/// Exact versioned schema identity.
pub schema_version: String,
/// Opaque accepted-run identity.
pub run_id: String,
/// Immutable source snapshot identity.
pub snapshot_id: String,
/// Historical evidence cutoff used by the selection.
pub knowledge_cutoff: String,
/// Statistically selected topic count `K`.
pub selected_k: u64,
/// Number of candidates offered to the Pareto gate.
pub candidate_count: u64,
/// Number of statistically supported candidates.
pub statistical_count: u64,
/// Known-truth topic count used for RMSE.
pub truth_k: u64,
/// RMSE of selected-`K` replications against known truth.
pub selected_k_rmse: f64,
/// Fixed claim boundary for consumer copy.
pub inference_status: String,
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 Mutable artifacts weaken invariants

Public fields let callers invalidate completed artifacts after execution. Serialization catches mutations, but in-memory consumers can observe unchecked states.

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +188 to +190
if request.knowledge_cutoff != knowledge_cutoff.to_rfc3339()
|| request.model_contract_version != PARETO_CANDIDATE_K_MODEL_CONTRACT_VERSION
|| request.output_profile != PARETO_CANDIDATE_K_OUTPUT_PROFILE

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 Cutoff matching rejects equivalent timestamps

Exact string matching rejects valid RFC 3339 representations of the same instant. Confirm whether profile binding requires textual identity rather than temporal equality.

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

seonghobae added a commit that referenced this pull request Aug 31, 2026
ADR 0053 is already live on #409 (Pareto candidate-K vs main).
Rename this stack's decision identity rather than collide.
@seonghobae
seonghobae marked this pull request as draft September 1, 2026 16:36
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.

1 participant