clidomain

package module
v0.2.15 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 24, 2026 License: MIT Imports: 6 Imported by: 0

README

Documentation

Overview

Package clidomain provides a go/analysis analyzer enforcing the domain tier of the opinionated three-tier CLI layout.

The layout splits a CLI into three tiers. The APP tier (internal/app/commands/<verb>) owns flags and help text; the DOMAIN tier (internal/domain/<verb>) owns orchestration; the implementation tier (internal/<capability>) owns reusable logic. The other parts are policed elsewhere — stickler/clilayout checks that command and domain packages correspond across the whole module, and yze/cliapp checks the command package's own shape — so this one covers the tier neither reaches: the domain package's contract.

That contract is exact, which is what makes it checkable. Every domain package declares a Config carrying the flags the CLI binds and NO behaviour, a Result, and a single entry point:

func Run(context.Context, *slog.Logger, Config, ...domain.Argument) (Result, error)

Config and Result mean THIS package's declarations: Run's third parameter and first result are matched by type identity against them, so a Run wired to another package's types — leaving the declared ones dead — is a signature violation, not a pass. Run itself must be a function; a package-level var or a type named Run is the same violation. Nor may it be GENERIC: a type parameter cannot be inferred from the call the CLI tier writes, so an entry point carrying one is an entry point nothing can call — the same violation again, wearing the right signature. The variadic must use the SHARED domain.Argument alias rather than a locally-redeclared one: both spellings compile, so nothing but a rule keeps them from diverging. Spelling alone is not enough — the domain qualifier must also RESOLVE to the repo's shared internal/domain vocabulary package, since importing any other package as domain reproduces the spelling while defeating the rule.

Config carries no behaviour BY ANY ROUTE. A method declared on it, one promoted from an embedded field, and one promised by an interface are the same defect, because logic lands in the tier that exists to hold none however it arrives — and a rule that reads only the declared route is turned off by embedding the type instead of aliasing it, which is one character and no record anywhere.

Scope is every package beneath internal/domain/, at any depth — a nested verb like internal/domain/tenant/create is as much a verb as a top-level one. The shared internal/domain vocabulary package itself declares no command, so it is skipped, and so is any grouping or helper package that declares no element of the contract. Only PRODUCTION declarations count — for the contract's types AND for Config's methods: test files may freely declare Config-shaped test tables, Run-shaped drivers and builder methods on Config without imposing the contract or making Config behave. A package whose files are all _test.go therefore declares nothing this rule reads, which is how the driver-synthesized external-test and test-main passes go unjudged — no package NAME and no import path is consulted, since a name ending in _test or a path ending in .test is a thing an author writes.

A missing-contract report anchors at the package clause of the verb's FIRST PRODUCTION file, because a finding a _test.go file holds is dropped rather than relocated: this analyzer's Registration below declares no TestScope, and the scope is instead applied by the runner's catalog, which lists clidomain in its sourceOnly set (gomatic/yze registrations.go:76, verified 2026-08-15). That is a claim about ANOTHER repository, so it is cited rather than asserted — nothing here fails if it changes, and a reader can check it. Anchoring in a test file would therefore not move the finding, it would delete it.

Index

Constants

This section is empty.

Variables

View Source
var Analyzer = &analysis.Analyzer{
	Name: "clidomain",
	Doc:  "reports domain packages that break the opinionated three-tier CLI contract (Config, Result, Run)",
	Run:  run,
}

Analyzer reports domain packages that break the three-tier CLI contract.

View Source
var Registration = goyze.Registration{
	Precision:  goyze.PrecisionExact,
	Name:       "clidomain",
	Categories: []goyze.Category{"cli", "structure"},
	URL:        "https://docs.gomatic.dev/yze/clidomain",
	Analyzer:   Analyzer,
}

Registration declares this analyzer to the yze framework.

Functions

This section is empty.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL