Skip to content

feat(analysis): bind TDT/CHRONOS composition to an analysis-run profile - #364

Draft
seonghobae wants to merge 2 commits into
mainfrom
feat/event-intelligence-analysis-run-gap-007
Draft

feat(analysis): bind TDT/CHRONOS composition to an analysis-run profile#364
seonghobae wants to merge 2 commits into
mainfrom
feat/event-intelligence-analysis-run-gap-007

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Summary

GAP-007 remaining operator-visible slice: bind the already-merged event_core TDT/CHRONOS composition (compose_event_intelligence, #269 on protected main) to an analysis_engine analysis-run output profile so operators can request the composed workflow.

  • New profile tdt_chronos_workflow_v1 / schema tepp.tdt_chronos_workflow.v1 (ADR 0030; 0026–0029 remain on other live PRs).
  • Cutoff-filters mentions by available_time against the request knowledge_cutoff; drops links that cite an excluded mention; keeps first-story/track streams aligned.
  • Digest-bound terminal result. Envelope layer stays tdt_detection; CHRONOS hypotheses stay chronos_prediction. Inference status is composed_workflow_not_instance_or_transition.
  • Invokes refuse_composition_as_instance and refuse_composition_as_transition. Does not invent an extractor, persist rows, or promote an instance/transition.

This is not implemented-main. Exact-head Checks on this head only. Predecessor-head evidence does not transfer.

Does not duplicate:

Test plan

  • cargo test -p analysis_engine
  • cargo clippy -p analysis_engine --all-targets -- -D warnings
  • RUSTDOCFLAGS="-D warnings" cargo doc -p analysis_engine --no-deps
  • Exact-head Required Checks on this SHA
  • Two independent (non-author, non-bot) APPROVE reviews

Merge bar

Ruleset 18156473: two independent approvals + exact-head Checks. Do not self-approve. Do not --admin merge.


Devin Review

Operators can request the existing event_core workflow as
tdt_chronos_workflow_v1. Mentions unavailable at the request cutoff are
excluded; the digest-bound tepp.tdt_chronos_workflow.v1 artifact records
detection versus prediction layers and refuses instance/transition
promotion. Not a new extractor, not persistence, and not implemented-main.
@coderabbitai

coderabbitai Bot commented Aug 31, 2026

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 42 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: a4ba1001-6c10-4f54-aba0-e9f9886db2c9

📥 Commits

Reviewing files that changed from the base of the PR and between 1bc02f5 and 8415d34.

⛔ 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/event_intelligence_artifact.rs
  • crates/analysis_engine/src/lib.rs
  • crates/analysis_engine/tests/event_intelligence_execution_contract.rs
  • docs/TRACEABILITY.md
  • docs/adr/0030-event-intelligence-analysis-run.md
  • docs/adr/README.md
  • docs/doctoring/event-intelligence-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.

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

Devin Review

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔍 Exact-head coverage remains pending

Repository rules require 100% production line and branch coverage. The PR description leaves exact-head checks pending for the new validation and error paths.

Devin Review

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

Comment on lines +363 to +370
config: input.config,
segmentation: input.segmentation,
mentions,
links,
first_story_labels,
track_assignments,
schema_slot_assignments: input.schema_slot_assignments,
occurrence_forecasts: input.occurrence_forecasts,

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

🔴 Late workflow evidence survives cutoff

When a run uses an earlier cutoff, admit_mentions_at_cutoff filters mentions but retains segmentation, schema slots, and forecasts unchanged. Results can include future-derived evidence.

Devin Review

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

Comment on lines +357 to +361
let links: Vec<_> = input
.links
.into_iter()
.filter(|link| eligible_ids.contains(&link.left()) && eligible_ids.contains(&link.right()))
.collect();

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

🟡 Foreign links are silently accepted

When a link references a mention absent from the input, filter drops it as cutoff-excluded. Malformed workflows can succeed with understated links.

Devin Review

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

run_id: accepted.run_id.clone(),
snapshot_id: snapshot_id.to_owned(),
knowledge_cutoff: knowledge_cutoff.to_rfc3339(),
workflow_version: composition.config_version(),

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

🟡 Workflow configuration escapes the digest

Replaying one accepted run with changed thresholds makes from_composition record only version 1. Different decision configurations can produce indistinguishable artifacts and digests.

Devin Review

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

Comment on lines +179 to +184
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.

🔍 Output limit is one-sided

to_json omits the advertised 256 KiB check. Current bounded fields stay small, but future variable-sized schema fields can bypass the output contract.

Devin Review

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

Comment on lines +258 to +259
let _ = refuse_composition_as_instance(&composition);
let _ = refuse_composition_as_transition(&composition);

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

📝 Info: Refusal calls are declarative

Both refusal APIs always return fixed errors without side effects. Ignoring their results preserves the boundary, but the calls add no runtime validation.

Devin Review

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

Comment on lines +328 to +346
if input.first_story_labels.len() != input.mentions.len()
|| input.track_assignments.len() != input.mentions.len()
{
return Err(AnalysisEngineError::Event(EventError::InvalidWirePayload));
}
let mut mentions = Vec::new();
let mut first_story_labels = Vec::new();
let mut track_assignments = Vec::new();
let mut excluded_after_cutoff_count = 0_u64;
for ((mention, first_story), track) in input
.mentions
.into_iter()
.zip(input.first_story_labels)
.zip(input.track_assignments)
{
if mention.clocks().available_time().instant() <= knowledge_cutoff.instant() {
mentions.push(mention);
first_story_labels.push(first_story);
track_assignments.push(track);

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

📝 Info: Indexed streams remain aligned

admit_mentions_at_cutoff checks equal lengths before zipping. Each excluded mention removes its corresponding label and track, then composition verifies track identities.

Devin Review

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

Comment on lines +247 to +248
let admitted = admit_mentions_at_cutoff(input, knowledge_cutoff)?;
let composition = compose_event_intelligence(

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

🟨 Untrusted workflow inputs lack resource bounds

execute_event_intelligence_run accepts unlimited collections before quadratic composition checks. An oversized request can exhaust service CPU and memory.

Devin Review

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

This was referenced Aug 31, 2026

@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 +279 to +285
let summary = AnalysisResultSummary::new(
"tdt_chronos_workflow",
artifact.mention_count,
statistic_count,
EVENT_INTELLIGENCE_INFERENCE_STATUS,
)
.expect("bounded event-intelligence summary constants are valid");

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 Oversized runs panic during completion

Over one billion evidence items or combined outputs makes AnalysisResultSummary::new fail. expect then crashes the executor instead of rejecting the run.

Suggested change
let summary = AnalysisResultSummary::new(
"tdt_chronos_workflow",
artifact.mention_count,
statistic_count,
EVENT_INTELLIGENCE_INFERENCE_STATUS,
)
.expect("bounded event-intelligence summary constants are valid");
let summary = AnalysisResultSummary::new(
"tdt_chronos_workflow",
artifact.mention_count,
statistic_count,
EVENT_INTELLIGENCE_INFERENCE_STATUS,
)?;
Devin Review

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

let links: Vec<_> = input
.links
.into_iter()
.filter(|link| eligible_ids.contains(&link.left()) & eligible_ids.contains(&link.right()))

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: Link filtering remains equivalent

Bitwise & evaluates both pure contains calls, but returns the same Boolean result as &&. No links change eligibility.

Devin Review

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

Comment on lines +270 to +271
)
.expect("validated composition produces a valid bounded artifact");

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: Artifact assertion remains unreachable

Successful composition guarantees every validation invariant used by from_composition. Its length conversions also fit u64 on supported platforms.

Devin Review

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

Comment on lines +529 to +546
#[test]
fn execution_refuses_invalid_completion_time() {
let fixture = KnownTruthFixture::build();
let request = request();
let accepted = accepted(&request);
assert_eq!(
execute_event_intelligence_run(
&request,
&accepted,
"snapshot-event-intelligence",
cutoff(),
fixture.input(),
"invalid",
),
Err(AnalysisEngineError::Api(
tepp_api::ApiError::InvalidWirePayload
))
);

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: Completion errors still propagate

An invalid completion timestamp reaches terminal-result validation and returns its contract error. The earlier assertions do not mask this failure.

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