Skip to content

extract: reconsider writing anonymous blocks by default #26

Closed

Description

@adrianbrowning

This was generated by AI during triage.

Split out of #21.

mdcode extract README.md writes every block without file= to block-<N>.<ext> in the working directory. On a real README this left more than 20 stray files (block-1.sh, block-4.json, block-198.sql). --ignore-anonymous already prevents this, and the behavior is documented, but it surprises users running a plain extract.

Options raised in #21:

  • Make --ignore-anonymous the default and add an opt-in flag for anonymous output. This is a breaking change.
  • Keep the current default and mention the behavior and flag in the extract --help text.

Activity

  1. adrianbrowning commented on Oct 8, 2026

    @adrianbrowning
    OwnerAuthor

    This was generated by AI during triage.

    Agent Brief

    Category: enhancement
    Summary: extract writes only blocks that have file= unless --update-source is given; remove --ignore-anonymous.

    Verification status: Confirmed on main (238c32e). mdcode extract README.md on a README with two untagged blocks (sh, json) wrote block-3.sh and block-4.json beside it. mdcode extract a.md b.md, where each document has one untagged sh block, refused both with ambiguous_target on block-1.sh and wrote nothing. With --ignore-anonymous, both runs wrote only file= targets.

    Current behavior:
    extract writes every selected block that has no file= (an anonymous block) to block-<N>.<ext> in the output directory. --ignore-anonymous skips them. --update-source writes them and adds file=block-<N>.<ext> back into the Markdown, so the block links to the file it produced. Combining --update-source with --ignore-anonymous is invalid_usage. The library mirrors this: the extract() options have ignoreAnonymous (default false) and updateSource, and validate() for the extract operation has ignoreAnonymous. validate --for extract has --ignore-anonymous. The check-sync GitHub Action has an ignore-anonymous input, default true. The README, CLI examples and the shipped Agent Skill pass --ignore-anonymous in nearly every extract example, because a plain extract on a README leaves stray block-<N> files behind.

    Desired behavior:
    Anonymous blocks are extracted only together with --update-source (library: updateSource: true), because that mode writes their file= back and so leaves no unlinked file. This was decided in triage.

    • Without --update-source, extract skips anonymous blocks exactly as --ignore-anonymous does today: no file is written, no error is raised, and they don't appear in the result's targets. When a document has no file= blocks, the message is the existing "No code blocks with file metadata found."
    • With --update-source, behaviour is unchanged: anonymous blocks are written as block-<N>.<ext> and get file= added in the Markdown (or the updated Markdown goes to stdout when reading stdin).
    • With several documents and --update-source, the all-or-nothing preflight must still include anonymous blocks: two documents that would both write block-1.sh are refused with ambiguous_target before anything is written, as today. The preflight that checks every document before writing must therefore know about --update-source. It must not take the new default and skip anonymous blocks, or the collision would only surface after writes began.
    • --ignore-anonymous is removed from extract and validate (clean cutover, no alias), so passing it is rejected as an unknown option. The ignoreAnonymous option is removed from the extract and validate library options.
    • validate --for extract follows the new default: anonymous blocks are not considered.
    • The check-sync action drops its ignore-anonymous input and stops passing the flag.

    Key interfaces:

    • ExtractOptions: remove ignoreAnonymous. updateSource now also decides whether anonymous blocks are extracted at all.
    • ValidateOptions (extract operation): remove ignoreAnonymous. Callers that preflight an --update-source run need a way to include anonymous blocks, such as passing updateSource through. The exact shape is the agent's choice; the requirement is the multi-document preflight above.
    • The CLI extract and validate commands: remove the --ignore-anonymous option. The --update-source / --ignore-anonymous conflict check goes with it.
    • The JSON envelope's shape is unchanged.

    Acceptance criteria:

    • mdcode extract README.md, on a document with one file= block and two untagged blocks, writes only the file= target, creates no block-* file and exits 0.
    • mdcode extract --update-source README.md writes block-<N>.<ext> for each anonymous block and adds file=block-<N>.<ext> to it in the Markdown, as before.
    • mdcode extract a.md b.md, where each document has one untagged sh block, exits 0 and writes nothing. The same run with --update-source exits 1 with ambiguous_target for both documents and writes nothing, in either document.
    • mdcode extract --ignore-anonymous README.md and mdcode validate --for extract --ignore-anonymous README.md are rejected as unknown options.
    • Library: extract({ source }) returns no targets for blocks without file=, and ExtractOptions has no ignoreAnonymous property (a type error if passed).
    • The check-sync action has no ignore-anonymous input, and its tests still pass.
    • No --ignore-anonymous or ignoreAnonymous remains in the package README, the CLI examples, the Agent Skill (including its "plain extract on a README" common mistake, which no longer applies) or the action docs. The README's "Changes from Earlier Versions" gains an entry: anonymous blocks are no longer extracted by default; drop --ignore-anonymous; pass --update-source to extract them.
    • A minor bump file describes the breaking change. It should land before the Version Packages PR (🐸 Versioned release #27) merges, so it ships in 0.1.0.
    • pnpm check passes, and the Intent maintainer check passes with the skill's review recorded.

    Out of scope:

    • The block-<N>.<ext> naming scheme.
    • dump and run, which keep covering anonymous blocks.
    • update, which never writes anonymous blocks.
    • Adding --update-source to validate as a user-facing flag. A run of extract --update-source refuses conflicts itself before writing anything.
    • Any size or shrink guard (rejected in extract: refuse writes that would shrink an existing file unless --force #25, see .out-of-scope/extract-shrink-guard.md).
  2. added
    ready-for-agentFully specified and ready for an AFK agent
    and removed
    needs-triageMaintainer needs to evaluate this issue
    on Oct 8, 2026
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

    enhancementNew feature or requestready-for-agentFully specified and ready for an AFK agent

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions