Skip to content

feat(lineage): require TEPP criterion anchor for channel weights - #606

Merged
seonghobae merged 10 commits into
mainfrom
feat/tepp-lineage-anchor-consumer
Aug 25, 2026
Merged

feat(lineage): require TEPP criterion anchor for channel weights#606
seonghobae merged 10 commits into
mainfrom
feat/tepp-lineage-anchor-consumer

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Outcome

Removes unanchored_internal_structure from the production activation path. A fast-mlsirm channel vector now activates only when the database contains an exact accepted TEPP tepp.lineage_criterion_anchor.v1 result bound to the same estimation run, source snapshot, knowledge cutoff, and pair count. Any mismatch disables the whole vector.

The LineageWeave request now asks for TEPP model contract tepp-lineage-criterion-v1 and output profile lineage_pair_criterion_anchor; it accepts no consumer-private nested validity flag.

Stack dependency

Verification

  • uv run --extra dev --extra backend pytest -q tests/test_analysis_run_start.py tests/test_lineage_ingestion.py tests/test_migration_replay.py (59 passed)
  • full repository suite before the final contract tightening: 1,115 passed, 141 skipped

Integrity boundary

No local theta, acceptance threshold, repaired provenance, arbitrary weight, keyword rule, or RankWeave substitute is introduced.


Open in Devin Review

@coderabbitai

coderabbitai Bot commented Aug 25, 2026

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 52 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: 847058b0-efbb-46b1-a6a6-bfed0107ecbd

📥 Commits

Reviewing files that changed from the base of the PR and between 3d6d718 and f8ad49d.

📒 Files selected for processing (42)
  • backend/app/analysis_run_start.py
  • backend/app/global_ask_queue.py
  • backend/app/lineage_ingestion.py
  • backend/app/main.py
  • backend/app/operations_case_ingestion.py
  • backend/app/operations_dashboard.py
  • backend/app/post_content_worker.py
  • docs/adr/0145-psychometric-channel-weight-estimation.md
  • docs/adr/0200-channel-weight-reconciliation.md
  • docs/adr/0205-tepp-lineage-anchor.md
  • docs/adr/0206-evidence-operations-dashboard.md
  • docs/adr/README.md
  • docs/storybook-inventory.md
  • frontend/src/App.css
  • frontend/src/App.test.tsx
  • frontend/src/App.tsx
  • frontend/src/api.ts
  • frontend/src/components/OperationsDashboard.stories.tsx
  • frontend/src/components/OperationsDashboard.test.tsx
  • frontend/src/components/OperationsDashboard.tsx
  • frontend/src/components/SimilarVocPanel.css
  • frontend/src/components/SimilarVocPanel.stories.tsx
  • frontend/src/components/SimilarVocPanel.test.tsx
  • frontend/src/components/SimilarVocPanel.tsx
  • frontend/src/components/WorkspaceNav.test.tsx
  • frontend/src/gnbChrome.ts
  • frontend/src/i18n.test.ts
  • frontend/src/styles/tokens.css
  • lineageweave/ask_delivery.py
  • lineageweave/operations_case_analysis.py
  • lineageweave/similar_voc.py
  • migrations/0207_lineage_weight_tepp_anchor.sql
  • migrations/0208_operations_case_analysis.sql
  • migrations/rollback/0207_lineage_weight_tepp_anchor.sql
  • tests/test_analysis_run_start.py
  • tests/test_ask_delivery.py
  • tests/test_lineage_ingestion.py
  • tests/test_operations_case_analysis.py
  • tests/test_operations_case_ingestion.py
  • tests/test_operations_dashboard.py
  • tests/test_post_content_worker.py
  • tests/test_similar_voc.py

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.

…hor-consumer

# Conflicts:
#	backend/app/analysis_run_start.py
devin-ai-integration[bot]

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor Author

Queue retry 2026-08-25T17:06 KST (Grok Build cycle).

Write-path probe: independent APPROVE is still missing on this exact head f2da8d3e959ee2cebf848193a9122ab12564209f. No self-approve. No squash-merge until an independent reviewer APPROVEs this SHA and required checks succeed.

Stale v0.71 queue items (#74/#89/#91/#92/#96 leftover-pair local patch) are superseded by current main@4f53190 and this TEPP criterion-anchor consumer. Issue #96 is already gone; #79/#87 remain open and incomplete.

@seonghobae
seonghobae enabled auto-merge August 25, 2026 08:10
devin-ai-integration[bot]

This comment was marked as resolved.

@seonghobae

Copy link
Copy Markdown
Contributor Author

Exact consumer alignment in f40ecef: after TEPP PR #237 made the published UUID representation canonical, this boundary now rejects compact/non-canonical estimation-run IDs instead of normalizing them silently. tests/test_analysis_run_start.py passes (26 tests); the combined TEPP/ingestion/seed slice passed 59 tests on the previous exact head. Upstream contract PR: ContextualWisdomLab/TEPP#237.

seonghobae and others added 2 commits August 25, 2026 17:22
…ions-dashboard

feat(dashboard): add evidence-grounded operations workspace

Copy link
Copy Markdown
Contributor Author

Cycle note (2026-08-25): this head still has no independent exact-head APPROVE. Devin COMMENTED only; seonghobae COMMENTED only. Merge stays blocked. Do not self-approve. Do not squash-merge until an independent reviewer APPROVEs this exact head (f40ecef49ff26a0d6743948a63efb004e7825543) and required checks succeed.

Naruon calendar Buyer wiring (ADR 0203 step 2 / #336) is being implemented on a separate branch (feat/naruon-calendar-buyer-wiring-v2170) and will not mix into this stack.

devin-ai-integration[bot]

This comment was marked as resolved.

github-code-quality[bot]

This comment was marked as resolved.

@opencode-agent
opencode-agent Bot disabled auto-merge August 25, 2026 08:39
# Conflicts:
#	backend/app/lineage_ingestion.py
#	backend/app/main.py
#	docs/product-technical-gap-baseline.md
#	frontend/src/App.tsx
@seonghobae

Copy link
Copy Markdown
Contributor Author

Exact-head repair f8ad49d composes current protected main, preserves the TEPP fail-closed boundary, routes shared ?post= links to the board before Dashboard rendering, and replaces the static-analysis placeholder expressions. Verified 68 focused backend/docstring tests, 9 Workspace navigation tests, frontend lint, and production build.

@seonghobae
seonghobae enabled auto-merge (squash) August 25, 2026 09:03
@seonghobae
seonghobae merged commit 3f47348 into main Aug 25, 2026
19 of 22 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 3 new potential issues.

Open in Devin Review

Comment on lines +86 to +103
for item in payload:
if not isinstance(item, dict) or item.get("case_kind_code") not in CASE_KINDS:
return None
summary = item.get("summary_text")
evidence = item.get("evidence_text")
facts = item.get("facts")
if not isinstance(summary, str) or not summary.strip() or not isinstance(evidence, str) or evidence not in source_body or not isinstance(facts, list):
return None
parsed_facts: list[OperationsCaseFact] = []
for fact in facts:
if not isinstance(fact, dict) or fact.get("fact_type_code") not in FACT_TYPES:
return None
value = fact.get("value_text")
fact_evidence = fact.get("evidence_text")
if not isinstance(value, str) or not value.strip() or not isinstance(fact_evidence, str) or fact_evidence not in source_body:
return None
parsed_facts.append(OperationsCaseFact(fact["fact_type_code"], value.strip(), fact_evidence))
cases.append(OperationsCase(item["case_kind_code"], summary.strip(), evidence, tuple(parsed_facts)))

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: Repeated case kind can fail persistence

parse_operations_case_response does not deduplicate case_kind_code across returned cases, but operations_case_classification keys on (post_id, case_kind_code). If the orchestrator returns two cases of the same kind, persist_operations_cases hits a unique violation and the content job fails and retries. Consider rejecting or collapsing duplicate kinds during parse.

Open in Devin Review

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

Comment on lines +127 to +135
case_complete = not require_structure or bool(
await conn.fetchval(
"select exists (select 1 from operations_case_analysis "
"where post_id = $1 and source_body_sha256 = $2)",
post_id,
source_body_digest,
)
)
if content_complete and case_complete:

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: Existing succeeded jobs reprocessed on rollout

_claim_job now reclaims a SUCCEEDED job when require_structure is true and no operations_case_analysis row matches the digest. Every job that succeeded before this deploy (orchestrator configured) will be reclaimed and fully reprocessed, re-running persist_post_content and the orchestrator case analysis. It converges since an empty result still writes the parent row, but it is a corpus-wide one-time reprocessing and provider-call cost.

Open in Devin Review

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

Comment on lines +44 to +46
return f"""
({alias}.visibility_code = 'public'
or {alias}.corporate_entity_id::text = any($1::text[]))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟥 Dashboard skips process-unit ABAC narrowing

The dashboard's visibility predicate _visible_period_sql admits any private post whose owning entity the account is affiliated with (corporate_entity_id::text = any($1::text[])) and never narrows by process unit; the handler passes only account.corporate_entity_ids and drops process_unit_ids. The canonical rule at main.py restricts a process-unit-limited account to its authorized units. Such a user then receives case summaries, verbatim evidence spans, and counts for private posts in units they cannot access.

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