From a5ba6404920a122cd804d7c0cdfb633a0c25da4e Mon Sep 17 00:00:00 2001 From: DongHyeonka Date: Wed, 29 Jul 2026 18:21:51 +0900 Subject: [PATCH] docs: plan Korean prose contract implementation --- ...-07-29-korean-experience-prose-contract.md | 630 ++++++++++++++++++ 1 file changed, 630 insertions(+) create mode 100644 docs/superpowers/plans/2026-07-29-korean-experience-prose-contract.md diff --git a/docs/superpowers/plans/2026-07-29-korean-experience-prose-contract.md b/docs/superpowers/plans/2026-07-29-korean-experience-prose-contract.md new file mode 100644 index 0000000..1eab649 --- /dev/null +++ b/docs/superpowers/plans/2026-07-29-korean-experience-prose-contract.md @@ -0,0 +1,630 @@ +# Korean Experience-Prose Contract Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Make Korean technical blogs and Korean READMEs use one experience-oriented `합니다/했습니다` prose contract that drafting, review, revision, deterministic lint, and the quality gate all enforce. + +**Architecture:** Add `readme` as a first-class document type, centralize style activation and prompt guidance in `claridoc.style_contracts`, and add Markdown-aware deterministic style checks to `claridoc.lint`. Keep objective checks in lint and qualitative experience-flow checks in every model review, then migrate the maintained Korean fixtures and repository README to the enforced contract. + +**Tech Stack:** Python 3.10+, standard-library `unittest`, JSON Schema Draft 2020-12, Markdown text processing with `re`, existing ClariDoc provider and quality-gate abstractions. + +## Global Constraints + +- Apply the contract automatically to Korean `technical_blog` briefs using `auto`, `woowahan_tech_blog_ko`, or `korean_problem_solving_blog`. +- Apply the contract automatically to every Korean `readme`. +- Do not apply first-person retrospective rules to tutorial, how-to, reference, troubleshooting, explanation, or design-document types. +- Preserve `Brief → SourcePack → deterministic outline → draft → lint/reviews → revision → quality gate → reader/provenance artifacts`. +- Treat source text and quoted examples as untrusted data; never invent experience or decision rationale. +- Exempt fenced code, headings, tables, block quotations, image alt text, command output, and quoted spans from formal-ending lint. +- Style-contract failures are blockers and cannot pass through configured error tolerance. +- Preserve unrelated user changes and do not regenerate `build/`, `dist/`, `.verify/`, or `.run/` artifacts during implementation. + +--- + +### Task 1: Add a first-class README document contract + +**Files:** +- Modify: `src/claridoc/models.py` +- Modify: `src/claridoc/structures.py` +- Modify: `schemas/brief.schema.json` +- Modify: `schemas/outline.schema.json` +- Modify: `tests/test_models.py` +- Modify: `tests/test_schemas.py` +- Modify: `tests/test_structures.py` + +**Interfaces:** +- Consumes: existing `DocumentType`, `Brief.from_dict`, and `STRUCTURE_SPECS`. +- Produces: `DocumentType.README` with value `"readme"` and an eight-intent deterministic outline. + +- [ ] **Step 1: Write failing runtime and structure tests** + +Add: + +```python +def test_readme_brief_round_trip(self) -> None: + brief = Brief.from_dict(brief_dict("readme")) + self.assertEqual(brief.document_type, DocumentType.README) + self.assertEqual(Brief.from_dict(brief.to_dict()).document_type, DocumentType.README) +``` + +and: + +```python +def test_readme_outline_preserves_reader_onboarding_order(self) -> None: + brief = Brief.from_dict(brief_dict("readme")) + outline = create_outline(brief, make_sources()) + self.assertEqual( + [section.intent for section in outline.sections], + [ + "problem_value", + "principles", + "workflow", + "installation", + "quickstart", + "configuration", + "verification", + "limits_next", + ], + ) +``` + +Extend the schema test to validate a `readme` brief and outline instance with +`jsonschema.Draft202012Validator`. + +- [ ] **Step 2: Run the focused tests and verify RED** + +Run: + +```bash +PYTHONPATH=src python3 -m unittest \ + tests.test_models.ModelTests.test_readme_brief_round_trip \ + tests.test_structures.StructureTests.test_readme_outline_preserves_reader_onboarding_order \ + tests.test_schemas.SchemaTests.test_readme_is_accepted_by_brief_and_outline_schemas -v +``` + +Expected: failures because `"readme"` is not in the runtime enum or schemas. + +- [ ] **Step 3: Implement the README type and deterministic outline** + +Add: + +```python +class DocumentType(str, Enum): + ... + README = "readme" +``` + +Add eight `SectionSpec` entries under `DocumentType.README` using the approved +intent order. Each section must have Korean and English titles, reader +questions, purposes, and concrete `must_include` fields. Add `"readme"` to the +two schema enums. + +- [ ] **Step 4: Run the focused tests and verify GREEN** + +Run the Step 2 command. + +Expected: all three tests pass. + +- [ ] **Step 5: Commit the model contract** + +```bash +git add src/claridoc/models.py src/claridoc/structures.py \ + schemas/brief.schema.json schemas/outline.schema.json \ + tests/test_models.py tests/test_schemas.py tests/test_structures.py +git commit -m "feat: add README document contract" +``` + +--- + +### Task 2: Centralize the Korean experience-prose prompt contract + +**Files:** +- Create: `src/claridoc/style_contracts.py` +- Modify: `src/claridoc/prompts.py` +- Modify: `tests/test_prompts.py` + +**Interfaces:** +- Consumes: `Brief.is_korean`, `Brief.document_type`, and `constraints.style_profile`. +- Produces: + +```python +KOREAN_EXPERIENCE_CONTRACT_ID = "korean_first_person_experience_v1" +def korean_experience_contract_applies(brief: Brief) -> bool: ... +def style_guidance(brief: Brief) -> str: ... +def mandatory_style_review_checks(brief: Brief) -> str: ... +def revision_style_protocol(brief: Brief) -> str: ... +``` + +- [ ] **Step 1: Write failing prompt propagation tests** + +Replace the narrow ordinal-only prompt test with separate tests that assert: + +```python +for prompt in (draft, review, revision): + self.assertIn("korean_first_person_experience_v1", prompt) + self.assertIn("저는", prompt) + self.assertIn("제가", prompt) + self.assertIn("했습니다", prompt) + self.assertIn("현재 동작과 기술 설명", prompt) +``` + +Add a Korean `readme` case with the same assertions, an English technical-blog +case that does not contain the contract ID, and a Korean `tutorial` case that +does not contain the contract ID. Assert that review asks whether first person +represents a real observation and revision asks for a whole-document recheck. + +- [ ] **Step 2: Run prompt tests and verify RED** + +Run: + +```bash +PYTHONPATH=src python3 -m unittest tests.test_prompts -v +``` + +Expected: contract-ID and README propagation assertions fail. + +- [ ] **Step 3: Implement the shared contract module** + +Move the existing Korean technical-blog profile out of `prompts.py`. Return a +single provider-facing contract for the approved activation cases. Include: + +```text +concrete starting point +→ initial expectation +→ observed difference +→ immediate term explanation +→ author action or decision +→ result, cost, or remaining limit +``` + +Require `했습니다` for performed or observed work and `합니다` for current +behavior. State that `저는/제가` must establish a supported experience, not +decorate an objective explanation. State that unsupported conversations, +emotions, failures, durations, results, and rationales are forbidden. + +- [ ] **Step 4: Inject the shared contract into every provider stage** + +Make planning and drafting call `style_guidance(brief)`. Add +`mandatory_style_review_checks(brief)` to the mandatory review section and +`revision_style_protocol(brief)` to the revision protocol. Keep ordinal-frame +guidance inside the shared contract so no abbreviated duplicate remains in +`prompts.py`. + +- [ ] **Step 5: Run prompt tests and verify GREEN** + +Run the Step 2 command. + +Expected: all prompt tests pass. + +- [ ] **Step 6: Commit prompt integration** + +```bash +git add src/claridoc/style_contracts.py src/claridoc/prompts.py tests/test_prompts.py +git commit -m "feat: propagate Korean prose contract to providers" +``` + +--- + +### Task 3: Add Markdown-aware deterministic style lint + +**Files:** +- Modify: `src/claridoc/style_contracts.py` +- Modify: `src/claridoc/lint.py` +- Modify: `tests/test_lint.py` + +**Interfaces:** +- Consumes: `korean_experience_contract_applies(brief)` and Markdown text. +- Produces: + +```python +@dataclass(frozen=True, slots=True) +class ReaderProseSegment: + text: str + line: int + h2_title: str | None + +def reader_prose_segments(markdown: str) -> list[ReaderProseSegment]: ... +def plain_form_ending_locations(markdown: str) -> list[int]: ... +def first_person_metrics(markdown: str) -> dict[str, int | float | bool]: ... +``` + +and lint codes `STYLE002` and `STYLE003`. + +- [ ] **Step 1: Write a failing formal-ending lint test** + +Create a Korean experience-contract brief and a structurally valid document, +then replace one prose sentence with `현재 구현은 이 값을 사용한다.`. Assert: + +```python +issues = [issue for issue in report.issues if issue.code == "STYLE002"] +self.assertEqual(len(issues), 1) +self.assertEqual(issues[0].severity, Severity.BLOCKER) +self.assertEqual(report.metrics["plain_form_ending_count"], 1) +``` + +- [ ] **Step 2: Run the focused test and verify RED** + +Run: + +```bash +PYTHONPATH=src python3 -m unittest \ + tests.test_lint.LintTests.test_korean_experience_contract_blocks_plain_form_endings -v +``` + +Expected: `STYLE002` is absent. + +- [ ] **Step 3: Implement minimal Markdown prose extraction and ending lint** + +Track fenced-code state and current H2 while scanning lines. Exclude headings, +block quotations, tables, image-only lines, and command-output blocks. Remove +inline code, Markdown link targets, and paired quoted spans before matching +plain Korean declarative endings with a boundary that does not match `니다.`. +Consolidate all matches into one blocker and record the total count. + +- [ ] **Step 4: Run the focused test and verify GREEN** + +Run the Step 2 command. + +Expected: the test passes. + +- [ ] **Step 5: Write failing exclusion tests** + +Build a document whose fenced code, heading, table cell, block quote, image alt +text, inline code, and direct quoted example contain `한다.` while reader prose +uses `합니다.`. Assert that `STYLE002` is absent and +`plain_form_ending_count == 0`. + +- [ ] **Step 6: Run the exclusion test and verify RED** + +Run: + +```bash +PYTHONPATH=src python3 -m unittest \ + tests.test_lint.LintTests.test_korean_style_lint_exempts_non_reader_prose -v +``` + +Expected: at least one exempt region is incorrectly counted until all +exclusions are implemented. + +- [ ] **Step 7: Complete the exclusion parser and verify GREEN** + +Refine `reader_prose_segments` only as needed for the failing examples. Do not +implement a general Markdown parser or add a dependency. + +- [ ] **Step 8: Write failing first-person coverage tests** + +Add tests for: + +- no `저는/제가` in the opening; +- fewer than half of substantive H2 sections containing a marker; +- table-only and code-only H2 sections not entering the denominator; +- opening plus at least half of substantive sections passing. + +Assert `STYLE003` is one consolidated blocker and that the metrics contain the +approved contract ID, counts, and coverage. + +- [ ] **Step 9: Run coverage tests and verify RED** + +Run: + +```bash +PYTHONPATH=src python3 -m unittest \ + tests.test_lint.LintTests.test_korean_style_lint_requires_first_person_opening \ + tests.test_lint.LintTests.test_korean_style_lint_requires_major_section_coverage \ + tests.test_lint.LintTests.test_korean_style_lint_ignores_non_prose_sections \ + tests.test_lint.LintTests.test_korean_style_lint_accepts_compliant_experience_prose -v +``` + +Expected: missing `STYLE003` and metrics failures. + +- [ ] **Step 10: Implement first-person metrics and verify GREEN** + +Treat the first substantive reader-prose paragraph as the opening. Count each +substantive H2 at most once. Require an opening marker and +`marked_sections / substantive_sections >= 0.5`. If there are no substantive +H2 sections, let existing structure checks handle the empty document while +recording zero coverage. + +- [ ] **Step 11: Run all lint tests** + +```bash +PYTHONPATH=src python3 -m unittest tests.test_lint -v +``` + +Expected: style tests pass; fixture-dependent failures, if any, identify the +next migration task rather than being hidden. + +- [ ] **Step 12: Commit deterministic enforcement** + +```bash +git add src/claridoc/style_contracts.py src/claridoc/lint.py tests/test_lint.py +git commit -m "feat: block Korean prose contract violations" +``` + +--- + +### Task 4: Make maintained fixtures satisfy the enforced contract + +**Files:** +- Modify: `src/claridoc/providers/mock.py` +- Modify: `examples/golden/application-core-spring-di-boundary.md` +- Modify: `tests/test_lint.py` +- Modify: `tests/test_pipeline.py` +- Modify: `src/claridoc/report.py` + +**Interfaces:** +- Consumes: new style metrics and existing mock `draft`/`revise` stages. +- Produces: contract-compliant mock Korean technical-blog prose and quality + reports that expose the active style contract and metrics. + +- [ ] **Step 1: Add failing mock-pipeline and report assertions** + +In `test_end_to_end_mock_run_creates_auditable_artifacts`, assert: + +```python +self.assertEqual( + result.rounds[-1].lint_report.metrics["style_contract"], + "korean_first_person_experience_v1", +) +self.assertIn("korean_first_person_experience_v1", report_text) +``` + +Add a pipeline test that supplies a provider document with a `STYLE002` +violation and sets `max_errors` above zero; assert `result.passed` is false and +the blocker appears in `quality-gate.json`. + +- [ ] **Step 2: Run pipeline and golden tests and verify RED** + +Run: + +```bash +PYTHONPATH=src python3 -m unittest \ + tests.test_pipeline \ + tests.test_lint.LintTests.test_golden_application_core_example_has_no_material_lint_issue -v +``` + +Expected: the report omits style metrics and maintained fixtures fail the new +blockers. + +- [ ] **Step 3: Update mock prose without weakening lint** + +Revise the mock technical-blog generator so its opening and at least half of +its H2 sections use supported `저는/제가` experience transitions and all +reader-facing Korean sentences use `합니다/했습니다`. Preserve synthetic +fixture warnings and never describe mock prose as quality evidence. + +- [ ] **Step 4: Migrate the golden document** + +Use the `revising-korean-technical-prose` skill to revise the golden document +in place. Preserve its exact H1/H2 contract, technical claims, decision +rationale, code block, evidence boundaries, and length intent. + +- [ ] **Step 5: Render style metrics in the run report** + +Add a `Reader-prose contract` subsection when +`final.lint_report.metrics["style_contract"] != "none"`. Render contract ID, +plain-ending count, first-person marker count, substantive-section count, and +coverage. + +- [ ] **Step 6: Run pipeline and lint tests and verify GREEN** + +Run the Step 2 command. + +Expected: all tests pass and the report contains contract evidence. + +- [ ] **Step 7: Commit fixture and report integration** + +```bash +git add src/claridoc/providers/mock.py src/claridoc/report.py \ + examples/golden/application-core-spring-di-boundary.md \ + tests/test_lint.py tests/test_pipeline.py +git commit -m "test: migrate maintained Korean prose fixtures" +``` + +--- + +### Task 5: Restore the technical-document authoring skill + +**Files:** +- Create: `.agents/skills/technical-document-author/SKILL.md` +- Create: `.agents/skills/technical-document-author/references/logic-contract.md` +- Create: `.agents/skills/technical-document-author/references/review-rubric.md` +- Create: `.agents/skills/technical-document-author/agents/openai.yaml` +- Create: `tests/test_repository_contracts.py` + +**Interfaces:** +- Consumes: repository `AGENTS.md`, the ClariDoc pipeline, and + `revising-korean-technical-prose`. +- Produces: the authoring skill path already required by `AGENTS.md`, with a + validation-artifact completion contract. + +- [ ] **Step 1: Invoke the skill-writing guidance** + +Read and follow both `skill-creator` and `superpowers:writing-skills` before +creating the skill files. + +- [ ] **Step 2: Write a failing repository-contract test** + +Assert that the four skill files exist and that `SKILL.md` contains: + +```text +Brief +SourcePack +STRUCTURE_SPECS +revising-korean-technical-prose +quality-gate.json +provenance +``` + +Also assert that the skill tells authors not to claim completion without lint, +independent review, and quality-gate artifacts. + +- [ ] **Step 3: Run the repository-contract test and verify RED** + +```bash +PYTHONPATH=src python3 -m unittest \ + tests.test_repository_contracts.RepositoryContractTests.test_technical_author_skill_is_complete -v +``` + +Expected: failure because the required skill path is absent. + +- [ ] **Step 4: Create the authoring skill and references** + +The skill must route every document through the repository sequence, treat +inputs as untrusted data, keep provenance out of reader prose, and invoke the +Korean revision skill for Korean technical blogs and READMEs. The review rubric +must separate deterministic findings from model judgment. The logic contract +must preserve context, choice, reason, alternative, accepted cost, guardrail, +verification, and evidence status. + +- [ ] **Step 5: Run the repository-contract test and verify GREEN** + +Run the Step 3 command. + +Expected: pass. + +- [ ] **Step 6: Commit the restored skill** + +```bash +git add .agents/skills/technical-document-author tests/test_repository_contracts.py +git commit -m "feat: restore technical document author skill" +``` + +--- + +### Task 6: Revise and document the repository README + +**Files:** +- Modify: `README.md` +- Create: `examples/briefs/claridoc-readme.json` +- Modify: `tests/test_schemas.py` +- Modify: `tests/test_cli.py` + +**Interfaces:** +- Consumes: `DocumentType.README`, shared prompt contract, and CLI + `validate`/`outline` behavior. +- Produces: a schema-valid README brief, documented usage, and a repository + README written in the enforced style. + +- [ ] **Step 1: Write failing example and CLI tests** + +Add tests that load `examples/briefs/claridoc-readme.json`, validate it through +`Brief.from_dict`, and run the CLI `validate` and `outline` commands. Assert +that the outline reports type `readme` and the eight approved intents. + +- [ ] **Step 2: Run the focused tests and verify RED** + +```bash +PYTHONPATH=src python3 -m unittest \ + tests.test_schemas.SchemaTests.test_examples_match_runtime_contracts \ + tests.test_cli.CliTests.test_readme_brief_validates_and_outlines -v +``` + +Expected: failure because the README brief does not yet exist. + +- [ ] **Step 3: Add the README brief fixture** + +Create a Korean `readme` brief for ClariDoc with hidden citations, +`style_profile: "auto"`, the current project scope, and no invented operational +claims. + +- [ ] **Step 4: Run the focused tests and verify GREEN** + +Run the Step 2 command. + +Expected: pass. + +- [ ] **Step 5: Revise README in place** + +Use `revising-korean-technical-prose` and its sentence-pattern reference. +Preserve commands, tables, links, diagrams, versions, source hierarchy, +provider descriptions, and safety statements. Convert reader-facing Korean +prose to `합니다/했습니다`, add supported `저는/제가` experience transitions, +and add a section describing: + +- automatic activation for Korean technical blogs and READMEs; +- `STYLE002` and `STYLE003`; +- model-review responsibilities; +- a `readme` brief example and validation command. + +- [ ] **Step 6: Scan the README contract** + +Run a read-only scanner using `reader_prose_segments` and assert: + +```text +plain_form_ending_count = 0 +opening_has_first_person = true +experience_section_coverage >= 0.5 +``` + +Review the diff to confirm facts, code blocks, links, and information order +remain intact. + +- [ ] **Step 7: Commit README migration** + +```bash +git add README.md examples/briefs/claridoc-readme.json \ + tests/test_schemas.py tests/test_cli.py +git commit -m "docs: apply Korean prose contract to README" +``` + +--- + +### Task 7: Run regression validation and review the implementation + +**Files:** +- Modify only files required by verified failures in the preceding tasks. + +**Interfaces:** +- Consumes: all implemented tasks. +- Produces: test and review evidence with no regenerated user-owned build or + distribution artifacts. + +- [ ] **Step 1: Run the full unit and integration suite** + +```bash +PYTHONPATH=src python3 -m unittest discover -s tests -v +``` + +Expected: all tests pass. + +- [ ] **Step 2: Run non-destructive contract commands** + +```bash +PYTHONPATH=src python3 -m claridoc validate \ + --brief examples/briefs/claridoc-readme.json \ + --sources examples/sources/retry-policy-sources.json + +PYTHONPATH=src python3 -m claridoc outline \ + --brief examples/briefs/claridoc-readme.json \ + --sources examples/sources/retry-policy-sources.json \ + --output /tmp/claridoc-readme-outline.json +``` + +Expected: both commands succeed and the output uses `document_type: readme`. + +- [ ] **Step 3: Inspect destructive verification scope** + +Do not run `scripts/verify.sh` because it removes and rebuilds `.verify`, +`build`, `dist`, egg-info, and demo outputs that already contain user changes. +Run its non-destructive validation portions through the unit suite, schema +tests, CLI tests, JSON parsing, local-link scan, and an isolated wheel build in +`/tmp`. + +- [ ] **Step 4: Run independent code review** + +Use `superpowers:requesting-code-review` to inspect the final diff against the +design and plan. Resolve every blocker and error through a new failing test +before changing production code. + +- [ ] **Step 5: Run verification-before-completion** + +Use `superpowers:verification-before-completion`, rerun the full test suite, +README style scan, schema validation, and isolated package build, and record +the exact results. + +- [ ] **Step 6: Finish the development branch** + +Use `superpowers:finishing-a-development-branch`. Because the user explicitly +requested uninterrupted inline implementation on the current branch, do not +merge, push, or open a PR without a new explicit request.