Osy#betaRun it on Osyrin: osyrin.com

Reference / Local

Checking a kit composes — osy kits check

osy kits check [<dir>] [--offline] [--json]

Checks that a kit composes with the kits around it: it uses no other product kit it does not complete (KIT_REFERENCES_SIBLING), it never names a member a bridge adds to its own entities (KIT_NAMES_A_BRIDGES_MEMBER), a test shows every seam an app connects (KIT_SEAM_UNTESTED — required to publish), and its test app is about something of its own (KIT_TEST_APP_DOMAIN). It also compiles the kit into an app that keeps every default it offers (KIT_DOES_NOT_COMPOSE).

stablelocalclipackageskits

Summary#

Kits are valuable together only if each one can be added without dragging another in. osy kits check reads the kit in a directory — its package.osy and its model — and reports what would stop it composing, each finding with its rule, where it is, and what to write instead. It exits 1 on any MUST finding, so a kit's CI can hold it.

$ osy kits check kits/widgets
MUST KIT_REFERENCES_SIBLING  package.osy:5  `Acme.Widgets` uses `Acme.Shop`, which is a vertical (`role vertical;`) — a product kit other kits meet only through a bridge. A kit that reaches into a sibling vertical makes every app that wants one take the other.
      fix: move what needs `Acme.Shop` into a bridge — a package that `use`s both and says `completes Acme.Widgets@0, Acme.Shop@0;` — which arrives by itself in an app that uses both; or, if `Acme.Widgets` exists only to complete it, add `Acme.Shop` to its own `completes` line.
✗ Acme.Widgets — 1 finding.

Signature#

osy kits check [<dir>]      # the kit in <dir> (default: the current directory)
  --offline                 # find the bridges that complete it in the workspace and the platform only, not GitHub
  --json                    # { kit, role, findings: [{ rule, tier, file, line, message, fix }], notes }

Description#

What is a vertical, and why may a kit not use one?#

A kit says what it is to the kits around it with role in its package.osy — a bare word:

rolewhat it ismay another kit use it?
hubit holds the nouns other kits meet at — people, organisations, work itemsyes
horizontal (the default)something kits build on freely — the UI kit, mail, reports, automationsyes
verticala product — a shop, a knowledge base, a conversation deskonly a bridge that completes it, or an extension of it

KIT_REFERENCES_SIBLING (MUST) refuses a kit that uses a vertical it neither completes nor extends. An extension is a kit whose name continues the vertical's — Osysharp.Shop.Discounts on Osysharp.Shop. Two verticals meet in a bridge instead, which arrives by itself in an app that uses both (Bridges — a package that arrives when an app uses the two it completes): that is what keeps the number of dependencies growing with the kits, not with every pair of them.

What may a kit not say about its own entities?#

A bridge may add optional members to another kit's entities (Extension members): Osysharp.Crm.Cpq adds LatestQuote to CRM's Opportunity. KIT_NAMES_A_BRIDGES_MEMBER (MUST) refuses the CRM kit naming LatestQuote itself. CRM's own compile has no bridge in it, but an app that uses CRM and CPQ does — so a name that only resolves with the bridge is a kit that works in one composition and not in another. The code that needs the member belongs in the bridge.

The bridges that complete the kit are found where osy lock finds them — the workspace, the platform's packages, and GitHub (--offline leaves GitHub out) — and the notes list the ones it looked at.

Every seam is shown by a test#

A kit's tests are its worked examples: osy kits <kit> --surface prints, beside each seam, the test app code that connects it and the tests that show it working (Connecting a kit — each seam with the code that connects it). KIT_SEAM_UNTESTED names a seam an app connects — an event, a policy the kit asks for, a setting, a slot, a contract, an abstract base, an extension member, an action, a page the kit links to — that no test of the kit's test app reaches. It is SHOULD here and MUST at osy publish: a seam is never published without its example. Each finding says what to add for that kind of seam:

SHOULD KIT_SEAM_UNTESTED  model/reviews.osy:26  no test shows `ReviewWithdrawn` (event: [Event("Review withdrawn")] ReviewWithdrawn { Review }). An app connecting this kit is shown each seam by the test that exercises it (`osy kits --surface`); this one it would only be told about.
      fix: in the test app, hear it — `[On] void WhenReviewWithdrawn(ReviewWithdrawn e) { … }` writing something of the app's own — and add a test that makes it happen and asserts what the handler left.

KIT_TEST_APP_DOMAIN (SHOULD) — a kit that works on an app's records (it takes an Entity, offers an abstract base, or raises an event about any record) has a test app with a record of its own, so its tests prove it works for an app that is not about the kit. An adapter — a mail sender, a carrier — has no app record to be about and is not asked.

Does it compile for an app that keeps every default?#

A kit's test app usually overrides each virtual policy the kit offers — that is how it shows the seam — so a default that does not compile in a consumer stays hidden there, and the first app that keeps it fails instead, in a kit file its author never wrote. KIT_DOES_NOT_COMPOSE (MUST) composes the kit into an app that defines only what the kit asks it for and overrides nothing, and reports every error that app meets, on the kit's own line. It is the same composition osy validate checks in the kit's directory.

$ osy kits check kits/crates --offline
MUST KIT_DOES_NOT_COMPOSE  model/crates.osy:9  in an app that uses `Acme.Crates` and keeps every default it offers (no `virtual policy` overridden): a security policy predicate must be Boolean, but is 'string'

What a clean run says#

$ osy kits check kits/work-queues --offline
  · bridges that complete Osysharp.WorkQueues: Osysharp.WorkQueues.Notifications, Osysharp.WorkQueues.Reports
✓ Osysharp.WorkQueues (horizontal) — composable: it reaches no sibling vertical, names no member a bridge adds to it, and a test shows every seam.

See also#

Related

Bridges — a package that arrives when an app uses the two it completes

A bridge is a package whose manifest says `completes A@0, B@0;`. An app that uses every package it completes gets it…

package.osy

The manifest that makes a git repository a publishable Osy# package. It names the package, says which of the…

Finding a kit, and learning one from its tests

Lists the kits (packages) this project can build on — each one's contracts, the kits that implement them, and what this…

Connecting a kit — each seam with the code that connects it

Prints a kit's composition surface — every event, policy, setting, slot, contract, base, grant, extension member…

Extension members

A `partial entity X { … }` in a bridge package or in the app adds OPTIONAL members to an entity another package…