Claude-skill-registry layer-workflows
Use when creating or modifying code in nomarr/workflows/. Workflows implement use cases, accept dependencies as parameters, orchestrate components, and return DTOs.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/layer-workflows" ~/.claude/skills/majiayu000-claude-skill-registry-layer-workflows && rm -rf "$T"
manifest:
skills/data/layer-workflows/SKILL.mdsource content
Workflows Layer
Purpose: Implement core use cases ("what Nomarr does").
Workflows contain the story of how Nomarr performs operations. They are recipes that:
- Accept dependencies as parameters (DB, config, ML backends)
- Orchestrate components to perform work
- Return DTOs
Allowed Imports
# ✅ Allowed from nomarr.persistence import Database from nomarr.components.ml import compute_embeddings, run_inference from nomarr.components.tagging import predictions_to_tags from nomarr.helpers.dto import ProcessFileResult
Forbidden Imports
# ❌ NEVER import these in workflows from nomarr.services import ProcessingService # Workflows don't call services from nomarr.interfaces import ... # No interface imports from pydantic import BaseModel # No Pydantic
File & Function Naming
- File:
(e.g.,verb_object_wf.py
,scan_library_direct_wf.py
)process_file_wf.py - Function:
as the primary entrypointverb_object_workflow(...) - One public workflow per file
- Everything else is
_private_helper
Complexity Rule: Clear Sequences
Workflows should read like a recipe:
def process_file_workflow( db: Database, file_path: str, models_dir: str, namespace: str, ) -> ProcessFileResult: # Step 1: Load file file_record = load_file_from_db(db, file_path) # Step 2: Compute embeddings embeddings = compute_all_embeddings(file_path, models_dir) # Step 3: Run inference predictions = run_inference_for_heads(embeddings, models_dir) # Step 4: Convert to tags tags = predictions_to_tags(predictions, namespace) # Step 5: Write tags write_tags_to_db(db, file_record.id, tags) return ProcessFileResult(file=file_path, tags_written=len(tags))
Judge by clarity, not line count. Many component calls are fine if they form a clear sequence.
Accept All Dependencies as Parameters
Workflows receive everything via parameters—no global config reading:
# ✅ Good - dependencies injected def process_file_workflow( db: Database, file_path: str, models_dir: str, ) -> ProcessFileResult: ... # ❌ Bad - reading globals def process_file_workflow(file_path: str) -> ProcessFileResult: from nomarr.config import db, models_dir # NO GLOBALS ...
When to Extract
Extract to a component if:
- Workflow is doing non-trivial computation itself
- Complex branching logic embedded in workflow
- Heavy domain math/ML/statistics
Split into private helpers if:
- Workflow becomes hard to read
- Large, reusable sub-sequences
# Before - hard to read def complex_workflow(db: Database, ...) -> Result: # 50 lines of discovery # 50 lines of validation # 50 lines of processing # After - split with private helpers def complex_workflow(db: Database, ...) -> Result: discovered = _discover_and_validate(db, ...) processed = _process_files(db, discovered, ...) return Result(...)
Size Guidelines
- Soft limit: ~300–400 LOC per workflow module
- If multiple exported workflows with different user stories → split files
- Exception: analytics-style modules can group related read-only workflows
Validation Checklist
Before committing workflow code, verify:
- Does this file import from services or interfaces? → Violation
- Does this file import Pydantic? → Violation
- Does this workflow read global config? → Accept as parameter instead
- Is the workflow doing heavy computation? → Extract to component
- Does the function return a DTO? → Required
- Is there one public workflow per file? → Required
- Does the file name end in
? → Convention_wf.py
Layer Scripts
This skill includes validation scripts in
.github/skills/layer-workflows/scripts/:
lint.py
lint.pyRuns all linters on the workflows layer:
python .github/skills/layer-workflows/scripts/lint.py
Executes: ruff, mypy, vulture, bandit, radon, lint-imports
check_naming.py
check_naming.pyValidates workflows naming conventions:
python .github/skills/layer-workflows/scripts/check_naming.py
Checks:
- Files must end in
_wf.py - Each file must have exactly one
function*_workflow - Internal helpers must be
_private