---
name: yardoc
description: "Use when generating, adding, or improving documentation comments for Ruby files, including requests phrased as 'YARD docs'. Writes decode-style tags (@parameter, @returns, @raises, @yields, @option, @attribute, @example), converts existing YARD tags to decode tags, and measures documentation coverage with bake decode:index:coverage."
---
# RubyDev Yardoc — decode Documentation Generator
## Overview
This skill writes Ruby documentation comments in the tag format parsed by the [decode](https://github.com/socketry/decode) gem. decode reads the comments into structured nodes (`Decode::Comment::Parameter`, `Returns`, `Attribute`, ...), measures documentation coverage, and generates RBS signatures from them. The skill name stays `yardoc` for routing compatibility; the output is decode syntax, not YARD syntax.
**Core Mandate**: Every public definition in `PATHS` gets a full-sentence description and the tags its signature requires, and `bake decode:index:coverage` reports the before and after counts.
**Format rule**: decode does not parse YARD tags. A `@param` or `@return` line is read as plain text and produces no structured data. Never write YARD tags. Convert YARD tags on every definition the task touches, using the conversion table in [references/decode-tags.md](references/decode-tags.md).
**References**:
- decode tag reference, type notation, YARD-to-decode conversion table, writing rules: [references/decode-tags.md](references/decode-tags.md)
- Dry-struct type definitions for documentation results: [references/type-structures.md](references/type-structures.md)
- Context7 verification workflow for decode syntax and gem APIs: [references/context7-integration.md](references/context7-integration.md)
- Structured logging setup and example log calls: [references/logging.md](references/logging.md)
- Result monad error-handling patterns: [references/error-handling.md](references/error-handling.md)
- Full worked example (dry-struct class, generated `@attribute` comments, decode round-trip check): [references/dry-struct-example.md](references/dry-struct-example.md)
## When to Use
- **Generate documentation comments** for Ruby files or methods
- **Convert YARD comments** to decode tags
- **Improve documentation** quality and completeness
- **Document methods** with precise type annotations
- **Raise documentation coverage** reported by `bake decode:index:coverage`
**Don't use for:**
- README generation or project overview docs (use general writing skills)
- Non-Ruby files
- Code review or quality assessment (use [sift/SKILL.md](../sift/SKILL.md) instead)
- Debugging or root cause analysis (use [analyse/SKILL.md](../analyse/SKILL.md))
## Execution Layers
### Layer 1: Gem Context Check (Prerequisite)
Before writing type annotations, verify gem context:
1. **Check for non-stdlib gems** in the target file
2. **If gem-specific types are detected** (e.g., `RubyLLM::Chat`, `Sequel::Dataset`, `Async::Task`, `Dry::Schema::Result`):
- Query Context7 MCP (or DeepWiki for the gem's GitHub repo) for each gem involved, inline
- Use the verified class names and return types verbatim in `@parameter`, `@returns`, and `@attribute` tags
- If Context7 is unavailable, apply the fallback below and add `# type annotation based on stale cache — verify before publishing`
3. **Skip for**: stdlib-only files, Lite Mode tasks, gems already resolved this session
For tag syntax not covered by [references/decode-tags.md](references/decode-tags.md), query Context7 library `/socketry/decode`. See [references/context7-integration.md](references/context7-integration.md).
### Layer 2: Target and Baseline
#### Target File Validation
- Verify each target file exists and is readable
- Run `ruby -c` on each target file before editing
#### Baseline Measurement
- Run `bundle exec bake decode:index:coverage
` on the directory that holds the targets (usually `lib`). Record the line "N definitions have documentation, out of M public definitions."
- The command exits non-zero while any public definition is undocumented. That exit status is the measurement, not a failure of this skill.
- If `decode` or `bake` is missing from the bundle, the orchestrator did not run its Gemfile step. Report `not run: decode unavailable` and continue without the measurement.
#### Existing Style Assessment
- Count YARD tags (`@param`, `@return`, `@raise`, `@yieldparam`, `@!attribute`) in the target files. Each one on a touched definition is converted.
- Note the file's comment indentation (two spaces or tab) and match it for nested tags and example code.
### Layer 3: Semantic Code Analysis
#### Structure
Extract with Prism, or with the rubydex MCP tools (`get_file_declarations`, `get_declaration`) when the plugin's rubydex server is connected:
- Class and module hierarchies with ancestors
- Method signatures: positional, optional, keyword, splat, and block parameters
- Instance vs singleton method
- Ruby visibility (public, protected, private)
- `yield` and `block.call` sites
#### Type Inference
Infer from the implementation:
- Parameter types from the methods called on each parameter
- Return types from every return path, including early returns
- `| Nil` from paths that return `nil`
- `Interface(:method)` for parameters used only through one or two methods
- `@raises` entries from explicit `raise` statements, not from exceptions that propagate from callees
#### Behavior
Derive the description from control flow, side effects, state mutations, and calls to external dependencies.
### Layer 4: Comment Generation
#### Method Comment Template
```ruby
# [What the method does, as a full sentence in active voice.]
#
# [Optional second paragraph: constraints, side effects, related methods as {links}.]
#
# @parameter name [PreciseType] What the argument is and any constraint on it.
# @parameter optional_arg [Type | Nil] What it is. Defaults to `nil`, which means ...
# @option :key [Type] What the option controls. Defaults to ...
# @yields {|item| ...} When and how often the block is called.
# @parameter item [Type] What the block receives.
# @returns [SpecificType] What the return value contains.
# @raises [ExceptionClass] The condition that raises it.
#
# @example Typical call
# result = realistic_call(actual_value)
# result.size # => 3
```
Omit tags that do not apply. A method with no parameters has no `@parameter` lines. A method whose return value callers do not use gets `@returns [void]`.
#### Class, Module, and Attribute Comments
- Class: one sentence stating what the class is or does.
- Namespace-only module: `# @namespace`.
- `attr_*` and dry-struct `attribute` calls: one `# @attribute [Type] Description.` directly above each call.
#### Type Precision
Use decode notation: `Array(String)`, `Hash(Symbol, Integer)`, `String | Nil`, `Interface(:each)`, `bool`. The full table is in [references/decode-tags.md](references/decode-tags.md).
#### Examples
- Use realistic argument values and show the return shape with `# =>`
- Show the block form for methods that yield
- Skip examples for trivial accessors
### Layer 5: Verification
1. **Syntax**: `ruby -c` on every edited file.
2. **Parse check**: index each edited file with `Decode::Index` and confirm every definition with `@` lines in its comment has structured nodes, not only `Text`. Code: the "Tooling Commands" section of [references/decode-tags.md](references/decode-tags.md).
3. **Name match**: every `@parameter` name matches a parameter in the method signature, and every signature parameter except `&block` has a `@parameter` line.
4. **No YARD tags remain** on touched definitions: `grep -nE '@(param|return|raise|yieldparam|yieldreturn)\b|@!attribute' ` returns nothing for those lines.
5. **Coverage**: re-run `bundle exec bake decode:index:coverage ` and record the after count.
6. **RBS (optional, when the project has `sig/`)**: `bundle exec bake decode:rbs:generate ` succeeds.
### Layer 6: Output
#### Comment Insertion
- Insert comments directly above the definition, with no blank line between comment and definition
- Preserve code structure and indentation
- Handle nested classes and metaprogrammed definitions; use `@name` and `@scope` only when decode cannot see the definition
#### Report
- Coverage before and after: "N of M public definitions documented"
- Number of definitions documented and number of YARD tags converted
- Definitions left undocumented, with the reason
- Types marked unverified
## Advanced Features
### Error Handling
Documentation generation uses dry-monads Result types for explicit success/failure propagation, with rescue patterns for partial documentation when type inference fails. See [references/error-handling.md](references/error-handling.md).
### Type-Safe Data Structures
Documentation results are dry-struct types (`MethodDocumentation`, `GenerationResult`, `ParseResult`, etc.) rather than raw hashes. See [references/type-structures.md](references/type-structures.md).
### Logging
Parsing, analysis, generation, and validation emit structured logs via `journald-logger` with correlation IDs. See [references/logging.md](references/logging.md).
## Operational Protocol
### Decision Statement
At the start of every yardoc operation, state:
```
[YARDOC DECISION]
Target:
Mode:
Gems to Verify:
Definitions to Document:
YARD Tags to Convert:
Coverage Baseline:
[/YARDOC DECISION]
```
### Quality Gates
1. **Syntax Validation**: `ruby -c` passes on every edited file
2. **Type Verification**: every non-stdlib gem type is verified via Context7/DeepWiki or marked unverified
3. **Parse Check**: decode parses every tag on touched definitions into structured nodes
4. **Coverage**: the documented count after the edit is greater than or equal to the count before it
## Failover
| Dependency | If Unavailable | Fallback |
|------------|---------------|----------|
| Context7 / DeepWiki | Both unreachable | Use conservative types (`String`, `Object`) and add `# type annotation based on unverified API — verify before publishing`. |
| `decode` / `bake` in the bundle | Not installed | Skip the coverage and parse checks, record `not run: decode unavailable`, and check tag syntax by hand against [references/decode-tags.md](references/decode-tags.md). |
| rubydex MCP | Server not connected | Extract structure with Prism. |
| [sift/SKILL.md](../sift/SKILL.md) | Quality assessment unavailable | Check each tag against the decode tag table, confirm `@parameter` names match the signature, confirm the `@returns` type is plausible. |
| [analyse/SKILL.md](../analyse/SKILL.md) | Diagnostic unavailable | Mark uncertain types with `# TODO: verify this type`. |
## Common Pitfalls
1. **Writing YARD tags**: `@param`/`@return` parse as plain text in decode
2. **Type before name**: `@parameter name [Type]`, not `@parameter [Type] name`
3. **YARD type notation**: `Array(String)`, not `Array`; `String | Nil`, not `String, nil`
4. **Documenting without gem context**: check non-stdlib gems first
5. **Over-documenting trivial methods**: one-line accessors need an `@attribute` line, not prose
6. **Hallucinating types**: never invent types for unverified gem APIs
7. **Inline comments without a trailing colon**: comments inside method bodies end with `:`
8. **Skipping the coverage measurement**: the report states before and after counts, or `not run` with the reason