Skill v1.0.1
currentAutomated scan100/100+7 new
name: analyze-article description: >- Read a web source — an article OR a non-article (GitHub repo, project homepage, service site) — and write a TIL document (in Korean). The H1 title is written in Korean. Published pieces (articles, posts, papers, tweets, videos) get a 원문: [원문 제목](URL) titled-link source line and a ## 요약 section; non-articles get bare <URL> line(s) with NO 원문: label, no titled link, and a fitting first heading like ## 소개. Body structure follows the source's own job — analytical for a piece that argues, practical for one that teaches. The document shape is a closed spec enforced by scripts/check_format.py, which must print OK before the file is reported as written. Takes a URL as an argument. Use when the user asks to analyze an article/repo/site, document it, or organize a technical post. argument-hint: '<url> [output-path]' disable-model-invocation: true metadata: version: "1.0.1"
Read a web source and write a TIL document whose structure follows what the source is for: analytical when it argues, practical when it teaches.
The output document MUST be written in Korean. Every section is written in Korean, whichever body structure step 5a selects. Technical terms may be written alongside their original English form.
Usage
/analyze-article https://example.com/article [security/article-name.md]
- First argument: source URL (required)
- Second argument: output file path (optional; if omitted, ask the user)
Multiple URLs in one invocation
The user often pastes several URLs at once, sometimes each on its own /analyze-article line. Treat that as a queue, not as an error.
- Run the full procedure below once per URL, in the order given.
- Finish one document completely — write, run the post-processing and the
format gate of step 8b, weave community reactions, run the gate again in step 10 — before starting the next. Do NOT write all summaries first and circle back.
- A long queue never justifies skipping the gate for a file. A file that has
not printed OK is not finished and does not belong in the summary table.
- If a URL turns out to be a duplicate or cannot be fetched, report that one
and continue to the next. A single failure never aborts the queue.
- Report at the end as a table: one row per URL, with the resulting path or
the reason it was skipped.
- If the queue is long enough that finishing it in one run is implausible,
say so up front with a count, then start working through it in order rather than waiting for permission.
Procedure
1. Fetch the source
Fetch the content of the $0 URL with WebFetch.
If WebFetch returns a summary rather than the text, or returns too little to summarize accurately, fetch again asking for the body verbatim, or retrieve the page directly and strip the markup. Never write the 요약 section from a thin summary — numbers, names, and quoted phrasing must come from the actual text. For sources WebFetch cannot handle, see step 4a and _agent/rules/web-fetching.md.
For a YouTube URL (youtube.com, youtu.be), skip WebFetch entirely and go straight to yt-dlp as described in step 4a. WebFetch returns only the title.
2. Check for duplicates
Check in this order, and do all three before concluding anything:
- Grep the TIL for the source URL itself (and its slug). An existing
document that already cites the URL is a duplicate, full stop.
- Grep for distinctive proper nouns from the title and body.
- List the likely directory to see whether a differently-named document
covers the same subject.
If a duplicate exists, do NOT skip it and do NOT write a second document on the same source. Enhance the existing file instead.
Enhancing means: fetch the source again in full, then compare it against the existing document and add what is missing. Look for content the source carries that the document never captured, community reactions not yet woven in, sections the current structure requires but the document lacks, and passages where the existing text misreads the source — a document written from a thin fetch often critiques the source for an omission the source does not actually have. Correct those. Preserve everything already there that is still accurate, and keep the existing H1 unless the user asks otherwise. Report which file was enhanced and what was added or corrected.
A near-miss is not a duplicate: a document that merely mentions the subject (e.g. cites the project in passing) does not block a document about the source. Say which case it is when reporting.
3. Classify the subject — article vs. non-article (CRITICAL)
Before writing anything, decide what the source actually IS. This decision controls the source-link line AND the first section heading. Getting it wrong is a defect, not a style choice.
There are two kinds of subjects:
- Article / blog post / news / paper — the source is a piece of writing
by an author making an argument. Examples: a blog post, a newsletter issue, a news story, an academic paper, an essay, a documentation article that reads as prose.
- Non-article — the source is a thing you use or explore, not a piece of
writing. Examples: a GitHub repository, a project/product homepage, a library or framework landing page, a service marketing site, an API reference index, a tool's docs root.
When in doubt, ask: "Is there an author advancing a thesis I can summarize, or am I describing a tool/project/site?" A README that pitches a product is a non-article (it describes the project), even though it contains prose.
3-1. A product is the subject, its page is only a source (STRICT RULE)
When the URL is a product's page (a launch page, a product site, a pricing page, a spec sheet), the document is about the product, not about the page. Writing "이 페이지는 …한다", "제품 페이지이다", "페이지의 수치" makes the document read as a summary of marketing copy, which is the wrong subject.
- Name the subject as the product and its maker. Attribute claims to the
maker ("제조사는 … 말한다", "회사는 … 주장한다"), never to "the page".
- Organize the body around the product: what it is, its specifications,
price and availability, how people reacted, what the claims rest on, and what to check before buying or adopting. Do not follow the page's own section order.
- Everything a maker says about its own product is a claim, and the document
says so. Separate it from what an independent source, a user report, or the document's own calculation shows.
- Other pages that were actually opened (a press release, a localized
edition, documentation, a terms page, a pricing page of a different tier or deployment mode) are outside pages and carry titled footnotes. The product page the user gave is the analyzed source and takes no footnote, so what it says is stated in prose without one.
- The gate still requires one source line in the header (step 4). Keep the
bare URL there. Do not label it 원문: and do not describe it in prose as "the page".
- When the user supplies a second page as a supplement (a localized edition),
treat it as an outside page: footnote it, and say where the two disagree.
- Read an evidence table from the rendered page, not from extracted text.
Plan tables flatten, and a misaligned column turns a limit into its opposite. When extracted text and the rendered table cannot be matched with certainty, open the page in the browser and read the cells.
3a. Document title (H1) — write it in Korean
The `#` heading is written in Korean, not copied from the source. The document is a Korean note; its title is the first thing the reader sees and must read as Korean prose.
- Convey what the source is about. Do not transliterate the English title into
Hangul, and do not paste the original title as the H1.
- Keep product names, project names, and established technical terms in their
original form: SwiftUI, ClickHouse, Soppo, PostgreSQL, MCP. Translate the surrounding words, not these.
- A
<제품명>: <한국어 설명>shape works well when the subject is a named
thing. A plain Korean sentence or noun phrase works well when the subject is an argument.
- If the source title carries a claim, the Korean H1 should carry that claim
too — do not flatten it into a neutral topic label.
Examples:
| 원문 제목 | H1 | |
|---|---|---|
| SwiftUI After 7 Years: A Story of Mediocrity | SwiftUI 7년, 평범함의 기록 | |
| Devtools must be open source | 개발 도구는 오픈소스여야 한다 | |
| GitHub has alternatives, but no replacement | GitHub에는 대안이 있지만 대체재는 없다 | |
| Soppo (project homepage) | Soppo: Go에 빠진 기능을 더한 언어 | |
| The next chapter of our AI momentum | Google AI 모멘텀의 다음 장 |
This rule governs the H1 only. Two things stay in their original language:
- The
원문:link text keeps the source's own title, untranslated (step 4). - The file name stays lowercase English kebab-case.
If the H1 is in English, the document is wrong regardless of how good the body is. Fix it before writing the first section.
This rule applies to documents written from now on only. Many existing TIL documents have English H1 titles. That is a settled decision, not a backlog: do NOT retitle them, and do NOT propose a sweep. Touch an existing H1 only when the user asks for that specific file.
4. Source-link line — STRICT RULE (NO EXCEPTIONS)
This is the rule most often gotten wrong. Follow it exactly.
The link form depends on whether the subject is a published piece (an article, post, paper, tweet, or video) or a thing (a site address, a GitHub repository, a project homepage).
- Published piece → labeled source line directly under the title, written
as a titled markdown link with the source's own title as the link text:
``markdown 원문: [<원문 제목>](<URL>) ``
Use the title exactly as the source presents it, including its site suffix when the page title carries one (e.g. ... | Google Search Central Blog). Do not translate it, do not shorten it, do not invent one. If the page has no usable title, use the most specific heading on the page. A bare <URL> here is a defect: the reader cannot tell what they are about to open.
- Non-article (GitHub repo, homepage, service site, etc.) → **NEVER write
원문:, and NEVER use a titled link. An `원문:` label means "original *writing*," which a repo or homepage is not. Place the bare URL(s)** under the title with no label and no link text:
``markdown <https://github.com/org/project> ``
If the subject has both a homepage and a repo, list both as separate bare URL lines (homepage first, then repo), each on its own line separated by a blank line.
There is ZERO case where a GitHub repository or a product/service homepage gets an 원문: label or a [text](url) link. If you catch yourself typing either one for a repo or a homepage, STOP — you misclassified the subject in step 3.
Checklist before writing the source line:
- Is the subject a published piece or a thing?
- Published piece →
원문: [실제 제목](URL), never a bare<URL>. - Thing → bare
<URL>, never원문:and never[text](url).
If any answer is wrong, fix it before writing the first section.
Discussion links added later (HN 토론:, Lobste.rs 토론:, GN 토론:) also keep the bare <URL> form, because their score/comment count already identifies them.
4a. Special source types
Some sources need a fetch strategy or a link form of their own. Handle these explicitly rather than improvising.
| Source type | Fetch method | Source line | |
|---|---|---|---|
Claude in Chrome (see web-fetching.md) | 트윗: [<제목 또는 첫 문장>](URL) | ||
| YouTube | yt-dlp info JSON + captions (see below) | 영상: [<영상 제목>](URL) | |
| Paper (PDF/arXiv) | WebFetch, or Read the PDF | 논문: [<논문 제목>](URL) | |
| Press release | WebFetch | 원문: [<제목>](URL) | |
| Forum post (GN/HN) | WebFetch, or the site's JSON API | Ask GN: [<제목>](URL) 등 | |
| GeekNews Article | WebFetch, or curl the article page | GeekNews Article: [<제목>](URL) |
A Show GN / Ask GN / Show HN / Ask HN thread is written as a titled link labeled with the thread's own prefix: Show GN: [<제목>](URL). Where that line goes depends on what the subject is:
- The thread presents a thing that has its own address (a product
homepage, a GitHub repository, an app page). The subject is the thing, so the source line stays the bare <URL> of the thing (homepage first, then repo). The Show GN: line goes in the discussion block in place of the GN 토론: line (and Show HN: in place of HN 토론:). It never replaces or removes the bare source URL.
- The thread itself is the only source (an
Ask GNquestion, or a post
with no separate address). Then the labeled line is the source line.
Either way, never add both a Show GN: line and a GN 토론: line for the same thread.
For Twitter, the service is always called Twitter in prose, never X, even when the source writes X or 엑스; the format gate fails prose that calls it X. For Twitter, twitter.com is used instead of x.com per writing-guidelines.md. For a long tweet, call it a 트윗, not a 스레드, unless the user says otherwise.
A tweet that links to a Twitter Article (long-form post) shows only a t.co link in its text; the article body renders on the same status page. get_page_text cuts off around 50,000 characters, which an article with embedded quote tweets and code blocks can exceed. Read the rest with javascript_tool on document.querySelector('article').innerText, sliced into chunks of under 1,000 characters, because longer return values are truncated. Strip URLs and ?/&/= from the text first: a return value that contains query-string data is replaced wholesale with [BLOCKED: Cookie/query string data].
For YouTube, the first section is ## 요약 only if the video advances an argument (a talk, an essay video). For a demo or a walkthrough, choose a heading that fits — e.g. ## 내용, ## 데모.
YouTube: fetch with yt-dlp, never with WebFetch
WebFetch cannot read a YouTube video. It returns the page title and the site footer, with no description, no chapters and no transcript (verified October 2026). A document written from that is written from the title alone, which step 4a forbids. Use yt-dlp instead. YouTube extraction needs a JavaScript runtime (Deno) installed; see cli/yt-dlp.md.
Fetch in two calls, into a scratch directory, never into the repository:
D=<scratchpad>/yt-<video-id>mkdir -p "$D"# 1. metadata: title, channel, upload date, duration, description, chapters,# and the spoken language (`language`) plus which caption tracks existyt-dlp --skip-download --write-info-json -o "$D/v.%(ext)s" "<URL>"# 2. one caption track, in the spoken languageyt-dlp --skip-download --write-auto-subs --write-subs \--sub-langs "<lang>-orig" --sub-format vtt --sleep-subtitles 5 \-o "$D/v.%(ext)s" "<URL>"
Rules for what comes back:
- The source line uses `title` from the info JSON, verbatim, including
prefixes like [한글자막].
- Read the spoken-language track, not a translation. Pick
<lang>from
the info JSON language field (en-US → en). The -orig auto track is speech recognition in that language; other language tracks are machine translations of it. Quote and paraphrase from the original-language track.
- Request one track per call. Asking for several languages at once is the
usual way to hit HTTP Error 429: Too Many Requests on captions. On a 429, wait, then retry a single track once with --sleep-subtitles. Do not loop.
- Auto captions repeat and misspell. Rolling captions emit each line
several times; de-duplicate and group by minute so you can cite timestamps. Speech recognition mangles proper nouns (handles, product names, company names). Check every name against the description, the chapters, the uploader's links, or another source before writing it. Never copy a name from the transcript unverified.
- A re-upload is not the speaker's own channel. Translation channels
([한글자막] and the like) re-post someone else's talk. Name the speaker, not the uploader, as the author, and follow the description's links to find the original post or event. The source line still links the URL the user gave.
- No caption track at all means the source cannot be read as text. STOP
and report it; do not transcribe the audio unless the user asks for that.
If the source cannot be fetched at all, STOP and tell the user which URL failed and what was tried. Never write a document from the title alone or from prior knowledge of the subject.
5. Choose the first section heading
The first top-level section depends on the same classification:
- Article →
## 요약is the usual opening, but it is not the only one.
Choose the heading that matches what the first section actually does: a piece that argues gets ## 요약; a reference or a tutorial may open with ## 소개, a long document may open with ## 목차. The document's type decides, not a blanket rule.
- Non-article → do NOT use
## 요약. Choose a heading that fits what the
section actually covers — e.g. ## 소개, ## 명세, ## 사용법, ## 주요 기능, ## CLI. A single subject may warrant multiple top-level sections if its content naturally splits.
What is fixed is not the name of the opening section but the body structure step 5a selects. Getting ## 요약 versus ## 소개 slightly wrong is a matter of fit; shipping a document that was supposed to carry the analytical body and carries only half of it is a defect.
5a. Choose the body structure — argue vs. teach (CRITICAL)
The body structure follows the source's own job. Do not impose an analytical structure on a source whose job is to teach a task.
Decide which of these the source is, then use the matching body:
- The source argues. It advances a thesis, takes a position, reports an
event with a frame, or reviews something. Blog posts, essays, news stories, papers, opinion pieces, most conference talks. → Body is ## 분석 → ## 비평 → ## 인사이트, in that order, 비평 immediately after 분석 and 인사이트 last. This is the default.
- The source teaches. Its job is to let the reader do a task: reference
documentation, an API guide, a specification, a tutorial, a runbook, a tool's usage docs. The useful note is one the reader can work from, not one that critiques the manual's prose. → Body is practical. Choose headings that fit the task — e.g. ## 동작 방식, ## 설정하기, ## 구현하기, ## 값 정하기, ## 트레이드오프, ## 체크리스트, ## 함정. Cover: how it actually works, what to decide and on what basis, what the trade-offs cost on each side, what goes wrong in practice, and how to verify. End with a short ## 기억할 원칙 when there is a transferable principle worth stating.
The analytical body is all-or-nothing. If you pick it, the document carries ## 분석, ## 비평 and ## 인사이트, all three, in that order. A document that analyses and then offers insights without ever challenging the source is the most common way this structure fails, and 비평 is the section that makes the note worth more than the source. Half the structure is a defect, not a lighter version of it. The format gate in step 8b enforces this: once ## 분석 appears, all three must appear, in that order.
A practical note is free to borrow one of these headings without owing the other two. When a teaching source carries a strong claim worth contesting, a single ## 비평 among practical sections is welcome; a practical note may likewise close with ## 인사이트 instead of ## 기억할 원칙. What marks a document as analytical — and therefore owing all three — is ## 분석.
When genuinely torn, ask what the reader will do with the note. If they will think differently, the source argues. If they will build something, it teaches.
Trade-offs are where a teaching note earns its keep. A table of "what you gain / what you give up" in one line each is too thin. Show why the obvious fix does not work, what breaks when you pick each side, and what you cannot have at all. Name the difficulty, not just the cost.
6. Write the document
Two templates follow: one for a source that argues, one for a source that teaches. Pick the one step 5a selected. The `원문:` line and `## 요약` heading shown apply to ARTICLES ONLY — for non-articles, substitute per steps 4 and 5.
6a. Template — the source argues
# <한국어 제목>원문: [<원문 제목>](<URL>)## 요약Summarize the core content in 3-5 paragraphs.Convey technical details accurately — preserve numbers, names, andtechnical terms. Do not editorialize; save judgment for later sections.## 분석Analyze the logical structure and context. Go beyond restating what thearticle says — ask WHY the argument is structured this way, WHAT itassumes, and WHERE it connects to broader trends.Each sub-section (###) should make a distinct analytical point:-What is the article's core claim, and what does it rest on?-What historical or technical context explains why this matters now?-What structural pattern does this represent — and where else does itappear?-What does the author take for granted that deserves scrutiny?Aim for 3–4 sub-sections. Each sub-section is 2–4 paragraphs.Do NOT list observations — build an argument within each sub-section.## 비평Do NOT use "강점 / 약점" sub-headings. A list of pros and cons is notcritique — it is a summary with opinions attached.Real critique means: identify a specific flaw in the article's logic,generalizability, omissions, or framing — and develop that flaw into asubstantive argument with evidence or counter-examples. Each sub-sectiontargets one such flaw.Frame sub-headings as focused critical claims, not generic categories:Good examples:-"글의 논리는 성공 조건을 숨긴다"-"저자가 인식하고도 답하지 않은 문제"-"이 워크플로는 특정 맥락에서만 성립한다"-"결론의 일반화는 근거 없이 확장된다"Bad examples (forbidden):-"강점"-"약점"-"한계"-"긍정적 측면 / 부정적 측면"Aim for 3–4 sub-sections of 3–5 paragraphs each. The critique must beharder and sharper than the analysis — find the places where the articlefails to hold up under scrutiny.## 인사이트Insights are the most important section. They must offer something thereader could NOT have obtained by reading the source alone.Each insight (###) must be developed over 3–5 paragraphs. The sub-headingnames the insight as a declarative claim — not a question or topic label.Mandatory coverage across the insights:-A second-order effect or consequence the article does not anticipate-A historical analogy or structural pattern that reframes the issue-A tension or trade-off the article glosses over but that will matterat scale or over timeWhat to avoid:-Restating the article's own conclusions as insights-Surface-level observations ("this is an important trend")-Insights that follow directly from the article without adding a newframeWrite at least 3 insights. 4 is better if the subject warrants it.
6b. Template — the source teaches
Headings here are examples, not a fixed set. Choose ones that match the task and drop any that do not apply. What matters is that the reader can act from the note.
# <한국어 제목>원문: [<원문 제목>](<URL>)## <첫 섹션: 요약 또는 소개>Pick per step 5. A non-article never uses `## 요약`.What this is and what contract it offers. For a spec or reference, state theguarantee and its exact boundary — what it promises, and what it explicitlydoes not.## 동작 방식How it actually works, in enough depth that the reader can predict behaviorrather than memorize steps. Walk a concrete scenario in order (a timeline, arequest path, a state transition) when the mechanism is easy to misread.## <구현하기 / 설정하기>What the reader does. Include real, runnable code or commands — not fragmentsthat only illustrate. Comment the lines that encode a decision. Name thevalues that must be chosen and what each one depends on.## 값 정하기Starting values with the reasoning behind each, in a table. A starting valuewithout its basis is unusable, because the reader cannot tell when to changeit. Add what to measure so the value can be revised from evidence.## 트레이드오프The heart of a teaching note. For each decision, show what you gain, what itcosts, AND what remains hard afterward. Give each significant trade-off itsown sub-section when one line cannot carry it: why the obvious fix fails,what breaks on each side, what cannot be had at all. A two-columngain/loss table alone is too thin.## 함정Failure modes that show up in practice but not in the source. What lookscorrect and is not, what only breaks under load or at scale, what the sourceassumes but never states.## <확인하기>How to verify locally — a reproducible experiment, a command sequence, aminimal setup. A note the reader can run beats one they can only read.## 체크리스트Checkable items for before shipping or reviewing. Write each so the answer isyes or no, not "consider X."## 기억할 원칙Only when a transferable principle is genuinely there. One or two, each witha `###` sub-heading and a few paragraphs. Skip this section rather than padit.
7. Writing rules
Most of the rules below are enforced mechanically by the format gate in step 8b. They are written out here so you produce a conforming document the first time, rather than writing freely and patching afterwards.
- Follow
_agent/rules/writing-guidelines.mdin full: heading spacing, CJK
table alignment, inline code, fenced-block language identifiers, the 박다 vocabulary ban, and the rule that structure belongs to headings and never to bold text.
- Write in Korean. Technical terms may be written alongside their original
English form.
- Break body text at sentence boundaries and keep every line within 80
columns: each sentence starts a new line, no line exceeds 80 columns (CJK characters count as 2), and a sentence that does not fit breaks at natural semantic boundaries (after a comma, before 이며/하지만/그러나/ 그리고/하면/때문에, between clauses) as many times as needed. Never split a title, a name, a number with its counter, or a footnote reference across lines, never leave a one-syllable tail on its own line, and never indent a continuation line, because an indented line renders as a code block. This applies to prose only; tables, code blocks, headings, and footnote/URL lines are exempt from both the sentence-break rule and the 80-column limit, so never wrap or shorten them to fit. The full rule is in writing-guidelines.md. Check this before invoking the post-processing of step 8b, not after, and verify the 80-column limit on the finished file.
- Every fenced code block carries a language identifier (
python,bash,
text, …). A bare fence is always wrong.
- Code in a teaching note must be runnable, not illustrative. Prefer a complete
function over an ellipsis. Comment the lines that encode a decision, not the lines that restate the syntax.
- The H1 is Korean (step 3a). Every
##and###heading is Korean too. - Sections are marked with headings, never with bold text. When the first
section runs long enough to need internal divisions, give those divisions real sub-headings at the right level. A bold line standing alone above body text is a structural defect, not a formatting choice.
- Each section must do different work: 요약/소개 reports, 분석 explains,
비평 challenges, 인사이트 extends. Do not let sections overlap.
- The document should read as if written by someone who disagrees with
parts of the source and has thought carefully about why.
- Maintain the same tone and depth as existing TIL documents.
- Read the finished document once as a reader who has not seen the source.
A sentence whose meaning cannot be stated plainly is rebuilt from its meaning, not patched. The rule is Every Sentence Must Make Sense in writing-guidelines.md.
7a. Document shape — CLOSED SPEC (NO EXCEPTIONS)
A document produced by this skill has exactly the shape below. The set of line kinds allowed above the first `##` is closed: nothing else may appear there, however useful it seems.
# <한국어 제목>원문: [<원문 제목>](<URL>)HN 토론: <URL> (<점수>점, <댓글 수>개 댓글)Lobste.rs 토론: <URL> (<점수>점, <댓글 수>개 댓글)GN 토론: <URL>## <첫 섹션>...본문...---[^handle]: <URL>
Rules that follow from it:
- The H1 is line 1, Korean prose, followed by one blank line.
- Exactly one source line, in the form step 4 selected. When the user asks
for several published pieces to be combined into one document (a multi-part tutorial, for example), write one labeled source line per piece, in order, each separated by a blank line. A non-article may use two or more consecutive bare <URL> lines (homepage first, then repo), each separated by a blank line.
- Discussion lines come after the source line, one per line, separated by
blank lines, in the order HN → Lobste.rs → GN. HN and Lobste.rs carry (N점, N개 댓글), copied as the site reports it, including a negative score such as (-1점, 4개 댓글); GN carries the bare URL alone. A Show GN: / Ask GN: line takes the GN slot and a Show HN: / Ask HN: line takes the HN slot, as [<제목>](URL). Two threads on the same platform for the same subject get two lines of that platform, adjacent.
- Existing documents in this repository also use four older header forms,
and the gate accepts them so those documents are left as they are: a 원문: <URL> source line without a title, a > <제목> quote line directly above a bare source URL, a GeekNews: <URL> line in the GN slot, and an HN 토론: / Lobste.rs 토론: line without counts. New documents still use the forms above.
- No other labeled line exists.
제품 페이지:,저자:,발표:,
관련 글: and every other invented label is forbidden. Information like that belongs in a body section, in prose.
- The discussion lines are written by the reaction skills in step 9. Do not
invent, guess, or pre-fill them.
Sections are a closed set too. Use the headings the step 6 template for your chosen body gives you, plus subject-fitting sections for a non-article. Never add a section that reports on the process of writing the document. ## 반응 현황, ## 반응, ## 커뮤니티 반응 and the like are forbidden: when a platform has no thread, that is reported to the user in chat, never as a section of the document. A document records what is true about the subject, not what the search turned up.
7b. Footnotes — STRICT RULE (NO EXCEPTIONS)
Footnotes for outside pages are complete and exact; the analyzed source needs none per sentence. When the prose names where something came from, the footnote closes that sentence and links that exact page. References go at sentence ends, not mid-sentence. The analyzed source itself never takes a footnote — ABSOLUTE, ZERO TOLERANCE. The source line under the title is its only link: no footnote for a sentence, a quotation, a figure, the date, or the author, and none in the titled form. Say what is needed in the prose. Before the gate and again after the reaction skills, compare every footnote definition's URL with the source line's URL; any match is deleted with all of its references. A document you enhance is checked the same way. Every sentence that rests on an outside page — a page the source quotes that was also opened and read, or material fetched to check or extend the source — carries its own footnote in the titled form of writing-guidelines.md ([^label]: <매체>, [<원문 제목>](<URL>), <YYYY-MM-DD>), and two pages mean two references. Rules 2 and 5 below govern the community-comment footnotes only.
A woven-in reaction is attributed inline and carried by a footnote whose label is the commenter's handle:
tttttaa는 회색지대 사례를 살펴볼수록 미묘해진다고 적었다.[^tttttaa][^tttttaa]: <https://news.hada.io/topic?id=33582#cid123456>
- Definitions collect at the bottom, after the last body section, under a
--- rule, one per line, separated by blank lines.
- Every comment footnote definition is a bare
<URL>in angle brackets. No prose, no quoted
comment text, no trailing commentary.
- The target is a permalink to the individual comment, never the thread root.
- Labels and definitions are one-to-one. A defined label that nothing
references, and a reference with no definition, are both defects.
- The label is the handle exactly as that site spells it. On a collision with
an existing label, disambiguate with a suffix ([^handle-lobsters]), never by renaming the person.
- Never write an anchor you have not observed. Comment ids are read off
the page or the API response you actually fetched. Constructing one that looks plausible — guessing a #cid, incrementing an id, reusing a neighbouring comment's anchor — is fabrication, and it has happened in this repository before. If you cannot see the id, do not cite the comment.
- A footnote reference must not sit inside a code fence or an inline code
span. Regex character classes like [^,] and [^)] inside a fence read as footnote syntax to some tooling; rewrite the expression or move it out of the snippet rather than leaving the collision in place.
8. Output
If $1 is provided, create the file at that path. If it is not provided, propose an appropriate directory and filename and confirm with the user.
8a. File name — STRICT RULE (NO EXCEPTIONS)
The file name is the subject. Nothing else.
Use lowercase English kebab-case. Include only words that identify which subject this is. Never include words that state what category, medium, or kind of artifact the subject is, and never describe what this document does to the subject.
Name a named thing by its name. Name an argument by its claim. Name a specific release or incident by its identifier. Add words only to disambiguate, and only words that narrow the subject.
Keep it short. Do not transliterate Korean; the name stays English even though the H1 is Korean (step 3a).
Mandatory check before writing the file:
- Read the file name back without the extension.
- Ask of each word: does it answer which thing this is, or what kind of
thing this is?
- Delete every word that answers the second question.
8b. Post-processing and the format gate — MANDATORY SEQUENCE
Run these four commands, in this order, every time, on every file this skill writes or enhances. The document is not written until they pass.
# 1. straight quotes → curly, outside fenced codepython3 .claude/skills/quotes-curly/scripts/convert_quotes.py <file># 2. restore straight quotes inside inline `code spans`# (convert_quotes.py skips fenced blocks but not spans)python3 .claude/skills/analyze-article/scripts/fix_code_spans.py <file># 3. pad table cells so the pipes line up (CJK counts as two)python3 .claude/skills/analyze-article/scripts/align_tables.py <file># 4. the format gatepython3 .claude/skills/analyze-article/scripts/check_format.py <file>
check_format.py enforces the mechanical half of this skill: the H1, the closed header block of step 7a, the source-line form of step 4, the ban on ## 요약 in a non-article, the completeness and order of the analytical body from step 5a, code-fence language identifiers, CJK table alignment, standalone bold lines, indentation that would render as a code block, the 박다 vocabulary ban, quote direction inside and outside code, and footnote integrity from step 7b.
It prints OK or FAIL with a line number for each defect. A `FAIL` is not advisory. Fix the file and run it again until it prints OK. Never report a document as finished, and never move to the next URL in a queue, while the gate is failing. Do not edit the gate to make a document pass.
If you believe the gate is wrong about a specific rule, say so to the user and stop; do not route around it silently.
8c. What the gate cannot check
The script checks shape. These remain your judgment, and are checked by reading the file you just wrote:
- Is the H1 Korean prose that carries the source's claim, rather than a
transliteration or a flattened topic label?
- Does the body structure match step 5a's choice — analytical for a source
that argues, practical for one that teaches?
- Do the sections do different work, or do two of them restate each other?
- Is every number, name, and quoted phrase traceable to the fetched text
rather than to memory?
- Does every footnote point at a comment you actually observed?
- Is the file name the subject and nothing else (step 8a)?
9. Community reactions
After the gate in step 8b has printed OK, automatically invoke the following three skills in sequence via the Skill tool, passing the output file path as the argument to each:
hackernews-reactions— finds the Hacker News thread and weaves key
comments into the document.
lobsters-reactions— finds the Lobste.rs thread and weaves key comments
into the document.
geeknews-reactions— finds the GeekNews (news.hada.io) thread and weaves
key native GN comments into the document.
Run them regardless of whether the user asked. If a skill reports that no thread was found, that is a normal result — note it briefly and continue to the next skill.
Mandatory verification (NO EXCEPTIONS): A document is not done — and must NOT be reported to the user as done — until all three reaction skills have been explicitly run against it in this turn, each with a concrete outcome (comments woven in, or "no thread found"). This applies with equal force whether you are processing one URL or a long queue of many; a long queue is not a reason to compress or skip this step for any individual file.
Before reporting ANY file as complete (including in a queue's final summary table), run this checklist for that file:
- Was
hackernews-reactionsinvoked for this exact file this turn? What
was the outcome?
- Was
lobsters-reactionsinvoked for this exact file this turn? What was
the outcome?
- Was
geeknews-reactionsinvoked for this exact file this turn? What was
the outcome?
If the answer to any question is "not yet" or "unsure," STOP and run it before moving on — do not proceed to the next file or to the summary table with any of the three unresolved. GeekNews is the one most often skipped (it requires a browser, not a simple API call) — do not let that extra friction be a reason to defer or drop it. "I already checked HN and that was thin, so GN is probably thin too" is not a valid basis for skipping the GN check — each source must be searched independently regardless of what the others returned.
10. Run the format gate again — FINAL STEP
The reaction skills in step 9 edit the document: they insert discussion lines into the header block, weave sentences into body sections, and append footnote definitions. Every one of those edits can break the shape that step 8b just certified — a discussion line in the wrong order or missing its counts, a footnote defined but never referenced, a handle colliding with an existing label, curly quotes landing inside a code span in a quoted comment.
So the gate runs a second time, after the last reaction skill has finished:
python3 .claude/skills/analyze-article/scripts/check_format.py <file>
A document is finished when this second run prints `OK`. Not when the prose is good, not when the reactions are woven in, not when the queue is long and the next URL is waiting. Report the file as complete only after you have seen OK from this run, and in a queue report only files that reached it.