Skip to content

feat(dashboard): measure observed case lifecycles - #653

Merged
seonghobae merged 3 commits into
feat/dashboard-case-metricsfrom
feat/dashboard-delay-milestones
Aug 25, 2026
Merged

feat(dashboard): measure observed case lifecycles#653
seonghobae merged 3 commits into
feat/dashboard-case-metricsfrom
feat/dashboard-delay-milestones

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Outcome

Adds a normalized, evidence-bound observed-milestone contract for claim-cause investigation, rebid response, and handover gaps.

  • Uses only source-owned event_occurred_at or created_at instants; the model cannot generate dates.
  • Reports resolved/open/evidence-missing counts and exact elapsed seconds only when both observed endpoints exist.
  • Uses no delay threshold, current-time substitute, average, severity band, or invented weight.
  • Persists supported and explicitly missing milestones in replay-safe 3NF tables with exact evidence span, source post, digest, and clock provenance.
  • Rechecks current source visibility before dashboard projection.
  • Shows source-clock evidence and Korean next-action copy in the dashboard.

Stack

Depends on #640 and targets feat/dashboard-case-metrics.

Verification

  • Backend focused/schema/docstring: 55 passed
  • Frontend: 383 passed; lint, production build, and Storybook build passed
  • Storybook inspected locally at 1440x1100 and 390x844 using synthetic evidence-ready data

Research and standards

ADR 0206 records the adopted IEEE 1849-2023 XES event-log, Process Mining Manifesto, and W3C Time Ontology basis in APA 7 format.


Open in Devin Review

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@coderabbitai

coderabbitai Bot commented Aug 25, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3aa8c880-47f5-435d-9245-1652b808a27a

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

@seonghobae

Copy link
Copy Markdown
Contributor Author

Reviewed exact head 9d66d656 after synchronizing the current #640 parent without force-pushing. The merge repair preserved the milestone parser, ingestion, ABAC-filtered dashboard query, lifecycle projection, frontend rendering, and Storybook states. A real migration collision was fixed: #650 already owns 0214_topic_context_influence_projection.sql, so the milestone migration is now 0215_operations_case_milestone.sql and the schema test references the new number.

The conflict resolution also restored evidence visibility predicates for classification/fact/milestone queries, the lifecycle metrics projection, and frontend lifecycle fields/rendering; these are required for the PR contract rather than compatibility shims.

Exact-head local evidence:

  • uv run --extra dev --extra backend pytest -q tests/test_operations_case_analysis.py tests/test_operations_case_ingestion.py tests/test_operations_dashboard.py tests/test_post_content_worker.py -k 'operations or milestone' → 23 passed, 12 deselected.
  • uv run --extra dev --extra backend pytest -q tests/test_schema.py -k 'migration or operations' → 3 passed, 18 deselected.
  • corepack pnpm exec vitest run src/components/OperationsDashboard.test.tsx → 10 passed.
  • corepack pnpm run build and corepack pnpm run build-storybook completed successfully.

@seonghobae
seonghobae merged commit 6f42119 into feat/dashboard-case-metrics Aug 25, 2026
3 of 4 checks passed

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

Open in Devin Review

Comment thread tests/test_schema.py
Comment on lines +110 to 114
_OPERATIONS_CASE_MILESTONE_MIGRATION = (
Path(__file__).resolve().parents[1]
/ "migrations"
/ "0215_operations_case_milestone.sql"
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 New milestone migration left out of the schema test

The _OPERATIONS_CASE_MILESTONE_MIGRATION constant for 0215_operations_case_milestone.sql is defined but the schema_db fixture never executes it, unlike every other operations-case migration. The new milestone tables and their constraints are never created in the throwaway database, so the migration goes unvalidated by the real-DB schema test.

Prompt for agents
In tests/test_schema.py the schema_db fixture applies each operations-case migration explicitly via cur.execute(...). The newly added _OPERATIONS_CASE_MILESTONE_MIGRATION (migrations/0215_operations_case_milestone.sql) is defined but never executed inside the fixture's `with conn.cursor() as cur:` block, so the operations_case_milestone and operations_case_missing_milestone tables are never created and the migration is not exercised by the real-database schema replay test. Add a cur.execute(_OPERATIONS_CASE_MILESTONE_MIGRATION.read_text()) call in the fixture in the correct order (after the operations_case classification/missing-fact migrations it depends on, since the milestone tables reference operations_case_classification). Optionally assert the new tables appear in test_migration_applies_cleanly.
Open in Devin Review

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

Comment on lines +464 to +471
elif start and end_code in missing_milestones:
elapsed_seconds = None
status_code = "open"
next_action = f"{MILESTONE_TYPE_LABELS[end_code]} Event 근거를 연결하세요."
else:
elapsed_seconds = None
status_code = "evidence_missing"
next_action = f"{MILESTONE_TYPE_LABELS[start_code]} Event 근거를 연결하세요."

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: Hidden evidence posts silently downgrade lifecycle status

The observed-milestone query joins evidence_post under visible_evidence (operations_dashboard.py:290-294) while the missing branch does not. When a milestone's evidence post is no longer visible, it vanishes from the observed set and is absent from missing_milestones, so _project_lifecycles reports evidence_missing even when the start endpoint exists, and next_action can name the wrong milestone. This is the intended ABAC recheck, but the status/next-action copy can mislead for partially hidden cases.

Open in Devin Review

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

Comment on lines +296 to +303
union all
select missing.post_id, missing.case_kind_code,
missing.milestone_type_code, null, null, null, null, true
from operations_case_missing_milestone missing
join source_post post on post.post_id = missing.post_id
where {visible}
and ($5::boolean is false or missing.case_kind_code = 'external_information')
order by post_id, case_kind_code, milestone_type_code

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: Milestone array order in test differs from real DB

The union query orders by milestone_type_code (operations_dashboard.py:303), so a claim case returns cause_confirmed before claim_received, but the test mock returns them claim_received-first, so the asserted array order will not match production. No functional impact: the frontend derives endpoints via by-type lookup in _project_lifecycles, not from the raw milestones array order.

Open in Devin Review

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

Comment on lines 96 to +100
if source.evidence_facts
else ""
),
source_times[source.post_id][0],
source_times[source.post_id][1],

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: Milestone instants correctly bound to source clocks

Each source's observed instant is fetched from source_post and attached in _operations_evidence_sources (post_content_worker.py:75-100), and the parser binds observed_at from the cited source, rejecting sources missing an instant. source_times[source.post_id] cannot KeyError because gather_chat_sources only returns posts that exist in source_post, and ChatSourceDocument.post_id is already a canonical string matching the fetched keys.

(Refers to this code)

Open in 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