Rifqi Hafizuddin Claude Opus 5.5 commited on
Commit ·
effd6af
1
Parent(s): fc63682
[NOTICKET] fix(scope): lookup artefacts and typed site ids (P0-4)
Browse files- only a `${tN.col}` value handoff marks tN as a lookup; a Pattern-A
`${t2}` data feed made the answering query a "lookup", so the line fell back
to the site lookup and read "(sebagian kueri)".
- _strip_broken_id_filters strips both FK ends: a typed
`vw_dim_site.site_id = 2009` (Check 8j rejected it, costing a retry).
- the scope line no longer prints `site_id 2009` next to `site_code IPR`.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- src/agents/scope/engine.py +20 -9
src/agents/scope/engine.py
CHANGED
|
@@ -271,7 +271,10 @@ _QUANTIFIERS = ("semua", "seluruh", "setiap", "tiap", "per", "all", "every", "ea
|
|
| 271 |
#: entity's own attributes (requirement #4) — the focus is not forced onto it.
|
| 272 |
ENTITY_MIN_DISTINCT = 200
|
| 273 |
_NEG_OPS = ("!=", "not_in")
|
| 274 |
-
|
|
|
|
|
|
|
|
|
|
| 275 |
|
| 276 |
|
| 277 |
def _has_quantifier(text: str) -> bool:
|
|
@@ -592,13 +595,14 @@ def _strip_broken_id_filters(
|
|
| 592 |
a typed id, a string on the int key, a made-up `${scope.site_id}` (gate run 2: 6 of
|
| 593 |
31 turns refused on these). A real handoff from a lookup task (`${t1.site_id}`)
|
| 594 |
stays. True when something was dropped."""
|
| 595 |
-
|
| 596 |
-
fk
|
| 597 |
-
for
|
| 598 |
-
|
| 599 |
-
|
| 600 |
-
|
| 601 |
-
|
|
|
|
| 602 |
kept = [f for f in ir.filters if f.column_id not in id_cols or _is_handoff(f.value)]
|
| 603 |
if len(kept) == len(ir.filters):
|
| 604 |
return False
|
|
@@ -1002,6 +1006,11 @@ def focus_changed(
|
|
| 1002 |
return False
|
| 1003 |
|
| 1004 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1005 |
def _render_entry(entry: ScopeEntry, id_: bool) -> str:
|
| 1006 |
if entry.values is None:
|
| 1007 |
return f"{entry.column}: {'semua' if id_ else 'all'}"
|
|
@@ -1130,10 +1139,12 @@ def render_scope_line(
|
|
| 1130 |
# period ran (D1a, 2026-11-03), however many other filters a query carries.
|
| 1131 |
period_parts: list[str] = []
|
| 1132 |
others: list[str] = []
|
|
|
|
| 1133 |
for out in outputs:
|
| 1134 |
for f in _meta_filters(out):
|
| 1135 |
col = str(f.get("column", "")).lower()
|
| 1136 |
-
|
|
|
|
| 1137 |
continue
|
| 1138 |
rendered = _render_filter(f)
|
| 1139 |
bucket = period_parts if col in _PERIOD_COLUMNS else others
|
|
|
|
| 271 |
#: entity's own attributes (requirement #4) — the focus is not forced onto it.
|
| 272 |
ENTITY_MIN_DISTINCT = 200
|
| 273 |
_NEG_OPS = ("!=", "not_in")
|
| 274 |
+
# A VALUE handoff `${tN.col}` marks tN as a lookup. A Pattern-A data feed `${tN}` (the
|
| 275 |
+
# rows an analyze_* tool reads) does not: counting it made the answering query a
|
| 276 |
+
# "lookup", the line fell back to the site lookup and read "(sebagian kueri)" (P0-4).
|
| 277 |
+
_TASK_REF_RE = re.compile(r"\$\{(t\d+)\.")
|
| 278 |
|
| 279 |
|
| 280 |
def _has_quantifier(text: str) -> bool:
|
|
|
|
| 595 |
a typed id, a string on the int key, a made-up `${scope.site_id}` (gate run 2: 6 of
|
| 596 |
31 turns refused on these). A real handoff from a lookup task (`${t1.site_id}`)
|
| 597 |
stays. True when something was dropped."""
|
| 598 |
+
fks = [
|
| 599 |
+
fk for t in in_play if t is not owner
|
| 600 |
+
for fk in t.foreign_keys if fk.target_table_id == owner.table_id
|
| 601 |
+
]
|
| 602 |
+
# Both ends of the key: the measure table's `site_id` AND the lookup table's own
|
| 603 |
+
# `site_id` — a typed `vw_dim_site.site_id = 2009` is the same guess (P0-4; Check 8j
|
| 604 |
+
# rejected it, costing a retry, because only the FK side was stripped here).
|
| 605 |
+
id_cols = {fk.column_id for fk in fks} | {fk.target_column_id for fk in fks}
|
| 606 |
kept = [f for f in ir.filters if f.column_id not in id_cols or _is_handoff(f.value)]
|
| 607 |
if len(kept) == len(ir.filters):
|
| 608 |
return False
|
|
|
|
| 1006 |
return False
|
| 1007 |
|
| 1008 |
|
| 1009 |
+
def _stem(column: str) -> str:
|
| 1010 |
+
"""`site_id`, `site_code`, `site_name` → `site`: one dimension, several columns."""
|
| 1011 |
+
return re.sub(r"_(id|code|kode|no|name|nama)$", "", column.lower())
|
| 1012 |
+
|
| 1013 |
+
|
| 1014 |
def _render_entry(entry: ScopeEntry, id_: bool) -> str:
|
| 1015 |
if entry.values is None:
|
| 1016 |
return f"{entry.column}: {'semua' if id_ else 'all'}"
|
|
|
|
| 1139 |
# period ran (D1a, 2026-11-03), however many other filters a query carries.
|
| 1140 |
period_parts: list[str] = []
|
| 1141 |
others: list[str] = []
|
| 1142 |
+
eff_stems = {_stem(c) for c in eff_cols}
|
| 1143 |
for out in outputs:
|
| 1144 |
for f in _meta_filters(out):
|
| 1145 |
col = str(f.get("column", "")).lower()
|
| 1146 |
+
# `site_id 2009` is the resolved id of `site_code IPR`, already shown (P0-4).
|
| 1147 |
+
if col in eff_cols or _stem(col) in eff_stems:
|
| 1148 |
continue
|
| 1149 |
rendered = _render_filter(f)
|
| 1150 |
bucket = period_parts if col in _PERIOD_COLUMNS else others
|