Skip to content

Docs: F# doc comments with <param> lines must start with an explicit <summary> or createWithDocs gets no parameter descriptions #11

Description

@JordanMarr

Summary

Tool.createWithDocs returns empty parameter descriptions for a very common F# doc-comment style, even on 0.2.0 where #10 is fixed. The cause is on the F# compiler side, not in AgentNet, but it silently defeats <param> extraction and is worth documenting in the README.

What happens

The F# compiler has two modes for a /// block:

  • If the first non-blank character is <, the block is treated as XML you wrote and emitted verbatim.
  • Otherwise the whole block is treated as plain text: it is wrapped in an implicit <summary> and its contents are XML-escaped.

So a prose-first block with <param> lines, which is how most people write them:

/// Switches the weekly timesheet view to a specific week.
/// <param name="input">One of: "current", "last", "next", or an ISO date within the desired week.</param>
let selectWeek (deps: IProvider) (input: string) : Task<string> = ...

compiles to this in the assembly's .xml doc file:

<member name="M:TimeBotTools.selectWeek(IProvider,System.String)">
<summary>
 Switches the weekly timesheet view to a specific week.
 &lt;param name=&quot;input&quot;&gt;One of: "current", "last", "next", or an ISO date within the desired week.&lt;/param&gt;
</summary>
</member>

createWithDocs reads the <summary> child (works, so the tool description is fine) and looks for <param> children of <member> (none exist), so every ParamInfo.Description is "". As a bonus the model receives the escaped param text as trailing prose inside the tool description, which masks the problem: routing mostly still works, so nobody notices.

What works

Start the block with an explicit <summary> and close it before the first <param>:

/// <summary>
/// Switches the weekly timesheet view to a specific week.
/// </summary>
/// <param name="input">One of: "current", "last", "next", or an ISO date within the desired week.</param>
let selectWeek (deps: IProvider) (input: string) : Task<string> = ...

which compiles to a real <summary> element followed by a real <param> element, and createWithDocs picks up both.

A prose-only block with no <param> lines is fine as is; the implicit summary is exactly what the extractor wants.

Suggested README note

Something like:

XML doc comments in F#. If a tool's doc comment includes <param> lines, the comment must start with an explicit <summary> tag. The F# compiler only emits a /// block as XML when it begins with an element; a block that starts with prose is wrapped in an implicit summary with its contents escaped, so the <param> tags never reach the doc file and the parameter descriptions come back empty. A summary-only comment needs no tags.

Optionally the compiler can enforce it: <WarnOn>3390</WarnOn> in the project file turns on XML doc validation, which flags malformed structures at build time.

Context

Found while upgrading TimeBridge to 0.2.0 and pinning #10 with a test that asserts every model-facing parameter has a non-empty description. The test failed on 0.2.0 too until the doc comments were rewritten in the explicit form; the same test passes after that change. Happy to send a README PR if you would rather.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions