Skip to content

2. Conformance

Contents of ATD 0.1

2.1 Conformance classes

  • A description conforms to ATD 0.1 when every file of it parses with the grammar of section 4 under the version it declares (section 5.4) and the checker of section 14 reports no finding of severity error for it.
  • A checker conforms when, for every description, it reports exactly the findings of sections 14 and 15, by code, severity, file, line and column. The refused corpus beside this document (refused/, section 19.3) is the contract: a conforming checker gives each refused file exactly the findings its .findings.json states, and each example beside this document no finding.
  • A language server conforms when it reports, for the same text, the same diagnostics as a conforming checker (FR-054), and offers the capabilities FR-051 of spec 035 lists (colouring, completion, definition, references, rename, diagnostics, hover, formatting and an outline) in the parts of a file that parse when another part does not.
  • A runtime conforms when it runs a description that checks without errors, and, for every conformance fixture of that description, produces the readings, findings, splices, drawings and bytes the fixture states (section 2.3), with no code of its own for any tool type, apart from the capabilities of section 13.

2.2 Key words

The key words of the status section apply to every normative section. A requirement on "a reader" applies to a checker, a language server and a runtime alike.

2.3 Conformance fixtures

A conformance fixture is one case of one tool type: input files, the gestures made on them, and what the reference host produced for each. It extends FBL's round-trip fixture (FBL §15.3) with gestures, readings, findings, splices, drawings and the provenance of each part. A case is a folder definitions/<kind>s/conformance/<type>/<case>/ holding conformance.json (atd.schema.json#/$defs/ConformanceFixture) and its files.

  • tool is the tool type's origin; description the path of the root .atd, relative to the case's folder.
  • recordedFrom is the kind of host that recorded the case: module when the tool type's module opens its own documents, declared, the default, when the tool is drawn from its specification. A recorder MUST write module for a case recorded from such a module.
  • inputs names the input files by role (body, registration, and for a folder body each file); they are kept byte for byte, and Git never converts them (.gitattributes: -text).
  • read is what reading the inputs yields: the elements with their type, parent and the attributes compared; the relations with their ends; the findings (each with its rule or code and its line); and the parts the reader could not read.
  • drawing is the scene after reading (section 2.4), inline or as {"$ref": "<file>"} beside the case.
  • steps are the gestures, in order. A step has exactly one of action (with args, after select), property, move, create, connect, delete, outside, undo and redo, and states what it produces: splices (FBL $defs/Splice, UTF-8 byte offsets into the body before the step), the body's bytes after it (expect inline, or expectFile), findings, drawing, or refused with the reason the gesture was refused with. ids lists the ids the reference host generated in the step, in order; a runtime MUST be given them, in that order, in place of ids of its own, so that bytes can be equal.
  • A create step's type and a connect step's type name what the gesture is, as the tool's toolbox or its binding's wire form names it, or the element or relation type: a type alone cannot choose between tools that create one type. at is where a create lands. args.value answers a prompt the gesture raises; on an action, args.at is the canvas point it is made at. A connect to an end that does not exist yet carries that end as a create in the same step, the one exception to a step's having one gesture.
  • A step never carries a target string only one host understands. A gesture these steps cannot state is named when the case is recorded, and either ATD gains a step for it or the case leaves it out.
  • A refused reason is compared exactly, unless the case's is a host's or a module's own sentence that a gesture is not offered: Unknown action '<id>'., '<id>' does not apply to this selection., '<id>' cannot be edited on this selection. and That action is not available for this item., a closed set. Such a sentence says only that the tool refuses the step, and no description could have written it, so any reason given for refusing that step counts as the same refusal: the runtime's own sentence, or the description's own reason. A step one tool refuses and the other makes stays a difference, and a reason of the case's that is not one of these sentences is compared exactly.
  • A move step moves element to a place, x and y, by a distance from where it is drawn, dx and dy, or into parent: before the child at index there, counted among the parent's children as they are before the move, the element itself included, or after the last when index is -1 or absent, as the reference host's gesture placed it.
  • An outside step writes a file of the case as another program or an agent would, replacing the first occurrence of from in file by to, and tells the host the file changed, as its watcher does; the history starts afresh with it, so no step before it can be undone, and a refused step leaves the bytes as they were. A designer's gesture on its page is an action naming the operation, with the entry it is made on in select and the operation's parameters in args.
  • An undo MUST give back the bytes before the step it undoes exactly, and a redo the bytes after it.
  • provenance names, for each part (bytes, reading, findings, drawing), the host and repository that produced it, commit, the reference commit whose behaviour it records, recordedWith, for a recorded part the commit of the recorder, and source, a standalone host's golden or atd record. The reference host differs by part: the standalone host for bytes, as the desktop host's parity goldens record them, and the desktop host at its reference commit for readings, findings and drawings (spec 035, Q5). A tool type the desktop host did not have at its reference commit (the Hierarchical Requirement Designer, added by spec 036) takes its readings and findings from the desktop host at the commit that records them, which commit and recordedWith then both name. A designer's page has no recording painter, so a designer's case states no drawing.
  • A fixture changes only by recording it again, never by hand. A runtime passes a fixture when every part of every step equals what the fixture states, bytes byte for byte, a reading and a drawing recorded from a module as the next paragraph and section 2.4 compare them; a difference is reported with its step, its part, the expected and the actual value (for bytes, the first line that differs) and the construct of the description that produced the value (section 15.1, ATD9001).
  • A case whose recordedFrom is module states its reading in the module's own terms, so its read.elements and read.relations MUST be compared by what they mean, in place of exactly (spec 067, FR-012). Each is keyed by id. An element or relation the case states MUST be in the reading, with the same parent, source and target, unless the case's own drawing does not draw it and the reading does not have it: that is the module's own presentation, such as an element that stands for a view or a boundary. One the reading has and the case does not MUST be one the description's drawing does not draw, since a module reads the view it shows and a description the whole body. Values MUST be compared for the attributes both sides can state: those the description's model declares on the element's type, not derived, that the case states on some element or relation of its reading; an absent value is the empty text on either side, so neither side can drop a value unnoticed. A list of the reading whose case states attributes and has none of them in common with the description is a difference, counting only what an element or relation states beyond the names DISL §2.2 reserves and the painted values, the values a module writes for its own drawing: role, label, badges, width and height. A painted value the description does declare is compared like any other. type, and every other attribute, MUST NOT be compared. splices, bytes, findings and refused are compared exactly in every case, and a case recorded from a declared tool is compared exactly in every part.

