@metaobjectsdev/sdk 0.22.1 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -976,7 +976,28 @@ mapping).
976
976
 
977
977
  ## Requirements — capability ledger (opt-in)
978
978
 
979
- If this project declares `requirement.functional` / `requirement.architectural` nodes, read `references/requirements.md` for the full authoring rules.
979
+ **This capability exists whether or not the project uses it yet.** `requirement.functional` and `requirement.architectural` are registered metadata types, declared in `metaobjects/` beside the entities they describe and loaded by the same loader — no side file, no bespoke parser. They record *why* each part of the model exists, so a field with no reason to exist becomes visible as one.
980
+
981
+ Reach for it when the project needs to answer any of:
982
+
983
+ - **"Why is this field here?"** — an L5 requirement binds a claim to a specific member. Authoring these exhaustively is what surfaces columns nothing reads and vocabularies nobody documented.
984
+ - **"What is broken but known?"** — `@status: partial` plus `@disposition: accepted | deferred`. Absent disposition means *undecided*, and `meta verify` counts those: the gaps nobody has ruled on.
985
+ - **"What did we build and then retire?"** — `@status: abandoned` is the one status where a dangling `@implementedBy` is *correct*, so the record survives the deletion.
986
+ - **"What have we committed to build?"** — `@status: planned`. Its references may dangle, and it never counts toward object coverage.
987
+ - **"Which ticket covers this?"** — `@trackedBy`.
988
+
989
+ Every requirement must be **violable**: if you cannot say what breaking it looks like, it is a description, not a requirement.
990
+
991
+ If the project declares any `requirement.*` node, `references/requirements.md` is installed with the full authoring rules. If it does not and you are adding the first one, the shape is:
992
+
993
+ ```yaml
994
+ - requirement.architectural:
995
+ name: everyStoredRowIsAddressable
996
+ status: live
997
+ statement: Every persisted row declares the identity by which it is addressed.
998
+ violation: A row that can be inserted but never pointed at.
999
+ implementedBy: [acme::shop::Order]
1000
+ ```
980
1001
 
981
1002
  ---
982
1003
 
@@ -27,19 +27,63 @@ key. *"Things are persisted"* is not, and is a description rather than a require
27
27
  rule kills *"the system is reliable"*. If you cannot say what breaking it looks like,
28
28
  delete it.
29
29
 
30
- **Hierarchy is nesting, and links live at the bottom.** L1 solution, L2 segment (an
31
- application or library), L3 service these never reference the model. **L4** binds an
32
- object, **L5** binds a field, view or identity. `implementedBy` above L4 is an error.
33
- Regrouping *moves* a node; it does not edit a parent string.
30
+ **Four prose slots, and `statement` is the one that means "description".** A requirement can
31
+ also carry the common `title`, `description` and `notes`, and they overlap badly unless you
32
+ decide the split before writing any of them:
34
33
 
35
- **Architectural requirements are the other kind.** `requirement.architectural` carries no
36
- levela uuid-PK rule, change attribution, tenant scoping. Its check is *universality*
34
+ - `title` a short **noun-phrase** label (`name` is an identifier; this is what an index shows)
35
+ - `statement` **the claim**. This IS the description of what the requirement is
36
+ - `violation` — **the counterexample** that makes the claim checkable
37
+ - `description` — **the scope**: what the claim covers, what it deliberately does not, and
38
+ which sibling entry owns the rest
39
+ - `notes` — **the evidence**: how you know the `status` is true — citations, vocabularies, the
40
+ control you ran to prove an absence was real
41
+
42
+ Two failure modes, both of which look like diligence. A `description` that **paraphrases the
43
+ statement** is padding, and it makes every later reader trust the ledger less — leave it off
44
+ instead, it is optional. A `description` that **narrates the evidence** belongs in `notes`;
45
+ the tell is a fact you had to read the implementation to learn. Mechanical test for the last
46
+ line: *would this sentence have to change if the code changed but the model did not?* Then it
47
+ is `notes`.
48
+
49
+ **Hierarchy is nesting, and links live at the bottom.** L1 solution, L2 segment, L3
50
+ service — these never reference the model. **L4** binds an object, **L5** binds a field,
51
+ view or identity. `implementedBy` above L4 is an error. Regrouping *moves* a node; it does
52
+ not edit a parent string.
53
+
54
+ **L1–L3 are levels of abstraction and ownership in the problem domain** — whose need is
55
+ this, and at what altitude — and are NEVER a directory, package, deployable or module.
56
+ Technical constructs appear only at L4/L5, which is the allocation step. Test every node:
57
+ *if a refactor that changes no behaviour would force it to move, its level is wrong.*
58
+
59
+ **Architectural requirements are the other kind.** `requirement.architectural` is flat by
60
+ default — a uuid-PK rule, change attribution, tenant scoping. Its check is *universality*
37
61
  rather than existence, so one that is `live` and claimed by nothing fails: a policy
38
- declared and applied to nothing.
62
+ declared and applied to nothing. A `@level` is OPTIONAL here and opts the node into a tree
63
+ (for organising non-functional requirements under a quality taxonomy); once levelled, the
64
+ same nesting and link-floor rules apply as to a functional node.
39
65
 
40
66
  `@status` is a closed enum enforced by the loader, so a typo fails the load rather than
41
67
  silently disabling the entry.
42
68
 
69
+ **Record gaps rather than rounding them off.** `partial` says *this works and here is what
70
+ is wrong with it*, and it is the most useful status in the enum — a ledger with none is
71
+ usually one nobody read carefully. Then say what was DECIDED, which is a separate question:
72
+
73
+ - `@disposition: accepted` — understood, deliberately not being closed
74
+ - `@disposition: deferred` — will be closed, not now (name a ticket in `@trackedBy`, or
75
+ `verify` warns; deferring without one is how a known problem becomes an unknown one)
76
+ - **absent** — undecided, and that is a real state. `verify` counts these, because
77
+ *"which gaps has nobody ruled on?"* is the question a review exists to answer.
78
+
79
+ A `partial` nobody intends to finish is usually `abandoned` — built then deliberately
80
+ retired, the one status where a dangling reference is correct.
81
+
82
+ **`status: planned` locks in work you have not started.** Its references may dangle (write
83
+ the requirement before the entity), and it never counts toward object coverage — otherwise
84
+ declaring an intention would clear the unclaimed-entity warning and the gate would measure
85
+ ambition rather than work.
86
+
43
87
  ```yaml
44
88
  - requirement.functional:
45
89
  name: Pacing
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metaobjectsdev/sdk",
3
- "version": "0.22.1",
3
+ "version": "0.23.0",
4
4
  "description": "Workspace helpers and agent-docs utilities for MetaObjects projects.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -56,7 +56,7 @@
56
56
  "access": "public"
57
57
  },
58
58
  "dependencies": {
59
- "@metaobjectsdev/metadata": "0.22.1",
59
+ "@metaobjectsdev/metadata": "0.23.0",
60
60
  "zod": "^3.23.0"
61
61
  },
62
62
  "devDependencies": {