YouBothAgent▾
You — Business rules and flows you own. Read these yourself.
Both — Know the idea; your agent follows the details.
Agent — Conventions and references your agent follows. Look up as needed.
Workspace▾
App & Library▾
Domain▾
Scalar▾
scalar.abstract.md
Every scalar keeps one
lib/__scalar/<scalar>/<scalar>.abstract.md: a few lines of markdown about the value. A scalar is a value that something else holds, usually a model's field, so this file answers not what the value is, but what may be assumed about it.What May Be Assumed
Take
coordinate in libs/util. Its constant file and its abstract say different things about the same array.What The Constant File Shows
coordinates is an array of two floats.coordinates: field([Float], { default: [0, 0] })What Only The Abstract Says
Longitude comes first, the opposite of how almost everyone says a position out loud.
[127.114367, 37.497114] → [longitude, latitude]The Three Parts
A scalar abstract has three parts, and there is no fourth:
apps/koyo/lib/__scalar/price/price.abstract.md
PartDescription
# <scalar> Abstract
One title line with the scalar name spelled the way its folder spells it.
One sentence
What the value represents and, when it matters, who holds it, with no heading above.
## Rules
Two to five bullets: a fixed value, a field order, a unit, a lifetime, what a static computes.
- No workflow section. All 17 scalar abstracts in the Akan.js repository have these three parts, and none has a workflow. That is where a scalar differs from
model.abstract.md, whose optional fourth part is## Workflow. - A value has no lifecycle of its own. It is embedded in something else, so there is no flow of its own to describe.
- A state change still fits in one rule. When a held value does move between states, as
oauthRequestdoes, it is one## Rulesbullet:pending -> approved | denied, never back.
Writing The Rules
A bullet belongs in Rules only if a caller would get something wrong without it. One real abstract shows what that looks like.
A Real Example
The whole of
coordinate.abstract.md is eight lines, for a class with fourteen static helpers:libs/util/lib/__scalar/coordinate/coordinate.abstract.md
Four bullets, and each one is something a caller would otherwise get wrong:
| The rule says |
|---|
| ↳ Without it, a caller assumes |
type is always Point. |
That type is open and could hold another GeoJSON shape. |
coordinates is longitude, then latitude. |
| The spoken order, with latitude first. |
| Distance is spherical, and the 3D form folds in the altitude difference. |
| A flat-plane distance, or one that ignores altitude. |
| Bounds, center and zoom need a list of coordinates. |
That an empty list works, but computeCenterAndZoomFromLocations returns null. |
- Nothing the declaration already says. No bullet lists the fields or their types; each one says what
coordinate.constant.tscannot. - One language per file. Korean and English abstracts sit side by side in this repository (the
oauth*scalars are English), but a language switch inside one file is not.
What Earns A Bullet
Examples from the scalars in this repository, sorted by whether they belong in Rules:
Content
Write
Leave out
What the type cannot carry
A unit
✓
Kilometres rather than metres:
getDistanceKm and getDistanceM differ only by unit.An order
✓
Longitude before latitude in
coordinate.A match by position
✓
Each
fileMeta lines up with the uploaded file at the same index.A lifetime or a consumption rule
✓
For a held value: an
oauthGrant lives 60 seconds and is spent on first exchange, pass or fail.What a static computes
✓
Only when a caller could reasonably expect something else, such as a flat distance.
What the code already says
The field list
✓
The constant file already lists every field.
The types
✓
Each
field(...) declaration already states its type.That it is reusable
✓
Every scalar is reusable, so saying so tells the reader nothing.
✓Do thisNot this
Fill In The Scaffold
akan create-scalar writes the first abstract for you, called the scaffold. It already has the house shape: the title, a placeholder sentence and two placeholder rules. Every line in angle brackets is a prompt, and none of them survives the first real edit.What
akan create-scalar price writes:apps/koyo/lib/__scalar/price/price.abstract.md
What each line becomes:
| Scaffold |
|---|
| ↳ Becomes |
| # price Abstract |
| Written for you from the folder name. Keep it. |
| <One sentence …> |
| Replaced by the value this scalar holds and what embeds it, stated as fact. |
| ## Rules |
| Stays. Both placeholder bullets become what a caller may assume about the value, two to five in all. |
| A field's meaning |
Not here: a trailing comment beside the field in price.constant.ts. |
| Workflow |
| None: a value embedded in something else has no lifecycle of its own. |
- Field meaning lives beside the field. A trailing comment is where the next reader of that field looks, as in
oauthGrant.constant.ts:codeHash: field(String), // sha256 of the code; the code itself travels once, in the redirect
Keeping It Current
Read it before changing the scalar, and update it only when something callers rely on changes:
Change
Update
Leave
When what callers rely on changes
Validation meaning
✓
What counts as a valid value, such as the 1 to 5 satisfaction range in
leaveInfo.Public behavior
✓
What callers can observe, such as what a static returns.
Reuse rules
✓
How it combines with other scalars, as
accessLog stores its location as a coordinate.When only how the code looks changes
Formatting
✓
Whitespace and line breaks the formatter decides.
Imports
✓
Adding, removing or reordering imports.
Style
✓
A code style change that alters no behavior.
✓Do thisNot this