fixtures/mindmap/basic/ beside this document is a worked example, written by hand for the example mindmap.atd: a read, one action and its undo.

2.4 Drawings

A drawing is the scene of one view after a reading or a step, in the vocabulary of the desktop host's scene (adp-scene), never pixels (atd.schema.json#/$defs/Drawing):

  • elements: each drawn element with its id, type, shape, bounds (x, y, w, h), labels (text, the font token, position), style (paints resolved to colours, with the token names they came from), children and state;
  • edges: each drawn edge with its id, type, source, target, route (points), markers and labels;
  • chrome: bands, notices, legends, headers and rulers;
  • order: the ids of everything drawn, in drawing order.

Positions and sizes are in the canvas's domain units, rounded to 0.01. Two drawings are equal when their elements and their edges are equal as sets keyed by id, their chrome is equal, and their order lists are equal. fixtures/mindmap/basic/drawing.read.json is a worked example.

A drawing recorded from a module that opens its own documents (recordedFrom is module, section 2.3) MUST be compared by which elements appear and where, in place of exactly: two drawings then agree when their elements have the same ids and the same bounds, and their edges the same ids, source and target. An element's type, shape, labels, style, children and state, an edge's type, route, markers and labels, the chrome and the order are the module's painting, and MUST NOT be compared.

2.5 Traces

A trace is the file <name>.trace.json beside a tool description (atd.schema.json#/$defs/Trace). It shows that the description is complete (FR-021 to FR-023):

  • companion names the type's companion file and the sections of it whose items the description must state, and, in reports, any further companion file beside it, such as a conversion's report, that is read with it. An item is each ### heading and each top-level list item under a named section, numbered from 1 in each section; its id is <section-slug>/<n>, the slug being the section's heading in lowercase with every run of other characters than letters and digits made one -.
  • items lists every item exactly once, with its text (the item's heading or the start of its line), and one of statedBy, the part of the description that states it; hostConcern, one of section 17's concerns, with its reason; or open, the address of the etalii.adp issue that adds to ATD the construct the item needs, with its reason, for an item no construct of this version can state. An open item is not stated: it records a gap of the language rather than of the description, and it is closed by the change that adds the construct, which states the item and drops open.
  • hostCode lists every behaviour read in a host's code at its reference commit: host, repository, commit, path, lines and a one-sentence behaviour, and either statedBy (the reference host's behaviour, which the description states), or divergesFrom (another host's behaviour that differs from the reference host's and is not stated; it names the statedBy of the reference behaviour the description states instead), or hostConcern with its reason, or open with its reason, the address of the etalii.adp issue that adds the construct the reference host's behaviour needs, for a behaviour no construct of this version can state.

A statedBy names a construct as <keyword> <name>, with the names of its enclosing constructs where one name is not enough (fn siblingName, operation addSibling, binding freeplane element node, notation node Node label text, capability layout.twoSidedTree, algorithm mindmap). Every statedBy and divergesFrom MUST resolve in the description (atd check --trace), and every item of the named sections MUST be traced exactly once (validate-examples.py). mindmap.trace.json with its companion mindmap.md is a worked example.

2.6 Capability contracts

A capability (section 13) is specified in capabilities/<name>/ beside this document:

  • contract.json (atd.schema.json#/$defs/Capability): its name (<extension point>.<algorithm or format>), its version (semver), its extensionPoint, its input and output (references to $defs of atd.schema.json), its args (each with its type, values, default and documentation), its laws (deterministic, pinnedStay, stable, readingNeverFails, minimalSplices, pure), its exceptions to the determinism of section 12.5 with their reasons, its fallback and its status (provisional, standard, deprecated);
  • fixtures/<case>.json ($defs/CapabilityFixture): an input, the args and the expected output.

A host MUST pass every fixture of a capability before it offers it. capabilities/layout.twoSidedTree/contract.json is a worked example; its fixtures are recorded from the code that lays the mind map out today.

Referenced from