Files
document-haness/docs/superpowers/plans/2026-07-29-korean-experience-prose-contract.md
T

631 lines
21 KiB
Markdown

# 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.