---
title: "MGS1003: bespoke phase-fragment target name"
description: Doctor advice, not a failure. Notes a target named after a static-analysis or formatting subset (typecheck, vet, audit, style, prettify) that would usually be better composed into lint or format.
tags: [MGS1003, magusfile, targets, lint, format, doctor, naming]
---

# MGS1003: bespoke phase-fragment target name

`magus doctor` found a target whose normalized name is one of `typecheck`,
`type-check`, `vet`, `audit`, `style`, or `prettify`. Each of these
names a subset of an existing canonical phase - static analysis or formatting -
rather than a phase of its own.

```text
[advice] bespoke phase-fragment target names: 1 target(s) name static analysis or
formatting rather than a phase of their own; composing the op into lint (or
format) lets `magus affected ci` cover it (docs/targets.md#the-target-name, see
.../MGS1003.md)
    typecheck: "typecheck" in web/magusfile.buzz
```

**This does not fail anything.** It is `magus doctor` advice: reported, exit 0.
magus reserves exactly one target name, `ci`, and how the rest of your workspace
is laid out is your call.

## Why

`lint` is defined as "static analysis, type-check" (see
[targets.md](../../../concepts/targets.md#the-target-name)): a Go project's `go vet` and a
TypeScript project's `tsc --noEmit` both compose into `lint`, the same way
eslint and golangci-lint do. `format` plays the analogous role for style/prettify
tools. A standalone `typecheck` (or `vet`, `audit`, `style`,
`prettify`) target carves one tool's check out of that composition into its own
name.

The practical cost is that `ci` is composed from the canonical phases via
`magus\needs`. A bespoke `typecheck` target sitting beside `lint` is invisible to
any `ci` that only needs `lint` - the type-check silently never runs in CI unless
someone remembers to add it separately. Folding the op into `lint` means it rides
along automatically wherever `lint` already does.

This is **advice**, not a magusfile load error and not a failed check. Unlike
[MGS1002](MGS1002.md) (a spell shadow, which is dead code and unresolvable
without a rename or an acknowledgment), a bespoke name is a valid, working
target - just one that is easy to forget in a pipeline. Whether that trade is
worth it depends on your workspace, and that is not magus's call to make.

## Resolution

Move the tool invocation into `lint` (or `format` for prettify/style) instead of
a standalone target:

```buzz
// Before: a standalone typecheck target ci must remember to add separately.
export fun typecheck(ctx: magus\Context, args: [str]) > void {
    ts["tsc"](ctx);
}

// After: tsc composes into lint, alongside eslint - one target ci already needs.
export fun lint(ctx: magus\Context, args: [str]) > void {
    ts["tsc"](ctx);
    ts["eslint"](ctx);
}
```

### Keeping the name

Keep it. There is nothing to configure and nothing to acknowledge: the finding is
advice, `magus doctor` still exits 0, and the line stays in the report as a note
for the next reader.

Sometimes the target genuinely is not the fragment its name suggests. An advisory
audit is the clearest case: `lint` is cached on the tree, but an advisory scan's
answer changes when the registry's database does, so folding it into `lint` would
either replay a stale clean bill of health or force `lint` to stop caching. That
is a good reason, and magus does not need to be told it.

An earlier version of this check failed the build and grew a
`targets[...].allow_bespoke_name` key to opt out of it. Both are gone. A check
that costs a paragraph of justification to disagree with is still a requirement,
and the config surface was on course to accumulate one escape-hatch key per
opinion magus holds.

## What this is NOT

- **Not a failure.** The target runs, `magus doctor` exits 0, and nothing blocks
  the build. There is also no flag that turns this into a failure: that would be
  the same imposition wearing an opt-in label.
- **Not the canonical-name litmus test itself.** See
  [targets.md](../../../concepts/targets.md#the-target-name) for the full reasoning;
  this check only notes the specific set of known static-analysis and formatting
  fragments, not any custom target name.

## See also

- [targets.md](../../../concepts/targets.md#the-target-name): the seven canonical target
  names and what composes into `lint`/`format`.
- `magus describe targets`: lists every target and which spell ops compose into it.
