Repository: JoshuaKGoldberg/bingo (ts)

Issue:
🚀 Feature: Allow Blocks to define how to infer Addons from existing files
### Feature Request Checklist

- [x] I have pulled the latest `main` branch of the repository.
- [x] I have [searched for related issues](https://github.com/JoshuaKGoldberg/bingo/issues?q=is%3Aissue) and found none that matched my issue.

### Overview

#128 tracks letting Blocks infer Addons _completely automatically_. Which will be great. But:

* That's a large task with a lot of required thought
* Some Addons might want to define custom logic

So as a separate, smaller change leading up to #128, I'd like to allow Blocks to define an optional method to load in Addons. `infer()`? `load()`? `prepare()`? 

```ts
const blockExample = createBlock({
  addons: {
    globs: z.string(),
  },
  load({ files }) {
    const existingFile = files["example.config.js"]?.[0];
    if (!existingFile) {
      return undefined;
    }

    const matched = /defineConfig\((.+)\)/.exec(existingFile.content);
    if (!matched?.length) {
      return undefined;
    }

    return {
      globs: parseJSONSafe(matched[1]),
    };
  },
  produce({ addons }) {
    return {
      files: {
        "example.config.js": `import { defineConfig } from 'example-lib';
            
export default defineConfig(${JSON.stringify(addons.globs)});`,
      },
    };
  },
});
```

### Additional Info

💝 

Pull request:
feat(bingo-stratum): add optional 'intake' method to Blocks
## PR Checklist

- [x] Addresses an existing open issue: fixes #327
- [x] That issue was marked as [`status: accepting prs`](https://github.com/JoshuaKGoldberg/bingo/issues?q=is%3Aopen+is%3Aissue+label%3A%22status%3A+accepting+prs%22)
- [x] Steps in [CONTRIBUTING.md](https://github.com/JoshuaKGoldberg/bingo/blob/main/.github/CONTRIBUTING.md) were taken

## Overview

Also fills in some more JSDoc blocks that I hadn't gotten around to in #149. 

🎁 

Patch:
diff --git a/packages/bingo-stratum/src/producers/produceBlock.ts b/packages/bingo-stratum/src/producers/produceBlock.ts
index e6f66ea..580ffc3 100644
--- a/packages/bingo-stratum/src/producers/produceBlock.ts
+++ b/packages/bingo-stratum/src/producers/produceBlock.ts
@@ -7,7 +7,7 @@ import { StratumTemplateOptions } from "../types/templates.js";
 
 /**
  * Settings to run a Block with {@link produceBlock} that might have addons.
- * @template Addons Schema of Block-specific args defined by the Block, if defined.
+ * @template Addons Block-specific extensions, if defined by the Block's schema.
  * @template Options Options values as described by the Block's Base's options schema, as well as preset.
  * @see {@link https://www.create.bingo/engines/stratum/apis/producers#produceblock}
  */
@@ -20,7 +20,7 @@ export type ProduceBlockSettings<
 
 /**
  * Settings to run a Block with {@link produceBlock} that defines addons.
- * @template Addons Schema of Block-specific args defined by the Block.
+ * @template Addons Block-specific extensions as defined by the Block's schema.
  * @template Options Options values as described by the Block's Base's options schema, as well as preset.
  * @see {@link https://www.create.bingo/engines/stratum/apis/producers#produceblock}
  */
@@ -28,6 +28,9 @@ export interface ProduceBlockSettingsWithAddons<
 	Addons extends object,
 	Options extends object,
 > extends ProduceBlockSettingsWithoutAddons<Options> {
+	/**
+	 * Addon values to provide to the Block.
+	 */
 	addons?: Addons;
 }
 
@@ -44,7 +47,7 @@ export interface ProduceBlockSettingsWithoutAddons<Options extends object> {
 
 /**
  * Produces a single Block that defines addons.
- * @template Addons Schema of Block-specific args defined by the Block, if defined.
+ * @template Addons Block-specific extensions, if defined by the Block's schema.
  * @template Options Options values as described by the Block's Base's options schema, as well as preset.
  * @see {@link https://www.create.bingo/engines/stratum/apis/producers#produceblock}
  */
@@ -52,6 +55,7 @@ export function produceBlock<Addons extends object, Options extends object>(
 	block: BlockWithAddons<Addons, Options>,
 	settings: ProduceBlockSettingsWithAddons<Addons, Options>,
 ): Partial<BlockCreation<Options>>;
+
 /**
  * Produces a single Block that does not define addons.
  * @template Options Options values as described by the Block's Base's options schema, as well as preset.
@@ -61,9 +65,10 @@ export function produceBlock<Options extends object>(
 	block: BlockWithoutAddons<Options>,
 	settings: ProduceBlockSettingsWithoutAddons<Options>,
 ): Partial<BlockCreation<Options>>;
+
 /**
  * Produces a single Block.
- * @template Addons Schema of Block-specific args defined by the Block, if defined.
+ * @template Addons Block-specific extensions, if defined by the Block's schema.
  * @template Options Options values as described by the Block's Base's options schema, as well as preset.
  * @see {@link https://www.create.bingo/engines/stratum/apis/producers#produceblock}
  */
diff --git a/packages/bingo-stratum/src/producers/produceBlocks.ts b/packages/bingo-stratum/src/producers/produceBlocks.ts
index ee23e6e..0c79ac6 100644
--- a/packages/bingo-stratum/src/producers/produceBlocks.ts
+++ b/packages/bingo-stratum/src/producers/produceBlocks.ts
@@ -1,4 +1,5 @@
 import { ProductionMode } from "bingo";
+import { IntakeDirectory } from "bingo-fs";
 
 import { mergeBlockCreations } from "../mergers/mergeBlockCreations.js";
 import { Block, BlockWithAddons } from "../types/blocks.js";
@@ -10,7 +11,8 @@ import {
 import { produceBlock } from "./produceBlock.js";
 
 export interface ProduceBlocksSettings<Options extends object> {
-	addons?: CreatedBlockAddons<object, Options>[];
+	blockAddons?: CreatedBlockAddons<object, Options>[];
+	files?: IntakeDirectory;
 	mode?: ProductionMode;
 	offline?: boolean;
 	options: Options;
@@ -18,27 +20,52 @@ export interface ProduceBlocksSettings<Options extends object> {
 
 export function produceBlocks<Options extends object>(
 	blocks: Block<object | undefined, Options>[],
-	{ addons, mode, offline, options }: ProduceBlocksSettings<Options>,
+	{
+		blockAddons,
+		files = {},
+		mode,
+		offline,
+		options,
+	}: ProduceBlocksSettings<Options>,
 ) {
 	// From Templating Engines > Stratum > Details > Execution:
 	// This engine continuously re-runs Blocks until no new Addons are provided.
 
+	// Collect all Blocks defined in the Preset, along with their Addons:
 	const blockProductions = new Map<
 		Block<object | undefined, Options>,
 		BlockProduction<object>
-	>(addons?.map((addon) => [addon.block, { addons: addon.addons }]));
+	>();
 
-	// 1. Create a queue of Blocks to be run, starting with all defined in the Preset
+	// 1.1. Run any intake methods to generate default Addons values
+	for (const block of blocks) {
+		if (isBlockWithAddons(block) && block.intake) {
+			blockProductions.set(block, {
+				addons: block.intake({ files }),
+			});
+		}
+	}
+	// 2.2. Apply all provided refinements on top of those
+	for (const { addons, block } of blockAddons ?? []) {
+		blockProductions.set(block, {
+			addons: {
+				...blockProductions.get(block)?.addons,
+				...addons,
+			},
+		});
+	}
+
+	// 2. Create a queue of Blocks to be run, starting with all defined in the Preset
 	const allowedBlocks = new Set(blocks);
 	const blocksToBeRun = new Set(blocks);
 
-	// 2. For each Block in the queue:
+	// 3. For each Block in the queue:
 	while (blocksToBeRun.size) {
 		for (const currentBlock of blocksToBeRun) {
 			blocksToBeRun.delete(currentBlock);
 
-			// 2.1. Get the Creation from the Block, passing any current known Addons
-			// 2.2. If a mode is specified, additionally generate the appropriate Block Creations
+			// 3.1. Get the Creation from the Block, passing any current known Addons
+			// 3.2. If a mode is specified, additionally generate the appropriate Block Creations
 			const previousProduction = blockProductions.get(currentBlock);
 			const previousAddons = previousProduction?.addons ?? {};
 			const blockCreation = produceBlock(
@@ -51,20 +78,20 @@ export function produceBlocks<Options extends object>(
 				},
 			);
 
-			// 2.3. Store that Block's Creation
+			// 3.3. Store that Block's Creation
 			blockProductions.set(currentBlock, {
 				addons: previousAddons,
 				creation: blockCreation,
 			});
 
-			// 2.4. If the Block specified new addons for any defined Blocks:
+			// 3.4. If the Block specified new addons for any defined Blocks:
 			const updatedBlockAddons = getUpdatedBlockAddons(
 				allowedBlocks,
 				blockProductions,
 				blockCreation.addons,
 			);
 
-			// 2.4.1: Add those Blocks to the queue to re-run
+			// 3.4.1: Add those Blocks to the queue to re-run
 			for (const [updatedBlock, updatedAddons] of updatedBlockAddons) {
 				const addedBlockPreviousProduction = blockProductions.get(updatedBlock);
 				blockProductions.set(updatedBlock, {
@@ -76,7 +103,7 @@ export function produceBlocks<Options extends object>(
 		}
 	}
 
-	// 3. Merge all Block Creations together
+	// 4. Merge all Block Creations together
 	return (
 		Array.from(blockProductions.values()) as BlockProduction<Options>[]
 	).reduce(
@@ -84,3 +111,9 @@ export function produceBlocks<Options extends object>(
 		{},
 	);
 }
+
+function isBlockWithAddons<Options extends object>(
+	block: Block<object | undefined, Options>,
+): block is BlockWithAddons<object, Options> {
+	return !!("addons" in block);
+}
diff --git a/packages/bingo-stratum/src/producers/producePreset.ts b/packages/bingo-stratum/src/producers/producePreset.ts
index 08c5cbc..e8cc9d3 100644
--- a/packages/bingo-stratum/src/producers/producePreset.ts
+++ b/packages/bingo-stratum/src/producers/producePreset.ts
@@ -1,4 +1,5 @@
 import { AnyShape, InferredObject, ProduceTemplateSettings } from "bingo";
+import { IntakeDirectory } from "bingo-fs";
 
 import { BlockCreation } from "../types/creations.js";
 import { Preset } from "../types/presets.js";
@@ -17,6 +18,11 @@ export interface ProducePresetSettings<OptionsShape extends AnyShape>
 		OptionsShape,
 		StratumRefinements<InferredObject<OptionsShape>>
 	> {
+	/**
+	 * Existing file creations to be used for Blocks that can intake Addons.
+	 */
+	files?: IntakeDirectory;
+
 	/**
 	 * Any optional Stratum customizations.
 	 * @see {@link https://create.bingo/engines/stratum/details/configurations#refinements}
@@ -37,6 +43,7 @@ export interface ProducePresetSettings<OptionsShape extends AnyShape>
 export function producePreset<OptionsShape extends AnyShape>(
 	preset: Preset<OptionsShape>,
 	{
+		files,
 		mode,
 		offline,
 		options,
@@ -52,7 +59,8 @@ export function producePreset<OptionsShape extends AnyShape>(
 	);
 
 	const creation = produceBlocks(blocks, {
-		addons: refinements.addons,
+		blockAddons: refinements.addons,
+		files,
 		mode,
 		offline,
 		options,
diff --git a/packages/bingo-stratum/src/producers/produceStratumTemplate.ts b/packages/bingo-stratum/src/producers/produceStratumTemplate.ts
index dbcf0b2..14b634d 100644
--- a/packages/bingo-stratum/src/producers/produceStratumTemplate.ts
+++ b/packages/bingo-stratum/src/producers/produceStratumTemplate.ts
@@ -1,4 +1,5 @@
 import { AnyShape, InferredObject, ProductionMode } from "bingo";
+import { IntakeDirectory } from "bingo-fs";
 
 import { StratumRefinements } from "../types/refinements.js";
 import { StratumTemplate } from "../types/templates.js";
@@ -7,6 +8,7 @@ import { applyBlockRefinements } from "./applyBlockRefinements.js";
 import { produceBlocks } from "./produceBlocks.js";
 
 export interface ProduceStratumTemplateSettings<OptionsShape extends AnyShape> {
+	files?: IntakeDirectory;
 	mode?: ProductionMode;
 	offline?: boolean;
 	options: InferredObject<OptionsShape> & { preset: string };
@@ -18,6 +20,7 @@ export function produceStratumTemplate<
 >(
 	template: StratumTemplate<OptionsShape>,
 	{
+		files,
 		mode,
 		offline,
 		options,
@@ -37,7 +40,8 @@ export function produceStratumTemplate<
 	);
 
 	return produceBlocks(blocks, {
-		addons: refinements.addons,
+		blockAddons: refinements.addons,
+		files,
 		mode,
 		offline,
 		options,
diff --git a/packages/bingo-stratum/src/runners/runPreset.ts b/packages/bingo-stratum/src/runners/runPreset.ts
index f201ff9..76d867b 100644
--- a/packages/bingo-stratum/src/runners/runPreset.ts
+++ b/packages/bingo-stratum/src/runners/runPreset.ts
@@ -5,17 +5,23 @@ import {
 	runCreation,
 	RunTemplateSettings,
 } from "bingo";
+import { IntakeDirectory } from "bingo-fs";
 
 import { producePreset } from "../producers/producePreset.js";
 import { BlockCreation } from "../types/creations.js";
 import { Preset } from "../types/presets.js";
 import { StratumRefinements } from "../types/refinements.js";
 
-export type RunPresetSettings<OptionsShape extends AnyShape> =
-	RunTemplateSettings<
+export interface RunPresetSettings<OptionsShape extends AnyShape>
+	extends RunTemplateSettings<
 		OptionsShape,
 		StratumRefinements<InferredObject<OptionsShape>>
-	>;
+	> {
+	/**
+	 * Existing file creations to be used for Blocks that can intake Addons.
+	 */
+	files?: IntakeDirectory;
+}
 
 /**
  * Generates and applies the Blocks in a Preset.
diff --git a/packages/bingo-stratum/src/types/blocks.ts b/packages/bingo-stratum/src/types/blocks.ts
index 0c08a1f..515ec42 100644
--- a/packages/bingo-stratum/src/types/blocks.ts
+++ b/packages/bingo-stratum/src/types/blocks.ts
@@ -1,8 +1,14 @@
 import { AboutBase, AnyOptionalShape, InferredObject } from "bingo";
+import { IntakeDirectory } from "bingo-fs";
 
 import { BlockCreation, CreatedBlockAddons } from "./creations.js";
 import { StratumTemplateOptions } from "./templates.js";
 
+/**
+ * Logic to create one portion of a repository.
+ * @template Addons Block-specific extensions, if defined by the Block's schema.
+ * @template Options Options values as described by the Base's options schema.
+ */
 export type Block<
 	Addons extends object | undefined = object | undefined,
 	Options extends object = object,
@@ -10,6 +16,12 @@ export type Block<
 	? BlockWithAddons<Addons, Options>
 	: BlockWithoutAddons<Options>;
 
+/**
+ * Augments additional creations into a production from a Block with addons.
+ * @param context Shared Block helper functions and information.
+ * @template Addons Block-specific extensions, as defined by the Block's schema.
+ * @template Options Options values as described by the Base's options schema.
+ */
 export type BlockAugmentWithAddons<
 	Addons extends object,
 	Options extends object,
@@ -17,14 +29,28 @@ export type BlockAugmentWithAddons<
 	context: BlockContextWithAddons<Addons, Options>,
 ) => Partial<BlockCreation<Options>>;
 
+/**
+ * Augments additional creations into a production from a Block without addons.
+ * @param context Shared Block helper functions and information.
+ * @template Options Options values as described by the Base's options schema.
+ */
 export type BlockAugmentWithoutAddons<Options extends object> = (
 	context: BlockContextWithoutAddons<Options>,
 ) => Partial<BlockCreation<Options>>;
 
 export interface BlockBase {
+	/**
+	 * Metadata about the Block that can be used by tooling to describe it.
+	 * @see {@link https://www.create.bingo/engines/stratum/apis/create-base#createblock-about}
+	 */
 	about?: AboutBase;
 }
 
+/**
+ * Shared helper functions and information passed to producers of Blocks with required Addons.
+ * @template Addons Block-specific extensions, as defined by the Block's schema.
+ * @template Options Options values as described by the Base's options schema.
+ */
 export interface BlockContextWithAddons<
 	Addons extends object,
 	Options extends object,
@@ -32,6 +58,21 @@ export interface BlockContextWithAddons<
 	addons: Addons;
 }
 
+/**
+ * Shared helper functions and information passed to Block intake()s.
+ */
+export interface BlockIntakeContext {
+	/**
+	 * Any existing files on disk.
+	 */
+	files: IntakeDirectory;
+}
+
+/**
+ * Shared helper functions and information passed to producers of Blocks with optional Addons.
+ * @template Addons Block-specific extensions, as defined by the Block's schema.
+ * @template Options Options values as described by the Base's options schema.
+ */
 export interface BlockContextWithOptionalAddons<
 	Addons extends object,
 	Options extends object,
@@ -39,11 +80,20 @@ export interface BlockContextWithOptionalAddons<
 	addons?: Addons;
 }
 
+/**
+ * Shared helper functions and information passed to producers of Blocks without Addons.
+ * @template Options Options values as described by the Base's options schema.
+ */
 export interface BlockContextWithoutAddons<Options extends object> {
 	offline?: boolean;
 	options: Options & StratumTemplateOptions;
 }
 
+/**
+ * Definition for creating a new Block that may have Addons.
+ * @template AddonsShape Schema of Addons the Block takes in, if defined.
+ * @template Options Options values as described by the Base's options schema.
+ */
 export type BlockDefinition<
 	AddonsShape extends AnyOptionalShape | undefined,
 	Options extends object,
@@ -51,10 +101,11 @@ export type BlockDefinition<
 	? BlockDefinitionWithAddons<AddonsShape, Options>
 	: BlockDefinitionWithoutAddons<Options>;
 
-export interface BlockDefinitionBase {
-	about?: AboutBase;
-}
-
+/**
+ * Generates the creations describing a portion of a repository from a Block with Addons.
+ * @template Addons Block-specific extensions, as defined by the Block's schema.
+ * @template Options Options values as described by the Base's options schema.
+ */
 export type BlockDefinitionProducerWithAddons<
 	Addons extends object,
 	Options extends object,
@@ -62,30 +113,101 @@ export type BlockDefinitionProducerWithAddons<
 	context: BlockContextWithAddons<Addons, Options>,
 ) => Partial<BlockCreation<Options>>;
 
+/**
+ * Generates the creations describing a portion of a repository from a Block without Addons.
+ * @template Options Options values as described by the Base's options schema.
+ */
 export type BlockDefinitionProducerWithoutAddons<Options extends object> = (
 	context: BlockContextWithoutAddons<Options>,
 ) => Partial<BlockCreation<Options>>;
 
+/**
+ * Definition for creating a new Block with Addons.
+ * @template AddonsShape Schema of Addons the Block takes in.
+ * @template Options Options values as described by the Base's options schema.
+ */
 export interface BlockDefinitionWithAddons<
 	AddonsShape extends AnyOptionalShape,
 	Options extends object,
-> extends BlockDefinitionBase {
+> extends BlockBase {
+	/**
+	 * Schema of Addons the Block takes in.
+	 */
 	addons: AddonsShape;
+
+	/**
+	 * Infers Addons from existing files in the repository.
+	 * @see {@link https://www.create.bingo/engines/stratum/apis/create-base#createblock-intake}
+	 */
+	intake?: BlockIntake<InferredObject<AddonsShape>>;
+
+	/**
+	 * Generates the creations describing a portion of a repository.
+	 * @see {@link https://www.create.bingo/engines/stratum/apis/create-base#createblock-produce}
+	 */
 	produce: BlockDefinitionProducerWithAddons<
 		InferredObject<AddonsShape>,
 		Options
 	>;
+
+	/**
+	 * Augments a Block creation with additional creations for setup mode.
+	 * @template Options Options values as described by the Base's options schema.
+	 * @see {@link https://www.create.bingo/engines/stratum/apis/create-base#createblock-setup}
+	 */
 	setup?: BlockAugmentWithAddons<InferredObject<AddonsShape>, Options>;
+
+	/**
+	 * Augments a Block creation with additional creations for transition mode.
+	 * @template Options Options values as described by the Base's options schema.
+	 * @see {@link https://www.create.bingo/engines/stratum/apis/create-base#createblock-transition}
+	 */
 	transition?: BlockAugmentWithAddons<InferredObject<AddonsShape>, Options>;
 }
 
+/**
+ * Definition for creating a new Block without Addons.
+ * @template Options Options values as described by the Base's options schema.
+ */
 export interface BlockDefinitionWithoutAddons<Options extends object>
-	extends BlockDefinitionBase {
+	extends BlockBase {
+	/**
+	 * Generates the creations describing a portion of a repository.
+	 * @see {@link https://www.create.bingo/engines/stratum/apis/create-base#createblock-produce}
+	 */
 	produce: BlockDefinitionProducerWithoutAddons<Options>;
+
+	/**
+	 * Augments a Block creation with additional creations for setup mode.
+	 * @template Options Options values as described by the Base's options schema.
+	 * @see {@link https://www.create.bingo/engines/stratum/apis/create-base#createblock-setup}
+	 */
 	setup?: BlockAugmentWithoutAddons<Options>;
+
+	/**
+	 * Augments a Block creation with additional creations for transition mode.
+	 * @template Options Options values as described by the Base's options schema.
+	 * @see {@link https://www.create.bingo/engines/stratum/apis/create-base#createblock-transition}
+	 */
 	transition?: BlockAugmentWithoutAddons<Options>;
 }
 
+/**
+ * Infers any Addons for the Block from existing creations.
+ * @param context Shared Block helper functions and information.
+ * @template Addons Block-specific extensions, as defined by the Block's schema.
+ */
+export type BlockIntake<Addons extends object> = (
+	context: BlockIntakeContext,
+) => Partial<Addons>;
+
+/**
+ * Generates the creations describing a portion of a repository with addons.
+ * @param context Shared Block helper functions and information.
+ * @template Addons Block-specific extensions, as defined by the Block's schema.
+ * @template Options Options values as described by the template's options schema.
+ * @see {@link https://www.create.bingo/engines/stratum/concepts/blocks#production}
+ */
 export type BlockProducerWithAddons<
 	Addons extends object,
 	Options extends object,
@@ -93,20 +215,77 @@ export type BlockProducerWithAddons<
 	context: BlockContextWithOptionalAddons<Addons, Options>,
 ) => Partial<BlockCreation<Options>>;
 
+/**
+ * Generates the creations describing a portion of a repository without addons.
+ * @param context Shared Block helper functions and information.
+ * @template Options Options values as described by the template's options schema.
+ * @see {@link https://www.create.bingo/engines/stratum/concepts/blocks#production}
+ */
 export type BlockProducerWithoutAddons<Options extends object> = (
 	context: BlockContextWithoutAddons<Options>,
 ) => Partial<BlockCreation<Options>>;
 
+/**
+ * Block that defines a schema for Addons.
+ * @template Addons Block-specific extensions, as defined by the Block's schema.
+ * @template Options Options values as described by the Base's options schema.
+ */
 export interface BlockWithAddons<Addons extends object, Options extends object>
 	extends BlockBase {
+	/**
+	 * Infers Addons from existing files in the repository.
+	 * @see {@link https://www.create.bingo/engines/stratum/apis/create-base#createblock-intake}
+	 */
+	intake?: BlockIntake<Addons>;
+
+	/**
+	 * Generates the creations describing a portion of a repository.
+	 * @see {@link https://www.create.bingo/engines/stratum/apis/create-base#createblock-produce}
+	 */
 	produce: BlockProducerWithAddons<Addons, Options>;
+
+	/**
+	 * Augments a Block creation with additional creations for setup mode.
+	 * @template Options Options values as described by the Base's options schema.
+	 * @see {@link https://www.create.bingo/engines/stratum/apis/create-base#createblock-setup}
+	 */
 	setup?: BlockAugmentWithAddons<Addons, Options>;
+
+	/**
+	 * Augments a Block creation with additional creations for transition mode.
+	 * @template Options Options values as described by the Base's options schema.
+	 * @see {@link https://www.create.bingo/engines/stratum/apis/create-base#createblock-transition}
+	 */
 	transition?: BlockAugmentWithAddons<Addons, Options>;
+
+	/**
+	 * Creates a description of Addons to provide for the Block.
+	 */
 	(addons: Partial<Addons>): CreatedBlockAddons<Addons, Options>;
 }
 
+/**
+ * Block that does not define a schema for Addons.
+ * @template Options Options values as described by the Base's options schema.
+ */
 export interface BlockWithoutAddons<Options extends object> extends BlockBase {
+	/**
+	 * Generates the creations describing a portion of a repository.
+	 * @see {@link https://www.create.bingo/engines/stratum/apis/create-base#createblock-produce}
+	 */
 	produce: BlockProducerWithoutAddons<Options>;
+
+	/**
+	 * Augments a Block creation with additional creations for setup mode.
+	 * @template Options Options values as described by the Base's options schema.
+	 * @see {@link https://www.create.bingo/engines/stratum/apis/create-base#createblock-setup}
+	 */
 	setup?: BlockAugmentWithoutAddons<Options>;
+
+	/**
+	 * Augments a Block creation with additional creations for transition mode.
+	 * @template Options Options values as described by the Base's options schema.
+	 * @see {@link https://www.create.bingo/engines/stratum/apis/create-base#createblock-transition}
+	 */
 	transition?: BlockAugmentWithoutAddons<Options>;
 }
diff --git a/packages/bingo-stratum/src/types/creations.ts b/packages/bingo-stratum/src/types/creations.ts
index fe2954d..219e002 100644
--- a/packages/bingo-stratum/src/types/creations.ts
+++ b/packages/bingo-stratum/src/types/creations.ts
@@ -10,6 +10,11 @@ export interface BlockCreation<Options extends object> extends Creation {
 	addons: CreatedBlockAddons<any, Options>[];
 }
 
+/**
+ * Describes Addons to provide to a Block before production.
+ * @template Addons Block-specific extensions, as defined by the Block's schema.
+ * @template Options Options values as described by the Base's options schema.
+ */
 export interface CreatedBlockAddons<
 	Addons extends object = object,
 	Options extends object = object,
diff --git a/packages/site/src/content/docs/build/apis/create-template.mdx b/packages/site/src/content/docs/build/apis/create-template.mdx
index 624e11d..13f625a 100644
--- a/packages/site/src/content/docs/build/apis/create-template.mdx
+++ b/packages/site/src/content/docs/build/apis/create-template.mdx
@@ -376,7 +376,7 @@ For example, this template creates a starter `index.js` file when first run:
 import { createTemplate } from "bingo";
 
 export default createTemplate({
-	setup({ addons }) {
+	setup() {
 		return {
 			files: {
 				"index.js": `console.log("Hello, world!");`,
diff --git a/packages/site/src/content/docs/engines/stratum/apis/create-base.mdx b/packages/site/src/content/docs/engines/stratum/apis/create-base.mdx
index def466c..edc55af 100644
--- a/packages/site/src/content/docs/engines/stratum/apis/create-base.mdx
+++ b/packages/site/src/content/docs/engines/stratum/apis/create-base.mdx
@@ -120,17 +120,17 @@ import { z } from "zod";
 import { base } from "./base";
 
 export const blockPrettier = base.createBlock({
-	args: {
+	addons: {
 		plugins: z.array(z.string()).optional(),
 	},
-	async produce({ args }) {
+	async produce({ addons }) {
 		return {
 			files: {
 				".prettierrc.json":
-					args.plugins &&
+					addons.plugins &&
 					JSON.stringify({
 						$schema: "http://json.schemastore.org/prettierrc",
-						plugins: args.plugins,
+						plugins: addons.plugins,
 					}),
 			},
 		};
@@ -140,6 +140,83 @@ export const blockPrettier = base.createBlock({
 
 See [Stratum > Concepts > Blocks > Addons](/engines/stratum/concepts/blocks#addons) for more information.
 
+### `intake` {#createblock-intake}
+
+An optional function to intake default [`addons`](#createblock-addons) values from existing files on disk.
+
+It receives one parameter: an [Intake Context](/engines/stratum/details/contexts#intake-contexts) object containing any existing files.
+It may return an object with any default values for the Block's Addons.
+
+For example, this Block reads in existing Prettier plugins from a Prettier config file:
+
+```ts
+import { z } from "zod";
+
+import { base } from "./base";
+
+export const blockPrettier = base.createBlock({
+	addons: {
+		plugins: z.array(z.string()).optional(),
+	},
+	intake({ files }) {
+		const existingConfig = files[".prettierrc.json"]?.[0];
+
+		return {
+			plugins: existingConfig && JSON.parse(existingConfig).plugins,
+		};
+	},
+	async produce({ addons }) {
+		// ...
+	},
+});
+```
+
+### `setup` {#createblock-setup}
+
+Additional production function for initializing a new repository with the Block.
+If defined, it will only be called in [setup mode](/execution#setup-mode).
+
+For example, this Block creates a starter `index.js` file when first run:
+
+```ts
+import { base } from "./base";
+
+export const blockStarterFile = createBlock({
+	setup() {
+		return {
+			files: {
+				"index.js": `console.log("Hello, world!");`,
+			},
+		};
+	},
+	produce() {
+		// ...
+	},
+});
+```
+
+### `transition` {#createblock-transition}
+
+Additional production function for migrating an existing repository to the Block.
+If defined, it will only be called in [transition mode](/execution#transition-mode).
+
+For example, this Block deletes any already-existing test config files when run on an existing repository:
+
+```ts
+import { base } from "./base";
+
+export const blockConfigFiles = createBlock({
+	setup({ addons }) {
+		return {
+			commands: ["rm .mocha* jest.config.* vitest.config.*"],
+		};
+	},
+	produce() {
+		// ...
+	},
+});
+```
+
 ### `produce` {#createblock-produce}
 
 Block Definitions must include a `produce()` function for their core logic.
diff --git a/packages/site/src/content/docs/engines/stratum/details/contexts.mdx b/packages/site/src/content/docs/engines/stratum/details/contexts.mdx
index e668e89..81d4332 100644
--- a/packages/site/src/content/docs/engines/stratum/details/contexts.mdx
+++ b/packages/site/src/content/docs/engines/stratum/details/contexts.mdx
@@ -10,12 +10,13 @@ Some Stratum constructs reuse the same contexts as described in [Details > Conte
 
 Other Stratum constructs do not reuse Bingo's existing contexts:
 
-- [Blocks](/engines/stratum/concepts/blocks) receive a [Block Context](#block-contexts)
+- [Blocks](/engines/stratum/concepts/blocks) generally receive a [Block Context](#block-contexts)
+  - A specialized [Intake Context](#intake-contexts) is used for specific intake APIs
 - [Presets](/engines/stratum/concepts/presets) don't have their own contexts
 
 ## Block Contexts
 
-The Context object provided to the `produce` object of [Blocks](/engines/stratum/concepts/blocks).
+The Context object provided to the [`produce`](/engines/stratum/apis/create-base#createblock-produce), [`setup`](/engines/stratum/apis/create-base#createblock-setup), and [`transition`](/engines/stratum/apis/create-base#createblock-transition) properties of [Blocks](/engines/stratum/concepts/blocks).
 
 ### `addons`
 
@@ -68,3 +69,39 @@ export const blockPackageJson = createBlock({
 	},
 });
 ```
+
+## Intake Contexts
+
+The Context object provided to the [`intake`](/engines/stratum/apis/create-base#createblock-intake) properties of [Blocks](/engines/stratum/concepts/blocks).
+
+### `files` {#intake-files}
+
+Any existing files on disk as a [bingo-fs `CreatedDirectory`](/build/packages/bingo-fs#directories), if running in [transition mode](/execution#transition-mode).
+
+Files in the directory are stored as [`[string, CreatedFileMetatdata?]` tuples](/build/packages/bingo-fs#files)
+
+For example, this Block reads in existing npm ignore lines from an `.npmignore` file if it exists:
+
+```ts
+import { z } from "zod";
+
+import { base } from "./base";
+
+export const blockNpmignore = base.createBlock({
+	addons: {
+		ignores: z.array(z.string()).optional(),
+	},
+	intake({ files }) {
+		return {
+			ignores: files[".npmignore"]?.split("\n").filter(Boolean),
+		};
+	},
+	async produce({ addons }) {
+		return {
+			files: {
+				".npmignore": [...addons.ignores, ""].join("\n"),
+			},
+		};
+	},
+});
+```
diff --git a/packages/site/src/content/docs/engines/stratum/details/execution.mdx b/packages/site/src/content/docs/engines/stratum/details/execution.mdx
index c1488c8..d6b7787 100644
--- a/packages/site/src/content/docs/engines/stratum/details/execution.mdx
+++ b/packages/site/src/content/docs/engines/stratum/details/execution.mdx
@@ -9,12 +9,14 @@ They instead automatically produce all the [Blocks](/engines/stratum/concepts/bl
 Stratum continuosly re-runs Blocks until no new Addons are provided.
 The algorithm is roughly...
 
-1. Create a queue of Blocks to be run, starting with all defined in the Preset
-   1. This also factors in any modifications per [Configurations > `refinements`](/engines/stratum/details/configurations#refinements)
-2. For each Block in the queue:
+1. Collect all Blocks defined in the Preset, along with their Addons:
+   1. Run any [`intake`](/engines/stratum/apis/create-base#createblock-intake) methods to generate default Addons value
+   2. Apply all [`refinements`](/engines/stratum/details/configurations/#refinements) on top of those
+2. Create a queue of Blocks to be run, starting with all defined in the Preset
+3. For each Block in the queue:
    1. Get the Creation from the Block, passing any current known Addons
    2. If a [Mode](/build/concepts/modes) is specified, additionally generate the approprate Block Creations
    3. Store that Block's Creation
    4. If the Block specified new addons for any defined Blocks:
       1. Add those Blocks to the queue of Blocks to re-run
-3. Merge all Block Creations together
+4. Merge all Block Creations together


Test patch:
diff --git a/packages/bingo-stratum/src/producers/produceBlock.test.ts b/packages/bingo-stratum/src/producers/produceBlock.test.ts
new file mode 100644
index 0000000..4b9663e
--- /dev/null
+++ b/packages/bingo-stratum/src/producers/produceBlock.test.ts
@@ -0,0 +1,94 @@
+import { describe, expect, it } from "vitest";
+import { z } from "zod";
+
+import { createBase } from "../creators/createBase.js";
+import { produceBlock } from "./produceBlock.js";
+
+const base = createBase({
+	options: {
+		value: z.string(),
+	},
+});
+
+const options = {
+	value: "Hello, world!",
+};
+
+describe("produceBlock", () => {
+	it("returns the creation when no Addons or mode are defined", () => {
+		const block = base.createBlock({
+			produce({ options }) {
+				return {
+					files: { "README.md": options.value },
+				};
+			},
+		});
+
+		const actual = produceBlock(block, { options });
+
+		expect(actual).toEqual({
+			files: {
+				"README.md": "Hello, world!",
+			},
+		});
+	});
+
+	it("passes Addons to the Block when addons is defined", () => {
+		const block = base.createBlock({
+			addons: {
+				extra: z.record(z.string()).optional(),
+			},
+			produce({ addons, options }) {
+				return {
+					files: {
+						"README.md": options.value,
+						...addons.extra,
+					},
+				};
+			},
+		});
+
+		const actual = produceBlock(block, {
+			addons: {
+				extra: {
+					"a.txt": "a",
+				},
+			},
+			options,
+		});
+
+		expect(actual).toEqual({
+			files: {
+				"a.txt": "a",
+				"README.md": "Hello, world!",
+			},
+		});
+	});
+
+	it("augments the creation when mode is provided and the Block has that mode-specific producer", () => {
+		const block = base.createBlock({
+			produce({ options }) {
+				return {
+					files: { "README.md": options.value },
+				};
+			},
+			setup() {
+				return {
+					files: { "extra.txt": "setup" },
+				};
+			},
+		});
+
+		const actual = produceBlock(block, {
+			mode: "setup",
+			options,
+		});
+
+		expect(actual).toEqual({
+			files: {
+				"extra.txt": "setup",
+				"README.md": "Hello, world!",
+			},
+		});
+	});
+});
diff --git a/packages/bingo-stratum/src/producers/produceBlocks.test.ts b/packages/bingo-stratum/src/producers/produceBlocks.test.ts
index 97c147d..ba1450e 100644
--- a/packages/bingo-stratum/src/producers/produceBlocks.test.ts
+++ b/packages/bingo-stratum/src/producers/produceBlocks.test.ts
@@ -1,3 +1,4 @@
+import { IntakeFileEntry } from "bingo-fs";
 import { describe, expect, it, test, vi } from "vitest";
 import { z } from "zod";
 
@@ -34,7 +35,7 @@ describe("produceBlocks", () => {
 		});
 	});
 
-	it("adds addons when provided", () => {
+	it("adds addons when provided only under blockAddons", () => {
 		const block = base.createBlock({
 			about: {
 				name: "Example Block",
@@ -50,7 +51,7 @@ describe("produceBlocks", () => {
 		});
 
 		const result = produceBlocks([block], {
-			addons: [block({ extra: "line" })],
+			blockAddons: [block({ extra: "line" })],
 			options: { value: "Hello, world!" },
 		});
 
@@ -61,6 +62,84 @@ describe("produceBlocks", () => {
 		});
 	});
 
+	it("adds addons when provided only via Block intake", () => {
+		const block = base.createBlock({
+			about: {
+				name: "Example Block",
+			},
+			addons: {
+				extra: z.string().optional(),
+			},
+			intake({ files }) {
+				return {
+					extra: (files["README.md"] as IntakeFileEntry)[0].split("\n").at(-1),
+				};
+			},
+			produce({ addons, options }) {
+				return {
+					files: { "README.md": [options.value, addons.extra].join("\n") },
+				};
+			},
+		});
+
+		const result = produceBlocks([block], {
+			files: {
+				"README.md": ["Before\nline"],
+			},
+			options: { value: "Hello, world!" },
+		});
+
+		expect(result).toEqual({
+			files: {
+				"README.md": "Hello, world!\nline",
+			},
+		});
+	});
+
+	it("adds merges addons when provided by Block intake and blockAddons", () => {
+		const block = base.createBlock({
+			about: {
+				name: "Example Block",
+			},
+			addons: {
+				a: z.string().optional(),
+				b: z.string().optional(),
+				c: z.string().optional(),
+			},
+			intake() {
+				return {
+					a: "intake",
+					b: "intake",
+				};
+			},
+			produce({ addons, options }) {
+				return {
+					files: {
+						"README.md": [options.value, addons.a, addons.b, addons.c].join(
+							"\n",
+						),
+					},
+				};
+			},
+		});
+
+		const result = produceBlocks([block], {
+			blockAddons: [
+				block({
+					b: "provided",
+					c: "provided",
+				}),
+			],
+			options: { value: "Hello, world!" },
+		});
+
+		expect(result).toEqual({
+			files: {
+				"README.md": "Hello, world!\nintake\nprovided\nprovided",
+			},
+		});
+	});
+
 	it("doesn't include addons to blocks that aren't defined", () => {
 		const blockKnown = base.createBlock({
 			about: {