Commit History
-
[NOTICKET] docs(knowledge): bring the DDL handoff current for Harry
Rifqi Hafizuddin +1: Claude Opus 5The header had accreted three rounds of banner and started contradicting itself - it opened with "this file is the exact SQL that was executed" and then carried "NOT RUN" markers further down. Rewritten as one coherent handoff. What it now says plainly, because the copy Harry already has is incomplete in two ways and one of them is silent: 1. Section 7 (review modes) is missing from what was sent. Without it, POST /knowledge/ingest with review_mode=llm fails on insert and nothing is ever auto-approved. 2. Sections 1-5 DRIFTED AFTER the 2026-09-07 run, and CREATE TABLE IF NOT EXISTS does not repair an existing table. `kind` gained 'document' and the two parent columns became nullable for kind='domain'. Both are in the file below; adopting the old copy reproduces neither. Adds an inventory with per-section adoption status, and a VERIFIED AGAINST LIVE block read back out of dedorch rather than asserted: 5 tables, 7 of 7 section 6+7 columns, 19 indexes. The …e433561 -
[NOTICKET] feat(knowledge): two review modes, recorded against a person (r1, r2, r3)
Rifqi Hafizuddin +1: Claude Opus 5Closes Sistem review. Section 7 landed in dedorch, so the columns are declared and written; verified read-only through the ORM against live before committing. r1 `review_mode` on the batch, chosen at ingest. "expert" leaves entries waiting for a human; "llm" approves them on arrival with NO reviewer step. Worth being plain about what the second one is: there is no second model call and no second opinion. The entries were written by a model already, and this mode means accepting them without a human looking. Default is "expert" - nobody gets LLM approval by accident. r2/r3 What makes that offerable rather than reckless is the record. `decided_by` says whether a human looked; `authorised_by` says on whose authority it happened. They are separate columns because the admin who clicks ingest and the expert who reviews can be different people, and in "llm" mode there is no reviewer at all - so without the clicker's id reaching the review row the de…6ef7990 -
[NOTICKET] feat(knowledge): review diff + the rule/domain boundary (r4, o2)
Rifqi Hafizuddin +1: Claude Opus 5r4 `changed_fields()` and `review_diff()`. The queue can now say WHAT moved rather than only that something did - which was the ask: show before / after, do not send the expert back to read the entry from the start. `changed` is empty when the approval still stands, so the screen can say "nothing to re-read" instead of rendering two identical panes. `before` is what the expert actually had in front of them; for an `edited` decision that is their own corrected text, not the model's claim. A test pins changed_fields() and has_mutated() to the same answer - two notions of "has this changed" that can disagree is the same defect as two notions of readiness. o2 The rule/domain boundary, written down in the output contract. The two blurred on screen during the 8 Sep review and a boundary nobody has recorded is one the prompts cannot hold. The test: if removing it would change how a NUMBER IS COMPUTED OR SOURCED it is a rule; if it would only …5cb2e2d -
[NOTICKET] feat(knowledge): incremental ingest — versions, reuse, staleness (i1-i7)
Rifqi Hafizuddin +1: Claude Opus 5The 2026-09-08 "ingest bertahap" items, against four rulings taken 2026-09-14. i5 Identity is `doc_id`; the same document arriving with different bytes is a NEW VERSION of it, not a new document. That is what keeps an amended file's approvals attached - entity_id derives from doc_id, which does not move. The reuse check moves to find_document_by_hash (any version): computing the next version first and then looking it up would miss the row that already holds those bytes and re-parse a document we already have, turning the idempotency guarantee into a paid no-op. The artifact's own `version` is ignored - parsing stamps 1 on every parse and cannot know what the tenant already holds. i2 A term this company has already approved is no longer re-extracted. One LLM call per cluster is the entire cost of the glossary branch, so every recognised term is a call not made - and it is also what stops one concept arriving as term 1.1 and term 1.2. Ids s…72e18a5 -
[NOTICKET] feat(knowledge): readable concept keys + key-value lookup (m1, m2, m6, m8)
Rifqi Hafizuddin +1: Claude Opus 5From the 2026-09-08 discussion. `label` now carries a TYPE_SUBJECT key - GLOSSARY_PA - so an agent that meets an unknown term writes the key and hits the row: no scan, no embedding, no model call. Searching a list is O(N), searching a dictionary is O(1), which was the ask. m1 `src/knowledge_extraction/keys.py`. Prefixes come from the `kind` column vocabulary (English, singular) so the system holds one spelling per branch rather than two to keep in sync. Subjects cap at 40 chars, cut on a word boundary. A rule has no canonical surface of its own, so it borrows the term it governs plus a short digest (RULE_PA_C07BE4); asking the model to name it is the option ids.py already rules out, and a model-written rule_id was a real defect here. m2 A key is a LABEL, never an identity. `entity_id` stays the hash an expert's approval hangs on; a key is built from a surface and moves when clustering canonicalises differently. Pinned by a test: one term from two …0ba89b1
-
[NOTICKET] fix: add a fault-code label, measured; re-diagnose the Komatsu tables
Rifqi Hafizuddin +1: Claude Opus 5The Komatsu manual prints 27 service codes ([CA559], [CB2249]) in plain prose and the pipeline returned ZERO mentions for them. Not a parsing problem -- the codes are in `Chunk.text` verbatim. No label was asking: a code is not a component, a symptom, a check or an action, so neither `broad` nor the parked `diagnostic` set proposed one. GLiNER finds them readily once asked, 6 of 6 on the probe chunk at 0.54-0.69 against a 0.25 floor. `fault code` added to `diagnostic`, plus a `broad_codes` A/B arm. It is deliberately NOT in `broad`, because a label is not additive -- GLiNER runs flat NER and a new label competes for spans: mentions clusters code clusters E1c_strict BUMA 251 -> 200 86 -> 67 0 -> 0 0.8537 -> 0.7805 Komatsu 449 -> 548 93 -> 161 0 -> 17 -- Open Pit 787 -> 711 427 -> 377 0 -> 0 -- BUMA loses 51 mentions, 19 clusters and three gold terms; Open Pit loses 76 mentions…366697c -
[NOTICKET] feat: pull one linked partner chunk into the evidence window
Rifqi Hafizuddin +1: Claude Opus 50.4.0 pairs a table chunk with the prose that introduces it (`referenced_by`, both directions) and nothing consumed the pointer. Measured what it would buy, ranking only on the three v2 artifacts -- free, no GLiNER, no spend: clusters top-5 touches a pair BOTH sides only ONE BUMA 83 31 0 31 Komatsu 93 55 0 55 Open Pit 427 70 0 70 Zero of 603 clusters saw both sides. The ranker never co-selects a table and the prose that names it, so the partner is unseen content rather than a duplicate -- and for a bare grid that prose is often its only title ("Troubleshooting of engine (S-mode)" above "S-1 | 6"). Cost at the cap of 1: evidence read +14.5%/+24.5%/+9.9%, i.e. +1.6%/+4.1%/+4.2% of total prompt spend; Open Pit moves 71% -> ~74% of the 2M ceiling. The expansion lives in `top_k`, not `rank_evidence`, for two rea…5d51025 -
[NOTICKET] docs: sync for the open-queue pass, add the Step 8 and Step 7 proposals
Rifqi Hafizuddin +1: Claude Opus 5REPO_STATUS section 14 and DEV_PLAN section 0.8 get the 2026-09-11 delta, with per-item rows K17-K23. Three stale claims corrected while in there, all of which would have misled the next session: * REPO_STATUS gave `schema_version` as 0.3.3 in two places while the delta directly above it documented 0.4.0. * Its "Not yet done" paragraph still listed persistence, the HTTP surface, the full-document run and E3 as open. All four have landed. * KNOWLEDGE_PIPELINE_TODO rows X17, D2 and D4 read "not started" for four days after persistence and the 8 routes shipped on 2026-09-07, while DEV_PLAN recorded them done. Anyone reading that file first would have concluded the pipeline was still offline. It also records nothing of v2 or of this pass, so it now says outright that DEV_PLAN section 0.8 is canonical and the checklist covers the original build-out only. Two proposals, nothing built from either, both needing sign-off: * TABLE_BRANCH_PROPOSAL (Step 8). A shop manual is 74…7659cf0 -
[NOTICKET] fix: cap key-parameter pre-emption in the review queue (Step 2)
Rifqi Hafizuddin +1: Claude Opus 5Unresolved key parameters held their own sort tier beneath conflicts, so EVERY one of them outranked EVERY routine term regardless of how many there were. The branch emits them in bulk on exactly the documents it understands least, so the promotion fired hardest where it was least deserved: on the Komatsu shop manual that is 24 junk rows standing in front of `Engine`, a term with 108 mentions, at rank 25. The original reason for promoting them is preserved and still sound -- that branch has no span check, so an unresolvable surface is the one hallucination signal it can raise and it must not sink beneath sixty routine rows. A CAP expresses that without letting the tail take the queue over: at most one parameter per five term rows. Also heads the parameter name. The branch picks the right CONCEPTS and returns them wrapped in their whole defining sentence (185 chars in one measured case); `term` now carries the head and the new `surface_full` carries the untruncated text. Split only pa…4e3a6ae -
[NOTICKET] docs: sync REPO_STATUS / DEV_PLAN / contracts for pipeline v2
Rifqi Hafizuddin +1: Claude Opus 5Doc sync for the two changes in 2cc21c9 and e662ac0, in the same unit of work. - REPO_STATUS §14: dated delta covering the retired fuzzy pass, parsing 0.4.0, the new E1c metric, E2's removed kill line, and the two settings changes that were measured and rejected. - DEV_PLAN §0.8: banner + task rows K13 (clustering), K14 (asset pointers) and K15 (the paid comparison, still in flight). Existing task numbering untouched; new rows appended. - KNOWLEDGE_PARSING_OUTPUT_CONTRACT: 0.4.0 banner, the full `Asset` field table, a worked inline-reference example, and the two obligations on a consumer (resolve asset:// locally; switch on caption-vs-description). - KNOWLEDGE_OUTPUT_CONTRACT §2c: what the extraction branches now receive, with the quotable/not-quotable table. Also flags a PRE-EXISTING drift found while working: the code writes `document_brief.json` with `brief_id`/`b_` while §8 documents `domain_context.json` with `domain_id`/`d_`. Not reconciled here — it matters …c3c184d
-
/feat knowledge management (#20)
- [NOTICKET] docs: knowledge pipeline test integration — context, audited task checklist, DEV_PLAN §0.8 (8e69dc6c638509f4dd7b6775d520fb4aa4efbd3e) - [NOTICKET] docs: knowledge pipeline — reframe kex as prototype, not port target (7cce5ffc9ab88791ac139dbef8e88e124a3d049e) - [NOTICKET] feat(eval): knowledge-extraction gold set, scorer + frozen prototype baseline (60cf4a885ef31a8aa64916f5a70ac5a0e8062c5f) - [NOTICKET] chore: add missing planner and readiness eval results (bd6659b3bf523597e4482b04ab1fcff5e1284d25) - [NOTICKET] feat(knowledge_extraction): free stages — models, seam adapter, filters, cluster, ranking (024c30abd1189119d33508eded334fe5a3ed5011) - [NOTICKET] fix(knowledge_extraction): move runner into the package; fix two ranking defects (72605ff6876a7936ab685d417c766ce820f6214b) - [NOTICKET] feat(knowledge_extraction): span filter — E1 recall 0.8537, matches the frozen baseline (3a016343398753cf730d50548c0e92ff47c6716c) - [NOTICKET] feat(knowledge_extraction): paid extraction …b68816f