Build CoreOrdered learning track

Learn Ai Docs Km Cli Part 020 Example Aware Doc Generation

12 min read2377 words
PrevNext
Lesson 2048 lesson track10–26 Build Core

title: Build From Scratch: Mintlify-like AI-driven Documentation Generator CLI - Part 020 description: Membangun pipeline example-aware documentation generation berbasis test, fixture, contract, dan real usage episode agar docs tidak mengarang contoh. series: learn-ai-docs-km-cli seriesTitle: Build From Scratch: Mintlify-like AI-driven Documentation Generator CLI with Code2Prompt and Open-source Knowledge Management order: 20 partTitle: Example-aware Documentation Generation tags:

  • ai-docs
  • documentation
  • cli
  • examples
  • testing
  • source-grounded-generation
  • mdx
  • verification date: 2026-07-04

Part 020 — Example-aware Documentation Generation

Dokumentasi developer yang baik hampir selalu berputar di sekitar contoh.

Bukan contoh asal-asalan seperti:

const result = doSomething();
console.log(result);

Melainkan contoh yang menjawab:

  • Bagaimana cara memulai?
  • Input minimalnya apa?
  • Output yang benar seperti apa?
  • Error yang mungkin muncul apa?
  • Konfigurasi apa yang wajib?
  • Apa edge case yang sering salah?
  • Bagaimana ini dipakai dalam aplikasi nyata?

Masalahnya: LLM sangat mudah membuat contoh yang terlihat masuk akal tetapi tidak benar-benar ada di repo.

Part ini membangun example-aware documentation generation:

Generate docs dengan contoh yang berasal dari test, fixture, contract, sample app, command manifest, atau source-backed usage episode — bukan dari imajinasi model.


1. Fakta Dasar yang Perlu Dipegang

OpenAPI Specification mendefinisikan interface standar untuk HTTP API agar manusia dan komputer dapat memahami kapabilitas service tanpa akses ke source code atau inspeksi network. OpenAPI document sendiri dapat direpresentasikan sebagai JSON atau YAML. Ini penting karena API examples sebaiknya bisa diturunkan dari contract, bukan dikarang ulang.

JUnit 5 User Guide adalah referensi komprehensif untuk programmer yang menulis test, extension author, dan tool vendor. Pytest documentation menekankan test yang kecil dan readable serta bisa scale ke functional testing kompleks. Playwright menyediakan codegen yang dapat menghasilkan test dari interaksi browser dan memilih locator yang lebih resilient. GitHub Docs menjelaskan praktik fenced code block untuk dokumentasi Markdown.

Referensi:

Konsekuensi untuk sistem kita:

  1. Test dan contract adalah sumber contoh yang lebih kuat daripada output bebas LLM.
  2. Example docs harus bisa ditelusuri ke source.
  3. Snippet perlu divalidasi terhadap bahasa/framework-nya jika memungkinkan.
  4. Example yang outdated harus terdeteksi sebagai doc drift.
  5. Generated docs harus membedakan contoh runnable, pseudo-code, dan conceptual sketch.

2. Mental Model: Example as Usage Episode

Jangan modelkan example sebagai string code.

Modelkan sebagai usage episode.

Sebuah usage episode memiliki:

  • actor,
  • goal,
  • setup,
  • input,
  • action,
  • expected output,
  • assertion,
  • cleanup,
  • source provenance,
  • risk flags.

Contoh:

{
  "id": "ex-http-create-project-success",
  "kind": "http-request",
  "goal": "Create a project",
  "source": {
    "path": "tests/api/projects.create.test.ts",
    "lines": [12, 48],
    "hash": "sha256:..."
  },
  "setup": [
    "User has a valid API token"
  ],
  "action": {
    "method": "POST",
    "path": "/v1/projects",
    "body": {
      "name": "Docs Engine"
    }
  },
  "expected": {
    "status": 201,
    "bodyShape": {
      "id": "string",
      "name": "Docs Engine"
    }
  },
  "assertions": [
    "response.status === 201",
    "response.body.name === 'Docs Engine'"
  ],
  "redaction": "clean",
  "runnable": true
}

