Skip to content

feat(analysis): bind simulation method-effect labels to an analysis-run profile - #415

Draft
seonghobae wants to merge 2 commits into
mainfrom
feat/method-effects-analysis-run-gap-004
Draft

feat(analysis): bind simulation method-effect labels to an analysis-run profile#415
seonghobae wants to merge 2 commits into
mainfrom
feat/method-effects-analysis-run-gap-004

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Summary

GAP-004 leftover / ADR 0057. Bind existing tepp_simulation::generate and refuse_unavailable_document to a cutoff-safe method_effects_v1 analysis-run profile (tepp.method_effects.v1).

  • Invokes the simulation method-effect labels already on protected main (original, revision, translation, template_copy). Does not reimplement document generation.
  • Artifact carries seed, config/content digests, original/revision/translation/template-copy/derivative counts, and inference status simulation_method_effect_labels_not_estimator_model.
  • Empty/undersized available corpora, missing originals, and snapshot/profile/cutoff mismatch fail closed, including reuse of trsl_topic_lineage_v1, fitted_candidate_k_v1, pareto_candidate_k_v1, joint_posterior_draws_v1, composed_fitted_lineage_v1, case_deletion_refit_v1, and topic_activity_v1.

Not an estimator-side method model. Not GPU. Not MCMC. Not topic birth/split/merge. Not exhaustive case-deletion (#413 / ADR 0056). Not composed fitted-K+lineage (#412 / ADR 0055). Not Pareto (#409 / ADR 0053). Not joint Laplace (#408 / ADR 0052). Not implemented-main.

Distinct from live slices

Does not duplicate #413 (case-deletion refit), #412 (composed fitted lineage), #411 (export GET), #410 (export-authorize CLI), #409 (Pareto candidate-K), #408 (joint posterior Laplace), #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), #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

Summary by CodeRabbit

  • 새 기능

    • 컷오프 기준 문서의 원본·개정·번역·템플릿·파생 문서를 분류하는 방법 효과 분석 프로필을 추가했습니다.
    • 실행 결과에 검증 가능한 JSON 아티팩트와 SHA-256 다이제스트를 제공합니다.
    • 스냅샷, 지식 컷오프, 메타데이터 불일치 및 사용할 수 없는 문서를 안전하게 거부합니다.
  • 문서

    • 방법 효과 분석 실행 프로필, 추적성 및 관련 결정 사항을 문서화했습니다.

…un profile

GAP-004 leftover / ADR 0057. Bind existing tepp_simulation::generate and
refuse_unavailable_document to cutoff-safe method_effects_v1. Census of
original/revision/translation/template_copy labels, not an estimator-side
method model, not GPU, not MCMC, and not topic birth/split/merge.
@coderabbitai

coderabbitai Bot commented Aug 31, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

Next included review available in 25 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: Team

Run ID: bd062d46-ea7d-4f6a-9a07-b0f857c21a2d

📥 Commits

Reviewing files that changed from the base of the PR and between 39d9956 and 8cf56a1.

📒 Files selected for processing (7)
  • crates/analysis_engine/Cargo.toml
  • crates/analysis_engine/src/method_effects_artifact.rs
  • crates/analysis_engine/tests/method_effects_execution_contract.rs
  • crates/tepp_simulation/src/lib.rs
  • crates/tepp_simulation/src/truth_manifest.rs
  • docs/adr/0057-method-effects-analysis-run.md
  • docs/doctoring/method-effects-analysis-run.md
📝 Walkthrough

Walkthrough

analysis_enginemethod_effects_v1 실행 프로필을 추가했습니다. 실행기는 cutoff와 snapshot을 검증하고, 사용 가능한 문서를 집계한 SHA-256 artifact와 terminal result를 생성합니다. 통합 테스트와 ADR, 추적성 문서도 추가했습니다.

Changes

메서드 효과 분석 실행 프로필

Layer / File(s) Summary
실행 계약과 공개 API
crates/analysis_engine/Cargo.toml, crates/analysis_engine/src/lib.rs
tepp_simulation 의존성, method-effects 모듈, 공개 실행 API와 InvalidMethodEffectsArtifact 오류를 추가했습니다.
Artifact 생성과 실행 검증
crates/analysis_engine/src/method_effects_artifact.rs
요청과 접수 identity, snapshot, cutoff, model contract, output profile을 검증합니다. 사용 가능한 문서를 집계하고 method_effects_v1 artifact와 terminal result를 생성합니다. JSON 왕복, SHA-256 digest, 크기와 불변식을 검증합니다.
계약 테스트와 추적성 문서
crates/analysis_engine/tests/method_effects_execution_contract.rs, docs/adr/*, docs/TRACEABILITY.md, docs/doctoring/*, DOCUMENTATION.md, CHANGELOG.md
정상 실행과 빈 corpus, 단일 원본, snapshot·cutoff·profile 불일치의 fail-closed 동작을 검증합니다. ADR, 추적성, 문서 맵과 변경 기록을 갱신합니다.

Estimated code review effort: 4 (Complex) | ~45 minutes

Merge Risk: 🔵 Low · up to 39d99

This change adds a versioned method-effects analysis artifact and execution result. Invalid digest metadata can pass validation, and tenant authorization is not visibly bound to the accepted run if the execution boundary is reachable by an untrusted caller. The PR is mergeable with explicit owner awareness and follow-up on digest validation and authorization binding.

Sequence Diagram(s)

sequenceDiagram
  participant AnalysisRunRequest
  participant execute_method_effects_run
  participant tepp_simulation
  participant MethodEffectsArtifact
  participant AnalysisRunTerminalResult
  AnalysisRunRequest->>execute_method_effects_run: 요청 및 접수 identity 전달
  execute_method_effects_run->>tepp_simulation: cutoff-safe simulation manifest 생성
  tepp_simulation-->>execute_method_effects_run: 사용 가능한 문서와 method effects 반환
  execute_method_effects_run->>MethodEffectsArtifact: 문서 집계와 digest 생성
  MethodEffectsArtifact-->>execute_method_effects_run: 검증된 artifact 반환
  execute_method_effects_run->>AnalysisRunTerminalResult: 성공 상태와 artifact digest 연결
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 52.63% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 19 functions across 3 files. (7 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목은 기존 시뮬레이션 method-effect 라벨을 analysis-run 프로파일에 연결하는 PR의 주요 변경 사항을 정확하고 간결하게 설명합니다.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 52.63% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 19 functions across 3 files. (7 skipped: 7 unsupported.)

✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/method-effects-analysis-run-gap-004

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[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

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

Devin Review

Comment on lines +167 to +170
if request.knowledge_cutoff != knowledge_cutoff.to_rfc3339()
|| request.model_contract_version != METHOD_EFFECTS_MODEL_CONTRACT_VERSION
|| request.output_profile != METHOD_EFFECTS_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.

🟡 Equivalent cutoffs reject valid runs

A valid cutoff written with +00:00 fails execute_method_effects_run because it compares text instead of instants. Semantically matching requests cannot run.

Prompt for agents
In crates/analysis_engine/src/method_effects_artifact.rs, execute_method_effects_run compares request.knowledge_cutoff directly with KnowledgeCutoff::to_rfc3339(). AnalysisRunRequest validation and temporal_core accept equivalent RFC 3339 representations such as +00:00, while to_rfc3339 canonicalizes them to Z. Parse the request cutoff and compare the underlying instant to the supplied KnowledgeCutoff, preserving the existing profile and model checks. Add coverage for equivalent noncanonical RFC 3339 spellings.
Devin Review

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

Comment on lines +89 to +94
pub fn to_json(&self) -> Result<String, AnalysisEngineError> {
self.validate()?;
let payload =
serde_json::to_string(self).map_err(|_| AnalysisEngineError::SerializationFailure)?;
Ok(payload)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔍 Serialization limit is one-sided

from_json enforces the artifact byte limit, while to_json only validates fields. Current fixed-size contents remain safely below that limit.

Devin Review

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

Comment on lines +250 to +278
fn require_generation_budget(config: SimulationConfig) -> Result<(), AnalysisEngineError> {
let events = u64::from(config.event_count());
let originals = events
.checked_mul(u64::from(config.documents_per_event()))
.ok_or(AnalysisEngineError::LimitExceeded)?;
let documents = originals
.checked_mul(4)
.ok_or(AnalysisEngineError::LimitExceeded)?;
let memberships = documents
.checked_mul(u64::from(config.membership_targets()))
.ok_or(AnalysisEngineError::LimitExceeded)?;
let relations = originals
.checked_mul(8)
.and_then(|value| {
events
.checked_mul(3)
.and_then(|events| value.checked_add(events))
})
.and_then(|value| value.checked_add(1))
.ok_or(AnalysisEngineError::LimitExceeded)?;
let generated_rows = events
.checked_add(documents)
.and_then(|value| value.checked_add(memberships))
.and_then(|value| value.checked_add(relations))
.ok_or(AnalysisEngineError::LimitExceeded)?;
if generated_rows > METHOD_EFFECTS_GENERATED_ROW_LIMIT {
return Err(AnalysisEngineError::LimitExceeded);
}
Ok(())

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: Budget uses a conservative ceiling

require_generation_budget substantially overcounts optional variants and relations. This can reject feasible runs, but it honors the documented pre-allocation ceiling.

Devin Review

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

Comment on lines +205 to +237
fn hash_document(hasher: &mut Sha256, document: &SimulatedDocument) {
hasher.update(document.document_id().as_bytes());
hasher.update(document.event_id().as_bytes());
hasher.update(document.document_time().to_rfc3339().as_bytes());
hasher.update(document.available_time().to_rfc3339().as_bytes());
hasher.update(document.method_effect().wire_name().as_bytes());
if let Some(parent) = document.parent_document_id() {
hasher.update(parent.as_bytes());
}
if let Some(observed) = document.observed_event_time() {
hasher.update(observed.to_rfc3339().as_bytes());
} else {
hasher.update(b"missing");
}
for membership in document.memberships() {
hasher.update(membership.group_id().as_bytes());
hasher.update(membership.role_label().as_bytes());
hasher.update(membership.weight_bps().to_le_bytes());
}
}

/// Digest an ordered admitted-document population using canonical truth fields.
///
#[must_use]
pub fn digest_documents(documents: &[&SimulatedDocument]) -> String {
let mut hasher = Sha256::new();
hasher.update(b"tepp.simulated_documents.v1");
hasher.update(documents.len().to_string().as_bytes());
hasher.update([0]);
for document in documents {
hash_document(&mut hasher, document);
}
hex_encode(&hasher.finalize())

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: Manifest digests remain compatible

hash_document preserves the previous field order and encoding. Existing full-manifest digests remain stable while admitted-document digests use a separate domain.

Devin Review

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

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