Claude Code Plugins

Community-maintained marketplace

Feedback

three-path-wire

@site-bender/toolsmith
0
0

Wire up the three-path structure for a function. Ensures Maybe uses chain, Result/Validation use chainWiden, and Validation accumulates all errors. PREREQUISITE - help-system-prep must be complete for this function. Work on ONE function at a time.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name three-path-wire
description Wire up the three-path structure for a function. Ensures Maybe uses chain, Result/Validation use chainWiden, and Validation accumulates all errors. PREREQUISITE - help-system-prep must be complete for this function. Work on ONE function at a time.

Three Path Wire

Wire up the three-path structure for a function. This skill assumes help-system-prep is complete for this function.

MANDATORY: Follow ALL Rules

READ AND FOLLOW docs/THESE_ARE_THE_RULES.md WITHOUT EXCEPTION.

WE DO NOT ALLOW, UNDER ANY CIRCUMSTANCES, ANY TECH DEBT IN THIS LIBRARY.

Prerequisite

help-system-prep must be complete for this function. The following must exist and be canonical:

  • constants/index.ts with code strings only
  • types/index.ts with HelpCode type
  • All _*Help/ functions with pipeHelp pattern

Files This Skill Touches

  1. _functionNameToMaybe/index.ts
  2. _functionNameToMaybe/_processData/index.ts
  3. _functionNameToMaybe/_processData/index.test.ts
  4. _functionNameToMaybe/index.test.ts
  5. _functionNameToResult/index.ts
  6. _functionNameToResult/_processData/index.ts
  7. _functionNameToResult/_processData/index.test.ts
  8. _functionNameToResult/index.test.ts
  9. _functionNameToValidation/index.ts
  10. _functionNameToValidation/_processData/index.ts
  11. _functionNameToValidation/_processData/index.test.ts
  12. _functionNameToValidation/index.test.ts
  13. index.ts (main function)
  14. index.test.ts (main function tests)

Files This Skill Does NOT Touch

  • constants/index.ts
  • types/index.ts
  • _*Help/ functions

Rules Enforced

Rule 1: Maybe Routing Uses chain

File: _functionNameToMaybe/index.ts

import type { Maybe } from "path/to/monads/maybe/types/index.ts"
import chain from "path/to/monads/maybe/chain/index.ts"
import _processData from "./_processData/index.ts"

//++ Private helper for functionName on Maybe monads
export default function _functionNameToMaybe<T>(
	maybeData: Maybe<DataType>,
): Maybe<OutputType> {
	return chain<DataType, OutputType>(_processData<T>)(maybeData)
}

Rule 2: Result/Validation Routing Uses chainWiden

File: _functionNameToResult/index.ts

import type { BaseHelp } from "path/to/help/types/index.ts"
import type { Result } from "path/to/monads/result/types/index.ts"
import chainWiden from "path/to/monads/result/chainWiden/index.ts"
import type { FunctionNameHelpCode } from "../types/index.ts"
import _processData from "./_processData/index.ts"

//++ Private helper for functionName on Result monads
export default function _functionNameToResult<T, H>(
	result: Result<H, DataType>,
): Result<H | BaseHelp<FunctionNameHelpCode>, OutputType> {
	return chainWiden<DataType, OutputType, BaseHelp<FunctionNameHelpCode>>(
		_processData<T>,
	)(result)
}

Same pattern for Validation with chainWiden.

Note: FunctionNameHelpCode is the code string union. BaseHelp<FunctionNameHelpCode> is the full help object type.

Rule 3: Curry Levels

All Toolsmith functions are curried — exactly one parameter per function level.

1 curry level (data only):

export default function functionName<T, H>(
	data: Maybe<DataType> | Result<H, DataType> | Validation<H, DataType>,
): ...

2 curry levels (one param + data):

export default function functionName<T, H>(param1: Param1Type) {
	function functionNameWithParam1(
		data: Maybe<DataType> | Result<H, DataType> | Validation<H, DataType>,
	): ... {
		// implementation
	}
	return functionNameWithParam1
}

3 curry levels (two params + data):

export default function functionName<T, H>(param1: Param1Type) {
	return function functionNameWithParam1(param2: Param2Type) {
		function functionNameWithParam1AndParam2(
			data: Maybe<DataType> | Result<H, DataType> | Validation<H, DataType>,
		): ... {
			// implementation
		}
		return functionNameWithParam1AndParam2
	}
}

Rule 4: Overloads on Innermost Function

Overloads go on the function that takes the monad-wrapped data.

  • 1 curry level: Overloads on main function
  • 2+ curry levels: Overloads on inner function

Rule 5: _processData for Maybe

Returns Maybe<OutputType>. Returns nothing() for all failures.

export default function _processData<T>(param: ParamType) {
	return function _processDataWithParam(data: DataType): Maybe<OutputType> {
		if (isValidParam(param)) {
			if (isValidData(data)) {
				return just(result)
			}
		}
		return nothing()
	}
}

Rule 6: _processData for Result

Returns Result<BaseHelp<FunctionNameHelpCode>, OutputType>. Uses help() with extracted help functions.

import type { BaseHelp } from "path/to/help/types/index.ts"
import type { FunctionNameHelpCode } from "../../types/index.ts"

export default function _processData<T>(param: ParamType) {
	return function _processDataWithParam(
		data: DataType,
	): Result<BaseHelp<FunctionNameHelpCode>, OutputType> {
		if (isValidParam(param)) {
			if (isValidData(data)) {
				return ok(result)
			}
			return help(_dataNotUnderstoodHelp(data))
		}
		return help(_paramNotUnderstoodHelp(param))
	}
}

Rule 7: _processData for Validation — ACCUMULATES ERRORS

Returns Validation<BaseHelp<FunctionNameHelpCode>, OutputType>. Uses failure([]) with array. MUST accumulate ALL errors when multiple params fail.

import type { BaseHelp } from "path/to/help/types/index.ts"
import type { FunctionNameHelpCode } from "../../types/index.ts"

export default function _processData<T>(param: ParamType) {
	return function _processDataWithParam(
		data: DataType,
	): Validation<BaseHelp<FunctionNameHelpCode>, OutputType> {
		if (isValidParam(param)) {
			if (isValidData(data)) {
				return success(result)
			}
			return failure([_dataNotUnderstoodHelp(data)])
		}

		// param is invalid — check if data is also invalid
		if (isValidData(data)) {
			return failure([_paramNotUnderstoodHelp(param)])
		}

		// BOTH invalid — accumulate both helps
		return failure([
			_paramNotUnderstoodHelp(param),
			_dataNotUnderstoodHelp(data),
		])
	}
}

Accumulation with 2 params + data (3 curry levels):

  • param1 bad, param2 good, data good → 1 help
  • param1 good, param2 bad, data good → 1 help
  • param1 good, param2 good, data bad → 1 help
  • param1 bad, param2 bad, data good → 2 helps
  • param1 bad, param2 good, data bad → 2 helps
  • param1 good, param2 bad, data bad → 2 helps
  • param1 bad, param2 bad, data bad → 3 helps

Rule 8: Function Parameters Require try/catch

If a parameter is a user-provided function (predicate, transformer, reducer), wrap the operation in try/catch.

/*++
 + [EXCEPTION] try/catch permitted to wrap user-provided function
 + [description of what function does]
 */
export default function _processData<T>(
	fn: (value: T) => boolean,
) {
	return function _processDataWithFn(
		data: DataType,
	): Maybe<OutputType> {
		try {
			if (isFunction(fn)) {
				if (isValidData(data)) {
					return just(data.someMethod(fn))
				}
			}
			return nothing()
		} catch (_err) {
			return nothing()
		}
	}
}

For Result/Validation, catch returns help/failure with _functionFumbledHelp(err).

Rule 9: Main index.ts Uses _routeThreePaths

import type { BaseHelp } from "path/to/help/types/index.ts"
import type { FunctionNameHelpCode } from "./types/index.ts"

export default function functionName<T, H>(param: ParamType) {
	// overloads here for 2+ curry levels

	function functionNameWithParam(
		data: Maybe<DataType> | Result<H, DataType> | Validation<H, DataType>,
	):
		| Maybe<OutputType>
		| Result<H | BaseHelp<FunctionNameHelpCode>, OutputType>
		| Validation<H | BaseHelp<FunctionNameHelpCode>, OutputType> {
		return _routeThreePaths<H, BaseHelp<FunctionNameHelpCode>, DataType, OutputType>({
			toMaybe: _functionNameToMaybe<T>(param),
			toResult: _functionNameToResult<T, H>(param),
			toValidation: _functionNameToValidation<T, H>(param),
		})(data)
	}

	return functionNameWithParam
}

Workflow

For each function (one at a time):

  1. Verify help-system-prep is complete (constants, types, help functions exist and are canonical)
  2. Read all routing and processing files to understand current state
  3. Maybe path (complete before moving to Result):
    • Fix _functionNameToMaybe/_processData/index.ts
    • Run deno task fmt && deno task lint
    • Run deno check on the file
    • Fix _functionNameToMaybe/_processData/index.test.ts
    • Run tests, verify 100% coverage
    • Fix _functionNameToMaybe/index.ts
    • Run deno task fmt && deno task lint
    • Run deno check on the file
    • Fix _functionNameToMaybe/index.test.ts
    • Run tests, verify 100% coverage
  4. Result path (complete before moving to Validation):
    • Same workflow as Maybe path
  5. Validation path (complete before moving to main):
    • Same workflow as Maybe path
    • VERIFY accumulation logic is correct
  6. Main function:
    • Fix index.ts
    • Run deno task fmt && deno task lint
    • Run deno check index.ts
    • Fix index.test.ts
    • Run all tests for the function
    • Verify 100% coverage on all files
  7. Only then move to next function

Completion Criteria

A function is NOT complete until ALL of these are true:

  • Maybe routing uses chain
  • Result routing uses chainWiden
  • Validation routing uses chainWiden
  • All _processData functions use extracted help functions
  • Validation _processData accumulates ALL errors (all combinations tested)
  • Function params have try/catch wrapper with [EXCEPTION] comment
  • Main index.ts uses _routeThreePaths
  • Overloads on correct function (innermost that takes monad)
  • All curry levels have exactly one parameter
  • deno task lint passes with zero issues
  • deno check passes on all files
  • 100% test coverage on all files

Do not move to the next function until all criteria are met.