# Doc comments (`#`, `##`, `###`)

## Usage

Line comments run from `#` to end of line.

Doc comments use paired `##` … `##`. They can sit above declarations (top-level summary) or beside scoped constructs (inline annotations). Structured annotations use `@`-prefixed keywords inside `##` … `##` blocks (see Design decisions).

```ops
##
@note: $DATACENTER can be supplied manually through environment or flags
##
@deploy-single needs [$VERSION $DATACENTER] {
  ...
}
```

Block comments use paired `###` … `###`. They are ordinary comments and do not attach metadata to the following declaration or scoped construct.

### `@keyword` annotations

Doc-comment `@keyword` tags provide metadata annotations on steps and blocks. These replace the former "descriptor" concept — metadata that was previously expressed via postfix argless ops is now expressed as doc-comment annotations.

**Recognized keywords (closed set):**

| Keyword | Scope | Effect |
|---------|-------|--------|
| `@note` | block or step | Collects into **Notes:** section of `--help` |
| `@deprecated` | block or step | Compile warning at every call site; shows in `--help` |
| `@timed` | block or step | Runtime timing metadata emitted on completion |

```ops
## @deprecated: Use deploy-v2() instead ##
@legacy-deploy needs [$VERSION] {
  ...
}

## @timed ##
@benchmark {
  parallel.all() {
    lint()
    test()
  }
}
```

The keyword set is **closed** — the engine knows all recognized `@keyword` tags. Unknown tags produce a warning. This keeps `--help` generation predictable and allows the engine to enforce compile-time behavior (e.g. `@deprecated` warnings).

## Grammar

```peg
Comment         = '#' REST_OF_LINE
                | '###' (ANY_CHAR)* '###'
DocComment      = '##' (ANY_CHAR)* '##'               # top-level: summary before next declaration; inline: scoped annotation
```

In `grammar.md`, `###` … `###` is `Comment` (allowed at `TopLevel` among other places). `##` … `##` is `DocComment`, which is the form listed on `Statement` for inline / scoped doc comments inside `{ ... }`.

## IR representation

Doc comment text and extracted `@keyword` annotations are preserved through parse → AST and carried into emit metadata so generated `.op.sh` files can build `--help`. `@deprecated` annotations additionally produce explicit metadata on the affected pipeline or step IR, enabling compile-time call-site warnings.

## Runtime (bash API surface)

- Generated group / root scripts expose `--help` assembled from doc comments and env / flag drilling.
- **`--note "text"`** on an op: note text is merged into the same **Notes:** section as DSL `@note:` lines from `##` … `##` blocks. Op-level notes show for any pipeline that invokes that op.
- **`@deprecated`** on an op (via bash API): emits compile warning at call sites, same as DSL-level `@deprecated` annotation.

## Implementation

| | |
|---|---|
| **Tier** | Tier 1 — Lexer |
| **Crate / files** | `engine/src/lexer.rs` (disambiguate `#` vs `##` vs `###` by counting `#` at column start); `engine/src/token.rs` (`Comment`, `BlockComment`, `DocComment` per Tier 0 token kinds); parser attaches comment nodes to the following declaration or scoped construct; parser extracts `@keyword` tags and validates against the closed set; `engine/src/emit/*` (help text assembly) |
| **Validation** | Tier 1 unit tests: correct token kind and span for `#`, `##…##`, `###…###`; unterminated block comments should error. `@keyword` extraction and unknown-keyword warnings. |

## Design decisions

- **`@note:`** — collects into a **Notes:** section at the bottom of `--help`, regardless of where the tag appears inside the `##` … `##` block.
- **`@deprecated`** — compile warning at every call site. Replaces the former `std.deprecated` descriptor. Pipeline-level `deprecated` marker (prefix on block definition) and doc-comment `@deprecated` annotation serve different scopes: the marker on the block definition marks the entire pipeline as legacy; the annotation on a call site marks that specific invocation.
- **`@timed`** — runtime timing metadata. Replaces the former `std.timed` descriptor.
- **Closed keyword set** — unknown `@keyword` tags in doc comments produce a warning. New keywords require engine changes, keeping the annotation system predictable.
- **Drilling**: `##` … `##` content surfaces in `--help`: top-level blocks contribute summaries; inline placement provides scoped annotations next to the relevant pipeline or step.

Example help shape (conceptual):

```
deploy-single — ...

Flags:
  --version <semver>      required by: deploy-single
  --datacenter <string>   required by: deploy-single

Notes:
  $DATACENTER can be supplied manually through environment or flags
```

## Caveats

- Doc comments must terminate with a closing `##`; block comments must terminate with a closing `###`. The lexer should not treat partial markers as line comments only if that would hide structural errors.
- `@deprecated` annotations inside doc comments produce compile-time warnings; the `deprecated` pipeline marker on a block definition produces compile-time warnings at every import/call site. Both mechanisms exist; they are complementary, not redundant.

## Open questions

None.
