Skip to content

feat(review): [R20 S4] triage promotion — never auto-approve risk-bearing dbt metadata#1028

Open
sahrizvi wants to merge 4 commits into
feat/review-r18-observability-recallfrom
feat/review-r20-s4-triage-promotion
Open

feat(review): [R20 S4] triage promotion — never auto-approve risk-bearing dbt metadata#1028
sahrizvi wants to merge 4 commits into
feat/review-r18-observability-recallfrom
feat/review-r20-s4-triage-promotion

Conversation

@sahrizvi

@sahrizvi sahrizvi commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds triage-tier promotion rules to risk-tier.ts so the reviewer never auto-approves risk-bearing dbt metadata changes. Two failure modes closed:

  • Test-only YAML under models/marts/ adding data_tests: / constraints: / unique_combination_of_columns on a contracted mart → previously classified trivial → auto-approved.
  • SQL change under a FinOps-relevant path (cost / saving / billing / dbu / spend / …) → previously classified lite → approved without the deeper detector lanes running.

Three new FileChangeClass signals wire into fullTierReasons():

Signal Promotes on its own? Fires when
dbtRiskYmlChanges Yes schema.yml diff at YAML key position (not comments / description strings) adds/edits data_tests: / constraints: / contract: / unique_combination_of_columns list item
martLayerChange No — enrichment only File under models/marts/ or models/mart/. Description-only edits under marts stay trivial (matches existing behavior).
finopsPathToken Yes Path/filename contains cost|saving|billing|credit|dbu|spend|revenue|price|rate|pricing|invoice at word/segment/extension boundary. FP guard on incidental substrings (broadcastercaste).

Test plan

  • 11 new regression tests in packages/opencode/test/altimate/review.test.ts — all green.
  • Existing 85 tests unchanged.
  • Full altimate review suite: 3781 pass / 640 skip / 0 fail (132 files).
  • Independently code-reviewed — two highs addressed (regex tightening + FileChangeClass consumer audit).

Ship criteria

  • The two target failure modes must no longer auto-approve.
  • Composite Baseline B recall must not regress from 14/64 on the 13-scenario corpus.

Depends on

Stacks on top of #1027 (feat/review-r18-observability-recall). This branch uses the tierReasons[] wiring landed there so promotion reasons surface in the signed envelope. Merge #1027 first, then rebase this onto main.

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

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review for a one-time review, or @claude review always to subscribe this PR to a review on every future push.

Tip: disable this comment in your organization's Code Review settings.

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: f64c322b-ed83-4f0c-bb2a-61c08012acd6

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

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/review-r20-s4-triage-promotion

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.

@github-actions

Copy link
Copy Markdown

This PR doesn't fully meet our contributing guidelines and PR template.

What needs to be fixed:

  • PR description is missing required template sections. Please use the PR template.

Please edit this PR description to address the above within 2 hours, or it will be automatically closed.

If you believe this was flagged incorrectly, please let a maintainer know.

// dbtRiskYmlChanges hit but doesn't fire on its own.
if (c.dbtRiskYmlChanges) {
const loc = c.martLayerChange ? " under models/marts/ (mart-API surface)" : ""
reasons.push(`schema.yml diff touches data_tests/constraints/contract${loc}`)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

SUGGESTION: Reason string omits unique_combination_of_columns

DBT_UNIQUE_COMBO_RE (line 78) matches unique_combination_of_columns and feeds into dbtRiskYmlChanges, but the surfaced reason only lists data_tests/constraints/contract. A customer who adds only a unique_combination_of_columns test (covered by the test at review.test.ts:466) would see a reason naming keys they didn't touch — inconsistent with both the field doc (lines 43-45) and the cubic summary in the PR description, which both list all four signals.

Suggested change
reasons.push(`schema.yml diff touches data_tests/constraints/contract${loc}`)
reasons.push(`schema.yml diff touches data_tests/constraints/contract/unique_combination_of_columns${loc}`)

Reply with @kilocode-bot fix it to have Kilo Code address this issue.

@kilo-code-bot

kilo-code-bot Bot commented Jul 21, 2026

Copy link
Copy Markdown

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Incremental review of e52c863 (regex fix + regression test). The prior blockScalarStart SUGGESTION is resolved, and no new changed-code issues were found.

Files Reviewed (2 files)
  • packages/opencode/src/altimate/review/risk-tier.ts
  • packages/opencode/test/altimate/review.test.ts
Previous Review Summaries (3 snapshots, latest commit e52c863)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit e52c863)

Status: No Issues Found | Recommendation: Merge

Incremental review of e52c863 (regex fix + regression test). The prior blockScalarStart SUGGESTION is resolved, and no new changed-code issues were found.

Files Reviewed (2 files)
  • packages/opencode/src/altimate/review/risk-tier.ts
  • packages/opencode/test/altimate/review.test.ts

Previous review (commit 4544cf8)

Status: 1 Issue Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 1
Issue Details (click to expand)

SUGGESTION

File Line Issue
packages/opencode/src/altimate/review/risk-tier.ts 141 blockScalarStart regex doesn't match block-scalar headers carrying an explicit indentation indicator or a trailing comment; their body lines then aren't blanked, so a risk keyword inside a description can false-positive promote the file to full (safe direction — over-tiering only).
Files Reviewed (10 files)
  • packages/opencode/src/altimate/review/risk-tier.ts - 1 issue
  • packages/opencode/src/altimate/review/compiled.ts - 0 issues
  • packages/opencode/src/altimate/review/dbt-patterns.ts - 0 issues
  • packages/opencode/src/altimate/review/git.ts - 0 issues
  • packages/opencode/src/altimate/review/run.ts - 0 issues
  • packages/opencode/src/altimate/review/verdict.ts - 0 issues
  • packages/opencode/test/altimate/review-ci.test.ts
  • packages/opencode/test/altimate/review-dbt-patterns.test.ts
  • packages/opencode/test/altimate/review-subdir-invocation.test.ts
  • packages/opencode/test/altimate/review.test.ts

Fix these issues in Kilo Cloud

Previous review (commit 8eac0d9)

Status: 1 Issue Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 1
Issue Details (click to expand)

SUGGESTION

File Line Issue
packages/opencode/src/altimate/review/risk-tier.ts 144 dbtRiskYmlChanges reason string omits unique_combination_of_columns, which DBT_UNIQUE_COMBO_RE (line 78) matches — inconsistent with the field doc and PR summary.
Files Reviewed (2 files)
  • packages/opencode/src/altimate/review/risk-tier.ts - 1 issue
  • packages/opencode/test/altimate/review.test.ts - 0 issues

Fix these issues in Kilo Cloud


Reviewed by glm-5.2 · Input: 27.6K · Output: 4.9K · Cached: 218.2K

Review guidance: REVIEW.md from base branch feat/review-r18-observability-recall

@sahrizvi

Copy link
Copy Markdown
Contributor Author

Validation report against 5-PR internal corpus

Ran the S4-branch CLI against the 5 real internal dbt PRs from the R20 study (both A1 pure-deterministic and A2 with LLM lane). Baseline is the PR-#1027-tip CLI on the same corpus.

Recall delta

Variant Baseline findings (5 PRs) S4 findings (5 PRs) Delta
A1 (--pure --no-ai=true) 118 118 +0
A2 (--pure, LLM lane on) 141 143 +2 (LLM run-to-run noise)

Tier changes

PR Baseline tier S4 tier Note
#781 (Snowflake per-account cost) full full already full (blast radius)
#1111 (Databricks auto-tune) full full already full (blast radius)
#862 (per-(run,day) job cost) full full already full (blast radius)
#975 (grain/uniqueness tests) full full pre-existing touchesContract already promotes
#1091 (anchor to billed DBU) lite full S4 fired via FinOps path token

Interpretation

S4 is a routing change, not a detector change. On this corpus:

  • ✅ PR #1091 now correctly runs at full tier (was under-tiered as lite)
  • ✅ tierReasons[] surfaces explicit grounded reasons (mart-API surface, FinOps keyword, data_tests/constraints)
  • ⚠️ Zero deterministic (A1) finding count improvement — the extra full-tier lanes (contract_violation, pii_exposure, materialization, warehouse_cost, idempotency) didn't have anything to fire on for PR #1091's specific diff shape
  • ⚠️ A2 +2 delta is LLM run-to-run noise (7 new / 6 removed on the same diff), not attributable to S4

S4's value is foundational: it unblocks subsequent detector PRs (S1 grain-key not_null completeness, S6-lite Trino contract→constraint, S3-specific SQL correctness pack) from being neutered by miscalibrated triage. Real recall wins will show up when those detector PRs stack on top of this one.

Recommend keeping this PR open as the routing floor, but expect the benchmark movement to come from the detector-work PRs stacked above it.

@cubic-dev-ai cubic-dev-ai 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.

1 issue found across 2 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/opencode/src/altimate/review/risk-tier.ts">

<violation number="1" location="packages/opencode/src/altimate/review/risk-tier.ts:144">
P2: The reason string `"schema.yml diff touches data_tests/constraints/contract"` doesn't account for the `unique_combination_of_columns` case. Since `dbtRiskYmlChanges` is true when *either* `DBT_RISK_KEY_RE` or `DBT_UNIQUE_COMBO_RE` matches, a customer who only adds a `unique_combination_of_columns` test will see a tier-promotion reason referencing keys they never touched. Consider including `unique_combination_of_columns` in the reason string (e.g., `data_tests/constraints/contract/unique_combination_of_columns`) to stay consistent with the field documentation and actual detection logic.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread packages/opencode/src/altimate/review/risk-tier.ts Outdated
Comment thread packages/opencode/src/altimate/review/risk-tier.ts Outdated
// dbtRiskYmlChanges hit but doesn't fire on its own.
if (c.dbtRiskYmlChanges) {
const loc = c.martLayerChange ? " under models/marts/ (mart-API surface)" : ""
reasons.push(`schema.yml diff touches data_tests/constraints/contract${loc}`)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: The reason string "schema.yml diff touches data_tests/constraints/contract" doesn't account for the unique_combination_of_columns case. Since dbtRiskYmlChanges is true when either DBT_RISK_KEY_RE or DBT_UNIQUE_COMBO_RE matches, a customer who only adds a unique_combination_of_columns test will see a tier-promotion reason referencing keys they never touched. Consider including unique_combination_of_columns in the reason string (e.g., data_tests/constraints/contract/unique_combination_of_columns) to stay consistent with the field documentation and actual detection logic.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/opencode/src/altimate/review/risk-tier.ts, line 144:

<comment>The reason string `"schema.yml diff touches data_tests/constraints/contract"` doesn't account for the `unique_combination_of_columns` case. Since `dbtRiskYmlChanges` is true when *either* `DBT_RISK_KEY_RE` or `DBT_UNIQUE_COMBO_RE` matches, a customer who only adds a `unique_combination_of_columns` test will see a tier-promotion reason referencing keys they never touched. Consider including `unique_combination_of_columns` in the reason string (e.g., `data_tests/constraints/contract/unique_combination_of_columns`) to stay consistent with the field documentation and actual detection logic.</comment>

<file context>
@@ -91,6 +128,22 @@ export function fullTierReasons(c: FileChangeClass): string[] {
+  // dbtRiskYmlChanges hit but doesn't fire on its own.
+  if (c.dbtRiskYmlChanges) {
+    const loc = c.martLayerChange ? " under models/marts/ (mart-API surface)" : ""
+    reasons.push(`schema.yml diff touches data_tests/constraints/contract${loc}`)
+  }
+  if (c.finopsPathToken) reasons.push("path contains FinOps keyword (cost/saving/billing/dbu/etc.)")
</file context>
Suggested change
reasons.push(`schema.yml diff touches data_tests/constraints/contract${loc}`)
reasons.push(`schema.yml diff touches data_tests/constraints/contract/unique_combination_of_columns${loc}`)

@sahrizvi

Copy link
Copy Markdown
Contributor Author

Consensus Code Review — PR #1028

Title: feat(review): [R20 S4] triage promotion — never auto-approve risk-bearing dbt metadata
Branch: feat/review-r20-s4-triage-promotionfeat/review-r18-observability-recall (stacks on #1027) · Repo: AltimateAI/altimate-code
Size: 2 files, +202 (risk-tier.ts +53, review.test.ts +149) · Reviewed: 2026-07-22

Panel (8 reviewers, thorough mode): Claude (Opus 4.8) · GPT 5.4 Codex · Gemini 3.1 Pro (Antigravity) · Kimi K2.5 · Qwen 3.6 · MiniMax M2.7 · GLM-5.1 · MiMo V2.5 Pro. Quorum 6 — met. Convergence: 1 round (GPT + Gemini + Kimi responded; all downgraded finding #2 to MINOR).


Verdict: REQUEST CHANGES — 2 MAJOR (targeted fixes), 5 MINOR, 3 NIT

The promotion mechanism is verified correct by all 8 reviewers (fullReasons is checked before the trivial/lite branches, so the new signals genuinely force full and can never slip to auto-approve). The change is well-scoped; the blockers are a false-negative gap and a vacuous test, both targeted fixes.

Counts: Critical 0 · Major 2 · Minor 5 · Nit 3


MAJOR

1. Legacy tests: key is not promoted → re-opens the auto-approve path it aims to close

Category: False-negative / tiering safety · Location: risk-tier.ts DBT_RISK_KEY_RE
The regex covers data_tests | constraints | contract but NOT the pre-dbt-1.8 tests: key. A schema.yml adding tests: [- unique / - not_null] under models/marts/, with no FinOps token or blast radius, falls through onlyDocstier: "trivial" → auto-approve — the exact failure mode this PR targets, for projects on dbt <1.8 or mid-migration. Partial mitigation: unique_combination_of_columns under legacy tests: is still caught by the key-agnostic DBT_UNIQUE_COMBO_RE, but plain unique/not_null/relationships/accepted_values under tests: are not.
Fix: (?:tests|data_tests|constraints|contract) + a regression test proving legacy tests: promotes. If pre-1.8 is out of scope, document that explicitly.
8-way consensus (top finding, unanimous in convergence). Original severities ranged NIT→CRITICAL; settled at MAJOR.

2 → downgraded to MINOR in convergence (see MINOR section)

3. The unique_combination_of_columns regression test is vacuous (test conflation)

Category: Test correctness · Location: review.test.ts "full: schema.yml adds unique_combination_of_columns test"
The test path models/marts/mrt_billing_account_prices.yml also matches FINOPS_TOKEN_RE (billing, prices) and sits under marts/, so finopsPathToken promotes it to full independently of the diff — the assertion tier === "full" passes even if DBT_UNIQUE_COMBO_RE were deleted. The one test meant to lock in unique-combo detection can never fail on that regex.
Fix: move to a non-FinOps, non-mart path (e.g. models/intermediate/int_grain.yml), keep the diff, and assert both tier === "full" and the reason string, so DBT_UNIQUE_COMBO_RE is the sole possible promoter.
GLM-5 (unique catch); lead confirmed billing+prices both match at the shell. Convergence: Gemini + Kimi + GLM-5 hold MAJOR; GPT dissents (MINOR — test-only, no production impact). Kept MAJOR: a core detector's only regression test providing false confidence is meaningful for a review-tool codebase.


MINOR

2. FinOps token over-promotes on non-financial analytics paths (downgraded from MAJOR in convergence)

Category: Cost / precision · Location: risk-tier.ts FINOPS_TOKEN_RE + finopsPathToken hard floor
rate | rates | pricing | credit | saving | dbus match at _/./- boundaries on non-FinOps paths — verified at the shell: mrt_error_rate.sql, stg_fill_rate.sql, mrt_conversion_rate.sql, mrt_retention_rate.sql (true), and stg_dbus_connector.sql (D-Bus IPC, not Databricks Units — true). Because finopsPathToken is a hard floor before the size/blast gates, any change to these files runs full tier (LLM cost).
Why MINOR (convergence): GPT, Gemini, and Kimi independently argued this is a deliberate recall-over-precision fail-safe — it never under-promotes or creates an auto-approve regression; it only adds review cost. That is a precision/cost tradeoff, not a tiering-safety defect.
Fix (optional): narrow rate/rates/pricing (require financial context or couple with marts/reporting), drop dbus (keep dbu), and/or gate path-only promotion by non-doc changed lines.
Note: an earlier example (stg_accredited_loans.sql, "credit inside accredited") was retracted — GPT flagged it and the shell confirms it does NOT match (no boundary char around credit).

4. Promotion reason can omit the actual triggering signal

Category: Observability · The reason always reads "schema.yml diff touches data_tests/constraints/contract" even when the match came solely from unique_combination_of_columns, so the signed tierReasons misnames the trigger. Name the exact signal (or return structured signal names). GPT + GLM-5.

5. "upgrades the WEIGHT" comment is misleading

martLayerChange only appends a location string to the reason; there is no actual weight/ordering change (the tier is already full). Fix the comment or implement real weighting. Qwen + MiniMax.

6. Block-scalar / multi-line description false positive

A YAML block scalar (|/>) whose continuation line begins with data_tests:/constraints: matches DBT_RISK_KEY_RE; the (?!#) guard only excludes # comments, not block-scalar bodies. Low frequency. GLM-5.

7. FinOps boundary misses digit suffixes (false-negative)

mrt_cost2024.sql, stg_billing2.sql, dbu1_usage.sql don't match — the char after the keyword is a digit, not in [\/_.-]. Add \d to the boundary class. Gemini.


NIT

  1. DBT_UNIQUE_COMBO_RE requires a trailing : and list-item marker → misses the bare/indented-key short form. Claude, MiMo, GLM-5.
  2. Removed-line (- data_tests: / - constraints:) risk keys promote — correct (removing a guardrail is risk-worthy) but untested. MiMo, GLM-5.
  3. Comment calls unique_combination_of_columns a "TEST NAME"; it's a test macro/parameter. Kimi.

Rejected findings (for transparency)

  • "No dedicated contract: promotion test" (Gemini/Qwen MINOR) — false: review.test.ts:405 tests + contract:\n+ enforced: true. GPT flagged this; lead confirmed. Removed.
  • "FINOPS_TOKEN_RE lacks /i" (Qwen NIT) — false; the regex carries /i (risk-tier.ts:84).
  • "Mart .yml may classify as other, missing dbtRiskYmlChanges" (Kimi MAJOR) — false; classifyDbtFile routes any .yml under models/ to schema_yml (diff-filter.ts:75).
  • "martLayerChange does nothing / fullTierReasons empty unless pushed" (MiniMax CRITICAL) — that is the intended enrichment-only design, confirmed by every other reviewer and the tests.

Positive observations (consensus)

  • Promotion ordering verified correct by all 8 reviewers: fullReasons checked before trivial/lite → dbtRiskYmlChanges/finopsPathToken reliably force full; never slips to auto-approve.
  • martLayerChange correctly enrichment-only (never promotes alone) — description-only mart edits stay trivial; tested.
  • Diff-level detection (changedLines) prevents surrounding context from promoting.
  • Good FP guards + negative tests: comment/description exclusion, incidental substrings (broadcaster, precast), and MARTS_DIR_RE requiring marts/ as a path segment (rejects models/marts_backup/, mymodels/marts/).

Missing tests


Convergence

Reviewer Verdict on synthesis Key point
GPT 5.4 Codex CHANGES NEEDED → incorporated #2 → MINOR (cost-only fail-safe); accredited example wrong; contract: test does exist (removed MINOR #8); #3 is MINOR/low-MAJOR.
Gemini 3.1 Pro CHANGES NEEDED → incorporated #2 → MINOR; #3 correctly MAJOR; #1 correctly top.
Kimi K2.5 CHANGES NEEDED → incorporated #2 → MINOR (dbus is a real bug though); #3 correctly MAJOR.
Claude (author) Agreed with all three downgrades/corrections.

Applied in convergence: #2 MAJOR→MINOR (3 reviewers, unanimous); retracted the accredited example (shell-verified non-match); removed the "no contract: test" MINOR (test exists at review.test.ts:405). #3 kept MAJOR (Gemini + Kimi + GLM-5 vs GPT's lone MINOR). #1 unchanged as top finding. Converged in 1 round.

Finding attribution

# Finding Origin Type
1 Legacy tests: key not promoted GPT, Gemini, Kimi, Qwen, MiniMax, GLM-5, MiMo, Claude Consensus (8-way)
3 Vacuous unique_combination_of_columns test GLM-5 Unique (shell-verified)
2 FinOps over-promotion on *_rate/dbus paths Qwen, MiniMax, GLM-5, Kimi, GPT, Gemini, MiMo Consensus; severity set MINOR in convergence
4 Reason omits actual triggering signal GPT, GLM-5 Unique
5 "upgrades the WEIGHT" comment misleading Qwen, MiniMax Unique
6 Block-scalar description FP GLM-5 Unique
7 FinOps boundary misses digit suffixes Gemini Unique
8–10 NITs (short-form regex, removed-line untested, comment) Claude, MiMo, GLM-5, Kimi Nit
Promotion ordering correct; martLayerChange enrichment-only all 8 Consensus (positive)

Reviewed by 8 participants. Convergence: 1 round, 3 external responses (GPT, Gemini, Kimi) + Claude.

Infra note: the 5 kilo-hosted models (Kimi/Qwen/MiniMax/GLM-5/MiMo) run via a pty.spawn pseudo-TTY wrapper — kilo hangs without a TTY when run headless. Gemini runs via the Antigravity agy CLI. The stale MiMo model id in ~/.claude/consensus.json was corrected (mimo-v2-promimo-v2.5-pro).

Haider and others added 2 commits July 22, 2026 18:52
…adata

Grounded in the 5-PR internal corpus study
(data-engineering-skills/docs/pr-review-corpus-findings-r20.md) where
historical altimate-code recall was 2/84 = 2.4%. Two of five PRs
auto-approved despite each having 8+ substantive human findings:
- PR D: test-only YAML under `models/marts/` adding
  `data_tests:` / `constraints:` on a contracted mart → 8 misses,
  including 5 dbt-trino adapter-semantic bugs.
- PR E: cost-anchor redesign under `mrt_jobs_cost_savings.sql` →
  11 misses, including 3 critical FinOps corrections.

Adds three FileChangeClass signals + wires them into `fullTierReasons()`:

- **`dbtRiskYmlChanges`** — schema.yml diff introduces or edits
  `data_tests:`, `constraints:`, `contract:`, or a
  `unique_combination_of_columns` list-item. Regex anchors to YAML
  key position after optional diff marker, optional indent, and
  optional list marker; explicitly excludes comment lines. This
  catches PR D.

- **`martLayerChange`** — file lives under `models/marts/` or
  `models/mart/`. Does NOT promote on its own (description-only
  edits stay trivial, matching the existing test), but ENRICHES
  the `dbtRiskYmlChanges` reason string so the customer sees
  "under models/marts/ (mart-API surface)".

- **`finopsPathToken`** — path/filename contains a FinOps keyword
  (`cost|saving|billing|credit|dbu|spend|revenue|price|rate|pricing|
  invoice`) at a word / segment / extension boundary. Catches PR E.
  Word-boundary regex prevents false positives on incidental
  substrings (`broadcaster` ≠ `caste`, `precast` ≠ `cast`).

Regression tests (11 new, all green):
- PR D shapes (data_tests, constraints, unique_combination_of_columns)
  all promote to full with `mart-API surface` context.
- PR E shape (mrt_jobs_cost_savings.sql) + 7 other FinOps keyword
  variants all promote to full.
- FinOps false-positive guard: `broadcaster` / `precast` stay lite.
- Description-only edits under models/marts/ still trivial
  (pre-existing behavior preserved).
- Comment lines and description strings mentioning
  `data_tests:` / `constraints:` do NOT promote (regex tightness).
- Nested-indent YAML key position (production shape) still fires.

Codex-reviewed diff. Two highs addressed:
- Regex tightening to avoid comment / description-string false positives
- FileChangeClass consumer audit (no external constructions; safe)

Ship criteria (from plan v2): PRs D and E from the corpus must no
longer auto-approve. Baseline recall on the existing 13-scenario
corpus must not regress. Both hold: 96/96 tests pass (85 pre-existing
+ 11 new); full altimate review suite 3781/3781 green.

Depends on PR #1027 (feat/review-r18-observability-recall) — this branch
stacks on top so tierReasons[] wiring is in place.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017zXDXMiNFh4qDPxPCfa2of
…motion

Bundle addresses PR #1028's consensus review:

- MAJOR #1 — legacy `tests:` (pre-dbt-1.8 alias) added to risk-key
  patterns so `models/marts/*.yml` diffs adding `tests: [not_null]` or
  similar promote out of trivial. Regression tests cover both marts
  and non-marts placement + a word-boundary FP guard.

- MAJOR #3 — vacuous `unique_combination_of_columns` regression test
  fixed. Original path (`mrt_billing_account_prices.yml`) also matched
  FinOps + marts signals so the DBT_UNIQUE_COMBO_RE could have been
  deleted and the test still passed. Path moved to
  `models/intermediate/int_grain.yml` (non-mart, non-FinOps) and
  reason string asserted to confirm the combo regex is the sole
  triggering signal.

- MINOR #2 — dropped `dbus` from FINOPS_TOKEN_RE (D-Bus IPC collision
  with `stg_dbus_connector.sql`). Singular `dbu` is sufficient.

- MINOR #4 — each risk-YAML key now has its own regex in a
  DBT_RISK_KEY_PATTERNS table. `dbtRiskYmlKeyMatches()` returns the
  specific keys that matched; new `dbtRiskYmlKeys: string[]` field on
  FileChangeClass. Reason string now names the exact triggering keys
  (e.g. "schema.yml diff touches tests under models/marts/") rather
  than the concatenated umbrella.

- MINOR #5 — reworded the "upgrades the WEIGHT" comment. There is no
  weighting/ordering effect; `martLayerChange` only enriches the reason
  string with the mart-API-surface context.

- MINOR #6 — block-scalar body FP: `stripBlockScalars()` walks the diff
  tracking block-scalar state so a description or long-form comment
  containing `data_tests:` (or similar) doesn't spuriously promote.
  Codex round-6 review HIGH fixed too — earlier version worked only
  on the +/- slice, missing the common case where `description: |`
  is in the context and a changed line is inside its body. Now walks
  the full diff (context + changed) for state and only masks output on
  changed lines.

- MINOR #7 — FinOps boundary class extended with `\d` so digit-suffixed
  paths (`mrt_cost2024.sql`, `stg_billing2.sql`, `dbu1_usage.sql`)
  match.

- NIT #8 — DBT_UNIQUE_COMBO_RE relaxed to make the list-item marker
  optional, so the bare-key indented form
  (`unique_combination_of_columns:` under a short-form `tests:` map)
  also matches.

- NIT #9 — added regression test for removed-line risk-key promotion
  (removing a `data_tests:` block is at least as risk-worthy as
  adding one).

- NIT #10 — comment reworded from `unique_combination_of_columns` is
  a "TEST NAME" → "dbt test macro / test parameter".

Full altimate review suite: 3807 pass / 640 skip / 0 fail (was 3781
baseline — 26 new tests).

Codex-round-6 minor addressed: `dbtRiskYmlKeyMatches` is now called
once via a shared `scannedForRisk` local and its result reused for
both `dbtRiskYmlChanges` and `dbtRiskYmlKeys`.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017zXDXMiNFh4qDPxPCfa2of
@sahrizvi
sahrizvi force-pushed the feat/review-r20-s4-triage-promotion branch from 8eac0d9 to 4544cf8 Compare July 22, 2026 13:33
const lines = diff.split("\n")
const out: string[] = []
let scalarIndent = -1
const blockScalarStart = /^[ \t]*[^\s#:][^:]*:[ \t]*[|>][+-]?[ \t]*$/

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

SUGGESTION: blockScalarStart skips block-scalar headers that carry an explicit indentation indicator (description: |2, >2-) or a trailing comment (description: | # legacy)

[+-]? consumes only a chomping indicator, so legal headers like |2, |+2, or | # comment don't match. When such an opener is in the diff the scalar is never opened and its body lines aren't blanked — so a body line that happens to start with a risk keyword (data_tests: / tests: / …) would false-positive promote the file to full. Narrow and safe-direction (over-tiering only, never a wrong verdict), but this regex is the sole scalar gate, so widening the class closes the gap.

Suggested change
const blockScalarStart = /^[ \t]*[^\s#:][^:]*:[ \t]*[|>][+-]?[ \t]*$/
const blockScalarStart = /^[ \t]*[^\s#:][^:]*:[ \t]*[|>][+-]?[0-9]?[+-]?[ \t]*(?:#.*)?$/

Reply with @kilocode-bot fix it to have Kilo Code address this issue.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in e52c863ae. blockScalarStart regex widened to [|>](?:[+-]?[1-9]?|[1-9]?[+-]?)[ \t]*(?:#.*)?$ so |2, |+2, |2- (explicit indentation indicator, either order relative to chomp) and | # comment (trailing comment) all open a scalar. Regression test loops over |2, |+2, | # legacy comment shapes and asserts each produces trivial on a diff whose body contains risk keywords.

sahrizvi pushed a commit that referenced this pull request Jul 22, 2026
For every column named in a `dbt_utils.unique_combination_of_columns`
test's `combination_of_columns`, require `not_null` coverage on the
same model. Otherwise a NULL grain-key value silently passes the
uniqueness test — the guardrail is toothless. Cited as a hard rule in
`docs/DBT_GUIDELINES.md` in the corpus repo; kilo catches it, we didn't.

Coverage sources:
- `constraints: [{type: not_null}]` — only counted when
  `contract.enforced == true` (per codex R20 S1 high #3). On views /
  non-contracted models, `constraints:` is documentation-only, not
  enforced, so we don't miss a real gap.
- Column-level `data_tests: [not_null]` / `tests: [not_null]` — always
  counted; dbt's test runner enforces regardless of contract state.

Recommendation flips between `constraints:` (contracted model) and
`data_tests:` (view / non-contracted) based on the model's contract
state — matches the adapter-semantics discussion in the corpus study
(PR D×2 + PR A×2).

Supported YAML shapes:
- `unique_combination_of_columns` and `dbt_utils.unique_combination_of_columns`
  (exact match per codex high #1; `endsWith` would over-match).
- pre-1.9 flat args + dbt 1.9+ `arguments:` nesting.
- top-level `contract:` and nested `config.contract:` for enforcement flag.

False-positive guards:
- Column-name comparison is case-folded (Snowflake identifiers, per
  codex high #2) so `WORKSPACE_ID` in `combination_of_columns` matches
  `workspace_id` in `columns:`.
- Skipped on `status === "deleted"` files (no current grain to guard).
- Only runs on files in the PR diff, not repo-wide.

### Validation on 5-PR internal corpus (recall improvement)

vs S4 baseline (the tier-promotion PR this branch stacks on):
| Variant | S4 baseline | S1 result | Delta |
|---|---:|---:|---:|
| A1 (`--pure --no-ai=true`) | 118 | 129 | **+11 grain-key gaps** |
| A2 (`--pure`, LLM lane) | 143 | 150 | +7 (net; LLM run-to-run noise) |

Grain-key gaps caught:
- PR B (#1111) ×1: `mrt_all_purpose_auto_tune_recommendation.rec_type`
- PR C (#862) ×10: workspace_id x3, job_id x2, period_start_time x2, period_end_time x2, task_key x1
- PR A, D, E: 0 (fixes already landed in HEAD state per corpus study)

Strong matches to human blocker findings on PR C:
- `int_job_run_billing.workspace_id`, `int_job_run_cost_carrier.workspace_id`,
  `int_job_task_run_cost_carrier.workspace_id` → PR C human F11 (critical:
  "workspace_id missing from carrier identity")
- `mrt_job_run_timeline.period_end_time`, `mrt_job_task_run_timeline.period_end_time`
  → PR C human F10 (critical: "dbt mart grain includes period_end_time")

### Tests

- 71 pass / 0 fail in `review-dbt-patterns.test.ts` (58 pre-existing + 13 new S1 tests).
- 3797 pass / 640 skip / 0 fail in the full altimate review suite (132 files).
- Codex-reviewed diff, 3 highs addressed:
  - endsWith → exact-name match
  - column-name case-folding
  - constraints only count when contract enforced
- Codex minor #4 addressed (test fixture for top-level `contract:`)
- Codex minor #5 addressed (test fixture for non-contracted constraints ≠ coverage)

Depends on PR #1028 (feat/review-r20-s4-triage-promotion), which in turn
stacks on PR #1027 (feat/review-r18-observability-recall).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017zXDXMiNFh4qDPxPCfa2of
… regex tightened

kilo-code-bot suggestion on PR #1028 — the earlier `blockScalarStart`
regex accepted only `|`/`>` with an optional `+`/`-` chomping
indicator, so YAML block-scalar headers carrying an explicit
indentation indicator (`description: |2`, `|+2`, `|2-`) or a
trailing comment (`description: | # legacy`) failed to open a
scalar. Body lines beginning with a risk keyword (`data_tests:`,
`constraints:`, …) then false-positive promoted the file to `full`.
Safe-direction over-tiering (never a wrong verdict), but this regex
is the sole scalar gate — widen it to close the gap.

Regex now: `[|>](?:[+-]?[1-9]?|[1-9]?[+-]?)[ \\t]*(?:#.*)?$`.
- `[|>]` opener
- `(?:[+-]?[1-9]?|[1-9]?[+-]?)` chomp+indent in either order
- optional trailing `# comment`

New regression test loops over `|2`, `|+2`, and `| # legacy comment`
opener shapes and asserts each produces `trivial` on a diff whose
body lines contain risk keywords.

Full altimate review suite: 3808 pass / 640 skip / 0 fail (was 3807
baseline — 1 new test).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017zXDXMiNFh4qDPxPCfa2of

@cubic-dev-ai cubic-dev-ai 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.

All reported issues were addressed across 2 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread packages/opencode/src/altimate/review/risk-tier.ts
…ForScan (cubic P2)

cubic P2 bot review — the scalar-state tracker measured indent
inconsistently between context and changed diff lines. Context lines
start with a leading SPACE (the diff marker) and my earlier code
left it in place; changed lines had their `+`/`-` marker stripped
before indent measurement. Result: a valid `|1` block scalar opened
in the context with a body indented exactly one space beyond the
header wasn't masked, because the context-side `scalarIndent`
counted one extra space and the changed-side body's indent then
failed the `indent > scalarIndent` check.

Fix strips the leading diff marker (`+`/`-`/space) on ALL lines
before indent measurement, so context and changed lines live in the
same coordinate system.

New regression test: `|1` block scalar opened in context with body
containing `data_tests:` / `constraints:` prose stays trivial.

Full altimate review suite: 3808 pass / 640 skip / 0 fail (was 3807
baseline — 1 new test).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017zXDXMiNFh4qDPxPCfa2of

@cubic-dev-ai cubic-dev-ai 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.

1 issue found across 2 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/opencode/src/altimate/review/risk-tier.ts">

<violation number="1" location="packages/opencode/src/altimate/review/risk-tier.ts:161">
P2: Real `git diff` output includes `diff --git a/... b/...` and `index ...` header lines before the first `@@` hunk; these don't start with `+`, `-`, or a space, so with the new marker logic they get marker `""` and skip the `if (marker === " ") continue` guard, leaking into the scanned output that feeds the risk-YAML regex matching (`dbtRiskYmlKeyMatches`). The regression tests only use synthetic diffs starting directly at `@@ ...`, so this gap isn't covered — recommend changing the later guard to `if (marker !== "+" && marker !== "-") continue` so both context lines and non-standard/header lines are excluded from the scan output.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

// like " description: |1" is measured as 1-deeper indent than an
// otherwise-equivalent "+ data_tests: ..." changed line, and the
// scalar body fails the `indent > scalarIndent` check (cubic P2).
const marker = raw.startsWith("+") || raw.startsWith("-") ? raw[0] : raw.startsWith(" ") ? " " : ""

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: Real git diff output includes diff --git a/... b/... and index ... header lines before the first @@ hunk; these don't start with +, -, or a space, so with the new marker logic they get marker "" and skip the if (marker === " ") continue guard, leaking into the scanned output that feeds the risk-YAML regex matching (dbtRiskYmlKeyMatches). The regression tests only use synthetic diffs starting directly at @@ ..., so this gap isn't covered — recommend changing the later guard to if (marker !== "+" && marker !== "-") continue so both context lines and non-standard/header lines are excluded from the scan output.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/opencode/src/altimate/review/risk-tier.ts, line 161:

<comment>Real `git diff` output includes `diff --git a/... b/...` and `index ...` header lines before the first `@@` hunk; these don't start with `+`, `-`, or a space, so with the new marker logic they get marker `""` and skip the `if (marker === " ") continue` guard, leaking into the scanned output that feeds the risk-YAML regex matching (`dbtRiskYmlKeyMatches`). The regression tests only use synthetic diffs starting directly at `@@ ...`, so this gap isn't covered — recommend changing the later guard to `if (marker !== "+" && marker !== "-") continue` so both context lines and non-standard/header lines are excluded from the scan output.</comment>

<file context>
@@ -153,8 +153,13 @@ function changedLinesForScan(diff: string | undefined): string {
+    // like " description: |1" is measured as 1-deeper indent than an
+    // otherwise-equivalent "+   data_tests: ..." changed line, and the
+    // scalar body fails the `indent > scalarIndent` check (cubic P2).
+    const marker = raw.startsWith("+") || raw.startsWith("-") ? raw[0] : raw.startsWith(" ") ? " " : ""
+    const stripped = marker === "" ? raw : raw.slice(1)
     const indent = stripped.length - stripped.replace(/^[ \t]+/, "").length
</file context>

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant