@anatomytool/validate 1.0.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.
Files changed (156) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +127 -0
  3. package/dist/canonical.d.ts +21 -0
  4. package/dist/canonical.d.ts.map +1 -0
  5. package/dist/canonical.js +76 -0
  6. package/dist/canonical.js.map +1 -0
  7. package/dist/checks/commands-no-test-warn.d.ts +6 -0
  8. package/dist/checks/commands-no-test-warn.d.ts.map +1 -0
  9. package/dist/checks/commands-no-test-warn.js +35 -0
  10. package/dist/checks/commands-no-test-warn.js.map +1 -0
  11. package/dist/checks/description-warn.d.ts +6 -0
  12. package/dist/checks/description-warn.d.ts.map +1 -0
  13. package/dist/checks/description-warn.js +23 -0
  14. package/dist/checks/description-warn.js.map +1 -0
  15. package/dist/checks/entry-point-alias-warn.d.ts +6 -0
  16. package/dist/checks/entry-point-alias-warn.d.ts.map +1 -0
  17. package/dist/checks/entry-point-alias-warn.js +25 -0
  18. package/dist/checks/entry-point-alias-warn.js.map +1 -0
  19. package/dist/checks/fingerprint-check.d.ts +6 -0
  20. package/dist/checks/fingerprint-check.d.ts.map +1 -0
  21. package/dist/checks/fingerprint-check.js +59 -0
  22. package/dist/checks/fingerprint-check.js.map +1 -0
  23. package/dist/checks/hash-check.d.ts +6 -0
  24. package/dist/checks/hash-check.d.ts.map +1 -0
  25. package/dist/checks/hash-check.js +36 -0
  26. package/dist/checks/hash-check.js.map +1 -0
  27. package/dist/checks/interface-form-check.d.ts +6 -0
  28. package/dist/checks/interface-form-check.d.ts.map +1 -0
  29. package/dist/checks/interface-form-check.js +66 -0
  30. package/dist/checks/interface-form-check.js.map +1 -0
  31. package/dist/checks/memory-dangling-ref-check.d.ts +6 -0
  32. package/dist/checks/memory-dangling-ref-check.d.ts.map +1 -0
  33. package/dist/checks/memory-dangling-ref-check.js +34 -0
  34. package/dist/checks/memory-dangling-ref-check.js.map +1 -0
  35. package/dist/checks/memory-fingerprint-check.d.ts +6 -0
  36. package/dist/checks/memory-fingerprint-check.d.ts.map +1 -0
  37. package/dist/checks/memory-fingerprint-check.js +20 -0
  38. package/dist/checks/memory-fingerprint-check.js.map +1 -0
  39. package/dist/checks/memory-supersession-check.d.ts +6 -0
  40. package/dist/checks/memory-supersession-check.d.ts.map +1 -0
  41. package/dist/checks/memory-supersession-check.js +61 -0
  42. package/dist/checks/memory-supersession-check.js.map +1 -0
  43. package/dist/checks/memory-verification-check.d.ts +6 -0
  44. package/dist/checks/memory-verification-check.d.ts.map +1 -0
  45. package/dist/checks/memory-verification-check.js +61 -0
  46. package/dist/checks/memory-verification-check.js.map +1 -0
  47. package/dist/checks/nested-path-escape.d.ts +6 -0
  48. package/dist/checks/nested-path-escape.d.ts.map +1 -0
  49. package/dist/checks/nested-path-escape.js +76 -0
  50. package/dist/checks/nested-path-escape.js.map +1 -0
  51. package/dist/checks/schema-check.d.ts +6 -0
  52. package/dist/checks/schema-check.d.ts.map +1 -0
  53. package/dist/checks/schema-check.js +32 -0
  54. package/dist/checks/schema-check.js.map +1 -0
  55. package/dist/checks/source-cross-check.d.ts +52 -0
  56. package/dist/checks/source-cross-check.d.ts.map +1 -0
  57. package/dist/checks/source-cross-check.js +473 -0
  58. package/dist/checks/source-cross-check.js.map +1 -0
  59. package/dist/checks/source-path-check.d.ts +6 -0
  60. package/dist/checks/source-path-check.d.ts.map +1 -0
  61. package/dist/checks/source-path-check.js +62 -0
  62. package/dist/checks/source-path-check.js.map +1 -0
  63. package/dist/checks/structure-path-check.d.ts +6 -0
  64. package/dist/checks/structure-path-check.d.ts.map +1 -0
  65. package/dist/checks/structure-path-check.js +31 -0
  66. package/dist/checks/structure-path-check.js.map +1 -0
  67. package/dist/checks/verify/ast-grep-verifier.d.ts +4 -0
  68. package/dist/checks/verify/ast-grep-verifier.d.ts.map +1 -0
  69. package/dist/checks/verify/ast-grep-verifier.js +153 -0
  70. package/dist/checks/verify/ast-grep-verifier.js.map +1 -0
  71. package/dist/checks/verify/detect-ast-grep.d.ts +9 -0
  72. package/dist/checks/verify/detect-ast-grep.d.ts.map +1 -0
  73. package/dist/checks/verify/detect-ast-grep.js +26 -0
  74. package/dist/checks/verify/detect-ast-grep.js.map +1 -0
  75. package/dist/checks/verify/detect-semgrep.d.ts +8 -0
  76. package/dist/checks/verify/detect-semgrep.d.ts.map +1 -0
  77. package/dist/checks/verify/detect-semgrep.js +36 -0
  78. package/dist/checks/verify/detect-semgrep.js.map +1 -0
  79. package/dist/checks/verify/glob-verifier.d.ts +5 -0
  80. package/dist/checks/verify/glob-verifier.d.ts.map +1 -0
  81. package/dist/checks/verify/glob-verifier.js +58 -0
  82. package/dist/checks/verify/glob-verifier.js.map +1 -0
  83. package/dist/checks/verify/semgrep-pattern-verifier.d.ts +4 -0
  84. package/dist/checks/verify/semgrep-pattern-verifier.d.ts.map +1 -0
  85. package/dist/checks/verify/semgrep-pattern-verifier.js +121 -0
  86. package/dist/checks/verify/semgrep-pattern-verifier.js.map +1 -0
  87. package/dist/checks/verify/semgrep-rule-file-verifier.d.ts +9 -0
  88. package/dist/checks/verify/semgrep-rule-file-verifier.d.ts.map +1 -0
  89. package/dist/checks/verify/semgrep-rule-file-verifier.js +151 -0
  90. package/dist/checks/verify/semgrep-rule-file-verifier.js.map +1 -0
  91. package/dist/checks/verify/types.d.ts +44 -0
  92. package/dist/checks/verify/types.d.ts.map +1 -0
  93. package/dist/checks/verify/types.js +6 -0
  94. package/dist/checks/verify/types.js.map +1 -0
  95. package/dist/checks/verify-check.d.ts +9 -0
  96. package/dist/checks/verify-check.d.ts.map +1 -0
  97. package/dist/checks/verify-check.js +67 -0
  98. package/dist/checks/verify-check.js.map +1 -0
  99. package/dist/discovery.d.ts +13 -0
  100. package/dist/discovery.d.ts.map +1 -0
  101. package/dist/discovery.js +82 -0
  102. package/dist/discovery.js.map +1 -0
  103. package/dist/errors.d.ts +38 -0
  104. package/dist/errors.d.ts.map +1 -0
  105. package/dist/errors.js +5 -0
  106. package/dist/errors.js.map +1 -0
  107. package/dist/index.d.ts +43 -0
  108. package/dist/index.d.ts.map +1 -0
  109. package/dist/index.js +81 -0
  110. package/dist/index.js.map +1 -0
  111. package/dist/memory.d.ts +19 -0
  112. package/dist/memory.d.ts.map +1 -0
  113. package/dist/memory.js +80 -0
  114. package/dist/memory.js.map +1 -0
  115. package/dist/parse.d.ts +17 -0
  116. package/dist/parse.d.ts.map +1 -0
  117. package/dist/parse.js +47 -0
  118. package/dist/parse.js.map +1 -0
  119. package/dist/schema-0.10.json +194 -0
  120. package/dist/schema-0.11.json +203 -0
  121. package/dist/schema-0.12.json +243 -0
  122. package/dist/schema-0.13.json +267 -0
  123. package/dist/schema-0.14.json +288 -0
  124. package/dist/schema-0.15.json +347 -0
  125. package/dist/schema-0.2.json +283 -0
  126. package/dist/schema-0.4.json +280 -0
  127. package/dist/schema-0.5.json +300 -0
  128. package/dist/schema-0.6.json +328 -0
  129. package/dist/schema-0.7.json +311 -0
  130. package/dist/schema-0.8.json +245 -0
  131. package/dist/schema-0.9.json +172 -0
  132. package/dist/schema-1.0.json +347 -0
  133. package/dist/schema-memory-0.1.json +43 -0
  134. package/dist/schema-memory-0.2.json +49 -0
  135. package/dist/schema-memory.d.ts +5 -0
  136. package/dist/schema-memory.d.ts.map +1 -0
  137. package/dist/schema-memory.js +16 -0
  138. package/dist/schema-memory.js.map +1 -0
  139. package/dist/schema.d.ts +6 -0
  140. package/dist/schema.d.ts.map +1 -0
  141. package/dist/schema.js +62 -0
  142. package/dist/schema.js.map +1 -0
  143. package/dist/schema.json +129 -0
  144. package/dist/types.d.ts +2 -0
  145. package/dist/types.d.ts.map +1 -0
  146. package/dist/types.generated.d.ts +1103 -0
  147. package/dist/types.generated.d.ts.map +1 -0
  148. package/dist/types.generated.js +7 -0
  149. package/dist/types.generated.js.map +1 -0
  150. package/dist/types.js +7 -0
  151. package/dist/types.js.map +1 -0
  152. package/dist/validate-tree.d.ts +20 -0
  153. package/dist/validate-tree.d.ts.map +1 -0
  154. package/dist/validate-tree.js +64 -0
  155. package/dist/validate-tree.js.map +1 -0
  156. package/package.json +48 -0
