feat(project-graph): activate semantic extraction on import + LLM-grounded extractor (Phases 1–2, folds #927) - #931
Conversation
…agged) Wires the existing-but-dead project semantic graph pipeline into the import path: after an imported email commits, its content segments are projected into project_graph_objects via extract_project_semantics + persist_project_graph_ projection. This makes the projects /candidates surface return real data instead of an empty store. Safety: - Gated behind PROJECT_GRAPH_EXTRACTION_ENABLED (default False) -> zero change to existing import behavior until explicitly enabled. - Best-effort: runs AFTER the email is committed, wrapped in try/except with rollback, so a projection failure never fails the email import. - Segments are snapshotted before commit (in-memory, no async lazy-load) to avoid MissingGreenlet; persistence runs after commit when segments have ids. - Workspace scope uses the repository's convention (workspace-<org_id>, or workspace-<user_id> without an org). Tests (tests/test_project_graph_import_wiring.py, 6): real deterministic extractor + mocked persistence — mapping, workspace scoping (org + user fallback), no-op on empty/no-objects, and best-effort rollback on failure. Existing import + project-graph suites unaffected (56 passed). This is Phase 1 of docs/plans/2026-07-06-ai-moat-project-graph-activation.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017RkKdtHRLG4wSLh6PVsp8J
…ations Phase 2 of the project-graph activation plan (stacked on the Phase 1 import wiring): upgrades extraction from the deterministic keyword baseline to an LLM-backed extractor that cannot fabricate. - services/project_graph/llm_extractor.py: structured-output extraction over the imported email's content segments. Hard grounding rule: every object must cite content_segment_uids present in the input; objects with unknown, missing, or partial-unknown citations are DROPPED. Unknown object types dropped; confidence clamped to [0,1]; segment text passed as JSON data (prompt-injection hardening, mirrors api/llm.py); base_url goes through the SSRF-validated provider client; segments capped (40 x 2000 chars) to bound tokens. - Selection: PROJECT_GRAPH_EXTRACTOR=keyword|llm (default keyword -> zero behavior change). The llm path reuses the import's OpenAI-compatible provider credentials and falls back to the keyword extractor on any failure, so the projection is never lost to a provider outage. Tests (7): grounded mapping + evidence edges; hallucinated/empty citations dropped; unknown type dropped + confidence clamped; empty segments short- circuit without an LLM call; selection uses llm when configured, falls back to keyword on llm failure, defaults to keyword. Regressions green (18). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017RkKdtHRLG4wSLh6PVsp8J
|
PR governance metadata gate is not ready for
|
OpenCode Review Overview
Pull request overviewOpenCode reviewed the current-head bounded evidence and found no blocking issues. FindingsNo blocking findings. SummaryApproval sufficiency: bounded evidence supplied affirmative approval evidence for changed files, coverage/docstring posture, risk surfaces, and current-head verification; approval is not based merely on the absence of known blockers.
Changed-File Evidence Mapflowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Backend (5 files)"]
S1 --> I1["API and service runtime"]
I1 --> R1["Review risk: Backend (5 files)"]
R1 --> V1["backend tests"]
|
There was a problem hiding this comment.
Pull request overview
OpenCode reviewed the current-head bounded evidence and found no blocking issues.
Findings
No blocking findings.
Summary
Approval sufficiency: bounded evidence supplied affirmative approval evidence for changed files, coverage/docstring posture, risk surfaces, and current-head verification; approval is not based merely on the absence of known blockers.
Verification posture: CodeGraph evidence was initialized and bounded current-head evidence reviewed for changed-file evidence including backend/core/config.py, backend/core/env_paths.py, backend/scripts/private_mail_http_smoke.py, backend/scripts/start_backend.py, backend/services/email_import_service.py, and 5 more.
Linter/static: workflow/static review evidence is bounded by the current-head GitHub Checks gate and changed-file evidence.
TDD/regression: coverage execution evidence and focused changed hunks were reviewed from bounded-review-evidence.md.
Coverage: coverage execution evidence reports supported repository test suites passed.
Docstring coverage: coverage execution evidence reports configured repository docstring gates passed or docstring coverage was advisory.
DAG: CodeGraph/source-backed behavior map connects backend/core/config.py to the affected review, runtime, or workflow path and required checks.
PoC/execution: coverage-evidence job executed on the current head and reported PASS.
DDD/domain: workflow and repository-governance invariants were reviewed against changed files in bounded evidence.
CDD/context: CodeGraph evidence, changed-file history, and focused hunks were reviewed from bounded-review-evidence.md.
Similar issues: changed-file history evidence was reviewed for comparable local precedents.
Claim/concept check: bounded evidence, repository source, current-head workflow evidence, and, where numeric, scientific, statistical, or literature-backed claims are affected, original-paper/formula evidence and parameter-recovery expectations were used for claims.
Standards search: standards and external-source checks are delegated to configured OpenCode web_search/Context7/DeepWiki sources when applicable; no evidence-backed standards blocker is present in bounded evidence.
Compatibility/convention: changed workflow/script conventions, object naming, and reserved-word safety for schema/API/config/code surfaces were checked in bounded evidence.
Breaking-change/backcompat: deployment evidence and changed-file history were checked for backward-compatibility risk.
Performance: changed surfaces were checked for performance risk in bounded evidence.
Developer experience: changed automation, review, test, setup, and maintenance surfaces were checked for helpful or obstructive DX impact in bounded evidence.
User experience: connected user, operator, API, CLI, documentation, review-comment, status-check, rendering, and workflow-reader behavior was checked for contradictions against code, docs, and tests in bounded evidence.
Visual/DOM: Playwright visual, DOM locator, ARIA snapshot, console, and responsive evidence were checked when a web UI surface was present; for non-web surfaces, API/CLI/log/docs/workflow interaction evidence was reviewed instead.
Accessibility/i18n: accessibility, localization, and human-readable text surfaces were checked where UI, CLI, API message, docs, logs, or review text changed.
Supply-chain/license: dependency, package, model, container, and external-tool changes were checked in bounded evidence.
Packaging: package, build, test, lint, and security contracts were checked in bounded evidence.
Security/privacy: workflow-token, review-gate, and repository-automation security/privacy boundaries were checked in bounded evidence.
- Result: APPROVE
- Reason: All checks passed, no unresolved threads, and implementation completeness verified.
- Head SHA:
29c3ca09ee50eadb28b40ec477c374b13de7cbda - Workflow run: 29150489511
- Workflow attempt: 1
Changed-File Evidence Map
flowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Backend (10 files)"]
S1 --> I1["API and service runtime"]
I1 --> R1["Review risk: Backend (10 files)"]
R1 --> V1["backend tests"]
|
Current-head verification for
Auto-merge has been enabled. Direct merge remains blocked by branch protection review policy ( |
There was a problem hiding this comment.
Pull request overview
OpenCode reviewed the current-head bounded evidence and found no blocking issues.
Findings
No blocking findings.
Summary
Approval sufficiency: bounded evidence supplied affirmative approval evidence for changed files, coverage/docstring posture, risk surfaces, and current-head verification; approval is not based merely on the absence of known blockers.
Verification posture: CodeGraph evidence was initialized and bounded current-head evidence reviewed for changed-file evidence including backend/core/config.py, backend/services/email_import_service.py, backend/services/project_graph/llm_extractor.py, backend/tests/test_project_graph_import_wiring.py, backend/tests/test_project_graph_llm_extractor.py.
Linter/static: workflow/static review evidence is bounded by the current-head GitHub Checks gate and changed-file evidence.
TDD/regression: coverage execution evidence and focused changed hunks were reviewed from bounded-review-evidence.md.
Coverage: coverage execution evidence reports supported repository test suites passed.
Docstring coverage: coverage execution evidence reports configured repository docstring gates passed or docstring coverage was advisory.
DAG: CodeGraph/source-backed behavior map connects backend/core/config.py to the affected review, runtime, or workflow path and required checks.
PoC/execution: coverage-evidence job executed on the current head and reported PASS.
DDD/domain: workflow and repository-governance invariants were reviewed against changed files in bounded evidence.
CDD/context: CodeGraph evidence, changed-file history, and focused hunks were reviewed from bounded-review-evidence.md.
Similar issues: changed-file history evidence was reviewed for comparable local precedents.
Claim/concept check: bounded evidence, repository source, current-head workflow evidence, and, where numeric, scientific, statistical, or literature-backed claims are affected, original-paper/formula evidence and parameter-recovery expectations were used for claims.
Standards search: standards and external-source checks are delegated to configured OpenCode web_search/Context7/DeepWiki sources when applicable; no evidence-backed standards blocker is present in bounded evidence.
Compatibility/convention: changed workflow/script conventions, object naming, and reserved-word safety for schema/API/config/code surfaces were checked in bounded evidence.
Breaking-change/backcompat: deployment evidence and changed-file history were checked for backward-compatibility risk.
Performance: changed surfaces were checked for performance risk in bounded evidence.
Developer experience: changed automation, review, test, setup, and maintenance surfaces were checked for helpful or obstructive DX impact in bounded evidence.
User experience: connected user, operator, API, CLI, documentation, review-comment, status-check, rendering, and workflow-reader behavior was checked for contradictions against code, docs, and tests in bounded evidence.
Visual/DOM: Playwright visual, DOM locator, ARIA snapshot, console, and responsive evidence were checked when a web UI surface was present; for non-web surfaces, API/CLI/log/docs/workflow interaction evidence was reviewed instead.
Accessibility/i18n: accessibility, localization, and human-readable text surfaces were checked where UI, CLI, API message, docs, logs, or review text changed.
Supply-chain/license: dependency, package, model, container, and external-tool changes were checked in bounded evidence.
Packaging: package, build, test, lint, and security contracts were checked in bounded evidence.
Security/privacy: workflow-token, review-gate, and repository-automation security/privacy boundaries were checked in bounded evidence.
- Result: APPROVE
- Reason: No blocking issues found; changes are well-tested and documented.
- Head SHA:
c050fa0672c49e5a3c91f2d6f5a8cfef1cb8353a - Workflow run: 29163313061
- Workflow attempt: 1
Changed-File Evidence Map
flowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Backend (5 files)"]
S1 --> I1["API and service runtime"]
I1 --> R1["Review risk: Backend (5 files)"]
R1 --> V1["backend tests"]
What (stacked on #927 — Phase 2 of #925)
Upgrades project-graph extraction from the deterministic keyword baseline to an LLM-grounded extractor that cannot fabricate:
content_segment_uids present in the input segments — objects with unknown/missing/partially-unknown citations are dropped. The model cannot introduce uncited domain claims into the graph.object_typedropped;confidenceclamped to [0,1]; titles bounded to the DB column limit.api/llm.py);base_urlgoes through the SSRF-validated provider client; request bounded to 40 segments × 2000 chars.PROJECT_GRAPH_EXTRACTOR=keyword|llm(defaultkeyword→ zero behavior change). Thellmpath reuses the import's OpenAI-compatible provider credentials and falls back to keyword on any failure — the projection is never lost to a provider outage.Verification (local — 7 new tests + 18 regressions green)
grounded mapping + evidence edges · hallucinated/empty citations dropped · unknown type dropped + confidence clamped · empty segments short-circuit (no LLM call) · selection: llm-when-configured / keyword-fallback-on-failure / keyword-default.
Follow-up (Phase 3, per #925)
Corrections → per-tenant eval set + calibrated confidence.
🤖 Generated with Claude Code