Skip to content

feat(dashboard): quantify cases and preserve project journeys - #640

Draft
seonghobae wants to merge 286 commits into
mainfrom
feat/dashboard-case-metrics
Draft

feat(dashboard): quantify cases and preserve project journeys#640
seonghobae wants to merge 286 commits into
mainfrom
feat/dashboard-case-metrics

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Summary

  • report claim, rebid, external-information, and repeat-issue Event and distinct-post counts independently
  • preserve every explicit project membership and render each project journey in chronological order
  • add the external-information Dashboard filter as an independent GNB destination
  • refresh the exact-base product gap evidence

Verification

  • uv run --extra dev pytest -q tests/test_operations_dashboard.py tests/test_public_docstrings.py (4 passed before the multi-project extension; focused dashboard rerun 2 passed afterward)
  • corepack pnpm exec vitest run src/components/OperationsDashboard.test.tsx src/components/WorkspaceNav.test.tsx src/i18n.test.ts src/App.test.tsx (173 passed)
  • corepack pnpm lint
  • corepack pnpm build
  • corepack pnpm build-storybook
  • Storybook desktop and 390px mobile screenshots inspected; journey overflow remains bounded and metrics use a 4/2-column responsive grid

No keyword, heuristic, arbitrary threshold, or local measurement weight is introduced.


Open in Devin Review

Summary by CodeRabbit

  • 새 기능

    • 운영 대시보드에 외부 정보 전용 보기, 사례 생명주기·마일스톤·누락 근거·토픽 영향 정보를 추가했습니다.
    • Ask 답변에 인용 근거와 시간순 이벤트 타임라인을 제공하며, 서로 연결해 탐색할 수 있습니다.
    • 모바일 내비게이션과 대시보드가 반응형 레이아웃을 지원합니다.
    • 기업 계층 탐색과 관련 게시물 바로 열기를 지원합니다.
  • 버그 수정

    • 외부 정보 범위와 권한 필터가 대시보드 지표에 일관되게 적용됩니다.
    • 관측 시각, 진행 중 사례, 근거 누락 및 분석 결과 없음 상태를 더 정확히 표시합니다.
    • 다국어 안내 문구와 접근성·터치 영역을 개선했습니다.
  • 문서

    • 운영 대시보드, Ask 근거 타임라인, 배포 및 사용 기준을 갱신했습니다.

@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

Review Change Stack

Important

Review skipped

Too many files!

This PR contains 157 files, which is 57 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d7338a42-1b65-41a4-941d-8b98c7b53c2d

📥 Commits

Reviewing files that changed from the base of the PR and between dae28fb and bd73e0a.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (157)
  • .env.example
  • AGENTS.md
  • ARCHITECTURE.md
  • CHANGELOG.d/2.19.0-leftover-map-explained-share.md
  • CHANGELOG.md
  • CLAUDE.md
  • Makefile
  • README.md
  • backend/Dockerfile
  • backend/app/global_ask_queue.py
  • backend/app/main.py
  • backend/app/operations_case_ingestion.py
  • backend/app/post_chat_ingestion.py
  • backend/app/post_content_queue.py
  • backend/app/post_content_worker.py
  • backend/app/product_semantic_ingestion.py
  • backend/app/report_ingestion.py
  • backend/app/voice_taxonomy.py
  • backend/app/worker.py
  • backend/app/worker_health.py
  • backend/tests/test_api.py
  • backend/tests/test_operations_dashboard_postgres.py
  • backend/tests/test_product_semantic_ingestion.py
  • backend/tests/test_voice_taxonomy.py
  • docker-compose.postgres-tuned.yml
  • docker-compose.yml
  • docker/contextual-orchestrator/Dockerfile
  • docker/contextual-orchestrator/start.py
  • docs/adr/0003-fast-mlsirm-report-integration.md
  • docs/adr/0024-rankweave-fusion-fail-closed.md
  • docs/adr/0030-external-llm-gateway-environment.md
  • docs/adr/0048-persist-lsirm-leftover-pairs.md
  • docs/adr/0049-leftover-pair-report-ui.md
  • docs/adr/0062-semantic-unit-embedding.md
  • docs/adr/0071-post-scoped-llm-session-metadata.md
  • docs/adr/0083-orchestrator-runtime-commit-pin.md
  • docs/adr/0098-valkey-backed-post-content-ingestion.md
  • docs/adr/0122-otel-session-observability.md
  • docs/adr/0166-idempotent-migration-replay-window.md
  • docs/adr/0185-leftover-map-cross-share.md
  • docs/adr/0201-leftover-map-reconstruction.md
  • docs/adr/0206-evidence-operations-dashboard.md
  • docs/adr/0208-externalize-local-mathematical-compute.md
  • docs/adr/0224-canonical-compose-project.md
  • docs/adr/0226-macos-native-mlx-mathematical-compute-boundary.md
  • docs/adr/0227-observed-postgresql-runtime-tuning.md
  • docs/adr/0228-evidence-bound-product-semantic-catalog.md
  • docs/adr/0232-leftover-map-explained-share.md
  • docs/adr/0244-source-preserving-voice-semantic-taxonomy.md
  • docs/adr/0246-expanded-voice-of-x-post-taxonomy.md
  • docs/adr/0247-worker-cgroup-memory-evidence.md
  • docs/adr/README.md
  • docs/doctoring/WORKER_CGROUP_MEMORY_REFERENCES.md
  • docs/doctoring/python-mathematical-compute-boundary-audit.md
  • docs/lineage-bi-research-notes.md
  • docs/ontology/lineageweave-kg-shapes.ttl
  • docs/ontology/lineageweave-kg.ttl
  • docs/operability/http-concurrency-evidence.md
  • docs/operability/postgresql-observed-tuning.md
  • docs/operability/worker-memory-evidence.md
  • docs/product-requirements.md
  • docs/product-technical-gap-baseline.md
  • docs/storybook-inventory.md
  • frontend/package.json
  • frontend/src/App.css
  • frontend/src/App.test.tsx
  • frontend/src/App.tsx
  • frontend/src/AskAgentCutoff.stories.tsx
  • frontend/src/CustomerLinkingGuidance.stories.tsx
  • frontend/src/api.ts
  • frontend/src/components/AskAnswerTimeline.test.tsx
  • frontend/src/components/AskAnswerTimeline.tsx
  • frontend/src/components/LeftoverPairList.stories.tsx
  • frontend/src/components/LeftoverPairList.test.tsx
  • frontend/src/components/LeftoverPairList.tsx
  • frontend/src/components/OperationsDashboard.stories.tsx
  • frontend/src/components/OperationsDashboard.test.tsx
  • frontend/src/components/OperationsDashboard.tsx
  • frontend/src/components/ProductEvidenceList.stories.tsx
  • frontend/src/components/ProductEvidenceList.test.tsx
  • frontend/src/components/ProductEvidenceList.tsx
  • frontend/src/components/VoiceTaxonomySummary.stories.tsx
  • frontend/src/components/VoiceTaxonomySummary.test.tsx
  • frontend/src/components/VoiceTaxonomySummary.tsx
  • frontend/src/i18n.test.ts
  • frontend/src/i18n.ts
  • frontend/src/leftoverMapExplainedShare.test.ts
  • frontend/src/leftoverMapExplainedShare.ts
  • frontend/src/styles/tokens.test.ts
  • lineageweave/chunking.py
  • lineageweave/data/lineageweave-kg.ttl
  • lineageweave/embedding_backfill.py
  • lineageweave/embedding_client.py
  • lineageweave/http_client.py
  • lineageweave/leftover_pairs.py
  • lineageweave/ontology.py
  • lineageweave/operations_case_analysis.py
  • lineageweave/post_chat.py
  • lineageweave/product_semantics.py
  • lineageweave/rankweave_client.py
  • migrations/0035_body_search_prefix.sql
  • migrations/0214_topic_context_influence_projection.sql
  • migrations/0222_operations_case_analysis_input.sql
  • migrations/0228_product_semantic_catalog.sql
  • migrations/0229_post_content_admission_deferral.sql
  • migrations/0230_voice_semantic_taxonomy.sql
  • migrations/0231_post_content_failure_provenance.sql
  • migrations/0232_post_content_failure_error_type.sql
  • migrations/0234_post_content_failure_validation.sql
  • migrations/0235_voice_of_x_post_taxonomy.sql
  • migrations/0236_report_leftover_map_explained_share.sql
  • migrations/rollback/0236_report_leftover_map_explained_share.sql
  • pyproject.toml
  • scripts/backfill_post_embeddings.py
  • scripts/capture_worker_memory_evidence.py
  • scripts/k6_http_e2e.js
  • scripts/plan_postgres_tuning.py
  • scripts/queue_post_content_backfill.py
  • scripts/seed_demo_data.py
  • tests/test_backend_worker_process.py
  • tests/test_contextual_orchestrator_start.py
  • tests/test_contextual_orchestrator_vision.py
  • tests/test_documentation_hygiene.py
  • tests/test_embedding_backfill.py
  • tests/test_embedding_client.py
  • tests/test_embedding_client_edges.py
  • tests/test_global_ask_queue.py
  • tests/test_global_ask_sources.py
  • tests/test_http_client.py
  • tests/test_http_client_edges.py
  • tests/test_k6_http_e2e_contract.py
  • tests/test_leftover_pairs.py
  • tests/test_llm_context.py
  • tests/test_math_boundary_inventory.py
  • tests/test_migration_replay.py
  • tests/test_observability.py
  • tests/test_ontology.py
  • tests/test_ontology_shapes.py
  • tests/test_operations_case_analysis.py
  • tests/test_operations_case_ingestion.py
  • tests/test_orchestrator_compose_embedding_contract.py
  • tests/test_period_report.py
  • tests/test_post_chat.py
  • tests/test_post_chat_ingestion.py
  • tests/test_post_content_backfill_endpoint.py
  • tests/test_post_content_queue.py
  • tests/test_post_content_worker.py
  • tests/test_postgres_tuning_plan.py
  • tests/test_product_semantics.py
  • tests/test_queue_post_content_backfill_script.py
  • tests/test_rankweave_client.py
  • tests/test_real_provider_integration.py
  • tests/test_schema.py
  • tests/test_server_diagnostics.py
  • tests/test_static_sql_review_contracts.py
  • tests/test_worker_health.py
  • tests/test_worker_memory_evidence.py

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

📝 Walkthrough

Walkthrough

이번 변경은 운영 대시보드에 외부 정보 범위, 사례 생명주기, 누락 근거, 토픽 컨텍스트를 추가합니다. Ask 응답은 인용 이벤트 타임라인을 제공합니다. 잔여 계산은 fast-mlsirm으로 위임하고, 실행 환경과 검증 계약을 갱신합니다.

Changes

운영 분석과 대시보드

Layer / File(s) Summary
사례 분석과 증거 저장
lineageweave/operations_case_analysis.py, backend/app/operations_case_ingestion.py, migrations/0211...0216, tests/test_operations_case_*
필수 사실과 마일스톤의 누락·증거·출처 시계를 검증하고 저장합니다.
대시보드 조회와 응답 투영
backend/app/operations_dashboard.py, backend/app/main.py, backend/tests/test_operations_dashboard_postgres.py, tests/test_operations_dashboard.py
외부 전용 SQL 범위, lifecycle 집계, topic readiness, JSON-LD 투영과 not_persisted 상태를 처리합니다.
토픽 컨텍스트와 온톨로지 계약
migrations/0214_topic_context_influence_projection.sql, docs/ontology/*, tests/test_schema.py, tests/test_ontology.py
토픽 좌표, 계보, 멤버십, 영향력 결과와 provenance 제약을 저장·검증합니다. 운영 사례 온톨로지와 SHACL shape도 추가합니다.
대시보드 화면과 워크스페이스 연결
frontend/src/components/OperationsDashboard.tsx, frontend/src/components/OperationsDashboard.stories.tsx, frontend/src/api.ts, frontend/src/App.tsx, frontend/src/gnbChrome.ts
외부 정보 전용 화면, lifecycle 정보, 토픽 영향, 관측 이벤트와 새 GNB 목적지를 표시합니다.
Ask 증거 타임라인
lineageweave/post_chat.py, backend/app/global_ask_queue.py, frontend/src/components/AskAnswerTimeline.tsx, frontend/src/components/AskAnswerTimeline.test.tsx
인용 게시물의 관측 시계와 이벤트를 응답에 포함하고, 인용과 증거 카드 사이의 양방향 포커스를 제공합니다.
계산 위임과 랭킹 계약
lineageweave/leftover_pairs.py, lineageweave/period_report.py, lineageweave/rankweave_client.py, pyproject.toml
residual interaction map, 기대 응답, RRF 및 채널 기여도 계산을 외부 소유 계약으로 위임합니다.
실행 환경과 통합 검증
docker-compose.yml, backend/Dockerfile, frontend/Dockerfile, scripts/*, tests/test_schema.py, tests/test_k6_http_e2e_contract.py
Compose 프로젝트명, 빌드 캐시, Keyverse 변수, Dashboard k6 요청과 PostgreSQL 계약 검증을 갱신합니다. 관련 문서와 테스트 정리도 포함합니다.

Estimated code review effort: 5 (Critical) | ~120 minutes

Merge Risk: 🟠 High · up to dae28

The PR adds persisted topic and case evidence plus dashboard journey rendering, but the current head still contains migration paths that can fail during deployment or leave accepted evidence without required provenance, alongside missing citation fallbacks and incorrect journey/status rendering. These are concrete data and correctness risks, so the PR is not merge-ready until the migration and display issues are fixed or explicitly accepted.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 59.79% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 194 functions across 52 files. (31 skippe… 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 대시보드 사례 수량화와 프로젝트 여정 보존이라는 주요 변경 사항을 간결하고 정확하게 요약합니다.
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 59.79% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 194 functions across 52 files. (31 skipped: 31 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/dashboard-case-metrics

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 enabled auto-merge (squash) August 25, 2026 14:50
devin-ai-integration[bot]

This comment was marked as resolved.

@seonghobae

Copy link
Copy Markdown
Contributor Author

Refreshed docs/product-technical-gap-baseline.md at 724a5707 with the current aggregate queue evidence: protected main 04e6b610, 7 open PRs, 10 open issues, and exact observed heads for #640/#639/#636/#632/#631/#629/#579. The rows remain explicitly non-merge evidence and retain the no-real-data boundary. git diff --check passed; hosted checks are rerunning for this exact head.

@seonghobae

Copy link
Copy Markdown
Contributor Author

Local validation on the exact baseline-refresh tree: tests/test_operations_dashboard.py 2 passed; frontend oxlint passed; Vitest 41 files / 383 tests passed. The refreshed baseline commit is 724a5707; hosted checks remain authoritative and are still pending.

@seonghobae

Copy link
Copy Markdown
Contributor Author

Exact-head review reconciliation (2026-08-26):

  • feat: persist leftover interaction-map coordinates (v2.12.19) #579 689a21b6: the process-unit scoped period-report finding is already present in this exact head: report_ingestion.py selects and serializes p.process_unit_id, and read_period_reports uses it for ABAC before stripping it. The empty-map path in leftover_pairs.py returns axes=() (with regression coverage in tests/test_leftover_pairs.py::test_empty_upstream_map_does_not_invent_product_evidence), so zero-share axes are not persisted for an invalid complete-case map.
  • fix(semantic): preserve graph fact source provenance #632 3851c7cf: _graph_facts_for_posts performs one bounded query with a 64-fact global cap; gather_chat_sources calls it once per path and reuses the returned mapping. The cited duplicate-query review points to an older commit and is not present at this exact head.
  • feat: publish calibrated external lineage contract #636 1230a1a7: AGENTS.md already states that active_weights fails closed on an active-channel mismatch and loads a separately calibrated exact-channel vector; it no longer mandates renormalization. ARCHITECTURE.md and ADR 0172 carry the same contract.
  • feat(dashboard): quantify cases and preserve project journeys #640 4677052c: operations_dashboard.py currently computes primary_project_name by confidence desc, project_name, then uses it before the alphabetical project_names array. The cited fallback is not present at this exact head.

These are exact-head validations; no stale review snapshot was transferred as merge evidence. Hosted Checks and independent approval remain authoritative.

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

@seonghobae

Copy link
Copy Markdown
Contributor Author

Refreshed the baseline at bdef6531 with a single 2026-08-26 01:10 KST exact-head snapshot: 7 open PRs, 10 open issues, protected main 04e6b610, and current heads including #640 41527fa9, #632 bfeaecd9, #636 eeeb23c6, and #629 0f4665b5. Historical rows remain explicitly non-merge evidence. git diff --check passed.

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

@seonghobae

Copy link
Copy Markdown
Contributor Author

Verified and fixed the current Devin findings at head fae1d576: per-kind Event counts now come from persisted post_summary_event rows while post counts remain distinct classified posts; optional grounded fact types no longer reject a complete required answer set; the external destination now sends external_only=true so non-external rows/counts are excluded at the SQL boundary. The scoped view omits the corpus-wide rate label. Validation after rebasing the concurrent k6/optional-fact commits: backend 15 focused tests passed; frontend OperationsDashboard 7 tests passed; oxlint passed.

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[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 2 new potential issues.

Open in Devin Review

Comment on lines +4 to +10
const voiceLabels = {
voc: "Voice of Customer",
vocc: "Voice of Customer's customer",
voco: "Voice of Competitor",
vom: "Voice of Market",
vop: "Voice of Partner",
} as const;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Blank category names for new Voice-of-X codes

voiceLabels maps only the five original voice codes, but the summary aggregates all twelve codes that source posts can carry (ADR 0246 adds seven). A supplier, employee, regulator, investor, society, business, or process voice category resolves through t(voiceLabels[code]) to an empty label and renders its count with no name.

Prompt for agents
VoiceTaxonomySummary's voiceLabels map only covers the original five voc_type codes (voc, vocc, voco, vom, vop), but the voice-taxonomy summary aggregates category counts over post_voice_classification_assertion, which ADR 0246 / migration 0230 expanded to twelve codes (vos, voe, vob, vor, voi, voso, vops). When a category for one of the seven new codes is returned, voiceLabels[code] is undefined and the row renders with no name. Add English labels (and matching i18n entries in frontend/src/i18n.ts for each supported locale) for the seven new codes, and widen the category_memberships voice_concept_code union type in api.ts so the type reflects all twelve codes.
Open in Devin Review

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

Comment on lines +264 to +308
async def defer_post_content_job(
conn: asyncpg.Connection,
post_id: str,
*,
expected_attempt_count: int,
retry_after_seconds: int,
) -> bool:
"""Return one unadmitted lease to queued without consuming an attempt."""
if type(retry_after_seconds) is not int or retry_after_seconds <= 0:
raise ValueError("retry_after_seconds must be a positive integer")
updated = await conn.execute(
"""
update post_content_ingestion_job
set status_code = $2,
attempt_count = attempt_count - 1,
queued_at = now(),
next_attempt_at = now() + make_interval(secs => $5),
started_at = null,
completed_at = null,
updated_at = now(),
last_error_code = $6,
last_error_detail = $7
where post_id = $1
and status_code = $3
and attempt_count = $4
and attempt_count > 0
""",
post_id,
QUEUED,
RUNNING,
expected_attempt_count,
retry_after_seconds,
"no_viable_agent",
"Analysis capacity is being restored; this record will retry automatically.",
)
if not updated.endswith(" 1"):
return False
await _record_status(
conn,
post_id,
QUEUED,
failure_code="no_viable_agent",
detail_text="Analysis capacity is being restored; this record will retry automatically.",
)
return True

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: Admission deferral correctly does not consume an attempt

defer_post_content_job decrements the attempt increment applied by _claim_job, fenced on the exact running attempt, so a no_viable_agent deferral consumes no retry budget and a stale worker cannot defer a newer lease.

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

Note

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

Devin Review found 2 new potential issues.

Open in Devin Review

Comment on lines +179 to 216
), scoped_post as (
select visible_post.post_id
from visible_post
where $5::boolean is false
or exists (
select 1
from classified
where classified.post_id = visible_post.post_id
and classified.case_kind_code = 'external_information'
)
)
select (select count(*) from visible_post) as total_post_count,
(select count(*) from classified) as total_event_count,
(select count(*)
from post_summary_event summary_event
where exists (
select 1 from classified
where classified.post_id = summary_event.post_id
and ($5::boolean is false
or classified.case_kind_code = 'external_information')
)) as total_event_count,
(select count(distinct post_id) from classified
where case_kind_code = 'external_information') as external_post_count,
(select count(*) from visible_post
(select count(*) from scoped_post
where not exists (
select 1 from operations_case_analysis analysis
where analysis.post_id = visible_post.post_id
where analysis.post_id = scoped_post.post_id
) and not exists (
select 1 from post_content_ingestion_job job
where job.post_id = visible_post.post_id
where job.post_id = scoped_post.post_id
and job.status_code = 'post_content_ingestion_failed'
)) as pending_analysis_count,
(select count(*) from visible_post
(select count(*) from scoped_post
where exists (
select 1 from post_content_ingestion_job job
where job.post_id = visible_post.post_id
where job.post_id = scoped_post.post_id
and job.status_code = 'post_content_ingestion_failed'
)) as failed_analysis_count
""",

@devin-ai-integration devin-ai-integration Bot Aug 26, 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: External-only scoping keeps full coverage denominator

total_post_count, total_event_count, and external_percent use visible_post (all authorized posts), while pending/failed counts use scoped_post, which narrows to external_information only under external_only. The frontend hides pending/failed in that mode, so the split matches the stated coverage-denominator intent. No count inconsistency found.

Open in Devin Review

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

Comment on lines +285 to +296
union all
select fact.post_id, fact.case_kind_code, fact.fact_type_code
from operations_case_fact fact
join source_post post on post.post_id = fact.post_id
join source_post evidence_post on evidence_post.post_id = fact.evidence_post_id
where {visible}
and not ({visible_evidence})
and ($5::boolean is false or fact.case_kind_code = 'external_information')
order by post_id, case_kind_code, fact_type_code
""",
*args,
)

@devin-ai-integration devin-ai-integration Bot Aug 26, 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: Facts with unauthorized evidence surface as missing facts

The missing_rows UNION ALL reclassifies operations_case_fact rows whose evidence post is no longer visible as missing facts. This matches ADR 0206's re-check of current ABAC for each cited evidence post before returning a span. Behavior is intentional.

Open in Devin Review

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

Codex and others added 2 commits August 27, 2026 01:45
seonghobae and others added 4 commits August 26, 2026 10:40
* fix(ui): replace internal-boundary customer copy

* fix(ui): remove remaining internal customer copy

---------

Co-authored-by: Codex <codex@localhost>
* test(storybook): cover Global Ask next action

* fix(ask): offer an actionable retry path

---------

Co-authored-by: Codex <codex@localhost>
* ops: capture worker cgroup memory evidence

* fix: preserve terminal worker memory evidence

* fix: reject ambiguous worker containers

* fix(ops): preserve optional cgroup event evidence

* docs: refresh Dashboard exact-head evidence

* docs: record Storybook follow-up merge

---------

Co-authored-by: Codex <codex@localhost>
* feat(leftover): persist leftover-map explained share

Name e = R̂² / R² of raw residual after two-axis Gabriel reconstruction
on leftover pair rows (ADR 0232 / migration 0232). Unexplained leftover
share s stays omitted. A finite share greater than 1 is stored, never
clamped. Next action opens the named post.

* fix(report): align comparison leftover evidence

* fix(report): project Rust explained share

* build: pin reviewed interaction-map contract

* test(schema): apply explained-share migration

* build: pin unified Rust envelope head

* build: pin envelope parity proof

---------

Co-authored-by: Codex <codex@localhost>
* fix: pin validated structured workflow runtime

* fix: install structured schema runtime dependency

* fix: install orchestrator locked runtime manifest

* test: smoke locked telemetry exporter

* fix: pin protected orchestrator delivery

* Revert "fix: pin protected orchestrator delivery"

This reverts commit 3dec60c.

---------

Co-authored-by: Codex <codex@localhost>

@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 1 new potential issue.

Devin Review

Comment on lines +28 to +43
def heartbeat_has_advanced(
heartbeat_path: Path = HEARTBEAT_PATH,
state_path: Path = HEALTHCHECK_STATE_PATH,
) -> bool:
"""Return whether the heartbeat advanced since the prior health probe."""
try:
current = int(heartbeat_path.read_text(encoding="ascii"))
except (FileNotFoundError, ValueError):
return False
previous: int | None = None
try:
previous = int(state_path.read_text(encoding="ascii"))
except (FileNotFoundError, ValueError):
pass
state_path.write_text(str(current), encoding="ascii")
return current >= 0 and (previous is None or current > previous)

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: Cross-process monotonic heartbeat comparison

The heartbeat file stores time.monotonic_ns() written by the worker while heartbeat_has_advanced compares it across processes from the healthcheck. Python leaves the monotonic reference undefined across processes; correctness relies on Linux CLOCK_MONOTONIC being boot-based. Fragile if the platform assumption changes.

Devin Review

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

seonghobae added a commit that referenced this pull request Aug 27, 2026
Persist leftover-map unexplained leftover share s = U² / R² of raw
residual on leftover post–criterion pairs so the leftover the truncated
two-axis map cannot reconstruct is not read as leftover residual R,
leftover-map distance d, unexplained leftover U, or leftover-map cross
share x. Do not persist leftover-map explained share e.

After make seed, closest and farthest leftover pairs sit above the
member list with U²/R² next to leftover-map distance d; click opens
that post. Missing or non-finite share omits the badge rather than
inventing a leftover score. A share greater than 1 is stored, never
clamped. The grouping comparison strip stays on its reduced leftover
payload (distance, residual, reconstruction).

Independent of leftover stacks #640, #680, #720 and dashboard explained
share ADR 0232 (#728).
seonghobae added a commit that referenced this pull request Aug 27, 2026
Persist leftover-map unexplained leftover share s = U² / R² of raw
residual on leftover post–criterion pairs so the leftover the truncated
two-axis map cannot reconstruct is not read as leftover residual R,
leftover-map distance d, unexplained leftover U, or leftover-map cross
share x. Do not persist leftover-map explained share e.

After make seed, closest and farthest leftover pairs sit above the
member list with U²/R² next to leftover-map distance d; click opens
that post. Missing or non-finite share omits the badge rather than
inventing a leftover score. A share greater than 1 is stored, never
clamped. The grouping comparison strip stays on its reduced leftover
payload (distance, residual, reconstruction).

Independent of leftover stacks #640, #680, #720 and dashboard explained
share ADR 0232 (#728).
@opencode-agent
opencode-agent Bot disabled auto-merge August 27, 2026 16:58
@seonghobae
seonghobae marked this pull request as draft August 27, 2026 17:14
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.

2 participants