package/dist/parse.js ADDED
@@ -0,0 +1,47 @@
1
+ // src/parse.ts
2
+ // TOML parsing with TomlDate → ISO string normalization (so AJV's
3
+ // format: date-time validates the parsed JSON-equivalent model per
4
+ // the design Section 5).
5
+ import { parse as parseToml } from "smol-toml";
6
+ /**
7
+ * Parse a TOML string into its JSON-equivalent object model.
8
+ * smol-toml returns TomlDate (subclass of Date) for native datetimes;
9
+ * we normalize via Date.prototype.toISOString() so AJV's format:date-time
10
+ * validates the string representation. Returns a structured error on
11
+ * parse failure rather than throwing.
12
+ */
13
+ export function parseAnatomyToml(text) {
14
+ try {
15
+ const raw = parseToml(text);
16
+ return { ok: true, doc: normalizeDates(raw) };
17
+ }
18
+ catch (err) {
19
+ // smol-toml throws TomlError with `line` and `column` properties (1-based).
20
+ const e = err;
21
+ return {
22
+ ok: false,
23
+ error: {
24
+ code: "toml-parse-error",
25
+ message: e.message ?? String(err),
26
+ pointer: "",
27
+ source: typeof e.line === "number" && typeof e.column === "number"
28
+ ? { line: e.line, column: e.column }
29
+ : undefined,
30
+ },
31
+ };
32
+ }
33
+ }
34
+ function normalizeDates(value) {
35
+ if (value instanceof Date)
36
+ return value.toISOString();
37
+ if (Array.isArray(value))
38
+ return value.map(normalizeDates);
39
+ if (value && typeof value === "object") {
40
+ const out = {};
41
+ for (const [k, v] of Object.entries(value))
42
+ out[k] = normalizeDates(v);
43
+ return out;
44
+ }
45
+ return value;
46
+ }
47
+ //# sourceMappingURL=parse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.js","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"AAAA,eAAe;AACf,kEAAkE;AAClE,mEAAmE;AACnE,yBAAyB;AAEzB,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,WAAW,CAAC;AAO/C;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAC5B,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,cAAc,CAAC,GAAG,CAA4B,EAAE,CAAC;IAC3E,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,4EAA4E;QAC5E,MAAM,CAAC,GAAG,GAA2D,CAAC;QACtE,OAAO;YACL,EAAE,EAAE,KAAK;YACT,KAAK,EAAE;gBACL,IAAI,EAAE,kBAAkB;gBACxB,OAAO,EAAE,CAAC,CAAC,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC;gBACjC,OAAO,EAAE,EAAE;gBACX,MAAM,EACJ,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ;oBACxD,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;oBACpC,CAAC,CAAC,SAAS;aAChB;SACF,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,KAAc;IACpC,IAAI,KAAK,YAAY,IAAI;QAAE,OAAO,KAAK,CAAC,WAAW,EAAE,CAAC;IACtD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAC3D,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvC,MAAM,GAAG,GAA4B,EAAE,CAAC;QACxC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;YAAE,GAAG,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;QACvE,OAAO,GAAG,CAAC;IACb,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,194 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://anatomy.dev/spec/0.10/schema.json",
4
+ "title": "Anatomy",
5
+ "description": "Schema for .anatomy files (v0.10). Additive over v0.9: adds optional [generate] top-level section for per-repo render preferences (AGENTS.md emission, token budget, memory count). All [generate] fields are optional with defaults; v0.9 files migrate to v0.10 with no data change. The optional section conforms to the 'no derivable fields' rule — it holds per-repo human choices about rendering, not content an LLM could re-derive from source.",
6
+ "type": "object",
7
+ "required": ["anatomy_version", "tagline", "identity", "generated"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "anatomy_version": { "type": "string", "const": "0.10" },
11
+ "tagline": { "type": "string", "minLength": 1, "maxLength": 120, "pattern": "^[^\\n\\r]+$" },
12
+ "description": { "type": "string", "minLength": 1, "maxLength": 2000 },
13
+ "identity": { "$ref": "#/$defs/identity" },
14
+ "generated": { "$ref": "#/$defs/generated" },
15
+ "generate": { "$ref": "#/$defs/generate" },
16
+ "operation": { "$ref": "#/$defs/operation" },
17
+ "structure": { "$ref": "#/$defs/structure" },
18
+ "environment": { "$ref": "#/$defs/environment" },
19
+ "rules": {
20
+ "type": "array", "minItems": 1, "maxItems": 20,
21
+ "items": { "$ref": "#/$defs/rule" }
22
+ },
23
+ "flows": {
24
+ "type": "array", "minItems": 1, "maxItems": 15,
25
+ "items": { "$ref": "#/$defs/flow" }
26
+ },
27
+ "decisions": {
28
+ "type": "array", "minItems": 1, "maxItems": 15,
29
+ "items": { "$ref": "#/$defs/decision" }
30
+ }
31
+ },
32
+ "$defs": {
33
+ "identity": {
34
+ "type": "object",
35
+ "required": ["stack", "form", "domain", "function", "fingerprint"],
36
+ "additionalProperties": false,
37
+ "properties": {
38
+ "stack": { "type": "string", "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$", "maxLength": 40 },
39
+ "form": { "type": "string", "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$", "maxLength": 40 },
40
+ "domain": { "type": "string", "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$", "maxLength": 40 },
41
+ "function": { "type": "string", "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$", "maxLength": 40 },
42
+ "fingerprint": { "type": "string", "pattern": "^[a-z0-9]{20}$" }
43
+ }
44
+ },
45
+ "rule": {
46
+ "type": "object",
47
+ "required": ["rule"],
48
+ "additionalProperties": false,
49
+ "properties": {
50
+ "rule": { "type": "string", "minLength": 1, "maxLength": 300 },
51
+ "why": { "type": "string", "minLength": 1, "maxLength": 200 }
52
+ }
53
+ },
54
+ "flow": {
55
+ "type": "object",
56
+ "required": ["name", "summary"],
57
+ "additionalProperties": false,
58
+ "properties": {
59
+ "name": { "type": "string", "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$", "maxLength": 40 },
60
+ "summary": { "type": "string", "minLength": 1, "maxLength": 300, "pattern": "^[^\\n\\r]+$" }
61
+ }
62
+ },
63
+ "decision": {
64
+ "type": "object",
65
+ "required": ["topic", "reason"],
66
+ "additionalProperties": false,
67
+ "properties": {
68
+ "topic": { "type": "string", "minLength": 1, "maxLength": 120, "pattern": "^[^\\n\\r]+$" },
69
+ "reason": { "type": "string", "minLength": 1, "maxLength": 400 }
70
+ }
71
+ },
72
+ "generated": {
73
+ "type": "object",
74
+ "required": ["at", "by", "model", "schema"],
75
+ "additionalProperties": false,
76
+ "properties": {
77
+ "at": { "type": "string", "format": "date-time" },
78
+ "commit": { "type": "string", "pattern": "^[0-9a-f]{7,12}$" },
79
+ "by": { "type": "string", "minLength": 1 },
80
+ "model": { "type": "string", "minLength": 1 },
81
+ "schema": { "type": "string", "format": "uri" }
82
+ }
83
+ },
84
+ "generate": {
85
+ "type": "object",
86
+ "additionalProperties": false,
87
+ "description": "Per-repo render preferences. All fields optional with defaults. Holds human choice (uncapturable), not derivable content.",
88
+ "properties": {
89
+ "agents_md": {
90
+ "type": "boolean",
91
+ "description": "Emit AGENTS.md on `anatomy render` (default true)."
92
+ },
93
+ "agents_md_budget": {
94
+ "type": "integer",
95
+ "minimum": 500,
96
+ "description": "Token cap for the emitted AGENTS.md (default 1500)."
97
+ },
98
+ "agents_md_memory_count": {
99
+ "type": "integer",
100
+ "minimum": 0,
101
+ "description": "Max recent-memory entries surfaced in AGENTS.md (default 10)."
102
+ }
103
+ }
104
+ },
105
+ "operation": {
106
+ "type": "object",
107
+ "additionalProperties": false,
108
+ "properties": {
109
+ "entry_points": {
110
+ "type": "array", "maxItems": 10,
111
+ "items": { "$ref": "#/$defs/entry_point" }
112
+ },
113
+ "commands": {
114
+ "type": "object",
115
+ "propertyNames": { "pattern": "^[a-z0-9]+(-[a-z0-9]+)*(\\.[a-z0-9]+(-[a-z0-9]+)*)?$" },
116
+ "additionalProperties": { "type": "string", "minLength": 1, "maxLength": 200 },
117
+ "maxProperties": 25
118
+ },
119
+ "conventions": {
120
+ "type": "object",
121
+ "propertyNames": { "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$" },
122
+ "additionalProperties": { "type": "string", "minLength": 1, "maxLength": 120 },
123
+ "maxProperties": 15
124
+ }
125
+ }
126
+ },
127
+ "entry_point": {
128
+ "type": "object",
129
+ "required": ["path", "role"],
130
+ "additionalProperties": false,
131
+ "not": { "required": ["description", "purpose"] },
132
+ "properties": {
133
+ "path": { "type": "string", "minLength": 1, "maxLength": 256 },
134
+ "role": { "type": "string", "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$" },
135
+ "purpose": { "type": "string", "minLength": 1, "maxLength": 80, "pattern": "^[^\\n\\r]+$" },
136
+ "description": { "type": "string", "minLength": 1, "maxLength": 80, "pattern": "^[^\\n\\r]+$" }
137
+ }
138
+ },
139
+ "structure": {
140
+ "type": "object", "additionalProperties": false, "required": ["entries"],
141
+ "properties": {
142
+ "entries": {
143
+ "type": "array", "minItems": 1, "maxItems": 25,
144
+ "items": {
145
+ "type": "object", "required": ["path", "purpose", "kind"], "additionalProperties": false,
146
+ "properties": {
147
+ "path": { "type": "string", "minLength": 1, "maxLength": 256 },
148
+ "purpose": { "type": "string", "minLength": 1, "maxLength": 120, "pattern": "^[^\\n\\r]+$" },
149
+ "kind": { "enum": ["source", "tests", "docs", "config", "build", "scripts", "examples", "generated", "other"] },
150
+ "convention": { "type": "string", "minLength": 1, "maxLength": 200, "pattern": "^[^\\n\\r]+$" }
151
+ }
152
+ }
153
+ }
154
+ }
155
+ },
156
+ "environment": {
157
+ "type": "object", "additionalProperties": false,
158
+ "anyOf": [
159
+ { "required": ["language_version"] }, { "required": ["runtime"] },
160
+ { "required": ["os"] }, { "required": ["required_services"] }, { "required": ["required_env"] }
161
+ ],
162
+ "properties": {
163
+ "language_version": { "type": "string", "minLength": 1, "maxLength": 80 },
164
+ "runtime": { "type": "string", "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$", "maxLength": 40 },
165
+ "os": {
166
+ "oneOf": [
167
+ { "type": "array", "items": { "const": "any" }, "minItems": 1, "maxItems": 1 },
168
+ { "type": "array", "minItems": 1, "maxItems": 5, "uniqueItems": true, "items": { "enum": ["linux", "macos", "windows", "freebsd"] } }
169
+ ]
170
+ },
171
+ "required_services": {
172
+ "type": "array", "minItems": 1, "maxItems": 10,
173
+ "items": {
174
+ "type": "object", "required": ["name", "why"], "additionalProperties": false,
175
+ "properties": {
176
+ "name": { "type": "string", "minLength": 1, "maxLength": 80, "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$" },
177
+ "why": { "type": "string", "minLength": 1, "maxLength": 80 }
178
+ }
179
+ }
180
+ },
181
+ "required_env": {
182
+ "type": "array", "minItems": 1, "maxItems": 25,
183
+ "items": {
184
+ "type": "object", "required": ["name", "why"], "additionalProperties": false,
185
+ "properties": {
186
+ "name": { "type": "string", "minLength": 1, "maxLength": 80, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" },
187
+ "why": { "type": "string", "minLength": 1, "maxLength": 80 }
188
+ }
189
+ }
190
+ }
191
+ }
192
+ }
193
+ }
194
+ }
@@ -0,0 +1,203 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://anatomy.dev/spec/0.11/schema.json",
4
+ "title": "Anatomy",
5
+ "description": "Schema for .anatomy files (v0.11). Additive over v0.10: adds optional per-tool emit flags in [generate] for Cursor (.cursor/rules/anatomy.mdc + .cursorrules), Aider (CONVENTIONS.md), Cline (.clinerules), Roo Code (.roorules), Continue.dev (.continuerules), and Windsurf (.windsurfrules); plus shared render_budget and render_memory_count fields. All new fields are optional with default false / 1500 / 10. v0.10 files migrate to v0.11 with no data change.",
6
+ "type": "object",
7
+ "required": ["anatomy_version", "tagline", "identity", "generated"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "anatomy_version": { "type": "string", "const": "0.11" },
11
+ "tagline": { "type": "string", "minLength": 1, "maxLength": 120, "pattern": "^[^\\n\\r]+$" },
12
+ "description": { "type": "string", "minLength": 1, "maxLength": 2000 },
13
+ "identity": { "$ref": "#/$defs/identity" },
14
+ "generated": { "$ref": "#/$defs/generated" },
15
+ "generate": { "$ref": "#/$defs/generate" },
16
+ "operation": { "$ref": "#/$defs/operation" },
17
+ "structure": { "$ref": "#/$defs/structure" },
18
+ "environment": { "$ref": "#/$defs/environment" },
19
+ "rules": {
20
+ "type": "array", "minItems": 1, "maxItems": 20,
21
+ "items": { "$ref": "#/$defs/rule" }
22
+ },
23
+ "flows": {
24
+ "type": "array", "minItems": 1, "maxItems": 15,
25
+ "items": { "$ref": "#/$defs/flow" }
26
+ },
27
+ "decisions": {
28
+ "type": "array", "minItems": 1, "maxItems": 15,
29
+ "items": { "$ref": "#/$defs/decision" }
30
+ }
31
+ },
32
+ "$defs": {
33
+ "identity": {
34
+ "type": "object",
35
+ "required": ["stack", "form", "domain", "function", "fingerprint"],
36
+ "additionalProperties": false,
37
+ "properties": {
38
+ "stack": { "type": "string", "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$", "maxLength": 40 },
39
+ "form": { "type": "string", "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$", "maxLength": 40 },
40
+ "domain": { "type": "string", "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$", "maxLength": 40 },
41
+ "function": { "type": "string", "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$", "maxLength": 40 },
42
+ "fingerprint": { "type": "string", "pattern": "^[a-z0-9]{20}$" }
43
+ }
44
+ },
45
+ "rule": {
46
+ "type": "object",
47
+ "required": ["rule"],
48
+ "additionalProperties": false,
49
+ "properties": {
50
+ "rule": { "type": "string", "minLength": 1, "maxLength": 300 },
51
+ "why": { "type": "string", "minLength": 1, "maxLength": 200 }
52
+ }
53
+ },
54
+ "flow": {
55
+ "type": "object",
56
+ "required": ["name", "summary"],
57
+ "additionalProperties": false,
58
+ "properties": {
59
+ "name": { "type": "string", "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$", "maxLength": 40 },
60
+ "summary": { "type": "string", "minLength": 1, "maxLength": 300, "pattern": "^[^\\n\\r]+$" }
61
+ }
62
+ },
63
+ "decision": {
64
+ "type": "object",
65
+ "required": ["topic", "reason"],
66
+ "additionalProperties": false,
67
+ "properties": {
68
+ "topic": { "type": "string", "minLength": 1, "maxLength": 120, "pattern": "^[^\\n\\r]+$" },
69
+ "reason": { "type": "string", "minLength": 1, "maxLength": 400 }
70
+ }
71
+ },
72
+ "generated": {
73
+ "type": "object",
74
+ "required": ["at", "by", "model", "schema"],
75
+ "additionalProperties": false,
76
+ "properties": {
77
+ "at": { "type": "string", "format": "date-time" },
78
+ "commit": { "type": "string", "pattern": "^[0-9a-f]{7,12}$" },
79
+ "by": { "type": "string", "minLength": 1 },
80
+ "model": { "type": "string", "minLength": 1 },
81
+ "schema": { "type": "string", "format": "uri" }
82
+ }
83
+ },
84
+ "generate": {
85
+ "type": "object",
86
+ "additionalProperties": false,
87
+ "description": "Per-repo render preferences. All fields optional with defaults. Holds human choice (uncapturable), not derivable content. v0.11 adds per-tool emit flags (Cursor/Aider/Cline/Roo/Continue/Windsurf) plus a shared render_budget and render_memory_count for the new renderers.",
88
+ "properties": {
89
+ "agents_md": {
90
+ "type": "boolean",
91
+ "description": "Emit AGENTS.md on `anatomy render` (default true)."
92
+ },
93
+ "agents_md_budget": {
94
+ "type": "integer",
95
+ "minimum": 500,
96
+ "description": "Token cap for the emitted AGENTS.md (default 1500)."
97
+ },
98
+ "agents_md_memory_count": {
99
+ "type": "integer",
100
+ "minimum": 0,
101
+ "description": "Max recent-memory entries surfaced in AGENTS.md (default 10)."
102
+ },
103
+ "cursor_mdc": { "type": "boolean", "description": "Emit .cursor/rules/anatomy.mdc (default false)." },
104
+ "cursor_rules": { "type": "boolean", "description": "Emit .cursorrules (default false)." },
105
+ "aider_conventions": { "type": "boolean", "description": "Emit CONVENTIONS.md (default false)." },
106
+ "cline_rules": { "type": "boolean", "description": "Emit .clinerules (default false)." },
107
+ "roo_rules": { "type": "boolean", "description": "Emit .roorules (default false)." },
108
+ "continue_rules": { "type": "boolean", "description": "Emit .continuerules (default false)." },
109
+ "windsurf_rules": { "type": "boolean", "description": "Emit .windsurfrules (default false)." },
110
+ "render_budget": { "type": "integer", "minimum": 500, "description": "Token cap for all v0.11 renderers (default 1500)." },
111
+ "render_memory_count": { "type": "integer", "minimum": 0, "description": "Max memory entries for v0.11 renderers (default 10)." }
112
+ }
113
+ },
114
+ "operation": {
115
+ "type": "object",
116
+ "additionalProperties": false,
117
+ "properties": {
118
+ "entry_points": {
119
+ "type": "array", "maxItems": 10,
120
+ "items": { "$ref": "#/$defs/entry_point" }
121
+ },
122
+ "commands": {
123
+ "type": "object",
124
+ "propertyNames": { "pattern": "^[a-z0-9]+(-[a-z0-9]+)*(\\.[a-z0-9]+(-[a-z0-9]+)*)?$" },
125
+ "additionalProperties": { "type": "string", "minLength": 1, "maxLength": 200 },
126
+ "maxProperties": 25
127
+ },
128
+ "conventions": {
129
+ "type": "object",
130
+ "propertyNames": { "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$" },
131
+ "additionalProperties": { "type": "string", "minLength": 1, "maxLength": 120 },
132
+ "maxProperties": 15
133
+ }
134
+ }
135
+ },
136
+ "entry_point": {
137
+ "type": "object",
138
+ "required": ["path", "role"],
139
+ "additionalProperties": false,
140
+ "not": { "required": ["description", "purpose"] },
141
+ "properties": {
142
+ "path": { "type": "string", "minLength": 1, "maxLength": 256 },
143
+ "role": { "type": "string", "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$" },
144
+ "purpose": { "type": "string", "minLength": 1, "maxLength": 80, "pattern": "^[^\\n\\r]+$" },
145
+ "description": { "type": "string", "minLength": 1, "maxLength": 80, "pattern": "^[^\\n\\r]+$" }
146
+ }
147
+ },
148
+ "structure": {
149
+ "type": "object", "additionalProperties": false, "required": ["entries"],
150
+ "properties": {
151
+ "entries": {
152
+ "type": "array", "minItems": 1, "maxItems": 25,
153
+ "items": {
154
+ "type": "object", "required": ["path", "purpose", "kind"], "additionalProperties": false,
155
+ "properties": {
156
+ "path": { "type": "string", "minLength": 1, "maxLength": 256 },
157
+ "purpose": { "type": "string", "minLength": 1, "maxLength": 120, "pattern": "^[^\\n\\r]+$" },
158
+ "kind": { "enum": ["source", "tests", "docs", "config", "build", "scripts", "examples", "generated", "other"] },
159
+ "convention": { "type": "string", "minLength": 1, "maxLength": 200, "pattern": "^[^\\n\\r]+$" }
160
+ }
161
+ }
162
+ }
163
+ }
164
+ },
165
+ "environment": {
166
+ "type": "object", "additionalProperties": false,
167
+ "anyOf": [
168
+ { "required": ["language_version"] }, { "required": ["runtime"] },
169
+ { "required": ["os"] }, { "required": ["required_services"] }, { "required": ["required_env"] }
170
+ ],
171
+ "properties": {
172
+ "language_version": { "type": "string", "minLength": 1, "maxLength": 80 },
173
+ "runtime": { "type": "string", "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$", "maxLength": 40 },
174
+ "os": {
175
+ "oneOf": [
176
+ { "type": "array", "items": { "const": "any" }, "minItems": 1, "maxItems": 1 },
177
+ { "type": "array", "minItems": 1, "maxItems": 5, "uniqueItems": true, "items": { "enum": ["linux", "macos", "windows", "freebsd"] } }
178
+ ]
179
+ },
180
+ "required_services": {
181
+ "type": "array", "minItems": 1, "maxItems": 10,
182
+ "items": {
183
+ "type": "object", "required": ["name", "why"], "additionalProperties": false,
184
+ "properties": {
185
+ "name": { "type": "string", "minLength": 1, "maxLength": 80, "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$" },
186
+ "why": { "type": "string", "minLength": 1, "maxLength": 80 }
187
+ }
188
+ }
189
+ },
190
+ "required_env": {
191
+ "type": "array", "minItems": 1, "maxItems": 25,
192
+ "items": {
193
+ "type": "object", "required": ["name", "why"], "additionalProperties": false,
194
+ "properties": {
195
+ "name": { "type": "string", "minLength": 1, "maxLength": 80, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" },
196
+ "why": { "type": "string", "minLength": 1, "maxLength": 80 }
197
+ }
198
+ }
199
+ }
200
+ }
201
+ }
202
+ }
203
+ }