Using AI comes down to proving three things — whether the result can be trusted enough to put into real work, whether the gain stays with the organization and keeps running, and whether the tools are chosen critically. What each topic asks, and why, is restated at the head of its own section.
flowchart TB R(["🧭 How I use AI — three things to prove"]):::root R --> H1 R --> H2 R --> H3 H1["① Problem solving · architecture (§1)
Can the result be trusted in real work
reliability = risk management"]:::h1 H2["② Work productivity (§2)
Does the gain stay and keep running
personal skill → team capability"]:::h2 H3["③ Tools · models (§3)
Chosen knowing the limits
technical decision-making"]:::h3 classDef root fill:#EFEBFE,stroke:#5B3FD9,color:#3B2A82,stroke-width:2.4px; classDef h1 fill:#EFEBFE,stroke:#5B3FD9,color:#3B2A82,stroke-width:1.5px; classDef h2 fill:#fdf4e8,stroke:#a8560a,color:#7a3d06,stroke-width:1.5px; classDef h3 fill:#eef3f6,stroke:#33505f,color:#333C52,stroke-width:1.5px;
| Topic (assignment prompt) | One line | Case · evidence |
|---|---|---|
| 1. Problem solving or architecture improvement |
On a problem whose answers cannot be graded, I made every value the AI produced traceable back to its source. accuracy → replaced by traceability |
💧 Case 1 · Hydrological survey cost verification — Korea Management Analysis Institute, government budget verification · private repository Four layers of verification — source comparison · channel verification (PDFs shown as images, never extracted) · cross-file invariants · independent second estimate Invariants 38 of 42 with zero error (the rest within ±1.7%) · two different files both state 355 sites · the ~40% gap against the independent path was not tuned away but attributed to exposed variables Calculation 10 hours → 1 minute. The goal is not speed but that someone who knows nothing about hydrological surveys can verify it in an hour ✈️ Case 2 · Aviation-law RAG — the same problem under different conditions · data, code and scores all public A ground-truth set can be built, so 45 configurations were graded automatically. The retrieval axis was made free — 0 API calls On a tie, take the cheaper one — adopted a 38% token saving (which in fact ranks answers higher) · rejected agentic at 27× · the biggest variable was chunking (coverage 0.136 → 0.864) [external grading] instructor's score 9/10 for completeness · first among the course participants |
| 2. Productivity gains using AI |
I left mechanisms so the gain reproduces without me — and those mechanisms are under test right now. the metric is not hours saved but the scope that reproduces after the owner changes |
The way the same organization works — meeting notes → AI proposal → human item-by-item approval → Board Five mechanisms — division of labour (extraction by AI · Requirement Engineering by human) · approval gate · task model · two-layer leak gate · judgment recorded as ADRs What the gates actually caught, three times — overturned an assignment (domain) · filtered out internal terminology (security) · reverted "it's done" twice (completion) [stated] guideline review 10h → 2h [log] 3 ADRs · 6 learning lessons · three team repositories onto one Board And that metric is under test right now — since mid-June my available time dropped to two hours a day and two teammates joined. I am still watching how it turns out. |
| 3. Tool and model analysis |
I observed the limits myself — in a different place for each model — wrote them down, and chose knowing them. | Primary tool Claude Code — learning mode and flat-rate pricing are the reasons. Not taste, but the result of measuring tools one at a time Six limits, each on its own model — Solar claims to know what it does not · confidence ≠ accuracy · tokens grow non-linearly in agentic loops · Gemini loses numbers and relationships on long input · GPT · Gemini cannot draw logical development · local models (8B·16B) are weak on narrow domains The shared conclusion — take facts from tools and source documents; leave the model only judgment and assembly Why on-premise is separate engineering when data cannot leave the building |
| Appendix A. outside the prompt a system in production |
I applied the same principle to a system I run alone. not an organizational case, so it was moved out of the main text — but it sits on the same line |
Single-node k3s — about 20 services under *.bit-habit.com · 4 ARM cores · $0/monthWhat I asked AI for was not to build the infrastructure but to describe the running infrastructure so a third party can falsify it Three marks of a falsifiable document — leave the ❌ on the scorecard · name what you chose not to fix · commit the ordering as a decision Outage postmortem — 200 OK served the wrong site for 103 days. No check that only asked "did it respond?" could see it → checks now assert the response body, not the status code |
What this topic asks — can the result be trusted enough to put into real work.
Two projects are laid out in the same order — background → key prompts → verification. Read one, and the other puts the same things in the same places.
I chose these two because the presence or absence of a ground-truth set splits the entire verification design. The domains (river budgets / aviation law) have nothing to do with each other, and that is what separates what the design earned from what the domain gave.
flowchart TB
subgraph GA["💧 Case 1 · hydrology · no ground truth"]
direction LR
A1["1-1 Background"]:::s1 --> A2["1-2 Key prompts"]:::s1 --> A3["1-3 Verification
traceable to the source"]:::s1
end
subgraph GB["✈️ Case 2 · aviation RAG · ground truth exists"]
direction LR
B1["1-4 Background"]:::s1 --> B2["1-5 Key prompts"]:::s1 --> B3["1-6 Verification
hundreds of runs, auto-graded"]:::s1
end
GA --> GB
classDef s1 fill:#EFEBFE,stroke:#5B3FD9,color:#3B2A82,stroke-width:1.3px;
The point is to trace everything back to the standards the state has published, not to instinct or custom.
flowchart LR A["Allocated budget
per-site annual unit cost
money actually set aside"]:::a B["Back-calculated from the Manual
cost-plus-fixed-fee
money the standard implies"]:::b A --- Q{{"The two differ
at which assumption?"}}:::q --- B Q --> T["Trace each assumption back to the source
measurement count · staffing · adjustment factors …"]:::t classDef a fill:#fdf4e8,stroke:#a8560a,color:#7a3d06,stroke-width:1.3px; classDef b fill:#EFEBFE,stroke:#5B3FD9,color:#3B2A82,stroke-width:1.3px; classDef q fill:#EFEBFE,color:#3B2A82,stroke:#5B3FD9,stroke-width:2.4px; classDef t fill:#eef3f6,stroke:#33505f,color:#333C52,stroke-width:1.3px;
| What it did not do | What it did |
|---|---|
| Rule on which side is right | Put the two values side by side and let the source of the difference be traced |
| Substitute "the AI calculated it" for evidence | Attach the source document and cell to every assumption |
Three things are traced — how many measurements were assumed, how many people and hours per measurement, and which adjustment factors were applied. Change an assumption and the screen shows how the numbers move.
| Previous (manual Excel) | The app | |
|---|---|---|
| Estimation | over 10 hours | 1 minute |
| Verification — hydrology expert | not separated from estimation | about 10 minutes |
| Verification — non-expert | effectively impossible | about 1 hour ← this is the real goal |
That last row is the actual goal of the project: letting someone who knows nothing about hydrological surveys verify the work within an hour, just by following the evidence the app presents. It is about increasing the number of people who can verify.
So I replaced accuracy with traceability. Instead of grading whether a value is right, the criterion became whether every number can be traced back to its source — because if it can be compared by eye, you can say it is wrong even without knowing the right answer.
Instead of a polished summary, the first prompt is kept raw. It came from audio dictation, so the sentences are rough and there are typos ("파악을 할 수 있느", "validtion") — which is exactly why it shows the flow of thought rather than a conclusion. Only the key parts are highlighted. (One internal data folder name is masked.)
강 별로 수문조사들을 한 것들이 다 저장되어 있는 데 너무 내용이 많고 그 예산이라고 할만한 부분도 카테고리가 너무 많다. 그래서 이 전체적으로 파악이 안되는데. 파악을 할 수 있느. 어떻게 보면 1분만에 이해할 수 있는 적절한 spread sheet와 인사이트를 보여주는 html을 만들어주고, 그 후 10분 정도 시간 들여서 이해할 수 있는 html도 만들어주고. 그 다음에 결국에는 궁극적으로 내가 원하는것은 1개 강의 수문을 조사시 몇명이 몇시간 얼마의 비용이 들어가는지 분석하는 것이다. 하지만 이게 바로 하게 되면 환각이 일어날수도있고, 이게 나름의 방정식일텐데 이해하기가 어려울 수도 있다. 마치 선형회귀로 서울 아파트 가격을 예측할때 다양한 feature들을 고려해서 더 정확하게 예측할 수 있겠다만, 그러면 이해가 안되니 heuristic하게 일단 size만 가지고 예측하는 것처럼. 처음에는 아주 간단한 마치 하나의 feature 고려하는 것처럼 정확도는 떨어지더라도 validtion이 될 수 있는 방향으로 해야겟다. html을 만들때 아무래도 streamlit으로 해야될 거 같으니. 아까 말한것과 다르게 html이 아니라 streamlit으로 만들어줘. 다시한번 말하는데 validation이 가장 중요하니, 가 문장의 근거는 실제 [내부 데이터]를 한번 가공해서 그 데이터를 매번 citation해줘.
Original prompt, in Korean — kept verbatim.
The line of thought inside that one paragraph
Not a single line about code. Every requirement is about "how will I trust this", not "what shall we build".
This is the most misread part. It does not mean "make me three screens", nor "I will cross-check three results".
D24×E24=F24). All figures here are masked. Even reading only the remaining sentences, you can see what this screen does — every conclusion carries where it came from. And this screen was not a showpiece: the fourth item found that "the Standard Estimate Manual already prescribes person-days per measurement", and it ends with → used on the cost model v0 page. The key to the final calculation was picked up in the forest.
The conversation that followed is carried below in 1-2-4~1-2-8 as raw (masked) text, and the outcome is organized in 1-3 — the process of turning back an AI that had mistaken the purpose, refusing coordinate citations, and distrusting the extraction channel itself.
How the conversation developed — five corrections
In every one, the AI was wrong first and I found it and changed direction.
아이고 니가 목적을 완전히 헷갈렸는데 … 우리가 원가 검증을 하는 프로젝트를 하고 있거든. 이 예산이 실제 그 법령하고 맞는지를 항상 보는 …
Original prompt, in Korean — kept verbatim.
누가 그냥 todo를 해줘. 비용모델은 1개 강의 수문 조사시 몇명이 몇시간 얼마의 비용인지 부터 아는거로 하자.
새로운 비용모델을 만들자. 즉 매우 지엽적인 수문 1개 조사시에 몇명이 몇시간 얼마의 비용이 들어가는 지. 즉 특정 수문을 현재 조건을 보고 법령에 맞게 실제로 나오는지. 다른 예산은 일단 필요없다.
Original prompt, in Korean — kept verbatim.
그 근거라는 부분을 spreadsheet의 일부를 복사붙여넣기 해서 누구나 spreadsheet에서 온 것처럼 해줘. … 새로운 수식이 나오면 그걸 근거를 보여줘
Original prompt, in Korean — kept verbatim.
📎 source: unit-price table D4. It looks rigorous but cannot be checked on the spot, and above all a fabricated coordinate is outwardly indistinguishable from a real one.
B101:D103) along with the rows before and after the cited one — you need the neighbours to judge whether a value was truncated or is simply like that. Amounts, addresses and internal file names are masked; the grid structure is exactly as in the source.pdf는 확실히 표로 되어 있으니 읽기가 어렵네. pdf는 스크린샷도 그냥 찍어서 근거로 보여주라
Original prompt, in Korean — kept verbatim.
Extracting the staffing table as text actually produces this.
(1) 평ㆍ저수 유량측정회0.050.650.850.90②●
현장 출동인원이 몇명이 필요한지는 원래 알 수 없나? … 적용보정계수 같이 수식으로 계산한것들은 그 수식까지 표현해야지. 모든 수식은 다 표현해줘.
Original prompt, in Korean — kept verbatim.
3. There was nothing to write in the formula slot as evidence.⌈2.45⌉ = 3 people, with an upper bound of 4 given the grade composition.A constant was turned into a derivation. Without demanding the formula, that spot would never have been visible.
1.0 gives no way to check why it is 1.0, but unfolding the decision rule alongside makes the evidence comparable right there: 100 ≤ B=150 < 200 → factor 1.0. Page 7 of the published manual, the source of the rule, is attached as the original image.This is the core of the work — the validation that AI output passes through before it enters real use. In an environment where data cannot leave the building and a wrong value is immediately a legal and financial risk, reliability was not a feature but a requirement.
Since there is no single correct answer, nothing can be scored. Instead every value is made traceable to its source, so that if something is wrong, a person can find where.
flowchart TB A["AI output"]:::src A --> B["Source comparison
excerpt keeping row·column coords"]:::dev A --> C["Channel verification
PDF as image, table intact"]:::dev A --> D["Cross-file invariants
do other files say the same"]:::dev A --> E["Independent 2nd estimate
a path that never sees the budget"]:::dev B --> F["Put into real use"]:::ok C --> F D --> F E --> F D -.->|"mismatches are not hidden"| G["published as known data issues"]:::warn classDef src fill:#eef3f6,stroke:#33505f,color:#333C52,stroke-width:1.3px; classDef dev fill:#EFEBFE,stroke:#5B3FD9,color:#3B2A82,stroke-width:1.3px; classDef ok fill:#5B3FD9,stroke:#3A2A7A,color:#ffffff,stroke-width:1.4px; classDef warn fill:#fdf4e8,stroke:#a8560a,color:#7a3d06,stroke-width:1.3px;
Below is the actual code — not a claim, but how it runs. (File names and amounts are parameters, so nothing is exposed; the logic is unchanged.)
flowchart LR Q["cell to cite
e.g. E9"]:::inp --> R["raw_slice
keeps Excel row no. · column letter"]:::act R --> S["_row_style
called for every table row"]:::act S --> T{"is this cell
in the cited list"}:::dec T -->|"cell matches"| U["deep yellow + bold"]:::ok T -->|"row only"| V["pale yellow"]:::ok T -->|"no"| W["no colour"]:::inp classDef inp fill:#eef3f6,stroke:#33505f,color:#333C52,stroke-width:1.2px; classDef act fill:#EFEBFE,stroke:#5B3FD9,color:#3B2A82,stroke-width:1.2px; classDef dec fill:#fdf4e8,stroke:#a8560a,color:#7a3d06,stroke-width:1.3px; classDef ok fill:#eaf6f0,stroke:#0a7048,color:#08512f,stroke-width:1.2px; classDef bad fill:#fdeeec,stroke:#a3241d,color:#7a1a15,stroke-width:1.2px;
def evidence(rel_file, sheet_name, row_from, row_to, col_from="A", col_to=None,
note="", expanded=False, hl_rows=None, hl_cells=None):
"""Attach evidence as an excerpt of the original spreadsheet, highlighting cited rows (pale yellow) and cells (deep yellow)."""
if hl_rows is None:
hl_rows = []
if hl_cells is None:
hl_cells = []
rows = set(hl_rows) # Excel row numbers to highlight
cells = set(hl_cells) # cell coordinates to highlight (e.g. "E9")
df = raw_slice(rel_file, sheet_name, row_from, row_to, col_from, col_to)
# callback pandas Styler calls per row (same role as a function pointer argument in C)
def _row_style(row):
out = []
for col in df.columns:
cell_name = col + str(row.name) # column letter + row number = cell coord (e.g. "E9")
if cell_name in cells:
out.append("background-color:#ffd54a; font-weight:600") # cited cell
elif row.name in rows:
out.append("background-color:#fff3c4") # cited row
else:
out.append("")
return out
# → an invented coordinate and a real one are separated by colour on screen.
_row_style rendered directly as colour. Keeping the neighbouring rows (50·52) was deliberate too. Internal file names are masked.
flowchart LR
A["PDF evidence requested"]:::inp --> B{"is there a rendered
image of that page"}:::dec
B -->|"yes"| C["show the image as is
table layout survives"]:::ok
B -->|"no"| D["fall back to extracted text
accept that tables may break"]:::bad
classDef inp fill:#eef3f6,stroke:#33505f,color:#333C52,stroke-width:1.2px;
classDef act fill:#EFEBFE,stroke:#5B3FD9,color:#3B2A82,stroke-width:1.2px;
classDef dec fill:#fdf4e8,stroke:#a8560a,color:#7a3d06,stroke-width:1.3px;
classDef ok fill:#eaf6f0,stroke:#0a7048,color:#08512f,stroke-width:1.2px;
classDef bad fill:#fdeeec,stroke:#a3241d,color:#7a1a15,stroke-width:1.2px;
def evidence_pdf(label, txt_name, note="", expanded=False, hl=None):
"""PDF evidence: show a page screenshot (cited part highlighted). Fall back to text if absent."""
title = "📎 근거 발췌 — `표준품셈(2023).pdf` " + label
with st.expander(title, expanded=expanded):
png = DATA / (txt_name + ".png")
if png.exists():
st.image(str(png), width='stretch') # the image as is — nothing breaks the table
st.caption("↑ PDF 페이지 스크린샷 (etl.py가 렌더링, 🟡 = 인용 문구). " + note)
else:
st.code(_read_txt(txt_name), language=None) # fallback: machine-extracted text
st.caption("↑ PDF에서 기계 추출한 원문. " + note)
# raw_slice — slice into a 2-D array keeping Excel coordinates (row number, column letter) alive
data = [] # data[row][col]
row_names = [] # Excel row numbers as the index
for r in range(row_from, row_to + 1):
line = []
for c in range(c0, c1 + 1):
line.append(ws.cell(r, c).value)
data.append(line)
row_names.append(r)
This first checks whether the baseline the last mechanism will use is sound. The per-site unit price in the budget table is not a value to accept just because it is written down, and if the baseline is wrong, however precisely the gap (%) is computed it means nothing.
Where the previous three mechanisms make things checkable by a person, this check catches things even when nobody looks. A self-consistent hallucination cannot pass it.
| Invariant checked | How | Result |
|---|---|---|
quantity × unit price = total | Recompute the product without looking at the total cell, then compare | 38 of 42 exact · 4 within ±1.7% |
| Number of survey sites | Counted separately from the site-status file and from a separate travel-cost file | Both give 355 |
| Before / after revision | Row-by-row comparison | 7 mismatching rows printed individually |
| Missing values | Check whether the address carries a province | 1 case found |
flowchart TB
A["row list: records"]:::inp --> B{"any blank among
qty · price · total"}:::dec
B -->|"yes"| S["not eligible — skip"]:::inp
B -->|"no"| C["model = qty × price
the total cell is not read"]:::act
C --> D["err = total − model"]:::act
D --> E{"is the error below 0.5"}:::dec
E -->|"yes"| F["exact-match count +1"]:::ok
E -->|"no"| G["update max error rate, publish"]:::bad
classDef inp fill:#eef3f6,stroke:#33505f,color:#333C52,stroke-width:1.2px;
classDef act fill:#EFEBFE,stroke:#5B3FD9,color:#3B2A82,stroke-width:1.2px;
classDef dec fill:#fdf4e8,stroke:#a8560a,color:#7a3d06,stroke-width:1.3px;
classDef ok fill:#eaf6f0,stroke:#0a7048,color:#08512f,stroke-width:1.2px;
classDef bad fill:#fdeeec,stroke:#a3241d,color:#7a1a15,stroke-width:1.2px;
# Cross-file invariant check: quantity × unit price = total. Recompute the product without reading the total cell, then compare. records = items.to_dict("records") # DataFrame → array of dicts (iterated like an array of structs in C) n_exact = 0 # count of rows matching with zero error max_err_pct = 0.0 # maximum error rate (%) for i in range(len(records)): row = records[i] qty, price, total_val = row["수량"], row["단가_백만원"], row["총계_백만원"] if pd.isna(qty) or pd.isna(price) or pd.isna(total_val): continue # if any of the three is blank, the row is not eligible model = qty * price # these are facts stated by different cells, so err = total_val - model # a self-consistent hallucination cannot satisfy this equation if abs(err) < 0.5: n_exact = n_exact + 1 if total_val != 0: # rows with a zero total are excluded from the error rate err_pct = abs(err) / total_val * 100.0 if err_pct > max_err_pct: max_err_pct = err_pct
quantity × unit price, without reading the total cell, matches the original total. The sentence above is its summary (38 of 42 with zero error, the other 4 within ±1.7%). The unit-price, total and model columns are masked because they are internal budget amounts, but what this mechanism proves is not those values but the equation among the three, so masking leaves the argument intact.How the 4 mismatches were handled
| Where | They were not random but clustered in one item group — the new programme line being converted to automated measurement. |
|---|---|
| Why | The total is not an Excel formula but a separately computed value, and the unit price is that value rounded to an integer for display, so dividing the total by the quantity diverges below the decimal point. |
| Outcome | A single equation caught a 0.13% difference no eye would find — and narrowed it down to which item group, at that. |
| Therefore | The items used as the baseline held with zero error across all years. The divergences were not in the baseline, so the final comparison could proceed as planned. Without this check, there would have been no way even to ask whether the baseline was sound. |
The [data] / [assumption] labelling convention settled here
| What | Values with a confirmed source are distinguished on screen from assumptions that were filled in. |
|---|---|
| Why | When verification fails, "is the data wrong or is the assumption wrong" has to be separated immediately. Mixed together, that is impossible. |
| In practice | When the AI plausibly filled in a particular unit price without a source, that value was marked [assumption] and left editable by the user. |
The same cost is computed by two paths that know nothing of each other. Like debit = credit in double-entry bookkeeping, or two independent witnesses.
| Path A · from the budget | Path B · from the law | |
|---|---|---|
| Direction | top-down — allocated budget → per-site unit cost | bottom-up — Standard Estimate Manual × published wage rates → cost |
| Input | Tender material | Published law and published wage rates — never sees the budget |
| Precondition | A's unit price is used as the baseline only after the check in 1-3-4. If the baseline is wrong, the gap is meaningless. | |
| If the two agree | They have verified each other. | |
| If they differ | It is a signal of where something is wrong. In practice a gap of about 40% appeared, and rather than forcing the model to match, the causes of the gap (published wage rates · measurement counts · water-surface width) were exposed as adjustable variables and attributed. | |
flowchart TB L["Manual person-days
by grade"]:::inp --> M["× adjustment factor
derived from width band"]:::act M --> N["× published wage rates
summed by grade = direct labour"]:::act N --> O["× overhead·fee + travel"]:::act O --> P["annual cost
the budget has never been read"]:::ok P --> R{"gap = annual vs UNIT
how far apart"}:::dec U["allocated unit cost UNIT
an entirely separate source"]:::inp -.-> R R --> Z["expose the causes as adjustable variables"]:::act classDef inp fill:#eef3f6,stroke:#33505f,color:#333C52,stroke-width:1.2px; classDef act fill:#EFEBFE,stroke:#5B3FD9,color:#3B2A82,stroke-width:1.2px; classDef dec fill:#fdf4e8,stroke:#a8560a,color:#7a3d06,stroke-width:1.3px; classDef ok fill:#eaf6f0,stroke:#0a7048,color:#08512f,stroke-width:1.2px; classDef bad fill:#fdeeec,stroke:#a3241d,color:#7a1a15,stroke-width:1.2px;
def once_cost(task_name, fct):
"""Payment for one measurement (travel included, VAT excluded) — the budget is never read."""
r = labor[labor["업무"] == task_name].iloc[0] # one row for this task from the manual
dl = 0.0 # running sum of direct labour cost
for g in GRADES:
man_days = float(r[g]) * fct # person-days by grade × adjustment factor
dl = dl + man_days * wages[g] # × published wage rate → accumulate
cost = dl * (1 + ovh_rate) * (1 + fee_rate) + team * fare * 2
return cost
# Direct labour for per-site fixed tasks: double loop over task rows × grades
fixed_records = fixed_tasks.to_dict("records")
fixed_dl = 0.0
for i in range(len(fixed_records)):
r = fixed_records[i]
for g in GRADES:
fixed_dl = fixed_dl + float(r[g]) * wages[g]
annual = (n_py*cost_py + n_hs*cost_hs + fixed_cost) * vat_mult # annual cost derived from the law alone
gap = (annual - UNIT) / UNIT * 100 # UNIT = allocated unit cost (value lives elsewhere). Difference between the two paths (%)
# → annual has never seen the budget. That is why the gap is a real signal.
cost ÷ (1+gap). So absolute amounts, ratios and component items all have to be masked together. The item and formula columns are kept, because this section's claim is about structure, not values — once you can see which terms sum to the annual cost and which formula each term comes from, the screen is verifiable without the numbers.
The four above are verification before shipping; this is after. What is said here becomes the input to the next cycle.
The analysis closed with a results briefing to the decision-maker, a non-developer. There were three points. (Names and amounts masked; summarized, not verbatim.)
To find and feed, the code has to be prepared in advance. The terms that keep recurring below (1-5·1-6) are exactly those assembly parts.
| Part | What it does (analogy) | Where the choice is |
|---|---|---|
| ① Split chunking | Cut 1,297 pages into searchable pieces — breaking a book down to sticky-note size | Cut on § clause boundaries, or by character count? Performance turns on this. |
| ② Index embedding | Turn each piece into a meaning coordinate — a map that places similar meanings close together | Which embedding model. Even with no shared words, close meaning still matches. |
| ③ Retrieve search method | Pull the pieces that fit the question | By meaning (vector) · by word (keyword) · blend (hybrid) |
| ④ How many top-K | How many top pieces to hand over as grounds | Too few drops the grounds; too many lets noise in. |
| ⑤ Score LLM judge | Whether the answer is good is graded by another model — a grader instead of a person | Accurate, but it costs money every call. |
alpha=0.5 weighted sum. Five places in the public docs were corrected.This section shows the principles set in 1-2 operating in the same places even as the domain changes. Here too the prompts are kept raw, typos and dictation artefacts included.
Context — the AI described the hybrid search as RRF (rank fusion), and that description went straight into five places in the public documentation: diagrams, glossary, body text. Yet reading it, I never quite got it.
아니, 내가 궁금한건 앙상블을 어떻게 한지 아직 이해안돼. 어느 비율로 어떤 것을 쓰고, 언제 어떤 임베딩을 썼나?
Original prompt, in Korean — kept verbatim.
alpha = 0.5 weighted sum: normalize scores to 0–1 and add them in halves.Context — after implementing agentic RAG itself and showing a quality advantage, the AI handed the decision over with Your call. Which way should we settle on?
지금 에이전틱으로 하면 그래도 10배 정도의 토큰 소모가 있는거 아니가? 우리는 단일 래그로 했을 때 복잡한 문제도 이미 잘 풀었다는것을 확인했어. 이정도 데이터에서는 에이전틱 루프 보다는 단일 래그도 잘 된다면 굳이 토큰 많이 써가면서 에이전트를 붙일 필요성ㅇ ㅣ있을까?
Original prompt, in Korean — kept verbatim.
harness/agent_rag.py and only dropped from the deployment. It will be needed again once the corpus grows.Context — I was running two sessions at once. One handled experiment code, the other documentation, both on the same repository. That leads to one session committing the other's unfinished work.
그리고 너가 커밋할때는 너가 작업한것만 올려줘. 너가 작업하지 않은건 그대로 둬
claude-memory-backup 에서 커밋 관련된 모든 엠디 파일에 '한 세션에서는 그 세션이 작업한 것만 커밋한다'는 것을 추가해줘.
Original prompt, in Korean — kept verbatim.
git worktree) makes touching another session's files impossible to begin with. Parallel sessions have run on worktrees ever since.alpha=0.5),Where verification in Case 1 was about making things traceable by a person, here it is about making them gradable by a machine. Two mechanisms were built, and 45 configurations were run on top of them.
Holdout — sitting the exam with questions you tuned on inflates the score. So a few questions are set aside from the start as a "secret exam" used only for grading, never for tuning. I wrote 14 by hand and split them by purpose into three.
| Questions | Purpose | Why split |
|---|---|---|
| 4 | Final exam — never used for tuning (split:"final") | Fitting configurations to the remaining questions makes you strong only on those questions. Studying from the exam paper raises the score, not the ability. |
| 3 | Refusal is the right answer — out-of-scope questions | Measuring only how well it answers puts the model that bluffs about what it does not know in first place. |
| 7 | For tuning | The questions used to fit configurations. |
The refusal questions weren't there at first — I was only writing in-scope questions until I realized late that "does it avoid making up an answer to an out-of-scope question" also had to be tested, and added them.
| Retrieval grading retrieval | Generation grading generation | |
|---|---|---|
| What is measured | Is the correct § among the retrieved results | The quality of the answer actually produced |
| Grading method | Compared in code — local embeddings | LLM judge |
| Cost | 0 API calls · $0 | Charged per call |
| Execution | All 45 configurations, overnight | Only the few survivors, after retrieval was settled |
Because retrieval grading runs in code, all 45 configurations were swept for $0, and the paid generation grading was spent only on the few survivors — the same volume of experiments at roughly a tenth of the cost. That said, neither the generation grading nor checking that the grading is right is free, so this is less "completely free" than calling the expensive grader as little as possible.
Coverage = the fraction of correct clauses retrieval actually found (found ÷ total correct). MRR = how high the correct answer ranked in the results (closer to 1 the higher). Both are retrieval grading, scored in code — which is why they could be applied to all 45 configurations.
| Configuration | Coverage | MRR | Tokens |
|---|---|---|---|
| § boundary · bge · hybrid · K8 | 0.864 | 0.636 | 17,284 |
| § boundary · bge · vector · K5 — adopted | 0.818 | 0.718 | 10,802 |
| char count · minilm · hybrid · K3 (last) | 0.136 | 0.182 | 2,939 |
| Judgment | Grounds |
|---|---|
| The difference is marginal | A coverage gap of 0.046 against first place (K8) — across 11 questions, effectively one question. Not a gap wide enough to decide on. |
| The adopted one is better | First place packs 8 chunks of evidence (K8), so it responds slowly. The adopted K5 uses 38% fewer tokens and answers faster, while ranking the correct answer higher (MRR 0.718 vs 0.636). It loses only 0.046 in coverage — put usability on the scale too and K5 wins. |
| On a tie, the cheaper one | In an on-premise deployment, both inference cost and response latency are product constraints. |
| Rejected for the same reason | The agentic retrieval loop grows tokens roughly quadratically (about 81k · 27× the single-shot path), too expensive for the gain. The deployment is single-shot; the loop was kept as a documented experiment. |
| The biggest variable | Chunking. Switching from character count to § clause boundaries moved coverage from 0.136 to 0.864. In regulation the clause is the unit of meaning, and cutting at 1,000 characters slices across it. |
Same here. After the automatic grading was done, what a person pointed out became the starting point of the next improvement.
Different conditions split the verification method. Here is where they split, on one page.
| Case 1 · 💧 hydrology cost verification | Case 2 · ✈️ llm-app-lab RAG | |
|---|---|---|
| Domain | River budgets · government standards | Aviation law (14 CFR) |
| Ground-truth set | None | Can be built (holdout) |
| Verification method | A person traces back to the source | Code grades automatically |
| Bottleneck | Can it be trusted | Too many configurations · grading costs money |
| What is the same | Never trust AI output as given — make it falsifiable | |
What this topic asks — does the gain remain as team capability rather than personal skill. And for that, how far can work be delegated to AI.
flowchart LR
M{{"productivity = the scope that reproduces
after the owner changes"}}:::root
M --> P["Meeting notes
where decisions are made"]:::s2
P --> A["AI — read and propose
quoting the supporting sentence"]:::s2
A --> V["Human — judge
approve · question · reject, item by item"]:::gate
V -->|"only what is approved"| B["GitHub Projects board
where the record lives"]:::s2
V -.->|"ask back if ambiguous"| P
classDef root fill:#EFEBFE,color:#3B2A82,stroke:#5B3FD9,stroke-width:2.4px;
classDef s2 fill:#fdf4e8,stroke:#a8560a,color:#7a3d06,stroke-width:1.3px;
classDef gate fill:#EFEBFE,stroke:#5B3FD9,color:#3B2A82,stroke-width:1.8px;
[stated] About 40 staff, of whom 3 are developers — the team lead (me) and two team members.
| Who | What they know | So |
|---|---|---|
| The decision-maker | What they want. Though not interested in AI as such — only whether it gets automated. | Delegates technical judgment and looks only at results. |
| Team lead | Attends the meetings, so gets the intent and the nuance. | Up to here it travels. |
| Team members | Know the meeting outcome but not what to build. | This is where it breaks. |
Meetings run over video, following whatever comes to mind. Two things are in that record at once.
| What survives transcription | What does not | So |
|---|---|---|
| Decided facts · items mentioned | Urgency · importance — carried by non-verbal expression and the nuance of tone. | Priority can only be set by someone who was in the meeting, and must be re-aligned with the decision-maker. |
| Stage | Who | What |
|---|---|---|
| Extraction | AI | Splits the transcript into chunks, reads line by line, pulls out Issues. Nothing is summarized wholesale, so no context is lost, and in practice almost everything is caught. |
| Requirement Engineering | Human | Splits the extracted Issues, writes the body and the checklist, and assigns urgency and importance. |
| Execution | Team members + AI agents | Take the organized Issue and work on it with AI agents. |
It starts from the premise that AI can be wrong. So what was designed is not "how to instruct it well" but "how to make it come back to a human when it is wrong".
| Permission | What |
|---|---|
| Done without asking | Observing the Board · searching for duplicates · drafting proposed changes |
| Per-item approval required | Every write. The default is item by item; blanket approval only when a human has seen the whole list and says so explicitly |
| Forbidden even with approval | Deletion · permission and visibility changes · writes outside the designated Board · code and Issues below the Board · exposing note content on GitHub |
| Always required | Quote verbatim the sentence from the notes that grounds each proposal · when ambiguous, do not guess — surface it and ask back |
Moving what was said in a meeting into a Board item, the altitude to write at kept wobbling. You can write the ultimate goal, or a single checklist line.
I fixed it with one test — if you can clearly answer "is this done or not?", it is at task altitude.
| Altitude | Test | Example | Goes to |
|---|---|---|---|
| Too high | No end, so doneness cannot be judged | Build a staffing recommendation system | Milestone |
| Task (standard) | Doneness can be answered | Add a filter to a given screen | Issue |
| Too low | A single checkbox line | Add a parameter to a function | task list |
| Layer | What | Why |
|---|---|---|
| 1 · Human review | Notes first go into a folder excluded from git tracking. Only what passes review moves into the repository. | Once pushed, deleting the file later still leaves it in history. The gate has to sit before the push. |
| 2 · Machine patterns | The promotion script blocks five categories: national ID, phone, card number, bank account, email | The last net for whatever human review missed. |
| Not done | Separating by branch | A staging branch also lands on the remote once pushed. It must be exclusion from tracking, not separation. |
| What was left | Content |
|---|---|
| 3 ADRs | Why the tooling moved · the task model · the safety contract. Each records why it was decided that way. |
| Rejected alternatives | Written alongside each record. E.g. — "write first, audit later" was rejected because irreversible actions cannot be undone after the fact. |
| Open questions | Pinned down as open — "These really are undecided. Written down so we do not pretend otherwise." |
| Abandoned paths | Tools explored and dropped were preserved read-only rather than deleted. Not a deletion but a record of the route. |
[stated] Changes felt directly in the organization.
| What | How it changed |
|---|---|
| Long-document review | One guideline document, 10 hours → 2 hours (about 80% less) |
| Meeting → Issue | Previously the notes were effectively thrown away. Now Issues are extracted from the transcript without omission and go to the Board. |
| Requirement Engineering | Still human work, but the more context is injected, the less there is to fix. |
| Execution | Work the team lead used to clear alone began to be shared by the team — not evenly yet (→ 2-3-5). |
[log] Verifiable in the repository and session records.
| Item | Value |
|---|---|
| Team repositories gathered onto one Board | 3 |
| Work items migrated to the Board | 8 (all of them) |
| ADRs | 3 |
| Tool-usage learning course | 6 lessons (5–15 min each) |
This is the evidence that the earlier mechanisms were not decoration. It is the record of the three things named at the head of this section actually being caught — because the proof that a system works is not speed but what a human blocked.
| What the AI did | What the human did | So |
|---|---|---|
| Paired Board items with repositories and proposed one as "nearly certain", ranked first | Overturned it, saying another item was correct | Domain judgment cannot be handed over. |
| Wrote a repository introduction — terminology identifying the internal domain remained | Caught it — "it has to be more general so as not to leak company information…" | In effect, the security standard from §1 applied to its own output. |
| Declared "done" | Sent it back twice | The introduction still described the old tooling, and the examples were internal work verbatim. |
At the head of this section I set "the scope that reproduces after the owner changes" as the metric. That metric is now being tested in a way I did not design.
| Point in time | State |
|---|---|
| May 2026 | System started · full-time on it. |
| Mid-June | Two team members joined. At the same time my available hours shrank to two a day. |
| Now | The team members mainly carry the work · my remaining role is coordination and review. |
This is not a one-time handover but a loop that keeps turning. A person stands where business language becomes development language, and that spot is passed every week. Two things need to rise — verification speed and accuracy. Raising only one means nothing.
| Where it is stuck | Current response | What remains |
|---|---|---|
| Issues lack detail Even organized and handed over, what to start with is unclear |
Keep injecting context into the AI so drafts need less fixing | Split approval into two points — ① is this a requirement worth starting ② does the implementation match that requirement. ①'s checklist becomes ②'s acceptance criteria. |
| Cannot get started with Claude Code Given the tool, they stall on the first move |
Demonstrating it alongside them — not explanation but a scene they can copy | Turn the demonstration into an asset. I have not yet decided the form in which to preserve what I show — the learning lessons are the beginning of it. |
| Intent is missed What the Issue says gets done, but anything beyond it must go through the team lead |
Priority judgment stays human — nuance does not survive transcription | There is no automatic verification. Attach §1's verification design (invariants · citation consistency) ahead of human approval, so approval becomes comparison rather than judgment. |
What this topic asks — are the tools chosen with their limits understood.
flowchart TB C1["Tools · models used
what was used"]:::s3 --> C2["Why chosen
why this tool — a strategic choice"]:::s3 --> C3["Strengths · limits
where to trust, where to doubt"]:::s3 classDef s3 fill:#eef3f6,stroke:#33505f,color:#333C52,stroke-width:1.3px;
| Tool | Where it is used | Why there |
|---|---|---|
| Claude Code | Code · verification · documents | learning mode · Plan · sessions · worktrees · conversation export. A flat rate means no cost anxiety about repeated experiments. |
| Perplexity (Comet browser) | Current news · light browser work | Faster than search, and with browser use it can even make simple configuration changes in a cloud console. ChatGPT Atlas has the same feature but its quota fills up quickly. |
| Gemini | Long videos · bulk documents | Drop in a YouTube link and absorb one to two hours at reading speed. But without custom instructions a generic summary is useless. |
| Ollama (local) | A feel for on-premise | Running it on a laptop made hardware, memory and load time tangible as product constraints. |
| Grok | Tried in conversation only | Relatively unconstrained and free-form. I have not decided where to use it — I am waiting because it is said to be coming to the car (Tesla). |
| GitHub Copilot | Briefly, at a hackathon | Tried it at a Microsoft-hosted hackathon. Unremarkable. If it were far cheaper perhaps, but Claude Code is not especially expensive, so there was no reason to switch back. |
| Upstage Solar | Service implementation (Booktoss) | It worked well as an agent that calls tools. Its limit is in 3-3-2 ①. |
Switch the output to learning under /config → Output style and, before giving the answer, it also explains why it did it that way and what should be learned. (The old command was /output-style, deprecated in v2.1.73 and removed in v2.1.91.)
TODO(human) markers in the code for a person to fill in is documented too — meaning "not a tool that writes it for me but a senior engineer and teacher", as stated above, is not my personal usage but the definition of the style itself.| What is different | So |
|---|---|
| It makes you type terminal commands yourself | Your hands remember. Typed for you, you still cannot type it next time. |
| It gives context and intent alongside | What remains is not "this was done" but "this was done because of that". |
| It inserts insights along the way | Something learned remains after the task ends. |
| Tool | Billing | Result |
|---|---|---|
| Cursor | Metered API | The design was good but it got expensive with use. It makes you hesitate to experiment. |
| Claude Code | Flat rate · around $100/month | The same work can be repeated without cost arithmetic — part of why the 45-configuration experiment in §1 was possible. |
| Gemini | Family plan | Google offered it cheaply per family, and I started using it seriously from then. Which tool gets used when is sometimes decided by the pricing plan. |
| GitHub Copilot | — | If it were far cheaper perhaps, but Claude Code is not especially expensive, so there was no reason to move. |
| Model | Where used | Limit observed there |
|---|---|---|
| Claude | Work overall | Confidently wrong (②) · in agentic loops tokens grow close to quadratically (③) |
| Upstage Solar | Service implementation | Works well as a tool-calling agent, but claims to know what it does not (①) |
| Gemini | Bulk input | On long transcripts, numbers and relationships break from the 2–3 hour mark (④) |
| GPT · Gemini | Images and video | Cannot draw logical development — plausible but wrong (⑤) |
| Local (8B·16B) | On-premise experiments | Weak on lesser-known localities and narrow domains (⑥) |
| Strength | Model observed | Evidence |
|---|---|---|
| ① Set a principle and it follows without instruction | Claude | After nailing down "validation matters most" once in §1-2, the four verification mechanisms in §1-3 appeared without individual instruction. Follow-up work maintained that standard without being told each time what to verify. → What a human must set is the principle; repeatedly applying it can be delegated. |
| ② Told to criticize its own plan, it actually bites | Claude | Asked to argue against its own RAG experiment plan, it produced six valid objections — "there is no reason to explore even the free axis sequentially", "binary recall is a false signal on multi-answer questions", "do not trust the scores before label verification". All were flaws in my original plan, and all went into the experiment design. |
| ③ Context does not break in a large repository | Claude | Through file exploration → edit → execution it held on to earlier decisions. Code you cannot write by looking at a single file — such as an invariant check spanning several files — comes from that. |
| ④ It leaves the reasoning in writing | Claude | The prose quality is good enough that, alongside the code, why it was done that way survives as documentation. For someone who treats "can a successor pick this up" (§2) as the productivity metric, that was the point, not a side effect. |
| Limit | Model observed | Evidence and conclusion |
|---|---|---|
| ① It claims to know what it does not | Solar | I built a library federated-search agent on the Upstage Solar API and it worked correctly. But when I named that service and asked "what is this", it answered as if it knew while it did not. → It can be trusted as an agent that calls tools, but you must not assume the model knows facts. Take facts from tools and source documents; leave judgment and assembly to the model. |
| ② Strength of confidence ≠ accuracy | Claude · Solar | Both ① and ③ below are cases of a model being confidently wrong. If confidence cannot be used as a signal, the only option is to make things falsifiable by structure. That is why the mechanisms in §1 were a requirement, not a choice. |
| ③ Non-linear cost growth | Claude | In an agentic loop that calls repeatedly to improve retrieval quality, tokens grew close to quadratically (about 81k · 27× the single-shot path — measured in §1-5-2). The quality gain was not proportionate. → On equal quality take the cheaper option; the loop was kept as a documented experiment. |
| ④ It does not read all of a long input | Gemini | Feeding meeting transcripts of 1, 2 and 10 hours, it held up to one hour and content began vanishing from two or three. Numbers and relationships in particular came out wrong. → Context size is a ceiling on accuracy, not a guarantee. Rather than inserting a lot, I moved to finding and inserting only what is needed (RAG). |
| ⑤ It cannot draw logical development | GPT · Gemini | Ask for matrix operations or network flows as images or video and the output is plausible but wrong. Korean infographics barely work either (GPT ✗ · Gemini ○). → I draw this part myself with Manim. Presentation can be delegated; logic cannot. |
| ⑥ Weak on small localities and narrow domains | Local (Ollama) | I have a benchmark of my own — "where is Gamman-dong?". It is a lesser-known neighbourhood in Busan, so whether a model has learned that far is a ruler for how much it knows. Local models (8B/16B class) said a lot of wrong things here. → Even so, there are places to use them. For short reactions like "nice · keep going" they are sufficient and affordable. But they cannot be used where judgment is required. |
| Situation | Choice | Reason |
|---|---|---|
| Exploration · learning · writing documents | Claude Code (learning mode) | Result and understanding both remain |
| Looking up a fact | Not the model — tools and source documents | Limit ① |
| Bulk repetitive processing | Single-shot first; loops only after measurement | Limit ③ |
| Sensitive data | Local execution or on-premise | Environments where data cannot leave the building really exist |
The cost verification in §1 could not send client data outside, and the meeting notes in §2 ran into the standard that "company material must not be handed to outside services". Most of the work I have done has been in places like that.
| Option | What I weighed |
|---|---|
| Local models | I have run them, but the level drops in narrow domains, so they cannot be used as they are. Useful for getting a feel. |
| Open-weight models | I intend to attach recently released ones to toy projects. But a model whose training process and alignment method cannot be inspected is hard to put where judgment itself becomes evidence. |
| Domestic on-premise | The option that actually remains where data cannot leave. Both cases in this document fall there. |
The claim in §2 is about an organization; this appendix is the record of applying the same principle to a system run by one person. It is not an organizational case, so it was moved out of the main text, but it sits on the same line as this document's theme — "make what AI wrote falsifiable by a third party".
The subject is a single-node k3s cluster I have run alone since 2025 — about 20 services under *.bit-habit.com run on it.
I passed a Linux certification in my first year of middle school. I passed it by rote, and I knew then that I had not understood it. I am thirty-eight now, so for 25 years since, I have been looking for ways to overturn that.
This cluster is the continuation of that, and I imposed the constraint myself — how far can one person get on one free machine. Four ARM cores, 20 services, $0 a month.
| Task | Who |
|---|---|
Collecting the cluster's actual state (kubectl measurements) | AI — the source to compare the document's claims against |
| Writing the 5-stage learning structure · checkpoints · glossary | AI — scaffolding |
| Deciding what to publish and what to record as a limit | Human — judgment |
| Touching the production cluster | Human — the AI is given no execution rights |
The result is infra.bit-habit.com. The source is in the public repository bookseal/bit-habit-infra, and the live state is checked externally every 60 seconds at status.bit-habit.com.
"The documentation is good" is an unfalsifiable claim. Instead I look at whether it is in a form a third party can compare against. Three things went in.
Secrets ❌ gitignored, applied by hand · Namespaces ⚠️ mostly a single default. And the conclusion is written in one line: "the gap from industry standard is not the tooling and not the services, it is secrets."selfHeal, the property one actually wants from GitOps.habit.bit-habit.com served a different site for months. Not an error page — a valid certificate and 200 OK, serving a perfectly wrong site. Because the uptime monitor and my own status page both asked only "did a 200 come back?", the incident was invisible to every automated check.
Diagnosis went by layer-wise bisection — at each step, ask "is the problem above or below this layer" and cut one side away. The decisive move was calling the app's Service directly from inside the cluster. The app was fine, so the fault lay in front of it. The real cause was two independent failures overlapping.
flowchart TB B["Browser requests
habit.bit-habit.com"]:::s2b --> T["Traefik reads the routing table"]:::s2b T --> F1["Failure ①
rule points at the wrong Service
portfolio ← not the app"]:::bad F1 --> N["nginx in the portfolio Pod
receives the request"]:::s2b N --> F2["Failure ②
no server_name matches this host,
so it falls back to the default block"]:::bad F2 --> R["200 OK + the wrong site
no error anywhere"]:::bad APP["Flutter app
fine · healthy · unreachable
0 traffic for 103 days"]:::ghost classDef s2b fill:#EFEBFE,stroke:#5B3FD9,color:#3B2A82,stroke-width:1.3px; classDef bad fill:#fdeeec,stroke:#a3241d,color:#7a1a15,stroke-width:1.6px; classDef ghost fill:#f2f2f4,stroke:#8a8a95,color:#55555f,stroke-dasharray:4 3;
The root cause was not a routing bug. It was a single-source-of-truth bug. The app existed only in the cluster and in no repository at all. So the one line pointing at that app lived in a file that did not know the app existed. An ownerless rule drifts, and nobody notices.
apply quietly reverts it.| Why | What I got |
|---|---|
| Learning was the point | I had seen k3s while evaluating other people's assignments, but without building it myself I did not know it. It is the standard I have kept for 25 years since passing a certification by rote in middle school — what must remain is understanding, not the artifact. |
| I wanted my own server | I wanted to see how far one free machine goes. Certificates, routing, deployment, incidents — once all of it passes through your own hands, you get a feel for it. |
kubectl was delegated to the AI. That is the source to compare the document's claims against, and a human transcribing it by hand is more likely to get it wrong.git reset --hard origin/main.authorized_keys with a forced command — whatever command arrives, only the one fixed script runs.Before publication, everything was substituted exhaustively against the following criteria and re-checked by searching again.
| Target | Treatment |
|---|---|
| Names of contracting authorities, agencies, clients | Replaced with [contracting authority] and similar |
| Internal team and unit names | Removed |
| Facility and site addresses | Removed (counts kept). Site names published by the government, such as the national observation network, are kept so the screens remain readable |
| Internal budget amounts in absolute terms | All removed; only ratios used (±1.7%, about 40%) |
| Internal file names | Replaced with generic names |
| Local paths · accounts | Removed or generalized |
| IPs · API keys · tokens · passwords | Removed after an exhaustive search of text and logs |
| Personal data (names, contact details, etc.) | Exhaustive search found none |
| Published documents such as the Standard Estimate Manual | Quoted as is, being published government material |
.gitignore was built on the standard that "statutory and manual PDFs are published documents, so include them; internal budget spreadsheets are excluded".
AI session logs are a learning asset but are not published as they are — terminal output drags along absolute paths, environment values and credentials, so the exporter script is tracked while its output is excluded.The public repositories and live sites that support each claim in the text. You can open them and check directly.
| What it supports | Repository · live |
|---|---|
| §1-4 ~ §1-6 Case 2 — ground-truth set · 45-configuration benchmark · grading code | github.com/bookseal/llm-app-lab llm-app-lab.bit-habit.com (live) |
| All of §2 — agent operating rules (CLAUDE.md) · ADRs · Board scripts | KIBA-Automation/project_management_with_ai_agent Raw meeting notes are private — meetings/ is excluded from git tracking |
| §3 limit ① library federated-search agent (built on the Solar API and working, but does not know its own name) |
github.com/bookseal/Booktoss booktoss.bit-habit.com (live) |
| Publishing the limits of the operating and observability infrastructure as open problems | github.com/bookseal/bit-habit-infra status.bit-habit.com (live status) |
What is not publishedThe repository for the cost-verification app, the central case of this document, is private because it handles client data. The §1 screens above have internal budget figures, survey site addresses and internal file names masked, leaving only the published Standard Estimate Manual (Appendix B). Not being able to show the strongest evidence as it is, is the price accepted in this kind of work.