Files
document-haness/.agents/skills/rewriting-technical-prose-naturally/SKILL.md
T

30 KiB
Raw Blame History

name, description
name description
rewriting-technical-prose-naturally Use when an existing Korean technical document, section, or heading already contains grounded facts but sounds AI-written, slogan-like, overly polished, abstract, compressed, or mechanically contrasted and must be rewritten without changing its technical meaning.

Rewriting Technical Prose Naturally

Scope

Rewrite the style of existing Korean technical prose so it reads like a Korean engineer wrote it. Do not use this skill to create the technical content, fill an evidence gap, correct an implementation, or add a claim about this system that the source did not make.

Two things that look like new content but are not, and that this skill is expected to supply: the standard definition of a term the source already uses, and the ordering slots in references/document-skeleton.md — moving an existing definition ahead of its first use, or an existing outcome into the closing. Both rearrange or unpack what is already there. Neither invents a fact.

Priority: source preservation > natural Korean > polish. If preservation and naturalness conflict, keep the meaning — but fix the sentence by adding a short clause that states the condition, not by twisting a word into a shape no one uses. A sentence that is technically exact and unspeakable is a sentence that still needs work.

Before the first rewrite in a task, read both references:

Read the complete source and the nearby context needed to interpret pronouns, comparisons, and causes. Do not rewrite an isolated paragraph when its protected meaning depends on the surrounding section.

Establish the meaning contract

Make an internal claim ledger before editing. Do not print it unless asked. Record:

  • every number, sign, unit, date, version, identifier, annotation, command, path, status, and observed output;
  • success and failure results;
  • each stated cause and its stated result;
  • comparison targets and axes;
  • environment, dataset, topology, timing, and other verification conditions;
  • confirmed facts, inferences, possibilities, assumptions, recommendations, unknowns, and excluded scope;
  • exceptions, limitations, and facts the source explicitly did not verify.

Every material sentence in the rewrite must map to the source ledger. Every material source claim must remain represented. Do not combine claims when the combination creates a stronger generalization.

Structure comes from the source, not from a checklist

An earlier version of this skill listed nine slots a document "must have" and a checker that failed a document for missing them. That was wrong, and it produced a new defect: every rewrite came out in the same order — 요약 → 지도 → 호출 순서 → 테스트 → 공백 → 다음 읽기 — with a Findings list at the end. The sentences read like Korean; the document read like a report generator's stable output format.

references/document-skeleton.md records what five reference articles happen to do. It is an observation, not a form to fill in. Read it to see what moves exist, then let the source decide which of them this document needs.

Five things not to do

  1. Do not promote every verified fact to a section. A code reading turns up dozens of true observations. Only the ones the document's central question needs belong in the flow. The rest stay out, even though you confirmed them and it feels wasteful to drop them. Wanting to include everything confirmed is the most reliable machine tell there is.
  2. Do not build a fixed running order. No document owes you 지도 → 순서 → 테스트 → 공백 → 다음 읽기. Two documents about the same subsystem should not have the same section skeleton.
  3. Do not re-package what the body already said as a closing Findings list. Eight bullets of "현재 구현 공백" after the body already explained each one reads as an agent's analysis output, not as a person writing. If a limitation matters, it belongs next to the thing it limits.
  4. Do not write sentences that instruct the reader how to think. 먼저 결론을 구분해야 합니다, 여기서 typed label과 end-to-end 동작을 구분해야 합니다 — go straight to the event instead: CacheAsideExecutor까지 따라가면 동작이 달라집니다. One or two orienting sentences in a whole document is plenty; more than that and you are narrating your own analysis process.
  5. Do not keep working notes in the published document. 다음에 열어볼 source 순서, 잘못 읽기 쉬운 지점 are an agent's memo to itself. A reader did not ask what you plan to open next.

What to keep

Where the source genuinely carries one of these, keep it and put it in the right place: what the document is about, who it is for and what they need to know first, a definition before its first use, what happened and why. A slot the source is silent about stays absent — and so does a slot the source could fill but this particular document does not need.

Write Korean, not translated Korean

This is the part that keeps failing. Details and quoted corpus examples are in references/korean-tech-blog-register.md; the rules below are the ones to apply on every sentence.

Define the term before you use it

