| name | mas-function-design |
| description | Define backend function design standards for Python services. Use when implementing or refactoring functions in app/, choosing function boundaries, designing signatures and return contracts, controlling side effects, and reviewing correctness/readability in core/task/services/api modules. |
MAS Function Design
Objective
Design backend functions that are predictable, easy to trace, and easy to evolve.
Core Principles
- Keep one primary responsibility per function.
- Make data flow explicit through inputs and return values.
- Minimize hidden side effects and shared mutable state.
- Keep error semantics stable and actionable.
- Match function placement with module boundary ownership.
Responsibility
- Keep a function focused on one decision unit or one orchestration step.
- Split when a function mixes domain decision and integration IO.
- Split when one function serves unrelated call paths.
- Keep thin wrappers thin; move real logic only when it creates real reuse.
- Do not extract a helper for logic that is easier to understand inline at the call site.
- For frequently edited task-configuration code, keep the mutation block in the owning orchestration function with a short purpose comment and blank lines around it.
- Do not split one linear task flow into
builder/loader helpers unless the split removes real duplication or clarifies a true boundary.
- In AUTO-MAS task flows, keep config import/export, log monitoring, and end-state judgment as explicit orchestration steps; do not hide product-critical run criteria behind vague wrappers.
Signatures And Returns
- Use explicit named parameters for business-critical options.
- Avoid ambiguous boolean positional parameters.
- Group related data in typed models/dataclasses when argument count grows.
- Keep optional parameters truly optional with clear default meaning.
- Return one stable shape per function role.
- Return domain values, not transport-layer response objects.
- Prefer signatures that remain compatible with basic static type checking.
- If omission is a valid state, omit the argument or field instead of passing a typed placeholder that conflicts with the signature.
- Use positional arguments only for simple, obvious calls with at most two clear parameters.
- Use keyword arguments for boolean arguments and for calls with more than two parameters.
Error Handling
- Raise domain-meaningful exceptions at domain layers.
- Convert exceptions to API-safe output only at API boundary.
- Do not swallow exceptions without logging context and fallback reason.
- Keep retry logic near integration boundaries, not in pure helpers.
- Include enough context in errors for diagnosis (
script_id, user_id, step).
Side Effects And Async
- Keep file IO, network, process, and global state operations explicit.
- Isolate side effects behind service/helper functions.
- In pure transformation functions, avoid logging and external calls.
- Do not mutate input objects unless the contract explicitly states mutation.
- Use
async only when awaiting IO or async coordination primitives.
- Keep cancellation-safe cleanup in
finally blocks for long-running flows.
- Avoid mixing sync blocking calls directly in async hot paths.
- Keep task spawning in orchestrator-level functions, not leaf utilities.
- Trust existing base-layer guarantees instead of repeating their correction logic in every function.
- Prefer one clear wait/check block over several tiny sleeps, logs, or staged wrappers that express the same step.
- When success/failure depends on log text, log timestamps, and process exit together, keep that decision rule centralized and readable instead of scattering partial checks across helpers.
TaskExecuteBase.main_task, final_task, and on_crash are the required execution contract for task classes; keep their responsibilities distinct.
main_task and final_task may raise normally, but on_crash must protect itself from uncaught exceptions.
- Await child task spawning through
await self.spawn(...); do not fire child tasks without awaiting unless the owning orchestration has a documented reason.
- Use
.cancel() plus await .accomplish.wait() when parent code must wait for nested task shutdown and cleanup to finish.
Placement
api: parse input, call core/service, map output.
core: orchestrate flow and state transitions.
task: execute domain run lifecycle per script type.
services: wrap external/system capabilities.
utils: generic reusable helpers without business policy.
models/schema: no business logic functions.
Naming
- Use verb-first names for actions (
load_*, build_*, merge_*, send_*).
- Use
check_* for validation returning status/result.
- Use
prepare_* for pre-run setup.
- Use
finalize_* or cleanup_* for teardown semantics.
- Avoid vague names like
handle or process without scope words.
Refactor Triggers
- Function exceeds clear readability for one screenful of logic.
- Same decision branch appears in multiple places.
- Repeated parameter bundles travel together across call sites.
- Testing one behavior requires heavy environment setup.
- A dict/registry mapping can replace multiple near-identical branches without hiding the main flow.
- A proposed helper adds more lookup cost than it removes.
- A proposed fallback only mirrors an invariant already enforced by the owning model or base class.
Review Checklist
- Function has one primary responsibility.
- Signature is explicit and stable for callers.
- Return shape is typed and consistent.
- Error behavior is clear and layered correctly.
- Side effects are visible and isolated.
- Placement follows
mas-module-boundary.
- Shared schema semantics align with
mas-schema-naming.
- One-off helpers were not extracted unless they created real reuse.
- Existing base-layer guarantees were reused instead of reimplemented in the function body.
- Optional values and temporary placeholders remain type-safe under basic static analysis.
- Multi-argument and boolean-heavy calls use keyword arguments for readability and fewer ordering mistakes.
- Task classes preserve the documented
main_task/final_task/on_crash lifecycle and nested cancellation behavior.