Commit History
-
[NOTICKET] feat(knowledge-parsing): carry the document's human-readable title
`doc_id` is on its way to becoming an identifier rather than a label. Every `term_id` / `formula_id` / `rule_id` / `brief_id` downstream is a digest of it, so it must stop depending on what someone typed into a Save dialog — which it does today, being the file stem. A long name makes the cost visible: chunk_id: "STD_2026_006_MNO_ Rev.0.0 - Production Parameter and ECA::0000" That name is embedded in all 31 chunks and then in every entry derived from them. Renaming `Rev.0.0` to `Rev 0.0` re-keys the lot. `source_title` is the field the name moves to. It equals `doc_id` today, and that is the point: the two are now separate, so the identifier can change without the human-readable name going with it. `Provenance` is what a reviewing expert actually reads, and it carries `doc_id` — without this field they would be shown `f10807178b20531e` instead of the standard's name. Added ahead of the switch because it is needed whichever identifier wins (content hash or the Go service's upload…df571be
-
[NOTICKET] feat(knowledge-parsing): commit the reference artifact, and stop the stamp churning
Three changes, all aimed at one problem: the two halves of the pipeline could not reliably agree on which artifact they were measuring. **Metadata now precedes `chunks` in the artifact.** Pydantic serialises in declaration order, so it decides what a person sees on opening the file. With `chunks` first, checking which parser or normaliser produced an artifact meant scrolling past thousands of lines to the end — and that is a routine check now, not a rare one. JSON objects are unordered by specification and every consumer reads by key, so this changes nothing for code and `schema_version` is unchanged: no field, type or meaning moved. **`contracts.py` is out of the normaliser hash.** The artifact's SHAPE is already versioned by `schema_version`, so hashing it again counted the same change twice. The reordering above proved the cost: the stamp moved while the chunks came out byte-identical, which is a false "your artifact is stale". A signal that cries wolf gets ignored, and this one e…a0e59e4 -
[NOTICKET] eval(knowledge): commit the BUMA fixture artifact; K9/K10 close
Rifqi Hafizuddin +1: Claude Opus 5The 2026-08-27T13:28 re-parse of STD_2026_006_MNO becomes the committed fixture (S7/K10). Same document and content_hash as the 08-26 parse, same parser_config, five corrected chunk boundaries — of which ::0030 is the one that matters: it previously held only "Keterangan grafik:" and now carries the hierarchy-level paragraph, moving Controllable / Hierarki Level Analysis from E1 miss to hit. One paid run on it (90 calls, 170 s): E1 0.8293 / E2 2.556x / E3 1.000, all three above their kill lines, rule recall 0.4286 (6/14). 0 fields rejected by the span check, rules_without_term_link 0. Two caveats recorded beside the numbers rather than left for a reader to rediscover: E3's precision 1.000 sits on a scoreable base of 6 (57 of 63 entries abstain, recall 0.33 against the 18 gold terms with criteria), and the rule-recall delta is partly a denominator change — the same 6 rules matched as in the 08:29 run, the gold base went 15 to 14 when X23 closed. The harness now runs with data/knowled…e5f4abe -
[NOTICKET] feat(knowledge-parsing): stamp the artifact with the code that built it
A chunks.json is a frozen snapshot of the normalisation code at the moment it ran. When that code is fixed, existing artifacts do not update themselves — and nothing in their metadata said so. `parser_config` fingerprints MinerU's settings; `schema_version` versions the artifact's SHAPE, which a normalisation bugfix does not change. So a stale artifact and a correct one declared identical metadata, and the only observable difference was the character count. That cost a day. A pre-fix artifact reached the extraction half, term recall came back 0.7073 against a 0.8049 baseline, and it read as a regression in extraction's own work. It was neither side's setup: same filter code, different input. Verified here — scoring that artifact reproduces 169 mentions and 0.7073 exactly, against 186 and 0.8293 for the rebuilt one. `normaliser_version` is a hash of the modules that decide what a chunk CONTAINS: normalize.py, render.py, checks.py, contracts.py. A source hash rather than a hand-mainta…c64a0cb -
[NOTICKET] fix(knowledge-parsing): long names, name clashes, and a GPU check in the wrong place
Four defects, all found by asking what happens when a real person uploads a real file rather than the two well-named documents in the test folder. **Long file names failed the parse.** MinerU names its output folder after `pdf_file_names` and then writes images into it under a full SHA-256 filename. Measured on this repo the fixed part of the path costs 217 characters, leaving 43 for the name — and the BUMA standard's own name is 56. `_mineru_name` now passes a bounded name instead. Head AND tail are kept, because the names that collide in practice share a long prefix and differ at the end ("… and ECA" versus "… and ECA (2)"); keeping only the head would render exactly those indistinguishable. Verified with a real parse of the 56-character name: 239 characters, 31 chunks, where before it died on MAX_PATH. Uniqueness does not depend on that name — the parent folder is the cache key, which is the full SHA-256 of the file contents. It is cosmetic, exists so the cache can be browsed whil…9083dd1 -
[NOTICKET] eval(knowledge): X20 measures net -1; close X23 on expert ruling; instrument X25
Rifqi HafizuddinThree things, all from the same session. X20 -- FIRST CONTROLLED A/B IN THIS PROJECT, AND IT SAYS X20 COSTS A RULE. Arms alternated inside one session so drift hit both equally. Arm B reverts X20's three edits and KEEPS X23's synthetic examples, so the only variable is X20 itself. Rule branch only: 15 calls per run, ~35s, five rounds each. X20 in 5/14, every one of 5 runs X20 reverted 6/14, every one of 5 runs Zero variance in both arms, and exactly one rule differs: GAINLOSS_QTY_ZERO_PLAN, 0% with X20 and 100% without. The cause is X20's own final clause. That gold rule is a genuine conditional whose CONDITION is written symbolically -- "Jika (Qty_P(M) = 0, Qty_A(M) > 0), maka:" -- and X20 ends with "a statement that is mostly symbols, = and numbers is an equation". The heuristic cannot tell a computation from a symbolic condition, so it nulls a real rule. X20 is also not buying what it was written to buy. GAINLOSS_UNITS, the rule it targets, fires 0% in BOTH arms …e6ed414 -
[NOTICKET] feat(knowledge_extraction): cue class for declarative composition (X24b cause 3)
Rifqi HafizuddinThe rule branch could not see three gold rules because the cue taxonomy had no slot for the voice they are written in. It had conditional cues (jika, apabila, harus) and definitional ones (adalah, merupakan). This corpus states most of its calculation policy in a third voice -- declarative composition: "Nilai PA ... EKUIVALEN DENGAN rata-rata tertimbang ... dengan Quantity sebagai FAKTOR PEMBOBOT" "Perhitungan Pty ... DIPEROLEH DARI hasil pembobotan ..." "Gain/Loss grouping ... merupakan PENJUMLAHAN DARI Gain/Loss model unit" Those are calculation rules by the extraction prompt's own definition -- how a value is computed, sourced or aggregated -- and no existing cue reached any of them. Not a tuning gap; a missing class. Five patterns, chosen by measuring which chunks each reaches rather than by intuition, every one load-bearing for a previously invisible gold rule. Candidates 8 -> 15. \bdihitung menggunakan\b was REJECTED despite matching 5 chunks: it precedes every formu…e6d9d29
-
[NOTICKET] docs(knowledge-parsing): record B3 — MinerU reaches parity, and why
B3 is answered. MinerU hybrid/high through the PRODUCTION module scores E1 0.8293 (34/41) against PyMuPDF's frozen 0.8537 (35/41) — parity with the scratch converter calibration §10 measured, now from code that ships. §10 is EXTENDED, not corrected. Its numbers stand and its attribution was right: the scratch converter did handle list blocks, so `Uncontrollable` really was "present as prose but missed" in that run, exactly as recorded. What B3 adds is that the production module had regressed against that converter, and by how much. The residual 0.0244 is not parsing's to close, and the docs say so rather than leaving it as an open action. `Breakdown` appears three times in the text and sits in the SAME chunks as `Total Hours`, which the filter does find — same chunk, same sentence, `( Total Hours - Breakdown )`, one tagged and one not. So chunk arrangement cannot explain it. Chunk counts rule out over-splitting too: 31 chunks = 15 prose (11 headed, 9 distinct sections) + 14 tables + …e65e685 -
[NOTICKET] fix(knowledge-parsing): normalize.py silently dropped every list block
MinerU keeps list content in `list_items` and gives such items no `text` field. They therefore fell through the generic text path, which reads `item["text"]`, came back empty, and were skipped — no error, no warning, no trace. This is the same shape of bug the chart/image branch was written to prevent, and that branch's comment describes it exactly: "pictures have no such field — so BOTH its caption and its description vanish in silence". Lists have no such field either, and nobody noticed. Measured cost on the BUMA standard: two dropped blocks took five gold terms with them — Joint survey, Truck count, EWH, Controllable, Hierarki Level Analysis. None of the five were "missed by the model"; none were in the artifact at all. Term-filter recall 0.7073 -> 0.8293, +0.1220. List content joins the running text chunk rather than opening its own, because it is prose inside its section. It deliberately skips heading detection: a short bullet can look like a heading, and letting one open a se…6edfbe7 -
[NOTICKET] eval(knowledge): rule-branch noise band — X20 confirmed, X23 answered
Rifqi HafizuddinFive repeat runs at identical config, plus the two from earlier today: seven runs of the same pipeline on the same artifact at temperature 0. 3/15 x1 (the run carrying the latex-guard defect) 4/15 x5 6/15 x1 min 3, median 4, max 6, mean 4.14 The branch is much less noisy than one pair of runs suggested. Five of seven land on exactly 4/15. The rule from here on is: quote the median and the band, never a single run. Per-rule stability turned out to be the useful view, not the total. X20 IS CONFIRMED, and by the rule it names. GAINLOSS_UNITS -- the units sentence that shared a chunk with a Gain/Loss equation, the exact case the fix was written for -- fires in 6 of 7 runs against 0 at the 3/15 baseline. That is a stable +1 sitting outside the noise band, not a lucky sample. Three other rules fire 7/7 and two fire 1/7; those two are the whole of the variance. X23'S GOLD QUESTION IS ANSWERED. With the few-shot that forbade it removed, WATERFALL_TWO_METHODS still f…f754631 -
[NOTICKET] fix(knowledge_extraction): the latex guard was rejecting correct transcriptions
Rifqi Hafizuddin +1: Claude Opus 5First real run of the new runner, on Sofhia's hybrid artifact, and it caught a defect I shipped two commits ago. 4 of 6 formulas had formula_latex nulled -- Qty twice, PA and UA -- and all four rejections were FALSE. The cause is the same identity trap, one level deeper. The model reads RENDERED PROSE, and the document writes `Qty = (INPR Hours) / (Total Hours)`. So it answers with a slash and the document's own parentheses, while the source markup carries `\frac{INPR Hours}{Total Hours}` with neither. Two spellings of one division, and the guard called them different formulas. Three fixes, all notational: Division canonicalises to the prose spelling: `\frac{A}{B}` -> `(A)/(B)`, so a slash and a \frac converge instead of diverging. The old `frac(A)(B)` form was also unsafe on its own terms -- it used parentheses as delimiters, so a literal paren in the numerator collided with the delimiter and `\frac{(a)}{(b)}` could never match `\frac{a}{b}`. Redundant grouping parens collapse: `(…22eb3d4 -
[NOTICKET] fix(knowledge_extraction): close the notation rules against real backend markup
Rifqi Hafizuddin +1: Claude Opus 5Sofhia supplied the same 11 equations as MinerU transcribed them under four backends -- 44 real strings, committed as a fixture. Running the shipped normaliser over them reproduced her figures exactly: 11/11 for vlm/medium, 10/11 for hybrid/medium, 8/11 for pipeline, against hybrid/high as reference. Her independent check and this code agree on both the counts and which equations differ, which is the point of her having run it separately. The remaining gaps were in the command inventory, and the inventory is now evidence rather than guesswork. \mathsf and \displaystyle occur in this corpus and were missing -- \mathsf sets the whole of equation 7 under pipeline, including its multiplication sign, and \displaystyle appears in equation 4. Both are handled now, and the wrapped-x rule generalises across every presentational wrapper rather than being \mathrm specific. Equation 4 needed two more, and one of them was a decision Sofhia deliberately left open. The array ALIGNMENT SPEC arrives…01c76dd -
[NOTICKET] eval(knowledge): the runner the harness has been missing
Rifqi Hafizuddin +1: Claude Opus 5The 2026-08-24 figures were assembled by hand. That is why the rule-branch number in the committed result file is 1/15 measured with a scorer that has since been fixed, and why nobody could re-derive it. This is the reproducible version, following the house convention the other four harnesses already use: module mode, timestamped results, never overwritten. It takes a ParsedDocument artifact and never a PDF. MinerU is not invoked and is not required -- that is the seam doing its job, and it is what makes the pending X20 and X23 measurements possible on a machine with no GPU and no parser installed. Free by default: E1 term-filter recall and E2 compression, plus the funnel, with zero API calls. --extract adds the paid branches, E3 schema fill and rule recall. --dry-run prints the token estimate and the per-branch cache-floor status. --mock exercises every branch with no spend, and stamps the result NOT SCOREABLE so a fabricated number can never be quoted as a measurement. Two refusal…1edf61c
-
[NOTICKET] fix(eval/knowledge): stop the scorer treating `_` as a word character (X22)
Rifqi Hafizuddin +1: Claude Opus 5`norm()` flattened every punctuation mark to a space except the underscore, because `_` is inside `\w`. The gold writes notation bare (`QtyA`) while the renderer folds the LaTeX subscript and emits `Qty_A`. Those normalised to `qtya` and `qty_a`, the substring test failed, and a correct entry was scored as a miss — the instrument was wrong, not the extraction. Underscores are deleted rather than spaced. Spacing only turns `qty_a` into `qty a`, which still does not contain `qtya`; deletion is what makes the two notations meet. The gold is NOT edited. Verified: none of the 15 rules contains an underscore, so no gold fragment changes under the new normaliser and matches can only move from miss to hit. The alternative — rewriting the gold to `Qty_A` — was rejected because it binds the frozen instrument to one renderer's current output, and rendering has already changed once this week and will change again with the backend decision. Two rules use the affected notation, GAINLOSS_QTY_ZERO_…abae344 -
[NOTICKET] docs: reorganise into docs/ and give every doc a status banner
Rifqi Hafizuddin +1: Claude Opus 5The root carried 14 markdown files and no way to tell which were authoritative. That knowledge lived in CLAUDE.md §1 and in Rifqi's head, which works for us and fails for anyone else — and one of the stale ones already has a named failure mode ("The Stale-Doc Believer") for being implemented from. Root now holds four: REPO_STATUS, DEV_PLAN, API_CONTRACT_BE_PYTHON, README. Everything else moves under docs/, by git mv so history follows: docs/knowledge/ context, TODO, calibration, parsing output contract docs/plans/ SPINE_V2_PLAN (approved, W3 deferred), DS_TOOLS_PLAN (proposal) docs/archive/ API_ENDPOINTS_RESTRUCTURE, CODE_REVIEW_2026-07-23, PROJECT_BRD docs/reference/ API_CONTRACT_BE_GOLANG (the Go repo's, a copy that can drift) Every doc gains a one-line status banner under its H1, marked <!-- doc-status -->: LIVE / LIVE PLAN / PROPOSAL / ARCHIVED / REFERENCE. Archived ones name what superseded them — API_ENDPOINTS_RESTRUCTURE now opens with "DO NOT IMPLEMENT FROM…f1342ce -
[NOTICKET] eval(knowledge): full document through both halves — E3 0.90 PASS; fix legend blank-line bug
Rifqi Hafizuddin +1: Claude Fable 5First full-document run with the parsing module building the artifact and the extraction module running every branch. Result committed beside the frozen baseline: eval/knowledge/results/v2_full_document_2026-08-24_093051.json E1 term-filter recall 0.8049 (prototype 0.8537) PASS, kill 0.70 E3 schema fill 0.90 (prototype 0.75) PASS, kill 0.80 rule-branch recall 0.0667 (prototype 0.2667) REGRESSION E3 is the headline: the one experiment that FAILED in the prototype now clears its line. It needs the same care the original number did — the scoreable base is 10 entries, so one adjudication moves it ~10 points, and nano is not deterministic at temperature 0. The single failure (produksi) is the same one the prototype recorded and reads as a gold-adjudication case, not a model error. E1 sits below the baseline because the CHUNKING differs, not the filter: the parsing module splits to a token budget (31 chunks) where the earlier comparison used 14, so th…ec7d3d4
-
[NOTICKET] eval(knowledge): run the pipeline on MinerU-parsed input — parser comparison
Rifqi Hafizuddin +1: Claude Fable 5First run of the extraction half on Rifqi's MinerU output. Same document, same gold set, same pipeline code, so the only variable is the parse. PyMuPDF (what the frozen baseline used) E1 0.8537 35/41 MinerU, raw markup E1 0.7561 31/41 MinerU, formulas + tables rendered to prose E1 0.8293 34/41 The span model reads prose, not markup. MinerU's structure helps the formula branch and hurts the filter unless rendered first: - Terms wrapped in LaTeX are invisible. "\text {Total Hours} - \text {Breakdown}" produces no mentions for either, though both are gold terms found in the plain-text parse. Unwrapping \text/\mathrm/\frac and collapsing MinerU's character-spaced output recovers them (+7.3 points). - Raw <table> HTML sat in 8 of 14 chunks before rendering. The residual ~2.4 points are CHUNKING, not content: MinerU marks non-section labels (Keterangan:, Keterangan grafik:) as text_level titles, so opening a section at each splits a legend…6038b2b -
[NOTICKET] feat(knowledge_extraction): span filter — E1 recall 0.8537, matches the frozen baseline
Rifqi Hafizuddin +1: Claude Fable 5Adds the term-filter stage, the last free stage before the paid extraction call. Dependencies (approved): gliner>=0.2.13 (resolved 0.2.28), torch>=2.6 (resolved 2.11.0+cpu). Install verified clean — `import torchgen` succeeds, so not the corrupt-wheel failure recorded in the calibration doc. filters/span_filter.py runs the model on EVERY chunk, unconditionally. There is deliberately no relevance gate in front of it: a pre-filter's false negatives drop content before extraction sees it, and dropped content never reaches expert review to be caught. "Zero candidate spans" is the relevance signal instead. Two mechanical traps handled, both of which silently cost recall: - the model truncates long inputs and WARNS rather than failing, so chunks are fed as overlapping 130-word windows with character offsets remapped. Offsets are walked over the original spacing, never re-joined — re-joining would shift every offset in a chunk containing newlines and break every span check. - the ~12…3a01634 -
[NOTICKET] chore: add missing planner and readiness eval results
Fills gaps in the committed eval history (readiness 2026-06-23 and 2026-07-02, planner 2026-07-23). Same shape as the already-tracked results; the timestamped files are a standing baseline and are never overwritten. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>bd6659b -
[NOTICKET] feat(eval): knowledge-extraction gold set, scorer + frozen prototype baseline
Rifqi Hafizuddin +1: Claude Fable 5P2 + P3 + P4 from the knowledge-pipeline plan. Lifts the two things out of the kex prototype that could not be recreated if the machine died — the calibration knowledge and the measurement baseline — without porting any pipeline code. eval/knowledge/ (new, follows the eval/{intent,help,readiness,planner} convention): - knowledge_gold.yaml 41 terms + 15 rules, verbatim from the prototype. Still provisional (not expert-reviewed); accepted as good enough so the rebuild is not blocked on expert time. - score.py ported; only change is dropping the prototype's sys.path bootstrap. Pipeline-independent: scores plain lists, so it works against the prototype's artifacts and v2 alike. - results/baseline_prototype_2026-08-13_145132.json FROZEN. The numbers v2 must match or beat. - README.md provenance, what the scorer refuses to conflate, and how …60cf4a8 -
/fix planner count and report (#19)
- /fix planner count question (11de970ff65be9b4f81f773cfb355d3dc57358d7) - [noticket] fix report bug where some answered analysis isnt included in report summary answers (8dec1825cf803ad28f4ff0400b9c373250a7d90a) - [NOTICKET] fix: split report floor from report body; scope analysis reads by user_id (fd4865b20dfc46782706be9aab318f909b9903c3) - [NOTICKET] docs: sync report floor/body + security posture; add review remediation tracker (fc5200c994441ec505ea7a82469da577afe170a5) - [NOTICKET] test: planner eval harness (rule-compliance, --selfcheck/--rescore) (4292522aa3fa3a7af8f933307334cb7e5eb0b377) - [NOTICKET] eval: repair readiness harness; commit intent/help/readiness baselines (08a0a4ad5eacc6c90df22fab5be69f2d33579f29) - [NOTICKET] fix: compiler parity — F-17 fabricated column, F-18 LIKE nulls, F-25 empty in/not_in (8f736f90f1958960a83847d332b45b13fa346168) - [NOTICKET] feat: bound catalog render + blob read; scope charts/traceability; mark degraded seams (0cb7d53cb6f7f7e7b687dd6d9c27…f282b15
-
/fix change model to gpt 5.4 mini (#17)
- [NOTICKET] chore: rename LLM env quad __4o -> __54m (GPT-5.4-mini) (790ef0c7aaac6e76eb01b0ef9a3398ff4249416d)d65c41d -
fix/ check and new chart tool (#16)
- check: table-level column drill + drop misleading "name a table" hint (ef0c7b1c5aa49a244b02f1b5eea15cc77dcf2bcb) - [KM-715] charts: render_chart tool + message_charts store + GET /api/v1/charts + planner viz slice (87cfcf884d923ee4bcd722e0e4ef4d90d7eaedca) - [KM-715] checkpoint: S1a deterministic quality checkpoint between runner and assembler (f3c8de34dc19a573031b67fd4f48dcfbadcdfed8) - [KM-715] docs: sync REPO_STATUS/DEV_PLAN + land SPINE_V2_PLAN (W1/W2 done) (434eacbf2ac8324188ebe5e32775dbc9d2a3f49a) - planner: value-handoff (${tN.col} → list) for tabular lookup/anti-join (54070ac1407b751000e49dfe7f102a2be5ab1ff8) - [KM-715] charts: GET /charts by message_id only + tri-state status marker (b8d15761addf4d499c9631df64e7693aa1d61fa2) - [KM-715] report: embed charts as plotly EDA fences; render_chart counts toward the floor (89db8be6b6f11e86ad0776d2ee07f2306e3b6079) - [KM-715] docs: contract + status deltas for the charts lead-review round (96347ee7c55a4eb39a906409ec214463e25c5e35) - …5a60e93
-
/fix help and tools analyze (#14)
- [KM-711] Retire /report slash command; report is Generate-button only (f7f7b172da0dc16adac0a7555f6d34a704cc2050) - fix(analyze_trend): handle value_column == date_column (count events per period) (55e3327f7b2e21a954b317e143f46bcea8b5ada7) - [KM-711] Docs: drop /report from list_skills catalog examples (0772863b296e2ed3e2d559df05e98540764e58b0) - fix(planner): reject inlined table-ref as analyze_* data (Pattern A) (776fae3c7c6e3d3a07c22bef10898f6b1c33c701) - fix(analyze_aggregate): reject non-string group_by (CASE/binning) keys (b40fa76e2fa68572dad0d8532e07076207095d6b) - fix(planner): reply-language for infeasible_reason + answer-only-asked rule (4d89d7d93938e41892979cd20e5ccf0c97441dac) Co-authored-by: Sofhia Az-Zahra <sofhiaazzhr@users.noreply.huggingface.co>17e31c6
-
/fix validator and report (#10)
- /fix report: remove record_id hash citations, EDA (for future tool) change to data source, transform to mdx-safe (b1b101730ccf5628e43e80f2ad654f78fbed5207) - [NOTICKET] fix(planner): repair near-miss catalog ids in QueryIR before validation (aacd4d13def258a9815761aecbd7b246a8dae9fc) - /fix report: group findings by analysis, dedup, code-span-safe MDX escaping (029b48894e9f79af6c0d81c00a2d811a982f87ae) - [NOTICKET] fix(tools): log swallowed analytics tool errors in AnalyticsToolInvoker (93d9381b2a5f5efe058c913fe0b793ce994a9097) - fix(planner): harden plan validation to reduce retry thrash on structured questions (1619dd3c0fa74825010c7af6d4b375e3b9404847) - [NOTICKET] fix(tools): coerce numeric-string columns before analyze_* compute (6bda333866a1a8ccf1b3fe6fcee7a8e1832f28d7) - fix(planner): correct top-N guidance — in-query ranking IS supported (99aa4141aed8241a625d290fb170f74192a6d831) - feat(guardrails): add input guard, out_of_scope intent, and refusal handling (0bbc27bc40ba20e7a8e…0e5fdb5
-
/fix check and help tool (#8)
- /fix data_catalog model + CatalogStore to dedorch schema (data → catalog_payload) (09857fc52486354f53e752e3ea329b064a9e4c4b) - [NOTICKET] fix(help): lock reply language to user's language on button path (cb7f5ac484ad4a510e68faf5291091958b6d2f42) - /fix default SKIP_INIT_DB=true for dedorch cutover (skip init_db on Go-owned schema) (781b93c6b8744209a1101629b5170175e9212592) - /fix surface catalog foreign keys to the planner (FK-backed joins) (446c57524e932fcdbb0ddecc049189c443b6ae97) - [NOTICKET] feat(eval): add help-skill eval harness + goal-based language fallback (cbdbefb7ab0ffa36949713f18422213db480a959) - [NOTICKET] fix(eval): update readiness eval to post-KM-652 floor (drop problem_validated) (6f46e81bdeb1eb987f9dac8af0e22a975474cbb1) - /fix infer FKs for FK-less dedorch catalog + log repr(e) in db executor (3669290474583ae011f5ed5e50b94dad146fbc77) - Merge eval/help + readiness eval fix into PR #8 (5f4818a8e38f93988ab5756f3a06c94645826b15) - /docs REPO_STATUS: FK inference (FK-…3743cfe
-
feat/Knowledge & Data Tools (#3)
- [KM-641] refactor(tools): trim analytics registry to 4 active tools (66e2e4df66f1abf7eaa7e442d9900d428696ece4) - [NOTICKET] docs: add checkpoint plan for 2026-06-17 sync (8c1bb63ebdee02f9db0da9fc2b2269823b0a7688) - [KM-642] refactor(tools): rename data-access tools to data/knowledge naming (c38c0c29d3e6b245f67d03f2c35e451900e1abdb) - [KM-643] feat(tools): merge data sources into data_check + add knowledge_check (4bd5f1efdc560a64092cc8df672a7990fa949b59) - [NOTICKET] docs: record KM-642/643 in checkpoint plan + PROGRESS (4c57588b90fe0cac8d0d4d22cfe5701fc9eb52dd) - [NOTICKET] fix(chat): scope response cache by user_id + drop TTL to 1h (R5) (b701e95d300c7d2480a3608b2d4da6dfe102b19a) - [NOTICKET] feat(slow-path): persist AnalysisRecord via PostgresAnalysisStore (09f845188226dd01633cf74525caa569e4a7d37a) - [NOTICKET] Adopt verb-first skill naming (2d6406def7ed45edd1226e96645ba2a5cdbfa3d0) - [NOTICKET] docs: sync checkpoint plan — verb-first tool names + report-as-API (3b399f84d73b0d98bd99…0721bb4