At the first appearance of an API name, metric, counter, annotation, or domain word, write one sentence saying what it is and what it does. Korean tech blogs open this way as a matter of course: MDC(Mapped Diagnostic Context)는 ... 메타 정보를 넣고 관리하는 공간입니다, 화면에 렌더링되어 사용자에게 노출되는 문자열을 '문구'라고 하겠습니다.

Keep the original name. Expand an acronym in parentheses at first use. Where a plain-text field cannot carry a code name, put the meaning first and the name in parentheses: 준비된 SQL 문장(PreparedStatement).

This is not "adding content." A standard definition of a term the source already uses is prerequisite knowledge the reader needs, and supplying it is part of the job. What you may not add is a new claim about this system, this measurement, or this decision. Definition: yes. New finding: no.

A definition you can only produce by reading the identifier's name is not a definition — it is a guess. deniedCommandCount는 거절된 명령의 수이고 rejectedRequestCount는 거절된 요청의 수다 looks like a harmless gloss, but if the source never said what either one counts, you just decided it. A definition may come from the source document, the codebase, or the framework's own documentation — nowhere else. When none of those give you the meaning, keep the name, say what the source does say, and leave the rest alone: 두 값은 1과 200으로 달랐습니다. 각각이 무엇을 세는지는 이 문서에서 확인하지 않았습니다. This applies hardest to internal counters and metrics, where a plausible-sounding gloss silently redefines what was measured.

Write Korean words in Korean. Latin script is for identifiers only

This is the single largest difference between this repository's prose and the reference articles, and the earlier version of this skill made it worse by telling you to "keep the name" without saying which names.

Measured over the five reference articles versus nine rewritten sections here:

우아한형제들 이 저장소
문장당 영문 토큰 1.4 4.4
글자 중 한글 비율 0.58 0.34
쿼리 / query 66 / 5 5 / 4
캐시 / cache 2 / 0 0 / 19
상태 / status 48 / 0 6 / 7
설정 / config 49 / 3 5 / 6

A page of Latin nouns strung together with Korean particles is what "AI가 정리한 기술 보고서" actually means. Fixing it changes no fact, because a bare common noun was never a protected span.

Four buckets. Only the first stays in Latin script.

  1. 식별자 — 그대로 둔다. Class, method, field, config key, command, constant, file name, annotation: CacheAsideExecutor, getLoadCount(), min-replicas-to-write 1, application.yml, @ManyToOne. These are protected spans. Keep them in backticks and never translate them.
  2. 한국어에 자리잡은 외래어 — 한글로 적는다. 쿼리 · 캐시 · 클래스 · 테스트 · 요청 · 응답 · 상태 · 설정 · 키 · 스레드 · 세션 · 토큰 · 인덱스 · 라이브러리 · 컴포넌트 · 메서드 · 필드 · 어댑터 · 인스턴스 · 클라이언트 · 커넥션 · 타임아웃. The reference articles write every one of these in Hangul.
  3. 한국어 낱말이 이미 있는 영어 일반명사 — 한국어로 쓴다. credential 자격 증명 · budget 상한 · owner 소유자 · source 원본 · reply 응답 · warning 경고 · account 계정 · material 값 · group 묶음 · lane 갈래 · contributor 항목. Where the document has already declared one as its own term, keep that term — but declare it once, in Korean, rather than leaving the English in every sentence.
  4. 고유명사·제품명 — 그대로 둔다. Redis, Nginx, Hibernate, Spring, Actuator, Keycloak, PostgreSQL.

After the first mention, refer back in Korean. optional contributor는 … optional contributor가 … becomes … 이 항목이 …. Repeating the full English name in every sentence is what pushes the count to four per sentence. Pointing back with 이/그 + a Korean noun changes nothing about which thing you mean.

An unavoidably English term that has no Korean equivalent gets introduced once as 한글 뜻(English) and then used in Hangul. Do not carry the Latin form through the whole section.

Order: define, then what happens, then the problem, then the replacement

Where the source explains a term or a mechanism, keep that order: what it is → how it is used → what goes wrong → what to use instead. Deferring the definition makes the reader carry an unknown word through two paragraphs. Skip the fourth step when the source never considered an alternative.

TechLog records link to each other, so a record can be short. It still has to carry its own core claim and the prerequisite knowledge that claim needs. Deeper background belongs in a linked record; the definition a reader needs to parse this sentence does not.

Join cause and effect inside one sentence

Use ~기 때문에, ~다 보니, ~어서, ~(으)므로, ~는데, ~니, ~면. Do not chop a reason into separate sentences to satisfy a one-fact-per-sentence rule — A였다. B였다. 그래서 C였다. is machine Korean, and no Korean tech blog writes that way.

Break a sentence when the subject changes, not when the second clause starts. Same subject carrying a reason or condition stays in one sentence.

Measured across the five reference articles: prose sentences average 5666 characters, and fewer than 5% run past 120.

That average is a mixture, not a target length for every sentence. Joining every reason into a compound sentence pushes the average to 80+ and makes the section as hard to read as the choppy version it replaced. Some sentences are supposed to be short, and they are always the same five jobs:

짧게 끊는 문장 (20~35자)
정의 한 줄 '진입점'은 사용자 요청의 시작점을 의미합니다.
다음에 볼 것 예고 먼저 할당 API를 살펴보겠습니다.
수치 한 줄 쿼리를 수행한 인덱스의 문서 수는 4천만 건입니다.
코드·표로 넘기기 당시 쿼리는 다음과 같은 구조로 작성되어 있었습니다.
방향 전환 다만, 이와 같은 해결 방법에도 문제점이 있습니다.

Only the explanatory sentence — the one carrying a cause, a condition, or a consequence — earns 6090 characters. Definitions, announcements, bare numbers, and hand-offs stay short. Do not weld them onto the sentence next door to satisfy the joining rule.

None of these five require the vivid register. They are the reason the reference articles have short sentences without inventing an experience.

This cuts both ways. Joining is the fix for choppy prose, but a sentence that runs through two subjects, two measurement scales, or two results is now too long — split it at the point where the subject changes. N=10에서는 ~ 문제가 보이지 않았는데, N=1,000에서는 ~ 50.0×까지 벌어졌습니다 is two sentences wearing one comma.

Vary how sentences end

The reference articles use four to six different sentence endings; every document in this repository before the rewrite used two. That single number is most of what makes the prose feel machine-made, and it is the easiest thing to fix.

끝맺음 쓰는 자리
~합니다 / ~했습니다 사실·측정·코드 동작. 대부분 여기다
~입니다 정의, 지금 무엇인지
~하겠습니다 / ~살펴보겠습니다 다음에 무엇을 볼지 예고
~할까요? / ~뭐죠? 독자가 품을 물음을 대신 꺼낼 때
~해봅시다 / ~확인해봅시다 수치나 코드로 넘어갈 때
~지만 / ~인데요 앞과 어긋나는 것을 이어 붙일 때

Do not sprinkle these to hit a count. Each one belongs to a job: a heading that asks a question, a sentence that hands off to a table, a line that announces the next section. When those jobs are being done, the variety appears on its own. When the whole section is flat ~했습니다, it usually means those jobs are not being done at all — the document is a list of facts with no one walking the reader through it.

Say what happened with a verb, and pick the verb the context takes

쿼리가 나갔습니다 / 응답 속도가 개선되었습니다 / 약 1분이 소요되었습니다 / 문제가 발생합니다 / AST 노드를 순회합니다 / 위반으로 잡습니다. The register file has the full context→verb table.

Do not turn an event into a counted noun phrase — 채워진 목록 수, 준비한 SQL 문장, 획득한 문장 객체 수 — to keep a metric name technically safe. Code behavior takes present tense (~합니다); measurements and things that happened take past tense (~했습니다). Do not mix them.

Never invent a private idiom for a numeric relationship

~를 따라 늘었다, ~를 따라갔다, ~를 좇았다 are not Korean. 따라가다 takes a person, a path, or a standard — not a count. Write the relationship the way it is actually said:

관계 쓴다
같은 수 아이템이 100개면 조회도 100번 나갔습니다 · N과 같은 수로 늘었습니다
비례 N에 비례해 늘었습니다 · N이 커진 만큼 늘었습니다
배수 약 3배 증가했습니다 · 50배까지 벌어졌습니다
변하지 않음 N을 바꿔도 2개로 그대로였습니다 · 페이지 크기에 고정되었습니다
단위마다 증가 배치 크기마다 한 번씩 늘었습니다

Numbers take the shape <잰 것>이/가 <수치만큼> <동사>했습니다, with before/after as 기존에는 ~, 개선 후에는 ~. Keep , 이상, 정도, and every unit exactly as the source had them.

Particles

이/가 marks the measured subject. 은/는 marks a before/after contrast. (으)로 marks the resulting state. 에 비해/보다 marks a comparison. Do not chain three deep — 조회 수의 증가 형태의 비교 becomes 조회 수가 어떻게 늘었는지. Do not join nouns with ~에 대한; use the verb — 쿼리 수에 대한 측정 becomes 쿼리 수를 측정했습니다.

Choose the subject by what kind of sentence it is

Decisions and actions take a person (저는 ~하기로 했습니다). Results and observations take the measured thing with a passive verb (슬로우쿼리가 모두 제거되었습니다). Code explanations take the code element (이 규칙은 ~를 허용하는데). Drop the subject when the previous sentence already fixed it.

Name the thing, not its role in your argument

기준선, 비교 대상, 최소한의 선, 위반, 핵심, 본질, 구조적 문제, 증가 형태, 실체, and a bare 관계 name a slot in an argument instead of naming the thing. A word that only tells the reader how to read — 읽으면 안 된다, 봐야 한다, 주의해서 보자 — is not a fact either. State the observation that would make them read it that way.

쓰지 않는다 쓴다
이 구현을 기준선으로 삼았다 이 코드를 그대로 두고 측정했다
같은 기준선에 두 가지 위반이 있었다 어떤 요구가 어떤 두 가지 방식으로 깨졌는지 적는다
현재 기준선에는 batch가 없다 이 구현에는 batch 설정이 없다
두 값은 비교 대상이 아니다 두 값은 세는 것이 다르다. A는 <A가 세는 것>, B는 <B가 세는 것>이다
최소한의 선은 지켰다 <지킨 조건>은 지켰다
두 엔티티의 관계가 문제였다 FeedItemHighlight@OneToMany 매핑이 문제였다
이 실행계획을 최적이라고 읽으면 안 된다 실행 시간이 0.173 ms라고 해서 필요한 만큼만 읽는 것은 아니다
증가 기준은 A가 아니라 B였다 A가 늘어도 그대로였고, B가 늘 때 같이 늘었다

These are replacements, not deletions. The fact the framing word was standing in for still has to be in the rewrite. 관계 is fine as part of a real name (연관 관계, @ManyToOne 관계); it is not fine as a stand-in for a mapping you did not name.

Delete the sentence that only sets up the next one

Cut every sentence that prepares, frames, or restates:

  • a first sentence that repeats the heading (반복되는 ~를 실행계획으로 확인했다 under a heading that says so);
  • a scene-setter before the explanation (이 코드는 반복문이 없는 상황이다, 여기서는 ~를 다룬다);
  • a wrap-up that announces what you just showed (이 관찰은 두 가지를 보여준다).

Test: delete it and ask what the reader lost. If nothing, it stays deleted.

A forward-looking sentence that tells the reader from what angle the next part is examined is different, and Korean tech blogs do write it — 이번에는 ~를 ~ 중심으로 살펴보겠습니다. That adds information the heading did not carry. Keep at most one per section, and only when it names the angle.

Do not package the source

Do not newly introduce slogans, metaphors, or polished conclusions such as:

  • 이는 ~를 보여준다
  • 결국 문제는 ~이다
  • 단순히 ~가 아니라 ~이다
  • 비용이 ~로 이동했다
  • 새로운 책임이 생긴다
  • 정반대의 결과를 보였다
  • 회계 항등식

These strings are not a blind deletion list. If the source explicitly makes the same claim, restate it with the concrete facts that support it. Do not add a lesson, advantage, drawback, recommendation, or causal explanation just because it would complete the paragraph. End after the supported cause or result; do not force every paragraph into observation → interpretation → lesson.

Two things this rule does not ban. Korean tech blogs use both, and cutting them makes the prose worse, not cleaner:

  • Steering the reader inside the article. 중요한 것은 아래 세 가지 컨벤션을 반드시 지켜야 한다는 점입니다 picks which of the things just listed to carry forward. That is navigation, not a manufactured conclusion. The banned use is the same phrase pasted next to a measurement to make the data look like it proved something it did not.
  • A closing opinion in the closing section. 26388 ends with AI는 요술램프가 아닙니다 … 안목이 더욱 중요해지고 있습니다. That belongs in 맺는 글, is the author's own view, and appears once. Keep one the source already states; never write a new one, and never let it migrate into the middle of the document.

Use contrast words only when the contrast is needed to understand the facts. Do not manufacture symmetry with 반면, 반대로, 이에 비해, or 하지만.

Korean tech blogs also carry vivid, personal, sometimes funny sentences. Do not import that register. It comes from something the author actually lived through. Inventing an experience, a failure, an emotion, or a first-person aside that the source does not record breaks this repository's rules. What transfers without a source is plain verbs, concrete nouns, reasons joined inside the sentence, and definitions placed first.

Headings

A heading names what the section examines or what it does. These are the shapes the reference articles actually use — none of them builds a contrast or poses a riddle:

형태 실제 제목
용어를 묻는다 WMS란? · 진입점이 뭐죠? · MDC를 아시나요? · 공간 (Spatial) 데이터 타입이란?
이유를 묻는다 근데 왜 진입점 정보가 남아야 해요?
상황을 묻는다 할당과 취소를 동시에 요청한다면?
동작 + 목적 한글 문구에 번역 API를 사용해 번역 누락 막기 · <Trans> 계열 컴포넌트는 필요할 때만 사용해 코드 복잡도 낮추기
단계 1 단계: 분산 락 추가하기 · 2 단계: 분산 락 대기하기
청유 할당과 취소가 동시에 처리되는 것을 막아보자
대상 공간데이터 및 GeoJSON · @lib/i18n과 세 가지 컨벤션
상태·한계 사람과 AI 검수의 한계 · 한계점 · 남은 과제들

현재 구현 공백과 잘못 읽기 쉬운 지점 같은 분류형 제목은 이 목록에 없다. 보고서의 절 이름이지 블로그 글의 제목이 아니다. 한계를 분류해서 한곳에 모으지 말고, 그것이 제한하는 대상 옆에 적는다. | 고정 칸 | 현상 · 문제 원인 분석 및 해결 · 개선 결과 · 해결방법 · 문제점 |

동작 + 목적(~해 ~하기) is the one to reach for when a section describes a fix: it names the action and what the action buys, and it cannot become a slogan because both halves are concrete.

The 현상 / 문제 원인 분석 및 해결 / 개선 결과 triple repeats five times in 20161. When a document walks through several independent cases, reusing one fixed set of headings is clearer than inventing a fresh phrase per case.

Explain one scale, and let the table carry the series

Pick one N for the worked example and stay there. Picking the largest N to sound dramatic is padding. Restating 10/100/1,000 in every sentence forces the reader to re-orient each time; the table already shows the shape of the growth.

Figures

A figure earns its place only when it carries something the sentences cannot: a sequence with actors and order, a structure with parts and boundaries, a measurement with axes and values, or a captured artifact — a log, a plan, a screen. Three boxes and two arrows that redraw one sentence (요청 → 초기화 N회 → SELECT N회) add nothing; the sentence already said it, and the alt text says it a third time. Delete the figure instead of writing a caption that apologizes for it.

Before keeping a figure, say what a reader learns from it that the paragraph next to it does not tell them. If there is no answer, remove it.

Quick reference

Symptom Rewrite direction
Numbers became an adjective or trend Restore every value and its condition
A cause became 캐시 효과 or another summary State the actual reuse, query, or state change
Two results became a polished contrast Explain each result in the order observed
A sentence became shorter but denser Restore the subject, action, and reason
A paragraph ends with a generic lesson Remove the lesson unless the source stated it
A heading sounds like a slogan or riddle Name the checked operation, object, or limit
An API or metric name appears with no explanation Add one sentence defining it at first use and keep the name
A framing noun (기준선, 비교 대상, 관계) stands in for the thing Name the method, request, mapping, or requirement
The sentence tells the reader how to read Replace it with the observation that supports it
A metric name pushed the sentence into a noun phrase Say what happened with a verb; leave the metric name and its caution in the body
~를 따라 늘었다 / ~를 따라갔다 Use the real relationship: 같은 수 · 비례 · 배수 · 고정
Sentences are all short and choppy Rejoin with ~기 때문에, ~다 보니, ~어서; break only where the subject changes
One sentence runs through two subjects, scales, or results Split it at the subject change
A metric is glossed from its identifier name Only define it from the source, the code, or the framework docs; otherwise leave it undefined and say so
가 세 겹, or ~에 대한 Unfold into a verb
Code and measurement mix tense Code ~합니다, measurement ~했습니다
A sentence only prepares or restates the next one Delete it
The example jumps between N=10, 100, 1,000 Pick one scale and explain there; leave the series to the table
A figure redraws a sentence Remove it, or replace it with a log, plan, or measurement it cannot say
A possibility sounds certain Restore the original modality and unverified scope

Mechanical pass

Run the checker on the rewritten file before the final check.

node .agents/skills/rewriting-technical-prose-naturally/scripts/check_prose.mjs [--doc] [--warn] <파일.md>

--doc adds the whole-document checks (prerequisite knowledge, running order, closing); use it when you rewrote a full document, not a single section. --warn shows the judgment-call findings too.

--rules is for rule documents — README.md, CLAUDE.md, the skill files themselves. Those are lists of items ending in ~한다, and mixing in ~살펴보겠습니다 to satisfy a count makes them worse, so it turns off monotone-endings and no-reader-steering. Every other rule still runs. Do not reach for it on prose: those two errors are the ones that catch machine writing in an article.

It reports two levels. error must be zero before you call the rewrite done — these are the regressions that keep coming back, plus the four things whose absence made earlier rewrites read like a machine: a term defined after its first use, one single sentence ending used throughout, no sentence that carries the reader, and a missing closing. warn is a prompt to look, not a defect: 반면 is right where the source really contrasts, 관계 is right inside 연관 관계, and plenty of acronyms (SKU, GS, AOP) are left unexpanded by good writers.

The baseline is the reference articles themselves. All five Woowahan articles in references/document-skeleton.md pass with zero errors. If you add a rule, re-run it against them — a rule those articles fail is a rule that is stricter than the standard, and it will push you into contorting prose to satisfy a check no human writer meets.

Then take the style profile:

node .agents/skills/rewriting-technical-prose-naturally/scripts/style_profile.mjs <파일.md>

It prints six numbers and flags any that fall outside the band measured on the five reference articles. The two that catch machine prose almost every time are 종결어미 종류 수 (reference 46; this repository's documents scored 2 across the board) and 이유 연결어미 / 문장 100개 (reference 6.723.6). A number outside the band is a symptom to trace back to a real sentence, never something to fix by padding — inserting ~해봅시다 to raise a count produces exactly the kind of writing this skill exists to remove.

Clean output does not mean the rewrite is good. Both tools read surface patterns and cannot see meaning; every rule above still applies, and the read-aloud test below is the one that decides.

Final check

First, read every rewritten sentence aloud and ask: would a Korean-speaking developer say this to a colleague this way? A sentence that is accurate but unspeakable is not finished. Fix it by adding the condition as a short clause, never by bending a word into an unusual grammatical role.

Then compare the source and rewrite sentence by sentence:

  1. Are all numbers, units, code names, identifiers, and observed results preserved?
  2. Are cause and result still connected in the same direction?
  3. Are comparison targets and axes unchanged?
  4. Did a possibility, inference, proposal, or unknown become a confirmed fact?
  5. Was any new cause, benefit, drawback, conclusion, or recommendation added?
  6. Did any exception, failure, condition, or unverified scope disappear?
  7. Did a concrete technical statement become a broader abstraction?
  8. Can every rewritten claim be pointed back to a specific source claim?
  9. Is every API name, counter, and internal metric defined where it first appears, with what it counts unchanged?
  10. Does the reader have the prerequisite knowledge to follow the core claim, or does an undefined term still block them?
  11. Did any experience, emotion, or first-person aside appear that the source does not record?

If any answer reveals a mismatch, rewrite again or restore the original sentence. Do not declare the edit complete until the mismatch is gone.