Dari satu usage episode, kita bisa render banyak bentuk:

  • tutorial step,
  • API example,
  • SDK example,
  • troubleshooting scenario,
  • test-derived snippet,
  • knowledge graph note.

3. Kenapa Test adalah Sumber Dokumentasi yang Kuat

Test biasanya mengandung tiga hal yang docs butuhkan:

setup -> action -> assertion

Contoh test:

it("creates a project", async () => {
  const api = createClient({ token: testToken });

  const project = await api.projects.create({
    name: "Docs Engine"
  });

  expect(project.name).toBe("Docs Engine");
  expect(project.id).toBeDefined();
});

Dokumentasi yang bisa diturunkan:

```ts
const api = createClient({ token: process.env.API_TOKEN });

const project = await api.projects.create({
  name: "Docs Engine"
});

console.log(project.id);
```

Tapi transformasi ini tidak boleh sembarangan.

Bagian test yang perlu dibuang:

  • testToken,
  • mocking boilerplate,
  • assertion library syntax jika tidak relevan,
  • internal fixtures,
  • random data helper,
  • cleanup detail yang tidak perlu untuk reader.

Bagian test yang perlu dipertahankan:

  • cara membuat client,
  • required config,
  • method yang dipanggil,
  • request shape,
  • expected response shape,
  • error behavior jika test negative.

4. Example Mining Pipeline

Pipeline umum:

Artifact utama:

examples.v1.json

Example-aware generator tidak bertanya:

Contoh apa yang bisa dibuat?

Ia bertanya:

Contoh apa yang sudah terbukti atau tersirat kuat dari source?


5. Source Types untuk Example

SourceStrengthNotes
Integration testSangat tinggiBiasanya paling dekat dengan real usage.
Unit testSedang-tinggiBaik untuk fungsi kecil, kadang terlalu internal.
E2E testTinggiBaik untuk user journey, bisa noisy.
OpenAPI examplesTinggiBaik untuk API request/response.
Schema fixturesSedangBaik untuk payload shape.
README snippetsSedangPerlu validasi karena bisa stale.
/examples directoryTinggiBiasanya memang dibuat untuk docs.
CLI manifestTinggiBaik untuk command examples.
Issue/bug reproductionSedangBaik untuk troubleshooting, perlu sanitasi.
LLM-generated from nothingRendahDefault harus ditolak.

Kita beri score:

export type ExampleSourceStrength =
  | "verified-runtime"
  | "contract-backed"
  | "source-backed"
  | "human-doc-backed"
  | "inferred"
  | "unverified";

Default policy:

verified-runtime > contract-backed > source-backed > human-doc-backed > inferred > unverified

unverified tidak boleh masuk docs kecuali diberi label eksplisit sebagai conceptual pseudo-code.


6. Example Catalog Schema

Contoh schema minimal:

export type ExampleCatalog = {
  version: "examples.v1";
  repo: RepoIdentity;
  generatedAt: string;
  examples: UsageExample[];
  diagnostics: ExampleDiagnostic[];
};

export type UsageExample = {
  id: string;
  kind:
    | "http"
    | "sdk"
    | "cli"
    | "config"
    | "event"
    | "database"
    | "workflow"
    | "troubleshooting";
  title: string;
  goal: string;
  sourceRefs: SourceRef[];
  relatedSymbols: string[];
  relatedContracts: string[];
  setup: ExampleStep[];
  action: ExampleAction;
  expected: ExampleExpected;
  snippet?: CodeSnippet;
  assertions: string[];
  redaction: RedactionStatus;
  runnable: RunnableStatus;
  confidence: number;
  riskFlags: string[];
};

Snippet:

export type CodeSnippet = {
  language: string;
  code: string;
  sourceRefs: SourceRef[];
  derivedFromTest: boolean;
  transformationNotes: string[];
  validation?: SnippetValidation;
};

Validation:

export type SnippetValidation = {
  status: "passed" | "failed" | "skipped";
  mode: "syntax" | "compile" | "run" | "contract";
  command?: string;
  output?: string;
  errors?: string[];
};

7. Test Parser: Apa yang Dicari?

Untuk banyak bahasa, kita tidak perlu full semantic parser di awal. Kita bisa mulai dengan pattern.

Cari struktur:

describe/context/test/it
setup/helper/client initialization
action call
assertion/expect
fixture loading
HTTP request
CLI invocation
snapshot expectation

Contoh TypeScript/Jest/Vitest:

it("creates a project", async () => {
  const response = await request(app)
    .post("/v1/projects")
    .send({ name: "Docs Engine" })
    .expect(201);

  expect(response.body.name).toBe("Docs Engine");
});

Episode:

{
  "kind": "http",
  "goal": "Create a project",
  "action": {
    "method": "POST",
    "path": "/v1/projects",
    "body": { "name": "Docs Engine" }
  },
  "expected": {
    "status": 201,
    "bodyAssertions": ["name equals Docs Engine"]
  }
}

Contoh Java/JUnit:

@Test
void createsProject() {
    Project project = client.projects().create(new CreateProjectRequest("Docs Engine"));

    assertEquals("Docs Engine", project.name());
    assertNotNull(project.id());
}

Episode:

{
  "kind": "sdk",
  "language": "java",
  "goal": "Create a project using the Java client",
  "action": {
    "symbol": "client.projects().create",
    "inputType": "CreateProjectRequest"
  },
  "expected": {
    "assertions": ["project.name == Docs Engine", "project.id is not null"]
  }
}

8. Transforming Test Code into Documentation Code

Test code jarang cocok langsung dipaste ke docs.

Kita perlu transformasi.

8.1 Remove test-only noise

Dari:

it("creates a project", async () => {
  const api = createTestClient({ token: fixtures.validToken });
  const name = uniqueName("project");

  const project = await api.projects.create({ name });

  expect(project.id).toMatch(/^prj_/);
  expect(project.name).toBe(name);
});

Menjadi:

const api = createClient({ token: process.env.API_TOKEN });

const project = await api.projects.create({
  name: "Docs Engine"
});

console.log(project.id);

Transformation notes:

[
  "Replaced createTestClient with public createClient",
  "Replaced fixtures.validToken with process.env.API_TOKEN",
  "Replaced uniqueName helper with deterministic example value",
  "Removed test assertions and kept observable output"
]

8.2 Preserve essential setup

Jangan hilangkan setup yang penting.

Buruk:

const project = await api.projects.create({ name: "Docs Engine" });

Kalau reader belum tahu api berasal dari mana, snippet tidak followable.

Lebih baik:

import { createClient } from "@example/sdk";

const api = createClient({ token: process.env.API_TOKEN });

const project = await api.projects.create({
  name: "Docs Engine"
});

8.3 Mark non-runnable snippets

Jika snippet tidak lengkap:

```ts
// Inside your request handler
await auditLog.record({
  action: "project.created",
  actorId: user.id
});
```

Maka metadata internal harus:

{
  "runnable": "contextual",
  "reason": "Requires existing request handler context"
}

Jangan label semua snippet sebagai runnable.


9. Redaction Pipeline

Example mining bisa menemukan secrets atau PII.

Redaction harus berjalan sebelum snippet masuk context LLM.

Cari:

  • API keys,
  • tokens,
  • passwords,
  • private URLs,
  • emails personal,
  • phone numbers,
  • customer IDs,
  • internal hostnames,
  • JWT,
  • cloud credentials,
  • database connection string.

Contoh:

postgres://admin:secret@prod-db.company.internal:5432/main

Rendered docs aman:

postgres://USER:PASSWORD@HOST:5432/DATABASE

Atau:

