feat: propagate Korean prose contract to providers
This commit is contained in:
+11
-34
@@ -11,6 +11,11 @@ from claridoc.models import (
|
||||
Outline,
|
||||
SourcePack,
|
||||
)
|
||||
from claridoc.style_contracts import (
|
||||
mandatory_style_review_checks,
|
||||
revision_style_protocol,
|
||||
style_guidance,
|
||||
)
|
||||
|
||||
|
||||
FOUNDATION_RULES = """\
|
||||
@@ -29,25 +34,6 @@ FOUNDATION_RULES = """\
|
||||
13. End with the decision the reader should carry into a similar situation, not a generic recap or a checklist added by habit.
|
||||
"""
|
||||
|
||||
WOOWAHAN_TECH_BLOG_KO = """\
|
||||
Korean technical-blog operating profile (derived from a bounded sample of Woowahan engineering articles; it is not an official house-style specification):
|
||||
- Begin from the team or system's concrete context, then expose the friction in observable terms.
|
||||
- Explain why the problem mattered before introducing the selected tool or architecture.
|
||||
- Show prior approaches, failed attempts, or realistic alternatives when they affected the decision.
|
||||
- State the selection criteria and the reason for the final choice. Pair benefits with the cost or boundary that remained.
|
||||
- Let implementation details answer the problem already established; do not turn the article into a component inventory.
|
||||
- Connect verification to the original problem. Report only what the available tests or observations actually prove.
|
||||
- Treat problem -> constraints -> options -> decision as a semantic order, never as a sentence template. Do not narrate outline labels to the reader.
|
||||
- Start a paragraph from a concrete actor, state, change, consequence, or decision when the evidence supports one. Make the subject and impact visible instead of opening with an abstract category label.
|
||||
- Do not open consecutive paragraphs with formulaic ordinal frames such as “첫 번째 제약은”, “두 번째 제약은”, and “세 번째 제약은”. Use ordinals for a real sequence, method, layer, or figure; use a list or meaningful subheadings for genuinely parallel items.
|
||||
- A question heading or transition must receive an immediate answer in the following prose. Do not use unanswered rhetorical questions as decoration.
|
||||
- Use “하지만/다만” only for a real contrast and “이 때문에/그 결과/그래서/이에” only when the referenced cause is explicit in the preceding context.
|
||||
- Use “팀에서는/저희는/우리는” when ownership or project-local judgment matters, not as a filler subject and never to universalize a local choice.
|
||||
- Use conversational but disciplined Korean. Avoid canned phrases such as “이 절에서는”, “제공된 근거에 따르면”, “독자는 ~할 수 있다”, and repeated “먼저/다음으로/마지막으로”.
|
||||
- An “예상 독자” block is optional. Use it only when it materially prevents the wrong audience from reading the article; never insert it as mandatory boilerplate.
|
||||
- Revise for flow: when a paragraph feels paused or a connector feels forced, repair the logical relation rather than adding a transition word.
|
||||
"""
|
||||
|
||||
ROLE_GUIDANCE: dict[str, str] = {
|
||||
"logic": "Audit premises, causal links, section order, transitions, contradictions, and whether each conclusion follows from stated constraints and evidence.",
|
||||
"reader": "Simulate the declared reader. Audit orientation, missing context, cognitive load, examples, scan paths, and whether process language or internal metadata breaks immersion.",
|
||||
@@ -62,17 +48,6 @@ def _dump(value: Any) -> str:
|
||||
return json.dumps(value, ensure_ascii=False, indent=2)
|
||||
|
||||
|
||||
def _style_guidance(brief: Brief) -> str:
|
||||
profile = brief.constraints.style_profile.casefold()
|
||||
if brief.is_korean and brief.document_type.value == "technical_blog" and profile in {
|
||||
"auto",
|
||||
"woowahan_tech_blog_ko",
|
||||
"korean_problem_solving_blog",
|
||||
}:
|
||||
return WOOWAHAN_TECH_BLOG_KO
|
||||
return "Use a reader-facing style appropriate to the document type; never expose planning or evidence-processing scaffolding."
|
||||
|
||||
|
||||
def _citation_policy(brief: Brief) -> str:
|
||||
style = brief.constraints.citation_style
|
||||
if not brief.constraints.require_citations:
|
||||
@@ -134,7 +109,7 @@ Apply these foundation rules:
|
||||
{FOUNDATION_RULES}
|
||||
|
||||
Apply this style guidance:
|
||||
{_style_guidance(brief)}
|
||||
{style_guidance(brief)}
|
||||
|
||||
{_source_hierarchy()}
|
||||
|
||||
@@ -176,7 +151,7 @@ Apply these foundation rules:
|
||||
{FOUNDATION_RULES}
|
||||
|
||||
Apply this style guidance:
|
||||
{_style_guidance(brief)}
|
||||
{style_guidance(brief)}
|
||||
|
||||
{_source_hierarchy()}
|
||||
|
||||
@@ -232,7 +207,7 @@ Apply these foundation rules:
|
||||
{FOUNDATION_RULES}
|
||||
|
||||
Apply this style guidance:
|
||||
{_style_guidance(brief)}
|
||||
{style_guidance(brief)}
|
||||
|
||||
{_source_hierarchy()}
|
||||
|
||||
@@ -247,6 +222,7 @@ Mandatory checks:
|
||||
- The opening must establish a real problem or tension rather than recite audience, scope, and source metadata.
|
||||
- Information-architecture labels must not leak as repetitive sentence scaffolding. In Korean technical blogs, distinguish real ordered sequences from formulaic “첫 번째/두 번째/세 번째 + abstract category” paragraph openings.
|
||||
- A question heading or transition must be answered immediately, and each contrast or causal connector must point to a real relation in the surrounding prose.
|
||||
{mandatory_style_review_checks(brief)}
|
||||
|
||||
Scoring dimensions (0-100 each):
|
||||
{dimension_list}
|
||||
@@ -313,7 +289,7 @@ Apply these foundation rules:
|
||||
{FOUNDATION_RULES}
|
||||
|
||||
Apply this style guidance:
|
||||
{_style_guidance(brief)}
|
||||
{style_guidance(brief)}
|
||||
|
||||
{_source_hierarchy()}
|
||||
|
||||
@@ -328,6 +304,7 @@ Revision protocol:
|
||||
8. Preserve correct material and the author's project context; avoid generic filler and unrelated rewrites.
|
||||
9. Remove repeated ordinal sentence scaffolding that merely reads the outline aloud. Preserve ordinals when they identify a real procedure, method, layer, or figure, and prefer a list or meaningful subheadings for parallel items.
|
||||
10. Return the entire revised document, not a patch or explanation.
|
||||
{revision_style_protocol(brief)}
|
||||
|
||||
Citation policy: {_citation_policy(brief)}
|
||||
Date policy: {_date_policy(brief)}
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from claridoc.models import Brief, DocumentType
|
||||
|
||||
|
||||
KOREAN_EXPERIENCE_CONTRACT_ID = "korean_first_person_experience_v1"
|
||||
|
||||
_KOREAN_TECHNICAL_BLOG_PROFILES = frozenset(
|
||||
{
|
||||
"auto",
|
||||
"woowahan_tech_blog_ko",
|
||||
"korean_problem_solving_blog",
|
||||
}
|
||||
)
|
||||
|
||||
_GENERIC_STYLE_GUIDANCE = (
|
||||
"Use a reader-facing style appropriate to the document type; never expose "
|
||||
"planning or evidence-processing scaffolding."
|
||||
)
|
||||
|
||||
_KOREAN_EXPERIENCE_GUIDANCE = f"""\
|
||||
Reader-prose contract: {KOREAN_EXPERIENCE_CONTRACT_ID}
|
||||
|
||||
Write Korean reader-facing prose as a supported first-person experience, not as a list of settled facts.
|
||||
- Follow this semantic order, never as a sentence template: concrete starting point -> initial expectation -> observed difference -> immediate term explanation -> author action or decision -> result, cost, or remaining limit.
|
||||
- At the opening and major section transitions, use `저는` or `제가` when it establishes what the author actually inspected, ran, understood, selected, or changed. Do not repeat first person mechanically in every sentence.
|
||||
- A first-person marker must represent a real observation or action supported by the source material. Never add an unsupported emotion, conversation, advice, failure, duration, result, or technical rationale.
|
||||
- Use `했습니다` for directly observed or performed work: `확인했습니다`, `따라갔습니다`, `생각했습니다`.
|
||||
- Use `합니다` for 현재 동작과 기술 설명: `사용합니다`, `호출합니다`, `막습니다`.
|
||||
- Use `있습니다`, `없습니다`, `입니다`, and `아닙니다` for state and judgment. Do not mix reader prose ending in `한다`, `있다`, `아니다`, or `~했다`.
|
||||
- Explain an unfamiliar term beside its first necessary use, as something the author came to understand while following the work.
|
||||
- Connect a contrast to the concrete component and behavior that actually differ. Do not leave the reader with abstract conclusions such as a changed "position", "shape", "meaning", or "perspective".
|
||||
- Preserve the exact claims, evidence status, numbers, versions, identifiers, code, commands, tables, links, diagrams, outline intents, and section order.
|
||||
- Treat problem -> constraints -> options -> decision as a semantic order, never as a sentence template. Do not narrate outline labels or open consecutive paragraphs with formulaic `첫 번째 제약은`, `두 번째 제약은`, and `세 번째 제약은`.
|
||||
- Use conversational but disciplined Korean. A Korean developer should be able to say the sentence naturally to a colleague without turning it into forced colloquial speech.
|
||||
"""
|
||||
|
||||
|
||||
def korean_experience_contract_applies(brief: Brief) -> bool:
|
||||
if not brief.is_korean:
|
||||
return False
|
||||
if brief.document_type == DocumentType.README:
|
||||
return True
|
||||
return (
|
||||
brief.document_type == DocumentType.TECHNICAL_BLOG
|
||||
and brief.constraints.style_profile.casefold() in _KOREAN_TECHNICAL_BLOG_PROFILES
|
||||
)
|
||||
|
||||
|
||||
def style_guidance(brief: Brief) -> str:
|
||||
if korean_experience_contract_applies(brief):
|
||||
return _KOREAN_EXPERIENCE_GUIDANCE
|
||||
return _GENERIC_STYLE_GUIDANCE
|
||||
|
||||
|
||||
def mandatory_style_review_checks(brief: Brief) -> str:
|
||||
if not korean_experience_contract_applies(brief):
|
||||
return ""
|
||||
return """\
|
||||
- For the `korean_first_person_experience_v1` contract, verify that `저는` or `제가` expresses 실제 관찰(actual observation) or action rather than decorating an objective explanation.
|
||||
- Verify that the opening and major transitions let the reader follow a concrete starting point, expectation, observed difference, understanding, action, and result or remaining cost.
|
||||
- Verify that an unfamiliar term is explained where the reader first needs it and that each contrast names the actual component and behavior that differ.
|
||||
- Verify consistent `합니다/했습니다` reader prose outside headings, tables, quotations, code blocks, and command output.
|
||||
- Flag any invented personal history, advice, emotion, failure, duration, outcome, or project rationale as an evidence defect.
|
||||
"""
|
||||
|
||||
|
||||
def revision_style_protocol(brief: Brief) -> str:
|
||||
if not korean_experience_contract_applies(brief):
|
||||
return ""
|
||||
return """\
|
||||
After resolving individual findings, recheck 문서 전체(the complete document) against `korean_first_person_experience_v1`.
|
||||
Do not stop after adding one `저는` sentence. Confirm the opening and major transitions still form supported experience threads, all reader prose still uses `합니다/했습니다`, unfamiliar terms remain explained at first need, and no compliant section regressed during the whole-document rewrite.
|
||||
"""
|
||||
Reference in New Issue
Block a user