Skip to content

feat(analysis): compose fitted candidate-K selection with topic lineage - #412

Draft
seonghobae wants to merge 3 commits into
mainfrom
feat/composed-fitted-lineage-analysis-run-gap-004
Draft

feat(analysis): compose fitted candidate-K selection with topic lineage#412
seonghobae wants to merge 3 commits into
mainfrom
feat/composed-fitted-lineage-analysis-run-gap-004

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Summary

GAP-004/#166/#167 leftover / ADR 0055. Bind existing model_selection::select_fitted_candidate_k then execute_topic_lineage_run at the selected K to a cutoff-safe composed_fitted_lineage_v1 analysis-run profile (tepp.composed_fitted_lineage.v1).

  • Invokes fitted Schwarz selection and the CPU f64 topic-lineage executor already on protected main. Does not reimplement scoring or lineage edges.
  • Artifact carries selected K, candidate/evidence counts, lineage topic/edge counts, the inner lineage digest, and inference status fitted_k_composed_lineage_not_bayesian_sampler.
  • Lexical methods fail closed. Snapshot/profile/cutoff mismatch fails closed, including reuse of fitted_candidate_k_v1, pareto_candidate_k_v1, trsl_topic_lineage_v1, and joint_posterior_draws_v1.

Not standalone fitted candidate-K (#404 / ADR 0049). Not interpreter/verifier (#405 / ADR 0050). Not topic activity (#407 / ADR 0051). Not joint Gauss-Newton Laplace draws (#408 / ADR 0052). Not Pareto candidate-K (#409 / ADR 0053). Not export retrieval (#411 / ADR 0054). Not a Bayesian sampler. Not GPU. Not topic birth/split/merge. Not implemented-main.

Distinct from live slices

Does not duplicate #411 (export retrieval), #410 (export authorize CLI), #409 (Pareto candidate-K), #408 (joint posterior Laplace draws), #407 (topic activity), #406 (wait CLI), #405 (interpreter/verifier), #404 (fitted candidate-K), #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

GAP-004/#166/#167 leftover / ADR 0055. Bind existing
select_fitted_candidate_k then execute_topic_lineage_run at selected K
as cutoff-safe composed_fitted_lineage_v1. LLM votes cannot define the
numerical optimum. Not a Schwarz-only bind, not Pareto, not a Bayesian
sampler, and not implemented-main.

@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 e2b3c3b.

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 fitted candidate-K composed with topic lineage as composed_fitted_lineage_v1 (ADR 0055). Distinct from Schwarz-only (#404 / ADR 0049), Pareto (#409 / ADR 0053), joint Laplace (#408 / ADR 0052), topic activity (#407 / ADR 0051), interpreter/verifier (#405 / ADR 0050), and export retrieval (#411 / ADR 0054). 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.

@coderabbitai

coderabbitai Bot commented Aug 31, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

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.

@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.

Note

This report is out of date. Scroll down for Devin Review's latest report on this PR.

Devin Review found 4 potential issues.

Devin Review

Comment thread crates/analysis_engine/src/composed_fitted_lineage_artifact.rs Outdated
Comment thread crates/analysis_engine/src/composed_fitted_lineage_artifact.rs
Comment thread crates/analysis_engine/src/composed_fitted_lineage_artifact.rs Outdated
Comment on lines +194 to +214
pub fn execute_composed_fitted_lineage_run(
request: &AnalysisRunRequest,
accepted: &AnalysisRunAccepted,
snapshot_id: &str,
knowledge_cutoff: KnowledgeCutoff,
composition: &ComposedFittedLineageInput<'_>,
completed_at: impl Into<String>,
) -> Result<ComposedFittedLineageExecution, AnalysisEngineError> {
request.to_json()?;
accepted.to_json()?;
require_receipt_identity(request, accepted)?;
if request.snapshot_id != snapshot_id {
return Err(AnalysisEngineError::SnapshotMismatch);
}
if request.knowledge_cutoff != knowledge_cutoff.to_rfc3339()
|| request.model_contract_version != COMPOSED_FITTED_LINEAGE_MODEL_CONTRACT_VERSION
|| request.output_profile != COMPOSED_FITTED_LINEAGE_OUTPUT_PROFILE
|| !valid_identifier(composition.method_name())
{
return Err(AnalysisEngineError::InvalidEvidence);
}

@devin-ai-integration devin-ai-integration Bot Aug 31, 2026

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 binding remains caller asserted

ReferenceTopicInput retains no snapshot or cutoff provenance. The executor validates supplied labels, not the input’s actual construction boundary.

Devin Review

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

@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 3 new potential issues.

Devin Review

Comment on lines +175 to +179
pub struct ComposedFittedLineageExecution {
/// Digest-bound composed selection-plus-lineage artifact.
pub artifact: ComposedFittedLineageArtifact,
/// Terminal result carrying the composed artifact identity, digest, and schema.
pub terminal_result: AnalysisRunTerminalResult,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔍 Inner artifact retrieval is unclear

ComposedFittedLineageExecution retains only the inner digest and summary counts. No visible persistence path exposes the lineage edges identified by that digest.

Devin Review

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

};
let digest = artifact.sha256()?;
#[rustfmt::skip]
let summary = AnalysisResultSummary::new("composed_fitted_lineage", artifact.evidence_count, 4, COMPOSED_FITTED_LINEAGE_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.

🔍 Statistic count lacks a contract

The summary hard-codes four statistics without identifying them. Other executors derive this count, leaving consumers unable to interpret the composed total consistently.

Devin Review

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

Comment on lines 267 to +274
if candidates.is_empty() {
return Err(ModelSelectionError::NoSuccessfulFit);
}
select_candidate_k(&candidates)
let selected_k = select_candidate_k(&candidates)?;
fitted
.into_iter()
.find(|(candidate_k, _)| *candidate_k == selected_k)
.ok_or(ModelSelectionError::NoSuccessfulFit)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📝 Info: Failed fits remain isolated

select_fitted_candidate_model preserves the existing candidate-failure policy. LLM votes cannot supply the returned model because lookup uses only successful fits.

(Refers to this code)

Devin Review

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

Resolve the CHANGELOG.md append conflict by keeping both entries.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@seonghobae

Copy link
Copy Markdown
Contributor Author

Restack on protected main (a243f18)

Non-force merge of origin/main (merge commit 1286eba0); the only conflict was the CHANGELOG.md append, both entries kept. ADR 0055 already carries an admitted maturity value (active-PR).

Local evidence on the pushed head (toolchain 1.98.0): cargo test over the touched crates (analysis_engine, corpus_split, model_selection, topic_measurement) 104 passed / 0 failed, clippy -D warnings clean on the same crates, cargo fmt --all --check clean, documentation/workspace/docstring contracts PASS, git diff --check clean.

🤖 Generated with Claude Code

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant