Skip to content

Consolidate duplicated dialect and chain helpers - #1361

Merged
stranske merged 5 commits into
mainfrom
codex/issue-1313-shared-helper-consolidation
Jul 1, 2026
Merged

stranske merged 5 commits into
mainfrom
codex/issue-1313-shared-helper-consolidation

Conversation

@stranske

@stranske stranske commented Jul 1, 2026

Copy link
Copy Markdown
Owner

Closes #1313

Summary

  • add shared DB dialect/table/usage helpers in adapters.base and replace local placeholder/table-column/api_usage copies
  • add shared chain JSON/cursor/context connection helpers and shared CIK normalization
  • add a regression gate that fails if local helper definitions reappear outside the shared modules

Validation

  • python -m pytest tests/test_shared_helper_consolidation.py tests/test_llm_cost_tracking.py tests/test_chain_dialect_portability.py tests/test_filing_summary_chain.py tests/test_holdings_analysis_chain.py tests/test_adapter_base.py -q
  • python -m ruff check ... focused touched files
  • black --fast --check --line-length 100 --exclude '(\\.workflows-lib|node_modules)' ... focused touched files\n- git diff --check

Summary by CodeRabbit

  • New Features

    • Improved support for both SQLite and Postgres across search, chat, and ETL workflows.
    • Added consistent CIK normalization for imported and seeded records.
  • Bug Fixes

    • Made database queries more resilient when expected tables or columns are missing.
    • Standardized SQL parameter handling to reduce database-specific issues.
    • Improved API usage logging and schema setup for more reliable tracking.
  • Tests

    • Added regression coverage to prevent duplicate shared helper definitions.

@stranske stranske added agent:codex Assign to Codex agent autofix Let bots format/lint automatically agents:keepalive Enable keepalive monitoring on PR labels Jul 1, 2026
Copilot AI review requested due to automatic review settings July 1, 2026 19:18
@stranske stranske added agent:codex Assign to Codex agent autofix Let bots format/lint automatically agents:keepalive Enable keepalive monitoring on PR labels Jul 1, 2026
@stranske
stranske temporarily deployed to agent-standard July 1, 2026 19:18 — with GitHub Actions Inactive
@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 1 minute

Your organization has reached its usage spending cap. Adjust your spending cap in the billing tab.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 07b2c71c-9fb7-4764-b493-9a9ae21ec91d

📥 Commits

Reviewing files that changed from the base of the PR and between 6d8db9d and 89db4de.

📒 Files selected for processing (16)
  • adapters/base.py
  • api/chat.py
  • api/managers.py
  • api/search.py
  • api/signals.py
  • chains/utils.py
  • etl/activism_detection.py
  • etl/activism_flow.py
  • etl/conviction_flow.py
  • etl/daily_diff_flow.py
  • etl/ingest_flow.py
  • scripts/resolve_aliases.py
  • tests/test_chain_utils.py
  • tests/test_identifiers.py
  • tests/test_shared_helper_consolidation.py
  • utils/identifiers.py
📝 Walkthrough

Walkthrough

This PR consolidates duplicated database-dialect helpers (SQLite/Postgres detection, placeholder selection, table/column introspection, api_usage schema DDL) and chain utility functions (JSON extraction, row conversion, context guarding, connection acquisition) plus CIK normalization into shared modules (adapters/base.py, chains/utils.py, utils/identifiers.py), then updates all call sites across api/, chains/, etl/, llm/, and scripts/ to use them, removing local duplicate implementations. A regression test enforces single definitions of consolidated helpers.

Changes

Shared helper consolidation

Layer / File(s) Summary
Shared DB dialect helpers
adapters/base.py
Adds is_sqlite, get_placeholder, table_exists, get_table_columns, ensure_api_usage_schema; updates Postgres api_usage DDL types and tracked_call wiring.
Shared chain utilities
chains/utils.py
Adds rows_to_dicts, extract_json_text, guard_context_values, acquire_connection with supporting imports.
Shared CIK normalization
utils/identifiers.py, api/managers.py, scripts/resolve_aliases.py, scripts/seed_universe.py
Adds normalize_cik and switches call sites off local _normalize_cik implementations.
API modules DB wiring
api/activism.py, api/chat.py, api/search.py, api/signals.py
Removes local sqlite/placeholder/table/column helpers, switches to adapters.base equivalents across query and feedback logic.
Chain modules wiring
chains/filing_summary.py, chains/holdings_analysis.py, chains/nl_query.py, chains/rag_search.py
Removes local placeholder/DDL/JSON/context/connection helpers, switches to adapters.base and chains.utils equivalents.
ETL flow wiring
etl/activism_detection.py, etl/activism_flow.py, etl/conviction_flow.py, etl/daily_diff_flow.py, etl/digest_flow.py, etl/edgar_flow.py, etl/evaluation_flow.py, etl/ingest_flow.py, etl/news_flow.py
Removes local dialect/placeholder/column helpers, switches to adapters.base equivalents across schema setup and parameterized queries.
LLM cost tracking and regression tests
llm/cost_tracking.py, tests/test_cost_script_dialect_portability.py, tests/test_shared_helper_consolidation.py
Switches to shared helpers, updates a case-insensitive DDL assertion, and adds an AST-based test asserting single definitions of consolidated helpers.

Estimated code review effort: 4 (Complex) | ~75 minutes

Possibly related PRs

  • stranske/Manager-Database#1319: Modifies the same etl/edgar_flow.py placeholder/schema helpers (_delete_holdings_for_filing, _latest_filed_date_for_cik) touched by this consolidation.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title concisely matches the PR’s main change: consolidating duplicated dialect and chain helpers.
Linked Issues check ✅ Passed The changes cover the shared DB, chain, and CIK helpers plus the regression gate requested by #1313.
Out of Scope Changes check ✅ Passed The diff stays focused on helper consolidation and related regression tests, with no unrelated feature work.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/issue-1313-shared-helper-consolidation

Comment @coderabbitai help to get the list of available commands.

@stranske stranske added the agent:retry Add to trigger agent retry after rate limit or pause label Jul 1, 2026
@stranske
stranske temporarily deployed to agent-standard July 1, 2026 19:19 — with GitHub Actions Inactive

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR consolidates previously duplicated DB dialect/table helpers and chain utility helpers into shared modules (adapters.base, chains.utils, and utils.identifiers), updates call sites to use the shared implementations, and adds a regression test intended to prevent helper duplication from reappearing.

Changes:

  • Added shared DB helpers (is_sqlite, get_placeholder, table_exists, get_table_columns, ensure_api_usage_schema) in adapters/base.py and replaced many local copies across ETL/API/LLM code.
  • Added shared chain helpers (rows_to_dicts, extract_json_text, guard_context_values, acquire_connection) in chains/utils.py and replaced local chain implementations.
  • Added normalize_cik in utils/identifiers.py and updated API/scripts to import it; introduced a regression test to detect redefinitions.

Reviewed changes

Copilot reviewed 25 out of 25 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
utils/identifiers.py Introduces shared CIK normalization helper.
tests/test_shared_helper_consolidation.py Adds regression test intended to prevent helper redefinitions.
scripts/seed_universe.py Switches to shared normalize_cik.
scripts/resolve_aliases.py Switches to shared normalize_cik.
llm/cost_tracking.py Uses shared placeholder/dialect + shared api_usage schema helper.
etl/news_flow.py Replaces local placeholder/sqlite checks with shared helpers.
etl/ingest_flow.py Replaces local dialect/columns helpers with shared helpers.
etl/evaluation_flow.py Uses shared placeholder + shared api_usage schema helper.
etl/edgar_flow.py Replaces local columns/placeholder helpers with shared helpers.
etl/digest_flow.py Replaces local table/columns/placeholder helpers with shared helpers.
etl/daily_diff_flow.py Replaces local placeholder/sqlite checks with shared helpers.
etl/conviction_flow.py Uses shared placeholder + api_usage schema helper inside the flow.
etl/activism_flow.py Replaces local placeholder/sqlite checks with shared helpers.
etl/activism_detection.py Replaces local placeholder/sqlite checks with shared helpers.
chains/utils.py Adds shared chain parsing/connection/context-guard helpers.
chains/rag_search.py Adopts shared chain helpers + shared DB helpers for dialect/table checks.
chains/nl_query.py Adopts shared chain helpers + shared DB dialect detection.
chains/holdings_analysis.py Uses shared JSON extraction/row mapping + shared api_usage schema helper.
chains/filing_summary.py Uses shared JSON extraction/row mapping + shared api_usage schema helper.
api/signals.py Replaces local table/columns/placeholder helpers with shared helpers.
api/search.py Replaces local table/columns helpers with shared helpers.
api/managers.py Switches to shared normalize_cik.
api/chat.py Replaces local placeholder/columns/sqlite checks with shared helpers.
api/activism.py Replaces local placeholder/table/sqlite checks with shared helpers.
adapters/base.py Adds shared DB dialect/table helpers and consolidates api_usage schema creation.

Comment thread adapters/base.py Outdated
Comment thread tests/test_shared_helper_consolidation.py
Comment thread tests/test_shared_helper_consolidation.py
Comment thread etl/conviction_flow.py
@stranske

stranske commented Jul 1, 2026

Copy link
Copy Markdown
Owner Author

Closer pushed 36b1f5f to fix the Gate regressions from the shared-helper consolidation.

Changes:

  • Restored compatibility aliases for shared helper consumers: api.search._get_columns, etl.daily_diff_flow._placeholder, and etl.ingest_flow._table_columns.
  • Made shared SQLite column introspection avoid the audited ? placeholder/PRAGMA gate finding while keeping Postgres metadata lookup direct through information_schema.columns.
  • Restored test monkeypatch compatibility around ingest holdings replacement and made the BIGSERIAL assertion case-insensitive.

Validation from disposable checkout /tmp/imi-manager-1361-fix.mSS9zC/Manager-Database:

  • python -m pytest tests/test_api_alert_dialect_portability.py tests/test_etl_flows_additional.py tests/test_summariser.py tests/test_cost_script_dialect_portability.py tests/test_edgar_flow.py::test_fetch_and_store_uses_postgres_safe_persistence tests/test_edgar_flow.py::test_replace_holdings_for_filing_uses_postgres_transaction tests/test_dialect_portability_gate.py::test_dialect_gate_accepts_current_audited_repo_state tests/test_ingest_flow.py::test_replace_holdings_rows_uses_postgres_transaction -q -> 27 passed.
  • python -m ruff check adapters/base.py api/search.py etl/daily_diff_flow.py etl/ingest_flow.py tests/test_cost_script_dialect_portability.py -> passed.
  • python -m black --check adapters/base.py api/search.py etl/daily_diff_flow.py etl/ingest_flow.py tests/test_cost_script_dialect_portability.py -> passed.
  • git diff --check -> passed.

Fresh GitHub checks are expected on the new head.

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Runner dispatch state for codex on PR #1361. Do not edit.

@stranske-keepalive

stranske-keepalive Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

🤖 Keepalive Loop Status

PR #1361 | Agent: Codex | Iteration 0/12

Current State

Metric Value
Iteration progress [----------] 0/12
Action fix (agent-run-failed)
Gate failure
Tasks 0/6 complete
Timeout 45 min (default)
Timeout usage 3m elapsed (8%, 42m remaining)
Keepalive ✅ enabled
Autofix ❌ disabled

🔍 Failure Classification

| Error type | infrastructure |
| Error category | unknown |
| Suggested recovery | Capture logs and context; retry once and escalate if the issue persists. |

🧠 Task Analysis

| Provider | ✅ GitHub Models (primary) |
| Confidence | 40% |

⚠️ Failure Tracking

| Consecutive failures | 1/3 |
| Reason | agent-run-failed |

@stranske-keepalive

Copy link
Copy Markdown
Contributor
Keepalive Work Log (click to expand)
# Time (UTC) Agent Action Result Files Tasks Progress Commit Gate
0 2026-07-01 20:07:25 Codex fix (agent-run-failed) failure 5 file(s) 0 0/6 failure

@stranske-keepalive stranske-keepalive Bot added the agent:needs-attention Agent needs human review or intervention label Jul 1, 2026

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

Actionable comments posted: 10

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
etl/digest_flow.py (1)

164-175: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Missed consolidation: raw isinstance check alongside newly-imported shared helpers.

get_table_columns/get_placeholder/table_exists are now imported from adapters.base, but line 174 still does False if not isinstance(conn, sqlite3.Connection) else 0 instead of using is_sqlite(conn). This keeps a direct sqlite3 dependency in this function even though dialect detection was supposed to be centralized.

♻️ Suggested fix
-from adapters.base import connect_db, get_placeholder, get_table_columns, table_exists
+from adapters.base import connect_db, get_placeholder, get_table_columns, is_sqlite, table_exists
...
-            (False if not isinstance(conn, sqlite3.Connection) else 0, window_start.isoformat()),
+            (False if not is_sqlite(conn) else 0, window_start.isoformat()),
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@etl/digest_flow.py` around lines 164 - 175, Replace the remaining direct
sqlite3 type check in the alert_history query path with the shared dialect
helper so dialect detection stays centralized. In digest_flow.py, update the
logic in the alert_history fetch block that currently uses isinstance(conn,
sqlite3.Connection) to instead use is_sqlite(conn), matching the imported
helpers from adapters.base. Keep the query and parameter selection behavior the
same, just route the SQLite-specific placeholder/value choice through the shared
helper.
etl/evaluation_flow.py (1)

362-381: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Same missed consolidation as etl/digest_flow.py: raw isinstance instead of is_sqlite.

ensure_api_usage_schema and get_placeholder are pulled from adapters.base, but the commit decision at line 379 still uses isinstance(conn, sqlite3.Connection) directly rather than the shared is_sqlite(conn) helper used consistently elsewhere in this PR (e.g. etl/daily_diff_flow.py line 368).

♻️ Suggested fix
-from adapters.base import connect_db, ensure_api_usage_schema, get_placeholder
+from adapters.base import connect_db, ensure_api_usage_schema, get_placeholder, is_sqlite
...
-    if isinstance(conn, sqlite3.Connection):
+    if is_sqlite(conn):
         conn.commit()
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@etl/evaluation_flow.py` around lines 362 - 381, The commit check in
log_evaluation_summary still uses a raw sqlite3.Connection type test instead of
the shared adapter helper. Replace the direct isinstance(conn,
sqlite3.Connection) call with is_sqlite(conn) so this path matches the same
consolidation used elsewhere and stays consistent with ensure_api_usage_schema
and get_placeholder from adapters.base.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@api/chat.py`:
- Around line 571-573: The _manager_id_column helper in chat.py has drifted from
the shared version used in api/signals.py, api/managers.py, etl/ingest_flow.py,
and scripts/resolve_aliases.py. Update _manager_id_column to match the
consolidated behavior: add the table_exists guard, return None when the managers
table is absent, and align the return type with the shared helper so the
duplicated logic stays consistent across callers.
- Around line 870-877: The local `_postgres_table_exists` helper duplicates the
shared `table_exists` logic this PR is consolidating, so
`_ensure_chat_feedback_table` should use the shared `adapters.base.table_exists`
helper instead. Remove the local PostgreSQL-only existence check and update the
chat feedback table setup to call `table_exists(conn, "chat_feedback")` like the
other shared-helper call sites in `api/search.py` and `api/signals.py`, unless a
schema-qualified lookup is strictly required.

In `@api/signals.py`:
- Around line 132-141: The helper _manager_id_column is duplicated across
multiple modules and is not covered by the new consolidation gate, so it can
still drift in behavior. Move the shared logic into a single consolidated
location such as adapters.base alongside get_table_columns, or register
_manager_id_column in tests/test_shared_helper_consolidation.py’s
CONSOLIDATED_HELPERS map so all copies are enforced. Update the call sites in
api/managers.py, etl/ingest_flow.py, scripts/resolve_aliases.py, and the
simplified api/chat.py variant to reference the shared definition or match the
consolidated implementation.

In `@chains/utils.py`:
- Around line 121-134: guard_context_values currently only checks direct string
items in lists, so nested dicts inside list values can bypass the
prompt-injection guard. Update guard_context_values to recurse into nested
containers within the list branch as well, applying guard_input to every string
found inside items like dicts or deeper lists, while keeping the existing
behavior for top-level strings and dict values.

In `@etl/activism_detection.py`:
- Around line 44-45: The _is_postgres helper in activism_detection.py is still a
file-local duplicate and has drifted from the same logic in activism_flow.py and
daily_diff_flow.py. Move the dialect check into adapters.base as a shared
is_postgres helper alongside is_sqlite and get_placeholder, then replace each
local _is_postgres usage/import with the centralized is_postgres symbol so all
ETL flows share one implementation.

In `@etl/activism_flow.py`:
- Around line 36-41: The `_is_postgres` helper logic is duplicated and already
drifting across flows, so centralize it instead of keeping local copies. Hoist a
single `is_postgres` helper into `adapters.base`, then update
`etl/activism_flow.py` (and the matching helpers in `etl/activism_detection.py`
and `etl/daily_diff_flow.py`) to use that shared symbol rather than
reimplementing `not is_sqlite(conn)` / `hasattr(conn, "execute")` checks
locally.

In `@etl/daily_diff_flow.py`:
- Around line 30-31: The _is_postgres helper in daily_diff_flow.py has drifted
from the matching helpers in activism_detection.py and activism_flow.py by
dropping the hasattr(conn, "execute") guard. Update _is_postgres to use the same
logic as those other copies, or better, replace all three with a single shared
helper so the behavior stays consistent and the duplicated implementations do
not diverge again.

In `@tests/test_shared_helper_consolidation.py`:
- Around line 39-43: The duplicate scan in the shared-helper consolidation test
is too broad because `ast.walk` matches class methods as well as top-level
helpers, causing false positives for generic names like `_columns` and
`_placeholder`. Tighten the check in the test logic around
`CONSOLIDATED_HELPERS` so it only considers module-level `FunctionDef` and
`AsyncFunctionDef` nodes from the file’s top-level body, not methods nested
inside classes, while keeping the existing duplicate reporting format intact.
- Around line 10-24: The consolidation gate still keys off legacy helper names
instead of the current canonical shared names, so update CONSOLIDATED_HELPERS to
reference the real exported helpers in adapters/base.py and chains/utils.py (for
example the current table/connection and row/context helpers) rather than the
old private aliases, and make sure the scan covers the utils package too. Also
add utils to SCANNED_DIRS so duplicates of the shared identifier helper in
utils/identifiers.py are detected by the test.

In `@utils/identifiers.py`:
- Around line 8-16: normalize_cik is incorrectly deriving CIK digits from
stringified floats and can return more than 10 digits for malformed inputs.
Update the helper to normalize numeric inputs before digit extraction so values
like 1067983.0 preserve the intended integer CIK, and ensure any extracted digit
string is constrained to the documented 10-digit form. Keep the fix localized in
normalize_cik, since its output is consumed by api/managers.py,
scripts/resolve_aliases.py, and scripts/seed_universe.py for uniqueness and
upsert behavior.

---

Outside diff comments:
In `@etl/digest_flow.py`:
- Around line 164-175: Replace the remaining direct sqlite3 type check in the
alert_history query path with the shared dialect helper so dialect detection
stays centralized. In digest_flow.py, update the logic in the alert_history
fetch block that currently uses isinstance(conn, sqlite3.Connection) to instead
use is_sqlite(conn), matching the imported helpers from adapters.base. Keep the
query and parameter selection behavior the same, just route the SQLite-specific
placeholder/value choice through the shared helper.

In `@etl/evaluation_flow.py`:
- Around line 362-381: The commit check in log_evaluation_summary still uses a
raw sqlite3.Connection type test instead of the shared adapter helper. Replace
the direct isinstance(conn, sqlite3.Connection) call with is_sqlite(conn) so
this path matches the same consolidation used elsewhere and stays consistent
with ensure_api_usage_schema and get_placeholder from adapters.base.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 8325172e-2592-4184-8e2f-bdf915e253fe

📥 Commits

Reviewing files that changed from the base of the PR and between 0f08cb0 and 6d8db9d.

📒 Files selected for processing (26)
  • adapters/base.py
  • api/activism.py
  • api/chat.py
  • api/managers.py
  • api/search.py
  • api/signals.py
  • chains/filing_summary.py
  • chains/holdings_analysis.py
  • chains/nl_query.py
  • chains/rag_search.py
  • chains/utils.py
  • etl/activism_detection.py
  • etl/activism_flow.py
  • etl/conviction_flow.py
  • etl/daily_diff_flow.py
  • etl/digest_flow.py
  • etl/edgar_flow.py
  • etl/evaluation_flow.py
  • etl/ingest_flow.py
  • etl/news_flow.py
  • llm/cost_tracking.py
  • scripts/resolve_aliases.py
  • scripts/seed_universe.py
  • tests/test_cost_script_dialect_portability.py
  • tests/test_shared_helper_consolidation.py
  • utils/identifiers.py

Comment thread api/chat.py Outdated
Comment thread api/chat.py Outdated
Comment thread api/signals.py Outdated
Comment thread chains/utils.py
Comment thread etl/activism_detection.py Outdated
Comment thread etl/activism_flow.py Outdated
Comment thread etl/daily_diff_flow.py Outdated
Comment thread tests/test_shared_helper_consolidation.py Outdated
Comment thread tests/test_shared_helper_consolidation.py Outdated
Comment thread utils/identifiers.py
@stranske stranske removed the agent:needs-attention Agent needs human review or intervention label Jul 1, 2026
@stranske

stranske commented Jul 1, 2026

Copy link
Copy Markdown
Owner Author

Closer pushed c497c5c to address the current Gate failure and actionable review findings.

Changes:

  • Restored api.search._get_columns compatibility so tests/test_api_alert_dialect_portability.py imports cleanly.
  • Centralized shared helper behavior in adapters.base: is_postgres, tolerant get_table_columns, and manager_id_column; updated API/ETL/scripts call sites and preserved Postgres migration-required behavior for conviction flow.
  • Made guard_context_values() recurse through nested dict/list/tuple containers before prompt use.
  • Hardened normalize_cik() for integer-like floats and oversized digit strings.
  • Expanded tests/test_shared_helper_consolidation.py to scan canonical helper names plus utils/, assert home definitions exist, and avoid class-method false positives.

Validation before push:

  • python -m pytest tests/test_api_alert_dialect_portability.py tests/test_shared_helper_consolidation.py tests/test_chain_utils.py tests/test_identifiers.py tests/test_conviction_flow.py::test_conviction_flow_logs_api_usage_and_supports_elliott_sample tests/test_cost_script_dialect_portability.py::test_resolve_aliases_postgres_id_detection_and_update_are_dialect_aware -q -> 13 passed.
  • Focused python -m ruff check ... on touched files -> passed.
  • Focused python -m black --fast --check --line-length 100 --exclude '(\.workflows-lib|node_modules)' ... on touched files -> passed.
  • git diff --check -> passed.

Resolved the addressed review threads. Fresh Gate/review checks are async on the new head.

@stranske
stranske merged commit 06eb505 into main Jul 1, 2026
27 checks passed
@stranske
stranske deleted the codex/issue-1313-shared-helper-consolidation branch July 1, 2026 21:24
@stranske stranske added the verify:compare Runs verifier comparison mode after merge label Jul 1, 2026
@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Provider Comparison Report

Provider Summary

Provider Model Verdict Confidence Summary
openai gpt-5.4 PASS 91% The merged PR meets the documented consolidation goals. Shared DB helpers were added to adapters/base.py and call sites across API/ETL/LLM modules were updated to use them, removing the duplicated...
anthropic claude-sonnet-4-6 PASS 82% The PR successfully consolidates the duplicated dialect/chain helpers as required: is_sqlite, get_placeholder, get_table_columns, and ensure_api_usage_schema are added to adapters/base.py...
📋 Full Provider Details (click to expand)

openai

  • Model: gpt-5.4
  • Verdict: PASS
  • Confidence: 91%
  • Scores:
    • Correctness: 9.0/10
    • Completeness: 9.0/10
    • Quality: 9.0/10
    • Testing: 8.0/10
    • Risks: 8.0/10
  • Summary: The merged PR meets the documented consolidation goals. Shared DB helpers were added to adapters/base.py and call sites across API/ETL/LLM modules were updated to use them, removing the duplicated placeholder/SQLite/schema logic. Shared chain helpers were added in chains/utils.py and local copies in filing_summary/holdings_analysis plus shared connection/context handling in rag_search/nl_query were consolidated. CIK normalization was centralized in utils/identifiers.py and the prior duplicate implementations were replaced. The regression gate requirement is also addressed via tests/test_shared_helper_consolidation.py, which checks for reintroduced duplicate helper definitions. Overall the implementation is coherent, materially reduces duplication, and includes targeted tests for the new shared helpers and normalization behavior. The main residual risk is that some portability helpers favor permissive fallback behavior over explicit failure, but nothing in the diff indicates the acceptance criteria were missed.
  • Concerns:
    • The new shared helper set in adapters/base.py includes a few extra abstractions beyond the issue text (for example table_exists, manager_id_column, is_postgres). These appear reasonable, but they slightly expand the consolidation surface and should be watched for unintended coupling.
    • get_table_columns() swallows all exceptions and returns an empty set. This is pragmatic for portability, but it can hide schema/query bugs if callers rely on absence rather than surfacing an error.

anthropic

  • Model: claude-sonnet-4-6
  • Verdict: PASS
  • Confidence: 82%
  • Scores:
    • Correctness: 8.0/10
    • Completeness: 8.0/10
    • Quality: 8.0/10
    • Testing: 8.0/10
    • Risks: 7.0/10
  • Summary: The PR successfully consolidates the duplicated dialect/chain helpers as required: is_sqlite, get_placeholder, get_table_columns, and ensure_api_usage_schema are added to adapters/base.py; extract_json_text and rows_to_dicts are centralized in chains/utils.py; normalize_cik is moved to utils/identifiers.py. All 31 changed files are consistent with the stated scope of ~210 LOC of duplication being removed. The required test files (test_shared_helper_consolidation.py, test_identifiers.py, test_chain_utils.py, test_nl_query_chain.py) are added, and CI passes with all 12 jobs green. Minor concerns exist around the overly broad is_postgres check, silent exception swallowing in get_table_columns, a possible DDL syntax error in the truncated diff, and the inability to fully verify every call-site substitution due to prompt truncation. None of these rise to the level of blocking issues given the passing CI suite and the overall structural correctness of the consolidation approach.
  • Concerns:
    • The is_postgres() helper uses hasattr(conn, 'execute') as its positive check, which is overly broad — SQLite connections also have .execute, so the function relies entirely on the not is_sqlite(conn) guard. This is functionally correct but semantically misleading and could cause false positives with non-DB objects that happen to have an execute attribute.
    • The table_exists() Postgres branch calls conn.execute('SELECT to_regclass(%s)', (table_name,)) without schema-qualifying the lookup, which may return false negatives when the search_path is non-default. The SQLite branch is correct.
    • The get_table_columns() function silently swallows all exceptions (except Exception: return set()), which could mask real connectivity or permission errors and make debugging harder.
    • The diff is truncated in the verifier prompt, so a full audit of all 12+ call-site replacements (especially in etl/ modules) cannot be confirmed from the provided context. The file-level change counts are consistent with the claimed replacements, but individual correctness of each substitution cannot be fully verified.
    • The regression gate test (test_shared_helper_consolidation.py) is added, which is required by the acceptance criteria, but the exact grep/AST logic it uses to assert 'exactly one definition' cannot be confirmed from the truncated diff — there is a risk it only checks for string presence rather than enforcing the single-definition invariant robustly.
    • The _ensure_sqlite_usage_schema function visible in the truncated diff appears to have a syntax error (id IN instead of id INTEGER), though this may be a truncation artifact rather than a real defect. If real, it would be a breaking bug in the DDL path.
    • No explicit test for the table_exists() helper is visible in the added test files listed, leaving that helper without direct coverage.
    • The utils/identifiers.py addition for normalize_cik and the corresponding tests/test_identifiers.py are present, satisfying the CIK normalization consolidation requirement.

Agreement

  • Verdict: PASS (all providers)
  • Correctness: scores within 1 point (avg 8.5/10, range 8.0-9.0)
  • Completeness: scores within 1 point (avg 8.5/10, range 8.0-9.0)
  • Quality: scores within 1 point (avg 8.5/10, range 8.0-9.0)
  • Testing: scores within 1 point (avg 8.0/10, range 8.0-8.0)
  • Risks: scores within 1 point (avg 7.5/10, range 7.0-8.0)

Disagreement

No major disagreements detected.

Unique Insights

  • openai: The new shared helper set in adapters/base.py includes a few extra abstractions beyond the issue text (for example table_exists, manager_id_column, is_postgres). These appear reasonable, but they slightly expand the consolidation surface and should be watched for unintended coupling.; get_table_columns() swallows all exceptions and returns an empty set. This is pragmatic for portability, but it can hide schema/query bugs if callers rely on absence rather than surfacing an error.
  • anthropic: The is_postgres() helper uses hasattr(conn, 'execute') as its positive check, which is overly broad — SQLite connections also have .execute, so the function relies entirely on the not is_sqlite(conn) guard. This is functionally correct but semantically misleading and could cause false positives with non-DB objects that happen to have an execute attribute.; The table_exists() Postgres branch calls conn.execute('SELECT to_regclass(%s)', (table_name,)) without schema-qualifying the lookup, which may return false negatives when the search_path is non-default. The SQLite branch is correct.; The get_table_columns() function silently swallows all exceptions (except Exception: return set()), which could mask real connectivity or permission errors and make debugging harder.; The diff is truncated in the verifier prompt, so a full audit of all 12+ call-site replacements (especially in etl/ modules) cannot be confirmed from the provided context. The file-level change counts are consistent with the claimed replacements, but individual correctness of each substitution cannot be fully verified.; The regression gate test (test_shared_helper_consolidation.py) is added, which is required by the acceptance criteria, but the exact grep/AST logic it uses to assert 'exactly one definition' cannot be confirmed from the truncated diff — there is a risk it only checks for string presence rather than enforcing the single-definition invariant robustly.; The _ensure_sqlite_usage_schema function visible in the truncated diff appears to have a syntax error (id IN instead of id INTEGER), though this may be a truncation artifact rather than a real defect. If real, it would be a breaking bug in the DDL path.; No explicit test for the table_exists() helper is visible in the added test files listed, leaving that helper without direct coverage.; The utils/identifiers.py addition for normalize_cik and the corresponding tests/test_identifiers.py are present, satisfying the CIK normalization consolidation requirement.

🔍 LangSmith Traces

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Workflow state fingerprint for Agents Verifier. Do not edit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent:codex Assign to Codex agent agent:retry Add to trigger agent retry after rate limit or pause agents:keepalive Enable keepalive monitoring on PR autofix Let bots format/lint automatically verify:compare Runs verifier comparison mode after merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Audit] Consolidate duplicated dialect/DB/chain helpers into shared modules

2 participants