[NOTICKET] docs: PR-0/PR-1 spec for Sofhia, and the feedback-edge before/after
Rifqi Hafizuddin+1: Claude Opus 5
9c0fba7
docs/plans/PR0_PR1_TOOL_FIXES.md — six tool fixes, split into PR-0 (two that block QA)
and PR-1 (four that block nothing). Both stay on pr/22: the scope is one directory.
Every claim was RE-VERIFIED against the code today rather than taken from the review,
which was read-only and says so. That changed two of them:
- D-6 (pareto non-additive aggs) is already DOCUMENTED at pareto.py:24 — a deliberate
trade, not an oversight. The spec says so, and narrows the ask to the two real gaps:
the output still calls it "share" with no caveat, and negatives are unguarded.
- D-5 was dropped from Sofhia's scope entirely. The docstring states the empty-set
semantics are intended and correct; the actual gap is narrower (absent column vs
empty result) and lives in task_runner, which is not her lane.
D-12 also moved out — it is in planner/examples.py, Rifqi's file.
Flagged for her to DECIDE before starting: D-3's fix may need the planner to pass an
identifier column, which would c…
27 days ago
[NOTICKET] chore: untrack a render byproduct, and note what 7ffe004a swept in
Rifqi Hafizuddin+1: Claude Opus 5
171ac0c
Two corrections to the previous commit, fixed forward rather than by rewriting pushed
history.
1. docs/testing/agentic-flow.preview.html was tracked. It is a byproduct of the offline
excalidraw preview, regenerated on every render. Untracked and ignored.
2. 7ffe004a's message describes only the _bound threshold change, but the commit also
carried two files it never mentions:
docs/reviews/AGENTIC_DESIGN_REVIEW_2026-09-18.md (559 lines)
docs/testing/agentic-flow.excalidraw (80 elements)
Neither is mine. They are from a concurrent session working in this same tree, and
`git add -A` swept them into my commit. The work is legitimate and stays; what was
wrong was attributing it to a commit about something else. Recording it here so the
log is honest about which change is which.
Worth a decision, not made here: docs/testing now holds TWO flow diagrams whose names
differ only by a hyphen --
agentic_flow.excalidraw (mine, 109 elements, "T…
[NOTICKET] slow path: don't re-trim a payload the tool already bounded (A30 follow-up)
Rifqi Hafizuddin+1: Claude Opus 5
7ffe004
Sofhia's a2089edb caps analyze_anomaly's sample at source (200 -> 50) and reports
`anomalies_total` / `anomalies_shown` beside it. That is the right layer for it: my A30
cap protects what reaches the LLM, hers protects what gets persisted to
results_snapshot and traced to Langfuse, where the 50k blob was still landing whole.
But the two stacked badly. Her cap alone brings the padb payload to 1,180 tokens --
already sane. My generic list trim then cut it to 691 and left
anomalies_shown: 36 beside a list of 20 rows + "… (+16 more)"
The count is recoverable from the marker, and `anomalies_total` was exact throughout, so
nothing was ever wrong -- but a narrative reads straight past that, and "a number in the
payload that disagrees with the payload" is the exact class of bug this round has been
chasing.
Fixed at my end, not hers: `_bound` now leaves a value alone below _MIN_TRIM_CHARS
(8,000). The bound exists to stop floods, not to second-guess a tool that already
bounded itself …
28 days ago
[NOTICKET] docs: diagram of the agentic path, drawn from the code
Rifqi Hafizuddin+1: Claude Opus 5
10f94f3
docs/testing/agentic_flow.excalidraw.
The argument the shape makes: six intents leave the router, five are shallow, and only
structured_flow descends. Everything that guards correctness -- the validator's 10
checks, the retry loop, the S1a checkpoint, the infeasible exit -- sits on that one
spine. Strip the labels and the structure still says it: a narrow entry, a diamond
fanning to six, five short stubs, one long descending spine, converging to four outputs.
Built from the code rather than memory: the six intent branches are the ones in
chat_handler (lines 399-524), the slow-path order is the coordinator's Planner ->
TaskRunner -> Assembler with the checkpoint between, and the SSE order is the contract's
sources -> status -> chunk -> done. Carries three evidence artifacts -- a real TaskList
shape with the ${t1} handoff, the SSE event order, and the 14 tool names.
The rendered PNG is deliberately NOT committed. HF's pre-receive hook rejects binaries
that have not gone through Xet, a…
[NOTICKET] docs: fill bug 14's commit hash
Rifqi Hafizuddin+1: Claude Opus 5
198b4b3
Third time this round a hash had to be written after the fact rather than guessed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
[NOTICKET] planner: surface numeric min/max, so thresholds aren't chosen blind
Rifqi Hafizuddin+1: Claude Opus 5
9155dcb
BUG 14, found by giving analyze_segmentation its first end-to-end run — it was the
last active tool never to have executed outside unit tests.
Asked to band `pa` into low/medium/high, the planner used thirds of 0-100 and all 42
rows landed in "high". A segmentation where every row is in one bucket says nothing,
and nothing in the pipeline flagged it: the tool did exactly what it was told.
The column runs 68.8-95.9. Go has populated stats.min/max on 98 of 98 numeric columns
all along; CatalogSummary dropped them, keeping only sample values. The planner did not
guess badly — it could not see the range.
Same root cause as A28 (constant columns): the catalog knew, the prompt discarded it.
It is also the Python half of the date-range gap handed to Harry — his side populates
dates, this side renders whatever is there, and neither half is useful alone. Date
columns render automatically once he ships.
Rendered as `range=<min>..<max>`, skipped for constant columns because their marker
alrea…
[NOTICKET] docs: real commit hashes in the dry-run log
Rifqi Hafizuddin+1: Claude Opus 5
9d36f1e
Second time this round I wrote a hash from memory before the commit existed: the three
validator checks are 1bf70654, not d0d18e8. Also replaced two 'this commit' placeholders
with 59715a00 and ec492813, which only read correctly in the commit that added them.
A wrong hash in a reference doc is worse than none — it sends the reader looking for
something that was never there.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
[NOTICKET] assembler: never state the finding a failed step was meant to produce
Rifqi Hafizuddin+1: Claude Opus 5
ec49281
BUG 13, found by the certification run (2026-09-17, analysis 62c34bc6).
analyze_correlation refused a non-numeric column (eqm_no), so nothing was measured.
The reply opened:
"Ya, ada indikasi hubungan antara backlog dan bad actor score..."
(Yes, there is an indication of a relationship...)
assembler.md rule 2 already said "do not pretend they succeeded" AND "do not lead with
the failure". The model obeyed both and invented the conclusion in between. Nothing in
the rule forbade stating the very finding the failed step existed to produce.
This is the dangerous class again: the analysis failed, the narrative claimed a result,
and the hedge arrived two clauses later — where it does not help, because the reader
takes the first clause.
Rule 2 now says so explicitly: not "yes, there is an indication", not "X appears to
drive Y", and not softened with "tends to" or "seems". Name the question that stays
open, and answer only what the successful steps support.
Verified with --turns…
[NOTICKET] eval(chat_sim): --turns, so verifying a late fix doesn't cost a whole suite
Rifqi Hafizuddin+1: Claude Opus 5
0f99ba0
--max-turns only ever takes a PREFIX, so checking a fix to the last turn of an 8-turn
suite meant paying for all eight: ~290k to verify one ~30k turn.
--turns 8 runs exactly that turn. First use, verifying the bug-12 fix: 57,734 tokens
against ~290k for the full suite.
History is still built from whatever runs, so a turn that depends on an earlier one is
selected together with it (--turns 2,8). Noted in the flag's help and in the doc.
Verified on the real suite: turn 8 alone now returns the honest refusal — it names both
tables, says no foreign key is declared between them, and offers the per-table summaries
it CAN produce. No validator vocabulary reaches the user.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
[NOTICKET] planner: exhaustion refuses instead of crashing, + the dry-run findings log
Rifqi Hafizuddin+1: Claude Opus 5
59715a0
BUG 12 — retry exhaustion showed the user the validator's own words.
Asked whether backlog relates to bad actor score, the planner burned all three attempts
(cross-table select, then a join the schema does not declare) and the turn ended with
Analysis failed: planner could not produce a usable plan after 3 attempts;
last error: joins[0]: (...) is not a declared foreign key
That is internal vocabulary about an internal contract, and it reads as a broken product
rather than a limit of the data. The SAME question refused cleanly on the previous run,
so this is reachable by chance, not by input.
Two changes. On the final attempt the planner is now told that refusing is a valid
outcome — until now the retry prompt only ever said "this plan was invalid, fix it",
which pushes toward another plan even when none exists. And if it still exhausts, the
service returns the infeasible sentinel instead of raising, reusing the path that
already handles this well: the coordinator renders it…