Skip to content

feat: ship PROV-O actor lineage, accessible labels, and analysis-run evidence (v0.83.0) - #74

Open
seonghobae wants to merge 130 commits into
mainfrom
feat/role-responsibility-agent-ontology
Open

feat: ship PROV-O actor lineage, accessible labels, and analysis-run evidence (v0.83.0)#74
seonghobae wants to merge 130 commits into
mainfrom
feat/role-responsibility-agent-ontology

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Buyer impact

Ships the reviewed LineageWeave product through v0.83.0 with three connected buyer-visible capabilities:

  1. a standards-complete W3C PROV-O assertion layer that preserves qualified influence, time, type, inverse, domain/range, and inference evidence without flattening it into the compact navigation graph;
  2. durable cross-post actor identity for people, teams, and organizations, including accessible related-person labels such as Our side and Counterparty; and
  3. an authorized analysis-run registry on the product home page: list, detail, labeled status history, visible-post clickthrough, and knowledge-cutoff scoping. After make seed, Demo Analyst sees Lineage reconstruction · Succeeded · Demo Corp. Another tenant's run 404s and never appears in the list.

The v0.78.0 accessibility slice was reviewed and merged as stacked PR #80. Current main (c93d449, merged PR #91 adaptive orchestration defaults) is on this branch. Duplicate PR #96 was closed unmerged. This PR does not create a second application or database authority.

Product and data contracts

  • Registers the complete PROV-O class/property inventory and normalized PostgreSQL assertion tables.
  • Keeps knowledge_graph_edge as a buyer navigation projection while normalized provenance_* tables retain semantic truth and derivation evidence.
  • Supports person, organization, and team responsibility actors with stable cross-post identity.
  • Corroborates organization aliases and bounded hierarchy placement before persistence.
  • Serializes the rare corporate-entity creation path with a short transaction-scoped advisory lock after external inference and verification.
  • Reconciles Keyman and R&R person projections separately while canonical edge evidence remains per-post and source-aware. The 0016 upgrade copies R&R names and leaves Keyman mention_context in place.
  • Replaces post-summary state atomically, preventing stale buyer-visible actors and orphaned graph evidence.
  • Persists analysis-run ownership, status events, and immutable evidence in migrations/0018_analysis_run_registry.sql. Reads are SQL-scoped; payloads are labels and aggregates only.
  • Structured LLM consumers request contextual-orchestrator auto mode (ADR 0015); explicit checked verify paths remain unchanged.
  • Uses synthetic public fixtures, a hash-locked Python environment, normalized third-form relations, and two-or-more-word snake_case database objects.

Accessibility and next action

Related-node person chips use the localized business-side label supplied by the authorized API. The same caption is exposed in the button accessible name, so a screen reader announces Related nodes for Priya Nair (Counterparty) rather than the name alone. Home analysis-run rows are buttons that open the authorized detail.

Documentation and release

  • ADRs 0006–0016 record actor type, team semantics, organization normalization, cross-post identity, corporate hierarchy creation, complete PROV-O separation, creation-lock decisions, the analysis-run registry, authorized read, adaptive orchestrator defaults, and knowledge-cutoff posts.
  • Architecture, ontology profiles, implementation matrix, APA 7 doctoring, package metadata, universal lock, and changelog are advanced through v0.83.0.
  • No transient repair workflow or repair script remains in the final diff.

Exact-head verification

Exact head: 88a1a0f8b925206083884f5350f7bbab41433fa7
Base: main @ c93d44978c5ab724d591753127e8ff0b8b7a8232

  • Tests — queued on this head (31955059893); prior head 59cde23 was green (31952379160)
  • Security Scan — queued (31955059986); prior head 59cde23 was green (31952379253)
  • SAST Semgrep — queued (31955059866); prior head 59cde23 was green (31952379129)
  • PROV-O contract — queued (31955059900); prior head 59cde23 was green (31952379237)
  • Strix — queued (31955058003); prior head 59cde23 was green (31952378323, org backend-unavailable skip after a 0-finding fallback scan; see PR comments)
  • All current and historical review threads resolved at the last reviewed head
  • Auto-merge enabled; no protection bypass
  • Qualifying independent current-head approval required by the live ruleset

The branch is intentionally waiting on the independent approval gate and green exact-head required checks. No earlier review, stacked-base result, local verifier, or owner-authored comment substitutes for that approval. This update does not merge the PR.

Standards references

Lebo, T., Sahoo, S., McGuinness, D., Belhajjame, K., Cheney, J., Corsar, D., Garijo, D., Soiland-Reyes, S., Zednik, S., & Zhao, J. (2013). PROV-O: The PROV ontology. World Wide Web Consortium.

Reynolds, D. (Ed.). (2014). The organization ontology. World Wide Web Consortium.

Miles, A., & Bechhofer, S. (Eds.). (2009). SKOS simple knowledge organization system reference. World Wide Web Consortium.

Summary by CodeRabbit

  • 새로운 기능

    • 분석 실행의 목록·생성·상세 조회와 상태 이력을 제공합니다.
    • 지식 기준 시점과 권한 범위에 따른 게시물 가시성을 지원합니다.
    • 사람·팀·조직 간 관련 노드 탐색을 확장했습니다.
    • 조직명 정규화, 기업 계층 자동 생성, 인물 직함 표시를 지원합니다.
    • 인라인 이미지 표시와 OCR·캡션·태그 처리를 개선했습니다.
    • Storybook 기반 UI 컴포넌트 미리보기를 추가했습니다.
    • W3C PROV-O 표준 provenance 관계와 RDF 직렬화를 지원합니다.
  • 보안 및 안정성

    • 분석 실행 보존 데이터 삭제에 승인·관리자 권한 검증을 적용합니다.
    • 분석 결과에 원본 데이터와 민감한 제공자 정보가 노출되지 않습니다.
  • 문서화

    • PROV-O, 분석 실행, 팀·조직 탐색 및 운영 절차 문서를 추가했습니다.

Confirmed against real Milestone 2 SAP CRM VOC data: post_summary.py's
R&R extraction forced every named actor into a person slot, but real
business correspondence routinely names an organization acting in its
own name ("당사," "SEWA," "Siemens," "GECO"), not an individual.

- RoleResponsibility.actor_name (renamed from person_name) gains
  actor_type_code (prov_person/prov_organization, W3C PROV-O grounded:
  Lebo, Sahoo, & McGuinness, 2013) and an LLM-inferred
  affiliated_organization_name for person actors -- a bare name
  without an employer is hard to place.
- Ontology: :RoleActorPerson rdfs:subClassOf prov:Person,
  :RoleActorOrganization rdfs:subClassOf prov:Organization -- genuine
  subclasses of the real external PROV-O classes, distinct from the
  ontology's existing :Person (a cataloged Keyman with a stable
  person_id; an R&R actor is a free-text name with no cataloged
  identity).
- migrations/0012_role_responsibility_agent_type.sql renames the
  column via RENAME COLUMN (preserves existing rows), not a
  drop/recreate.
- Popup R&R list shows a Person/Organization badge and the inferred
  affiliation; only a person actor still links to the Keyman panel.
- Also fixes a real deployment gap found via browser E2E testing:
  migrations 0005-0011 had accumulated on main without ever being
  applied to the long-running demo Postgres volume, surfacing as
  CORS-looking failures (missing-table 500s lose their CORS header)
  on Evaluate, Reports, Summary, and Chat.

ADR 0006.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@seonghobae
seonghobae enabled auto-merge (squash) August 14, 2026 01:41
@coderabbitai

coderabbitai Bot commented Aug 14, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

<hidden_range_assignment>
<range_id>range_5f93e8a6a7f8</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>actor-model</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_92d2c52aae4c</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>actor-model</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_0f1274bd1162</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>actor-model</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_56393412e8af</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>actor-model</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_97b7588348c1</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>actor-model</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_0e790d12ce70</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>actor-model</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_69918025ead2</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>actor-model</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_474b195d0152</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>actor-model</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_6e454f39ce25</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>actor-model</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_9409ec8bd628</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>prov-o-runtime</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_dca1261d9709</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>actor-model</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_72639eca2bcc</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>actor-model</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_58db3af7f839</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>prov-o-runtime</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_42561bd523e8</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>organization-resolution</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_39c26d25bc24</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>organization-resolution</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_faf4229c6aeb</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>validation-and-frontend</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_6651bd0ed9a2</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>validation-and-frontend</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_ca397baced1b</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>actor-model</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_3f0d1bfea4c8</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>actor-model</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_f11bd227c47c</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>actor-model</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_60e4dab88f85</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>actor-model</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_5e3fd07aad2e</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>actor-model</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_a6112fe2fabf</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>actor-model</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_5308e220dc2c</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>actor-model</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_3d803ebc1160</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>actor-model</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_3cf67235574c</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>analysis-run-registry</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_1859bd79f67b</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>actor-model</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_bb70ab7a1a43</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>actor-model</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_a5c37f9abc28</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>analysis-run-registry</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_091bcd0a00a6</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>analysis-run-registry</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_8c3573b9282a</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>analysis-run-registry</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_b692806900d9</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>analysis-run-registry</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_a1421220e332</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>analysis-run-registry</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_d66e72876bfe</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>analysis-run-registry</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_0dd02dbefd1f</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>analysis-run-registry</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_93a44a46e8d2</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>actor-model</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_0a667781c6de</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>actor-model</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_13570485dee9</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>actor-model</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_cc6692faff58</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>actor-model</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_f23cd8c9a090</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>actor-model</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_c516d7b27ed2</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>actor-model</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_3b4f5170bc67</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>actor-model</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_a8a657b31480</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>actor-model</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_6da1bcda82c9</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>organization-resolution</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_4a44bad0397d</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>organization-resolution</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_a7ffd67c8b7d</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>organization-resolution</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_9633f6afefb1</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>organization-resolution</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_4551a7f2f0ef</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>organization-resolution</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_b42698045405</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>organization-resolution</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_39ed1efe6488</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>organization-resolution</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_89c706581475</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>analysis-run-registry</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_0ff37a7dc7f7</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>analysis-run-registry</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_9de82ebb64b4</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>actor-model</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_3ae7b15e5b14</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>validation-and-frontend</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_da21b19901fe</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>validation-and-frontend</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_8e6db8381dbd</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>actor-model</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_a9bb39160a8e</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>validation-and-frontend</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_d2189a2224df</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>validation-and-frontend</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_8cdb6fb0cfe2</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>validation-and-frontend</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_b981bc14b01d</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>validation-and-frontend</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_b7e26982c20a</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>validation-and-frontend</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_44c15dfa8ba8</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>validation-and-frontend</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_f58ca6013ba5</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>validation-and-frontend</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_c705c3d483cd</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>validation-and-frontend</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_e266e97ef1ad</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>validation-and-frontend</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_7536b0be5cb0</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>validation-and-frontend</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_d37411268668</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>validation-and-frontend</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_776009437c6a</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>validation-and-frontend</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_fe1920dd0087</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>actor-model</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_f388cc80bc30</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>organization-resolution</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_e7e329ba0b04</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>organization-resolution</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_ffc4e6f58ac5</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>organization-resolution</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_f5b325b0c335</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>organization-resolution</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_c4730864daa7</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>organization-resolution</layer_id>
</hidden_range_assignment>
<hidden_range_assignment>
<range_id>range_822d141cee48</range_id>
<cohort_id>actor-provenance-analysis</cohort_id>
<layer_id>organization-resolution</layer_id>
</hidden_range_assignment>

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 57.52% which is insufficient. The required threshold is 80.00%. 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 PROV-O 계보, 접근성 라벨, 분석 실행 증거라는 주요 변경 사항을 명확하고 간결하게 요약합니다.
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.
✨ 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/role-responsibility-agent-ontology

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.

Comment thread lineageweave/post_summary.py Fixed
Drop real-organization names from docs, prompts, and comments. Seed a
synthetic organization actor so the Person/Organization badge is visible
without a live LLM, and reject unknown actor_type_code values.
PersonMention now carries an optional job_title extracted by the LLM
from role phrasing (e.g. "our legal counsel, Sam Okonkwo"), not just
named affiliations. cataloged_person.last_known_job_title persists it,
and _upsert_person treats a conflicting stated title as evidence that a
same-name match is a different real person rather than a re-mention,
so two "Kim Cheolsu"s with different titles get distinct person rows.
Keyman panel renders the title next to the person and per-affiliation
role_title, which existed in the schema but was never surfaced before.

Migration 0013 adds the column additively; 0001_initial_schema.sql
bakes it in for fresh installs, matching this repo's existing pattern.
After make seed, Ada West / Priya Nair / Jordan Hale carry last_known_job_title
so the new title chip is visible without a live extraction.
@seonghobae seonghobae changed the title feat: R&R's named actor is a PROV-O Agent, not always a person feat: R&R actor types + Keyman job titles (v0.69.0) Aug 14, 2026
Strix flagged the local-dev password literal in seed_demo_data.py after
this branch started editing that file. make seed still injects the
compose default; a direct script run requires KEYCLOAK_ADMIN_PASSWORD.
…70.0)

Real post text named a company sub-unit ("설계팀"/design team) that
neither ADR 0006's prov_person nor prov_organization fits -- it's part
of a company, not a person and not the company itself. actor_type_code
gains prov_team, grounded in the W3C Organization Ontology's
org:OrganizationalUnit (Reynolds, 2014), a different W3C vocabulary
from PROV-O that exists specifically for this meso-level case.

A team actor requires affiliated_organization_name in the same way a
person actor does -- unlike an organization actor, a team's own name
never answers "which company." Fixed a real bug the new type surfaced:
the R&R badge's label text was a binary Person/Organization ternary
that would have mislabeled a team as "Organization" (the CSS class
name was already generic; the display text was not).

Migration 0014 is purely additive (one lookup row insert), no schema
change -- actor_type_code already stores an arbitrary FK'd code.
Real post text names organizations by abbreviation ("한수원" for
"한국수력원자력") that corporate_hierarchy_resolution's character-
similarity matching cannot bridge -- an initialism shares almost no
substring with its expansion, so no similarity threshold recovers it.

New lineageweave/organization_name_resolution.py: an LLM proposes the
full name from context (or declines with UNKNOWN), then the *existing*
relation_verification Searxng client cross-verifies the specific raw/
resolved pairing -- no second web-search integration built, reusing
what this repo already has for a structurally identical problem. Only
a search-corroborated resolution is ever substituted in for
resolve_corporate_entity; an unresolved or unverified name still flows
through unchanged, same never-trust-an-unverified-guess discipline as
every other channel here.

Cached in a new organization_name_resolution table
(migrations/0015), keyed by the raw name so the same abbreviation
across many posts is resolved once, not re-queried every mention.
Grounded in SKOS skos:altLabel/skos:prefLabel (Miles & Bechhofer, 2009).

Wired into backend/app/keyman_ingestion.py's affiliation loop and the
private real-data batch script's paced re-implementation of it -- which
was also found missing role_title persistence entirely (a stale copy
predating that feature), fixed alongside this.

Known, documented gap (ADR 0008): the same request's entity-
relationship classification step still uses the raw, unresolved
organization names -- not fixed here, tracked honestly instead of
silently shipped as if both sides already agreed.
…atch (v0.72.0)

_parse_description required a single regex to match TEXT/CAPTION/TAGS
in that exact order in one pass. Reproduced live against real embedded
images from the Milestone 2 batch: real vision responses with the
content right but the formatting only mostly right (bolded labels,
reordered labels, a missing TAGS line) were rejected wholesale,
producing the same "[image: content unavailable]" placeholder as a
genuinely unconfigured vision channel -- discarding real,
already-paid-for content, not a "genuinely could not get it" case.

Each label is now parsed independently by scanning lines for a
TEXT:/CAPTION:/TAGS: prefix (tolerant of markdown emphasis and any
order); only a response with neither TEXT nor CAPTION content raises
ImageDescriptionParseError. Multi-line TEXT (real multi-line OCR
output) is still preserved with real newlines, not flattened.
…ity-agent-ontology

# Conflicts:
#	CHANGELOG.md
#	frontend/package.json
#	lineageweave/__init__.py
#	pyproject.toml
…v0.74.0)

Extraction runs per-post; a team or organization's identity did not
survive across posts the way a Keyman's already did via
cataloged_person -- "설계팀" named in ten posts was ten unrelated
strings, not one entity the KG could link through. Extraction results
must themselves become cross-post lineage clues, not just per-post
artifacts.

New cataloged_team catalog (migrations/0016), identity key (team_name,
affiliated_organization_name) since a bare team name is not by itself
identifying ("설계팀" exists at many real companies) -- reuses the same
resolve_corporate_entity matching Keyman affiliations already use for
the team's parent org, not a second algorithm. An organization actor
resolves against the existing corporate_entity catalog directly, no
new table needed.

knowledge_graph_edges_for_post gains three new edge kinds
(edge_mention_team, edge_team_affiliation, edge_mention_organization)
as distinct object properties, not widened domain/range on the
existing :mentions (which would let RDFS entail every :mentions
subject is both a person and a team). persist_post_summary now
resolves each R&R actor's identity and calls the same
persist_edges_for_post Keyman ingestion already uses -- one function
computes a post's whole edge set regardless of trigger.

A person R&R actor is opportunistically joined to an existing
cataloged_person row by name, never originated by R&R itself --
documented as a real, deliberate gap in ADR 0009 (cataloged_person
needs person_side_code, which R&R's prompt does not currently ask
for), not silently half-done.
@seonghobae
seonghobae marked this pull request as draft August 14, 2026 04:29
auto-merge was automatically disabled August 14, 2026 04:29

Pull request was converted to draft

…y (v0.75.0)

corporate_hierarchy_resolution's similarity matching only ever finds an
ALREADY-cataloged corporate_entity -- it has no path to create one.
Real Milestone 2 data confirmed the actual consequence: 0 of 4,154
person_affiliation rows and 0 of 9,852 R&R organization-actor mentions
ever resolved, because corporate_entity for the real dataset only holds
the employer's own 2-row hierarchy. The standing "통합 고객사 계열
tree AI" requirement (Samsung -> Samsung Electronics Korea -> ...) was
never actually populated for real extraction.

New lineageweave/corporate_hierarchy_inference.py: an LLM proposes a
Group/Company/Plant placement (level + parent name) from the post's
own text, or declines with UNKNOWN. New
backend/app/corporate_entity_ingestion.py's get_or_create_corporate_entity
tries similarity matching first (unchanged), then only creates a real
new row once the proposal is corroborated by the *existing*
relation_verification Searxng client -- no new search integration,
reusing the same reused-verification-client pattern ADR 0008 already
established. Recurses up a bounded (4-level) parent chain so the whole
hierarchy gets real parent_entity_id links, not an orphaned row.

Auto-created corporate_entity_code values are AUTO-<hash>-prefixed --
that column doubles as the real login corp-code Keycloak claim, so an
auto-created counterparty must never collide with that namespace.

Wired into both existing organization-resolution call sites
(keyman_ingestion.py's affiliation loop, post_summary_ingestion.py's
R&R organization-actor loop) rather than a third path, so both routes
to corporate_entity share one creation policy. Found and fixed a
pre-existing gap in backend/tests/test_api.py's seeded_db fixture along
the way: it never seeded the 'plant' corporate_entity_level lookup row.
Comment thread .github/workflows/prov-o-bootstrap.yml Fixed
Comment thread .github/workflows/prov-o-bootstrap.yml Fixed
cursor Bot pushed a commit that referenced this pull request Aug 16, 2026
#74 already contains ADR 0021 / v0.88.0. Keep that start path and
follow with a purge-aware 0023 so a granted empty still works after
edges exist.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>

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

Review of 1cf0bd7 only (parent 69c035b)

Authorized start (ADR 0021 / v0.88.0) now lives on this PR. Open a Pending Demo Corp lineage row, then Start reconstruction. The designed A-100 fork (revised quote and delivery question under the pricing follow-up) is the acceptance tree. TEPP and period-report stay 422. This path does not invent a theta.

This commit closes the five start defects from #142 / #167

  1. FOR UPDATE of the run row happens before Running. UniqueViolation is 409, not 500. The HTTP handler wraps the write in one transaction, so a crash after Running rolls back to Pending.
  2. Create freezes analysis_source_snapshot_member. Start prefers that bag over a later cutoff re-query.
  3. Detail renders the Result digest prefix next to Code and Config; hover reads the parent-choice hash.
  4. fetch_reconstructed_edges applies the same public-or-affiliated title rule as cutoff posts.
  5. CI A-100 goes through records_from_source_posts, not only library sample_records(). The live API test (self-skip without Keycloak) recovers the revised-quote / delivery-question fork.

Prefer this head over #142, #152, and #167 for in-process start. Do not open another start-reconstruction PR unless 1cf0bd7 regresses.

Residuals (not merge blockers for this slice)

  • The live start test inserts fixture posts before create, so a post-create backfill with created_at <= cutoff is not proven excluded. Implementation still prefers member rows when the table has them.
  • analysis_run_lineage_edge.reconstructed_at repeats the parent reconstruction clock (3NF residual).
  • Failed lineage still has no Start button; retry remains a new Request (new snapshot), which matches ADR 0021's Pending-only start.
  • Home-list AccName, person-catalog LIMIT 1, live write-clock, and default-home fixture stay on their existing landings (#188, #179, #176, #186). Those successors must not reuse 0.88.0 / ADR 0021 now that this head occupies both. #186 is already 0.88.1.

Do not

  • Treat this COMMENT as independent approval of the 120-commit PR.
  • Merge #74 from this review.
  • Self-approve.
  • Invent a theta.
  • Merge #142 / #152 / #167 in parallel.
Open in Web View Automation 

Sent by Cursor Automation: Fix Issues

Comment thread backend/app/analysis_run_start.py Outdated
#193)

Analysis-run detail marks in-cutoff titles rewritten after the run.
Demo public post is the edited counter-example; Demo private post still
matches the January cutoff. Bodies stay live.
…194)

Opening a marked analysis-run title still shows the live post. The
popup now says to compare it with this run instead of inventing a
cutoff snapshot.
….0) (#195)

* feat: open reconstructed analysis-run edges as live posts (v0.91.0)

After start, the titled A-100 parent and child are buttons. A marked
child still shows the live-body warning. The popup does not invent a
cutoff snapshot.

* feat: start pending TEPP measurement through tepp_client (v0.92.0)

POST /api/analysis-runs/{id}/start submits AnalysisRunRequest via
tepp_client. A missing or refused transport stays Failed. An accepted
envelope is not persistable yet. Period-report remains 422. No theta
is invented.
Comment thread backend/app/analysis_run_ingestion.py Fixed
Comment thread backend/app/analysis_run_ingestion.py Fixed
Comment thread backend/app/analysis_run_ingestion.py Fixed
Comment thread backend/app/analysis_run_ingestion.py Fixed
Comment thread backend/app/analysis_run_ingestion.py Fixed
Comment thread backend/app/analysis_run_ingestion.py Fixed
…4.0) (#196)

* feat: seed the designed A-100 fork on the Demo Corp lineage run (v0.93.0)

make seed already stamped Succeeded. The home detail now persists
ThreadWeave's parent choices so open-after-seed shows the revised
quote and delivery question. No TEPP theta is invented.

* feat: persist start work on a durable outbox (v0.94.0)

Start commits Running plus one outbox row, wakes Valkey, then
delivers ThreadWeave or tepp_client. A crash no longer loses the
work item. No TEPP theta is invented.
import hashlib
import json
from datetime import datetime, timezone
from typing import Any
…0.96.0) (#197)

* feat: show labeled outbox delivery on analysis-run detail (v0.95.0)

Open the seeded Demo Corp lineage run to see Claimed then Delivered.
Stream entry ids stay off the payload. No TEPP theta is invented.

* feat: seed the Demo Corp period report on the analysis-run registry (v0.96.0)

After make seed, open Period report · Succeeded · Demo Corp to confirm
the cutoff posts. Mean θ stays on the period-report panel. Start stays
422. No TEPP theta is invented.
#198)

* feat: open the scored week from a period-report analysis run (v0.97.0)

After make seed, open Period report · Succeeded · Demo Corp and click
Open period report 2026-W02. Mean θ stays on the report panel. No TEPP
theta is invented.

* fix(ui): focus the opened week and keep failed report rows closed

Open period report 2026-W02 now focuses the report period field.
Failed rows stay without the button. Seed still writes scope_key
2026-W02 and never a theta.
* feat: open the corp grouping with the scored week (v0.98.0)

Open period report 2026-W02 from a corporate-entity analysis run also
switches Report grouping to Corporate entity. Mean θ stays on the
report panel. No TEPP theta is invented.

* fix(ui): name the opened Demo Corp grouping

Open period report 2026-W02 now marks Demo Corp current and shows
that label instead of a UUID. The persisted scope grouping key is
the corporate entity, never the week or a theta.
….98.1) (#200)

List and detail queries no longer format a WHERE fragment. The $1 / $2
/ $3 binds are unchanged. Semgrep no longer treats the predicate as
user-concatenated SQL.
…#201)

When the operator is already on 2026-W02, Open period report focuses
the Demo Corp comparison chip instead of the unchanged period field.
)

After Open period report lands on Demo Corp, the panel says to read
its mean θ and member posts. The focused chip uses the visible
Corporate entity caption plus the persisted mean θ.
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.

3 participants