DATABASE_URL=postgres://USER:PASSWORD@HOST:5432/DATABASE

Redaction artifact:

{
  "exampleId": "ex-config-database-url",
  "redactions": [
    {
      "kind": "database-url",
      "field": "DATABASE_URL",
      "replacement": "postgres://USER:PASSWORD@HOST:5432/DATABASE"
    }
  ],
  "status": "redacted"
}

Aturan keras:

No unredacted secret may enter prompt bundle or generated MDX.

10. HTTP Example Generation

HTTP example bisa datang dari:

  • OpenAPI examples,
  • integration tests,
  • supertest/request tests,
  • API client tests,
  • recorded fixtures.

Structured episode:

{
  "kind": "http",
  "method": "POST",
  "path": "/v1/projects",
  "headers": {
    "Authorization": "Bearer <API_TOKEN>",
    "Content-Type": "application/json"
  },
  "body": {
    "name": "Docs Engine"
  },
  "expected": {
    "status": 201,
    "body": {
      "id": "prj_123",
      "name": "Docs Engine"
    }
  }
}

Rendered MDX:

```bash
curl -X POST "https://api.example.com/v1/projects" \
  -H "Authorization: Bearer $API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Docs Engine"}'
```

Response:

```json
{
  "id": "prj_123",
  "name": "Docs Engine"
}
```

Verifier harus cek:

  • path ada di contract,
  • method cocok,
  • request body shape cocok,
  • response status valid,
  • field response tidak mengarang,
  • auth scheme sesuai contract.

11. SDK Example Generation

SDK docs harus menunjukkan public API, bukan internal class.

Source:

const project = await client.projects.create({ name: "Docs Engine" });

Generated docs:

```ts
import { createClient } from "@example/sdk";

const client = createClient({
  token: process.env.API_TOKEN
});

const project = await client.projects.create({
  name: "Docs Engine"
});

console.log(project.id);
```

Verifier:

Does package export createClient?
Does projects.create exist?
Does input type accept name?
Does return type include id?

Jika tidak bisa compile, set status:

{
  "validation": {
    "status": "skipped",
    "reason": "No package build available in current environment"
  }
}

Jangan pura-pura passed.


12. CLI Example Generation

CLI examples bisa datang dari:

  • command manifest,
  • CLI tests,
  • README,
  • shell snapshot tests.

Episode:

{
  "kind": "cli",
  "command": "aidocs scan",
  "args": ["--json"],
  "expectedExitCode": 0,
  "expectedOutputShape": {
    "filesScanned": "number",
    "filesSkipped": "number"
  }
}

Rendered:

```bash
npx aidocs scan --json
```

Expected output:

```json
{
  "filesScanned": 128,
  "filesSkipped": 14,
  "warnings": []
}
```

CLI example policy:

  1. Prefer --dry-run for destructive operations.
  2. Include expected exit code for troubleshooting docs.
  3. Show output shape, not environment-specific full output.
  4. Avoid commands requiring secrets unless clearly marked.
  5. Validate command exists in CLI manifest.

13. Config Example Generation

Config docs sering stale.

Config example harus berasal dari:

  • schema,
  • default config,
  • fixture config,
  • test config,
  • sample config.

Example:

model:
  provider: openai
  name: gpt-4.1-mini

docs:
  outputDir: docs
  navigation: docs.json

knowledge:
  sinks:
    - type: logseq
      path: ~/notes/logseq

Verifier:

Does model.provider allow openai?
Does docs.outputDir exist or is creatable?
Does knowledge.sinks[].type allow logseq?
Are deprecated fields absent?

Config docs should distinguish:

  • required fields,
  • optional fields,
  • default values,
  • environment-specific fields,
  • advanced fields.

14. Negative Examples

Good docs do not only show success paths.

Negative examples are useful for:

  • validation errors,
  • auth errors,
  • rate limits,
  • missing config,
  • wrong file path,
  • unsupported language,
  • unsafe prompt content.

Source from tests:

it("rejects generation when source contains unredacted secrets", async () => {
  const result = await run("aidocs generate", {
    files: ["fixtures/secret.env"]
  });

  expect(result.exitCode).toBe(2);
  expect(result.stderr).toContain("secret detected");
});

Generated troubleshooting docs:

```bash
npx aidocs generate
```

```txt
Error: secret detected in fixtures/secret.env
```

Run the scanner report to inspect the blocked file:

```bash
npx aidocs scan --show-risk
```

Negative examples need special care. Jangan expose secret fixture asli.


15. Example Ranking

Tidak semua example layak masuk docs.

Score:

score =
  sourceStrength * 0.30 +
  publicSurfaceRelevance * 0.25 +
  readerUsefulness * 0.20 +
  simplicity * 0.10 +
  freshness * 0.10 +
  validationStatus * 0.05 -
  riskPenalty;

Signals:

SignalMeaning
source strengthTest/contract/example dir lebih kuat dari inference.
public surface relevanceContoh memakai API publik, bukan internal helper.
reader usefulnessMenjawab use case nyata.
simplicityTidak terlalu banyak setup.
freshnessSource hash terbaru dan tidak stale.
validationSyntax/compile/run/contract check.
riskSecret, PII, destructive command, internal-only API.

Ranking harus explainable.

CLI:

npx aidocs examples rank --explain

Output:

ex-sdk-create-project
  score: 0.91
  reason:
    + integration test source
    + uses public SDK method
    + has assertion for id and name
    + snippet compiles
    - requires API token setup

16. Example-to-Page Matching

Example catalog besar tidak boleh dilempar semua ke setiap page.

Matching berdasarkan:

  • target page type,
  • related symbols,
  • related contracts,
  • reader journey stage,
  • difficulty,
  • language preference,
  • source confidence,
  • section requirement.

Contoh:

{
  "pageId": "quickstart",
  "needs": [
    "minimal-install",
    "first-command",
    "expected-output"
  ]
}

Candidate examples:

[
  {
    "id": "ex-cli-init",
    "matches": ["first-command"],
    "score": 0.88
  },
  {
    "id": "ex-cli-scan-json",
    "matches": ["expected-output"],
    "score": 0.81
  }
]

The generator receives selected examples only, not the entire catalog.


17. Page Generation Rule: No Example, No Claim of Usage

A hard rule:

If a page section claims "you can do X", there must be either:
1. a source-backed example,
2. a contract-backed example,
3. a verified command/API reference,
4. or the claim must be marked conceptual.

Bad generated sentence:

You can automatically publish the generated docs to any hosting provider.

Why bad?

  • “any hosting provider” is too broad.
  • No source-backed command or integration.

Better:

The CLI can generate a static docs artifact under the configured output directory. Publishing that artifact depends on the hosting adapter configured for the project.

Even better if source-backed:

Run the build command to generate the local docs artifact:

```bash
npx aidocs build --output docs-dist
But only if `aidocs build --output` exists in CLI manifest. --- ## 18. Example Rendering Pattern Use consistent pattern: ```mdx ## Create a project This example creates a project using the public SDK client. ### Before you start - Set `API_TOKEN` in your environment. - Install `@example/sdk`. ### Request ```ts import { createClient } from "@example/sdk"; const client = createClient({ token: process.env.API_TOKEN }); const project = await client.projects.create({ name: "Docs Engine" }); console.log(project.id);

Expected result

prj_123
For each example, reader should know: - what it does, - what must exist before running it, - the code/command, - expected output, - what to do if it fails. --- ## 19. Snippet Verification Verification levels: | Level | Description | Cost | |---|---|---:| | syntax | Parse snippet only | Low | | typecheck | Compile/typecheck snippet | Medium | | contract | Validate request/response against schema | Medium | | runtime | Run snippet/test | High | | snapshot | Compare output to expected snapshot | High | Default strategy: ```txt fast local generation: syntax + contract full verify: syntax + typecheck + contract CI verify: syntax + typecheck + contract + selected runtime release verify: full runtime where practical

Verifier artifact:

{
  "snippetId": "snippet-sdk-create-project-ts",
  "status": "passed",
  "checks": [
    { "kind": "syntax", "status": "passed" },
    { "kind": "typecheck", "status": "passed" },
    { "kind": "contract", "status": "passed" }
  ]
}

If verification fails, docs generation should not silently include snippet.

Options:

  1. remove snippet,
  2. include as conceptual pseudo-code with warning,
  3. generate repair task,
  4. block build in CI.

20. Keeping Examples Fresh

Example drift happens when code changes but docs snippets do not.

Use source hash:

{
  "exampleId": "ex-sdk-create-project",
  "sourceRefs": [
    {
      "path": "tests/sdk/projects.test.ts",
      "lines": [10, 34],
      "hash": "sha256:old"
    }
  ]
}

On next scan:

source hash changed -> example stale -> affected docs pages dirty

Dirty propagation:

CLI:

npx aidocs examples stale

Output:

Stale examples:
  ex-sdk-create-project
    source changed: tests/sdk/projects.test.ts
    affected pages:
      docs/quickstart.mdx
      docs/sdk/projects.mdx

21. Avoiding Example Overfitting

There is a subtle trap:

Tests describe what the code checks, not always what the user needs.

If docs follow tests too literally, examples can become awkward.

Example test:

it("handles null byte in project name", async () => {
  await expect(api.projects.create({ name: "abc\0def" }))
    .rejects.toThrow("invalid name");
});

This is important, but not quickstart material.

It belongs in:

  • validation rules,
  • troubleshooting,
  • error reference,
  • security notes.

So example matching must consider reader journey.

Page types:

PageExample type
Quickstartsimplest happy path
Tutorialrealistic end-to-end path
API referencerequest/response examples
Conceptssmall illustrative examples
Troubleshootingnegative examples
Architecturesequence/dataflow examples
Migration guidebefore/after examples

22. Handling Multiple Languages

If repo has multiple SDKs or examples:

examples/javascript
examples/python
examples/java

Use tabs.

Structured block:

{
  "type": "multi-language-example",
  "title": "Create a project",
  "variants": [
    { "language": "typescript", "exampleId": "ex-ts-create-project" },
    { "language": "python", "exampleId": "ex-py-create-project" },
    { "language": "java", "exampleId": "ex-java-create-project" }
  ]
}

Rendered conceptually:

<Tabs>
  <Tab title="TypeScript">

```ts
// TypeScript example

</Tab> <Tab title="Python">

# Python example

</Tab> </Tabs>

But renderer must ensure nested code fences and JSX are valid for target MDX. In practice, for complex nested code, it is often safer to render as separate headings instead of nested JSX if the target renderer has constraints. --- ## 23. Example-aware Prompting When asking LLM to write docs, do not give it raw repo and hope. Give it selected examples: ```txt You are writing the Quickstart page. Use only these examples: Example ex-cli-init: - command: npx aidocs init - expected output: Created aidocs.config.json - source: tests/cli/init.test.ts lines 8-24 Example ex-cli-scan: - command: npx aidocs scan --json - expected output shape: filesScanned, filesSkipped, warnings - source: tests/cli/scan.test.ts lines 14-39 Rules: - Do not invent commands. - Do not invent output fields. - If an example is incomplete, explain the missing prerequisite instead of filling it in.

LLM output should reference example IDs:

{
  "sectionId": "first-scan",
  "blocks": [
    {
      "type": "paragraph",
      "text": "Run the scanner to produce a repository inventory."
    },
    {
      "type": "exampleRef",
      "exampleId": "ex-cli-scan"
    }
  ]
}

Renderer resolves exampleRef into MDX.


24. Example Repair Loop

If snippet verification fails:

snippet-sdk-create-project-ts failed typecheck:
Cannot find module '@example/sdk'

Possible causes:

  • install command missing,
  • wrong package name,
  • monorepo package not built,
  • example uses internal path,
  • docs environment not configured.

Repair flow:

Repair must still be source-grounded.

Do not let model invent package names just to fix compile errors.


25. Example Diagnostics

CLI should expose diagnostics.

npx aidocs examples inspect ex-sdk-create-project

Output:

Example: ex-sdk-create-project
Kind: sdk
Goal: Create a project using the SDK
Confidence: 0.91
Runnable: yes
Redaction: clean

Sources:
  tests/sdk/projects.test.ts:12-36
  src/client/projects.ts:8-44

Used by pages:
  docs/quickstart.mdx
  docs/sdk/projects.mdx

Validation:
  syntax: passed
  typecheck: passed
  contract: passed

Transformation:
  - replaced createTestClient with createClient
  - replaced fixtures.validToken with process.env.API_TOKEN

This is not cosmetic. It is how developers trust generated docs.


26. Failure Modes

FailureCauseMitigation
Fake snippetLLM invents exampleOnly render exampleRef from catalog.
Stale snippetSource changedSource hash + dirty propagation.
Secret leakFixture contains credentialsRedaction before prompt/render.
Internal API docsTest uses private helperPublic surface filter.
Over-complex quickstartTest setup too noisySimplicity ranking.
Misleading expected outputOutput copied from local envOutput shape abstraction.
Broken multi-language tabsNested MDX invalidRenderer-level validation.
Negative example in quickstartWrong page matchingPage-type matching rules.
Runtime example flakyDepends on external serviceMark as non-runtime or mock-backed.
Silent validation skipTool unavailableExplicit skipped status with reason.

27. Minimal Implementation Plan

Build in this order:

  1. Parse tests and /examples directory into raw candidates.
  2. Create UsageExample model.
  3. Add source refs and hash.
  4. Add redaction pipeline.
  5. Add simple ranking.
  6. Generate examples.v1.json.
  7. Add exampleRef block to MDX authoring engine.
  8. Render CLI/HTTP/SDK snippets from structured examples.
  9. Add syntax validation.
  10. Add contract validation for HTTP examples.
  11. Add stale detection.
  12. Add page matching.
  13. Add repair loop later, not at the beginning.

Do not start with fully automatic test-to-doc transformation for every language. Start with two high-value sources:

/examples directory + integration tests

Then expand.


28. Practical Heuristic

A generated example is allowed into public docs only if at least one of these is true:

1. It exists in /examples and passes syntax check.
2. It is extracted from a test and transformed with recorded notes.
3. It is derived from OpenAPI/schema examples and validates against contract.
4. It is a CLI command from command manifest and passes command existence check.

Otherwise it must be labeled:

conceptual

or excluded.

This rule alone prevents a large class of hallucinated documentation.


29. Checklist Part 020

Setelah part ini, kamu harus memahami:

  • kenapa example harus dimodelkan sebagai usage episode,
  • kenapa test dan contract adalah sumber dokumentasi yang kuat,
  • bagaimana membuat examples.v1.json,
  • bagaimana mengekstrak setup/action/assertion dari test,
  • bagaimana mengubah test code menjadi docs-ready snippet,
  • bagaimana melakukan redaction,
  • bagaimana ranking dan matching example ke page,
  • bagaimana memverifikasi snippet,
  • bagaimana mendeteksi stale example,
  • kenapa generated docs tidak boleh membuat contoh tanpa source.

Di part berikutnya, kita akan masuk ke API Reference Generation: bagaimana OpenAPI, discovered endpoints, SDK methods, auth model, errors, pagination, dan examples digabung menjadi API reference yang bisa dipublish secara Mintlify-like tanpa duplikasi dengan guide naratif.

Lesson Recap

You just completed lesson 20 in build core. Use the series map if you want to review the broader track, or continue directly into the next lesson while the context is still warm.

Continue The Track

Keep the momentum while the lesson is still fresh. Move backward for review or continue forward into the next concept.