apcore-js 0.5.0 → 0.7.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 (319) hide show
  1. package/README.md +1 -1
  2. package/dist/acl.d.ts +27 -0
  3. package/dist/acl.d.ts.map +1 -0
  4. package/dist/acl.js +175 -0
  5. package/dist/acl.js.map +1 -0
  6. package/dist/approval.d.ts +85 -0
  7. package/dist/approval.d.ts.map +1 -0
  8. package/dist/approval.js +73 -0
  9. package/dist/approval.js.map +1 -0
  10. package/dist/async-task.d.ts +90 -0
  11. package/dist/async-task.d.ts.map +1 -0
  12. package/dist/async-task.js +215 -0
  13. package/dist/async-task.js.map +1 -0
  14. package/dist/bindings.d.ts +12 -0
  15. package/dist/bindings.d.ts.map +1 -0
  16. package/dist/bindings.js +185 -0
  17. package/dist/bindings.js.map +1 -0
  18. package/dist/cancel.d.ts +14 -0
  19. package/dist/cancel.d.ts.map +1 -0
  20. package/dist/cancel.js +27 -0
  21. package/dist/cancel.js.map +1 -0
  22. package/dist/config.d.ts +9 -0
  23. package/dist/config.d.ts.map +1 -0
  24. package/dist/config.js +23 -0
  25. package/dist/config.js.map +1 -0
  26. package/dist/context.d.ts +50 -0
  27. package/dist/context.d.ts.map +1 -0
  28. package/dist/context.js +87 -0
  29. package/dist/context.js.map +1 -0
  30. package/dist/decorator.d.ts +57 -0
  31. package/dist/decorator.d.ts.map +1 -0
  32. package/dist/decorator.js +74 -0
  33. package/dist/decorator.js.map +1 -0
  34. package/dist/errors.d.ts +204 -0
  35. package/dist/errors.d.ts.map +1 -0
  36. package/dist/errors.js +364 -0
  37. package/dist/errors.js.map +1 -0
  38. package/dist/executor.d.ts +82 -0
  39. package/dist/executor.d.ts.map +1 -0
  40. package/dist/executor.js +489 -0
  41. package/dist/executor.js.map +1 -0
  42. package/dist/extensions.d.ts +58 -0
  43. package/dist/extensions.d.ts.map +1 -0
  44. package/dist/extensions.js +239 -0
  45. package/dist/extensions.js.map +1 -0
  46. package/{src/index.ts → dist/index.d.ts} +6 -63
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +45 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/middleware/adapters.d.ts +18 -0
  51. package/dist/middleware/adapters.d.ts.map +1 -0
  52. package/dist/middleware/adapters.js +25 -0
  53. package/dist/middleware/adapters.js.map +1 -0
  54. package/dist/middleware/base.d.ts +10 -0
  55. package/dist/middleware/base.d.ts.map +1 -0
  56. package/dist/middleware/base.js +15 -0
  57. package/dist/middleware/base.js.map +1 -0
  58. package/{src/middleware/index.ts → dist/middleware/index.d.ts} +1 -0
  59. package/dist/middleware/index.d.ts.map +1 -0
  60. package/dist/middleware/index.js +5 -0
  61. package/dist/middleware/index.js.map +1 -0
  62. package/dist/middleware/logging.d.ts +25 -0
  63. package/dist/middleware/logging.d.ts.map +1 -0
  64. package/dist/middleware/logging.js +64 -0
  65. package/dist/middleware/logging.js.map +1 -0
  66. package/dist/middleware/manager.d.ts +21 -0
  67. package/dist/middleware/manager.d.ts.map +1 -0
  68. package/dist/middleware/manager.js +77 -0
  69. package/dist/middleware/manager.js.map +1 -0
  70. package/dist/module.d.ts +31 -0
  71. package/dist/module.d.ts.map +1 -0
  72. package/dist/module.js +12 -0
  73. package/dist/module.js.map +1 -0
  74. package/dist/observability/context-logger.d.ts +54 -0
  75. package/dist/observability/context-logger.d.ts.map +1 -0
  76. package/dist/observability/context-logger.js +151 -0
  77. package/dist/observability/context-logger.js.map +1 -0
  78. package/{src/observability/index.ts → dist/observability/index.d.ts} +1 -0
  79. package/dist/observability/index.d.ts.map +1 -0
  80. package/dist/observability/index.js +4 -0
  81. package/dist/observability/index.js.map +1 -0
  82. package/dist/observability/metrics.d.ts +30 -0
  83. package/dist/observability/metrics.d.ts.map +1 -0
  84. package/dist/observability/metrics.js +177 -0
  85. package/dist/observability/metrics.js.map +1 -0
  86. package/dist/observability/tracing.d.ts +62 -0
  87. package/dist/observability/tracing.d.ts.map +1 -0
  88. package/dist/observability/tracing.js +184 -0
  89. package/dist/observability/tracing.js.map +1 -0
  90. package/dist/registry/dependencies.d.ts +6 -0
  91. package/dist/registry/dependencies.d.ts.map +1 -0
  92. package/dist/registry/dependencies.js +83 -0
  93. package/dist/registry/dependencies.js.map +1 -0
  94. package/dist/registry/entry-point.d.ts +6 -0
  95. package/dist/registry/entry-point.d.ts.map +1 -0
  96. package/dist/registry/entry-point.js +55 -0
  97. package/dist/registry/entry-point.js.map +1 -0
  98. package/{src/registry/index.ts → dist/registry/index.d.ts} +1 -0
  99. package/dist/registry/index.d.ts.map +1 -0
  100. package/dist/registry/index.js +8 -0
  101. package/dist/registry/index.js.map +1 -0
  102. package/dist/registry/metadata.d.ts +9 -0
  103. package/dist/registry/metadata.d.ts.map +1 -0
  104. package/dist/registry/metadata.js +105 -0
  105. package/dist/registry/metadata.js.map +1 -0
  106. package/dist/registry/registry.d.ts +102 -0
  107. package/dist/registry/registry.d.ts.map +1 -0
  108. package/dist/registry/registry.js +534 -0
  109. package/dist/registry/registry.js.map +1 -0
  110. package/dist/registry/scanner.d.ts +7 -0
  111. package/dist/registry/scanner.d.ts.map +1 -0
  112. package/dist/registry/scanner.js +164 -0
  113. package/dist/registry/scanner.js.map +1 -0
  114. package/dist/registry/schema-export.d.ts +9 -0
  115. package/dist/registry/schema-export.d.ts.map +1 -0
  116. package/dist/registry/schema-export.js +132 -0
  117. package/dist/registry/schema-export.js.map +1 -0
  118. package/dist/registry/types.d.ts +29 -0
  119. package/dist/registry/types.d.ts.map +1 -0
  120. package/dist/registry/types.js +5 -0
  121. package/dist/registry/types.js.map +1 -0
  122. package/dist/registry/validation.d.ts +9 -0
  123. package/dist/registry/validation.d.ts.map +1 -0
  124. package/dist/registry/validation.js +33 -0
  125. package/dist/registry/validation.js.map +1 -0
  126. package/dist/schema/annotations.d.ts +8 -0
  127. package/dist/schema/annotations.d.ts.map +1 -0
  128. package/dist/schema/annotations.js +52 -0
  129. package/dist/schema/annotations.js.map +1 -0
  130. package/dist/schema/exporter.d.ts +13 -0
  131. package/dist/schema/exporter.d.ts.map +1 -0
  132. package/dist/schema/exporter.js +71 -0
  133. package/dist/schema/exporter.js.map +1 -0
  134. package/dist/schema/index.d.ts +9 -0
  135. package/dist/schema/index.d.ts.map +1 -0
  136. package/{src/schema/index.ts → dist/schema/index.js} +1 -7
  137. package/dist/schema/index.js.map +1 -0
  138. package/dist/schema/loader.d.ts +30 -0
  139. package/dist/schema/loader.d.ts.map +1 -0
  140. package/dist/schema/loader.js +260 -0
  141. package/dist/schema/loader.js.map +1 -0
  142. package/dist/schema/ref-resolver.d.ts +19 -0
  143. package/dist/schema/ref-resolver.d.ts.map +1 -0
  144. package/dist/schema/ref-resolver.js +212 -0
  145. package/dist/schema/ref-resolver.js.map +1 -0
  146. package/dist/schema/strict.d.ts +7 -0
  147. package/dist/schema/strict.d.ts.map +1 -0
  148. package/dist/schema/strict.js +127 -0
  149. package/dist/schema/strict.js.map +1 -0
  150. package/dist/schema/types.d.ts +53 -0
  151. package/dist/schema/types.d.ts.map +1 -0
  152. package/dist/schema/types.js +31 -0
  153. package/dist/schema/types.js.map +1 -0
  154. package/dist/schema/validator.d.ts +16 -0
  155. package/dist/schema/validator.d.ts.map +1 -0
  156. package/dist/schema/validator.js +71 -0
  157. package/dist/schema/validator.js.map +1 -0
  158. package/dist/trace-context.d.ts +35 -0
  159. package/dist/trace-context.d.ts.map +1 -0
  160. package/dist/trace-context.js +86 -0
  161. package/dist/trace-context.js.map +1 -0
  162. package/dist/utils/index.d.ts +11 -0
  163. package/dist/utils/index.d.ts.map +1 -0
  164. package/dist/utils/index.js +32 -0
  165. package/dist/utils/index.js.map +1 -0
  166. package/dist/utils/pattern.d.ts +5 -0
  167. package/dist/utils/pattern.d.ts.map +1 -0
  168. package/dist/utils/pattern.js +31 -0
  169. package/dist/utils/pattern.js.map +1 -0
  170. package/package.json +24 -3
  171. package/.claude/settings.local.json +0 -12
  172. package/.github/workflows/ci.yml +0 -39
  173. package/.gitmessage +0 -60
  174. package/.pre-commit-config.yaml +0 -28
  175. package/CHANGELOG.md +0 -214
  176. package/CLAUDE.md +0 -68
  177. package/apcore-logo.svg +0 -79
  178. package/planning/acl-system/overview.md +0 -54
  179. package/planning/acl-system/plan.md +0 -92
  180. package/planning/acl-system/state.json +0 -76
  181. package/planning/acl-system/tasks/acl-core.md +0 -226
  182. package/planning/acl-system/tasks/acl-rule.md +0 -92
  183. package/planning/acl-system/tasks/conditional-rules.md +0 -259
  184. package/planning/acl-system/tasks/pattern-matching.md +0 -152
  185. package/planning/acl-system/tasks/yaml-loading.md +0 -271
  186. package/planning/core-executor/overview.md +0 -53
  187. package/planning/core-executor/plan.md +0 -88
  188. package/planning/core-executor/state.json +0 -76
  189. package/planning/core-executor/tasks/async-support.md +0 -106
  190. package/planning/core-executor/tasks/execution-pipeline.md +0 -113
  191. package/planning/core-executor/tasks/redaction.md +0 -85
  192. package/planning/core-executor/tasks/safety-checks.md +0 -65
  193. package/planning/core-executor/tasks/setup.md +0 -75
  194. package/planning/decorator-bindings/overview.md +0 -62
  195. package/planning/decorator-bindings/plan.md +0 -104
  196. package/planning/decorator-bindings/state.json +0 -87
  197. package/planning/decorator-bindings/tasks/binding-directory.md +0 -79
  198. package/planning/decorator-bindings/tasks/binding-loader.md +0 -148
  199. package/planning/decorator-bindings/tasks/explicit-schemas.md +0 -85
  200. package/planning/decorator-bindings/tasks/function-module.md +0 -127
  201. package/planning/decorator-bindings/tasks/module-factory.md +0 -89
  202. package/planning/decorator-bindings/tasks/schema-modes.md +0 -142
  203. package/planning/middleware-system/overview.md +0 -48
  204. package/planning/middleware-system/plan.md +0 -102
  205. package/planning/middleware-system/state.json +0 -65
  206. package/planning/middleware-system/tasks/adapters.md +0 -170
  207. package/planning/middleware-system/tasks/base.md +0 -115
  208. package/planning/middleware-system/tasks/logging-middleware.md +0 -304
  209. package/planning/middleware-system/tasks/manager.md +0 -313
  210. package/planning/observability/overview.md +0 -53
  211. package/planning/observability/plan.md +0 -119
  212. package/planning/observability/state.json +0 -98
  213. package/planning/observability/tasks/context-logger.md +0 -201
  214. package/planning/observability/tasks/exporters.md +0 -121
  215. package/planning/observability/tasks/metrics-collector.md +0 -162
  216. package/planning/observability/tasks/metrics-middleware.md +0 -141
  217. package/planning/observability/tasks/obs-logging-middleware.md +0 -179
  218. package/planning/observability/tasks/span-model.md +0 -120
  219. package/planning/observability/tasks/tracing-middleware.md +0 -179
  220. package/planning/overview.md +0 -81
  221. package/planning/registry-system/overview.md +0 -57
  222. package/planning/registry-system/plan.md +0 -114
  223. package/planning/registry-system/state.json +0 -109
  224. package/planning/registry-system/tasks/dependencies.md +0 -157
  225. package/planning/registry-system/tasks/entry-point.md +0 -148
  226. package/planning/registry-system/tasks/metadata.md +0 -198
  227. package/planning/registry-system/tasks/registry-core.md +0 -323
  228. package/planning/registry-system/tasks/scanner.md +0 -172
  229. package/planning/registry-system/tasks/schema-export.md +0 -261
  230. package/planning/registry-system/tasks/types.md +0 -124
  231. package/planning/registry-system/tasks/validation.md +0 -177
  232. package/planning/schema-system/overview.md +0 -56
  233. package/planning/schema-system/plan.md +0 -121
  234. package/planning/schema-system/state.json +0 -98
  235. package/planning/schema-system/tasks/exporter.md +0 -153
  236. package/planning/schema-system/tasks/loader.md +0 -106
  237. package/planning/schema-system/tasks/ref-resolver.md +0 -133
  238. package/planning/schema-system/tasks/strict-mode.md +0 -140
  239. package/planning/schema-system/tasks/typebox-generation.md +0 -133
  240. package/planning/schema-system/tasks/types-and-annotations.md +0 -160
  241. package/planning/schema-system/tasks/validator.md +0 -149
  242. package/src/acl.ts +0 -200
  243. package/src/async-task.ts +0 -267
  244. package/src/bindings.ts +0 -207
  245. package/src/cancel.ts +0 -32
  246. package/src/config.ts +0 -24
  247. package/src/context.ts +0 -160
  248. package/src/decorator.ts +0 -110
  249. package/src/errors.ts +0 -429
  250. package/src/executor.ts +0 -493
  251. package/src/extensions.ts +0 -265
  252. package/src/middleware/adapters.ts +0 -54
  253. package/src/middleware/base.ts +0 -33
  254. package/src/middleware/logging.ts +0 -103
  255. package/src/middleware/manager.ts +0 -105
  256. package/src/module.ts +0 -43
  257. package/src/observability/context-logger.ts +0 -203
  258. package/src/observability/metrics.ts +0 -214
  259. package/src/observability/tracing.ts +0 -252
  260. package/src/registry/dependencies.ts +0 -99
  261. package/src/registry/entry-point.ts +0 -64
  262. package/src/registry/metadata.ts +0 -111
  263. package/src/registry/registry.ts +0 -580
  264. package/src/registry/scanner.ts +0 -168
  265. package/src/registry/schema-export.ts +0 -181
  266. package/src/registry/types.ts +0 -32
  267. package/src/registry/validation.ts +0 -38
  268. package/src/schema/annotations.ts +0 -68
  269. package/src/schema/exporter.ts +0 -90
  270. package/src/schema/loader.ts +0 -273
  271. package/src/schema/ref-resolver.ts +0 -244
  272. package/src/schema/strict.ts +0 -136
  273. package/src/schema/types.ts +0 -73
  274. package/src/schema/validator.ts +0 -82
  275. package/src/trace-context.ts +0 -102
  276. package/src/utils/index.ts +0 -5
  277. package/src/utils/pattern.ts +0 -30
  278. package/tests/async-task.test.ts +0 -335
  279. package/tests/helpers.ts +0 -30
  280. package/tests/integration/test-acl-safety.test.ts +0 -269
  281. package/tests/integration/test-binding-executor.test.ts +0 -194
  282. package/tests/integration/test-e2e-flow.test.ts +0 -117
  283. package/tests/integration/test-error-propagation.test.ts +0 -259
  284. package/tests/integration/test-middleware-chain.test.ts +0 -120
  285. package/tests/integration/test-observability-integration.test.ts +0 -438
  286. package/tests/observability/test-context-logger.test.ts +0 -123
  287. package/tests/observability/test-metrics.test.ts +0 -186
  288. package/tests/observability/test-tracing.test.ts +0 -303
  289. package/tests/registry/test-dependencies.test.ts +0 -70
  290. package/tests/registry/test-entry-point.test.ts +0 -133
  291. package/tests/registry/test-metadata.test.ts +0 -265
  292. package/tests/registry/test-registry.test.ts +0 -1397
  293. package/tests/registry/test-scanner.test.ts +0 -257
  294. package/tests/registry/test-schema-export.test.ts +0 -355
  295. package/tests/registry/test-validation.test.ts +0 -75
  296. package/tests/schema/test-annotations.test.ts +0 -137
  297. package/tests/schema/test-exporter.test.ts +0 -172
  298. package/tests/schema/test-loader.test.ts +0 -461
  299. package/tests/schema/test-ref-resolver.test.ts +0 -530
  300. package/tests/schema/test-strict.test.ts +0 -348
  301. package/tests/schema/test-validator.test.ts +0 -64
  302. package/tests/test-acl.test.ts +0 -423
  303. package/tests/test-bindings.test.ts +0 -227
  304. package/tests/test-cancel.test.ts +0 -71
  305. package/tests/test-config.test.ts +0 -76
  306. package/tests/test-context.test.ts +0 -266
  307. package/tests/test-decorator.test.ts +0 -173
  308. package/tests/test-errors.test.ts +0 -647
  309. package/tests/test-executor-stream.test.ts +0 -208
  310. package/tests/test-executor.test.ts +0 -252
  311. package/tests/test-extensions.test.ts +0 -310
  312. package/tests/test-logging-middleware.test.ts +0 -150
  313. package/tests/test-middleware-manager.test.ts +0 -185
  314. package/tests/test-middleware.test.ts +0 -86
  315. package/tests/test-trace-context.test.ts +0 -251
  316. package/tests/utils/test-pattern.test.ts +0 -109
  317. package/tsconfig.build.json +0 -8
  318. package/tsconfig.json +0 -20
  319. package/vitest.config.ts +0 -18
@@ -1,140 +0,0 @@
1
- # Task: Strict Mode
2
-
3
- ## Goal
4
-
5
- Implement the strict-mode transformation utilities for converting JSON Schemas to OpenAI-compatible strict mode format (Algorithm A23). This includes `toStrictSchema()` for full strict conversion, `stripExtensions()` for removing vendor extensions and defaults, and `applyLlmDescriptions()` for substituting `x-llm-description` into `description` fields.
6
-
7
- ## Files Involved
8
-
9
- - `src/schema/strict.ts` -- `toStrictSchema()`, `stripExtensions()`, `applyLlmDescriptions()`, internal `convertToStrict()`
10
- - `tests/schema/test-strict.test.ts` -- Unit tests
11
-
12
- ## Steps
13
-
14
- ### 1. Implement deepCopy utility
15
-
16
- ```typescript
17
- function deepCopy<T>(obj: T): T {
18
- return JSON.parse(JSON.stringify(obj));
19
- }
20
- ```
21
-
22
- Used internally to ensure all transformations operate on copies, never mutating the original schema.
23
-
24
- ### 2. Implement applyLlmDescriptions()
25
-
26
- Recursively walk the schema tree. At each object node, if both `x-llm-description` and `description` exist, replace `description` with the value of `x-llm-description`. Recurse into `properties`, `items`, `oneOf`/`anyOf`/`allOf`, and `definitions`/`$defs`.
27
-
28
- ```typescript
29
- export function applyLlmDescriptions(node: unknown): void {
30
- if (typeof node !== 'object' || node === null || Array.isArray(node)) return;
31
-
32
- const obj = node as Record<string, unknown>;
33
- if ('x-llm-description' in obj && 'description' in obj) {
34
- obj['description'] = obj['x-llm-description'];
35
- }
36
-
37
- if ('properties' in obj && typeof obj['properties'] === 'object' && obj['properties'] !== null) {
38
- for (const prop of Object.values(obj['properties'] as Record<string, unknown>)) {
39
- applyLlmDescriptions(prop);
40
- }
41
- }
42
- // ... recurse into items, oneOf, anyOf, allOf, definitions, $defs
43
- }
44
- ```
45
-
46
- TDD: Test root-level description replacement. Test nested property description replacement. Test no-op when `x-llm-description` is absent.
47
-
48
- ### 3. Implement stripExtensions()
49
-
50
- Recursively remove all keys starting with `x-` and the `default` key from every object node. Recurse into all nested objects and arrays.
51
-
52
- ```typescript
53
- export function stripExtensions(node: unknown): void {
54
- if (typeof node !== 'object' || node === null || Array.isArray(node)) return;
55
-
56
- const obj = node as Record<string, unknown>;
57
- const keysToRemove = Object.keys(obj).filter(
58
- (k) => (typeof k === 'string' && k.startsWith('x-')) || k === 'default',
59
- );
60
- for (const k of keysToRemove) {
61
- delete obj[k];
62
- }
63
-
64
- for (const value of Object.values(obj)) {
65
- if (typeof value === 'object' && value !== null) {
66
- if (Array.isArray(value)) {
67
- for (const item of value) {
68
- if (typeof item === 'object' && item !== null) {
69
- stripExtensions(item);
70
- }
71
- }
72
- } else {
73
- stripExtensions(value);
74
- }
75
- }
76
- }
77
- }
78
- ```
79
-
80
- TDD: Test `x-sensitive`, `x-custom`, `x-llm-description` are removed. Test `default` is removed. Test nested structures are processed. Test non-extension keys survive.
81
-
82
- ### 4. Implement convertToStrict() (internal)
83
-
84
- For each object node with `type: "object"` and `properties`:
85
- 1. Set `additionalProperties: false`
86
- 2. Collect existing `required` array into a Set
87
- 3. Find optional properties (not in `required`)
88
- 4. For optional properties with a `type` field: wrap type in array with `"null"` (e.g., `"string"` -> `["string", "null"]`)
89
- 5. For optional properties without a `type` field: wrap in `{ oneOf: [originalSchema, { type: "null" }] }`
90
- 6. Set `required` to sorted array of ALL property names
91
-
92
- Recurse into `properties`, `items`, `oneOf`/`anyOf`/`allOf`, and `definitions`/`$defs`.
93
-
94
- ```typescript
95
- function convertToStrict(node: unknown): void {
96
- // ... see implementation in src/schema/strict.ts
97
- }
98
- ```
99
-
100
- TDD: Test `additionalProperties: false` is added. Test all properties become required. Test optional properties get null-union wrapping. Test already-required properties keep their original type.
101
-
102
- ### 5. Implement toStrictSchema() composition
103
-
104
- Compose the three operations: deep-copy, strip extensions, then convert to strict.
105
-
106
- ```typescript
107
- export function toStrictSchema(schema: Record<string, unknown>): Record<string, unknown> {
108
- const result = deepCopy(schema);
109
- stripExtensions(result);
110
- convertToStrict(result);
111
- return result;
112
- }
113
- ```
114
-
115
- TDD: Test that the original schema is not mutated. Test full pipeline: extensions removed, `additionalProperties: false` set, all required, optionals nullable.
116
-
117
- ## Acceptance Criteria
118
-
119
- - [x] `applyLlmDescriptions()` replaces `description` with `x-llm-description` where both exist
120
- - [x] `applyLlmDescriptions()` recurses into `properties`, `items`, `oneOf`/`anyOf`/`allOf`, `definitions`/`$defs`
121
- - [x] `applyLlmDescriptions()` is a no-op when `x-llm-description` is absent
122
- - [x] `stripExtensions()` removes all `x-` prefixed keys recursively
123
- - [x] `stripExtensions()` removes `default` keys recursively
124
- - [x] `stripExtensions()` preserves non-extension keys
125
- - [x] `stripExtensions()` handles nested objects and arrays
126
- - [x] `toStrictSchema()` sets `additionalProperties: false` on all object schemas
127
- - [x] `toStrictSchema()` makes all properties required (sorted alphabetically)
128
- - [x] `toStrictSchema()` wraps optional type-bearing properties with null type array
129
- - [x] `toStrictSchema()` wraps optional non-type properties with `oneOf` null union
130
- - [x] `toStrictSchema()` does not mutate the original schema (returns deep copy)
131
- - [x] `toStrictSchema()` strips extensions before strict conversion
132
- - [x] All tests pass with `vitest`
133
-
134
- ## Dependencies
135
-
136
- - None (standalone utility, no internal dependencies)
137
-
138
- ## Estimated Time
139
-
140
- 2 hours
@@ -1,133 +0,0 @@
1
- # Task: TypeBox Generation
2
-
3
- ## Goal
4
-
5
- Implement the `jsonSchemaToTypeBox()` function that recursively converts a JSON Schema dictionary to a TypeBox `TSchema` object. This is the TypeScript equivalent of the Python `create_model()` approach, leveraging the fact that TypeBox schemas ARE valid JSON Schema.
6
-
7
- ## Files Involved
8
-
9
- - `src/schema/loader.ts` -- `jsonSchemaToTypeBox()` function (exported, co-located with SchemaLoader)
10
- - `tests/schema/test-loader.test.ts` -- Unit tests for `jsonSchemaToTypeBox()`
11
-
12
- ## Steps
13
-
14
- ### 1. Handle object type with properties
15
-
16
- Convert `{ type: "object", properties: {...}, required: [...] }` to `Type.Object({...})`. Recursively convert each property. Wrap non-required properties with `Type.Optional()`.
17
-
18
- ```typescript
19
- if (schemaType === 'object') {
20
- const properties = schema['properties'] as Record<string, Record<string, unknown>> | undefined;
21
- const required = new Set((schema['required'] as string[]) ?? []);
22
-
23
- if (properties) {
24
- const typeboxProps: Record<string, TSchema> = {};
25
- for (const [name, propSchema] of Object.entries(properties)) {
26
- const propType = jsonSchemaToTypeBox(propSchema);
27
- typeboxProps[name] = required.has(name) ? propType : Type.Optional(propType);
28
- }
29
- return Type.Object(typeboxProps);
30
- }
31
- return Type.Record(Type.String(), Type.Unknown());
32
- }
33
- ```
34
-
35
- TDD: Test object with required and optional properties. Verify `Value.Check()` accepts valid data and rejects missing required fields.
36
-
37
- ### 2. Handle object type without properties
38
-
39
- Convert `{ type: "object" }` (no properties) to `Type.Record(Type.String(), Type.Unknown())`, accepting any string-keyed object.
40
-
41
- TDD: Test that `{ any: "value" }` passes validation.
42
-
43
- ### 3. Handle array type
44
-
45
- Convert `{ type: "array", items: {...} }` to `Type.Array(jsonSchemaToTypeBox(items))`. Without items, use `Type.Array(Type.Unknown())`.
46
-
47
- ```typescript
48
- if (schemaType === 'array') {
49
- const items = schema['items'] as Record<string, unknown> | undefined;
50
- return items ? Type.Array(jsonSchemaToTypeBox(items)) : Type.Array(Type.Unknown());
51
- }
52
- ```
53
-
54
- TDD: Test typed array (string items), untyped array, valid and invalid data.
55
-
56
- ### 4. Handle string type with constraints
57
-
58
- Convert `{ type: "string" }` to `Type.String()`. Pass through constraint options: `minLength`, `maxLength`, `pattern`, `format`.
59
-
60
- ```typescript
61
- if (schemaType === 'string') {
62
- const opts: Record<string, unknown> = {};
63
- if ('minLength' in schema) opts['minLength'] = schema['minLength'];
64
- if ('maxLength' in schema) opts['maxLength'] = schema['maxLength'];
65
- if ('pattern' in schema) opts['pattern'] = schema['pattern'];
66
- if ('format' in schema) opts['format'] = schema['format'];
67
- return Type.String(opts);
68
- }
69
- ```
70
-
71
- TDD: Test plain string, string with `minLength`/`maxLength`, verify constraint enforcement.
72
-
73
- ### 5. Handle integer and number types with constraints
74
-
75
- Convert `{ type: "integer" }` to `Type.Integer()` and `{ type: "number" }` to `Type.Number()`. Pass through: `minimum`, `maximum`, `exclusiveMinimum`, `exclusiveMaximum`, `multipleOf`.
76
-
77
- TDD: Test integer rejects floats, number accepts both, constraint boundaries work.
78
-
79
- ### 6. Handle boolean and null types
80
-
81
- Convert `{ type: "boolean" }` to `Type.Boolean()` and `{ type: "null" }` to `Type.Null()`.
82
-
83
- TDD: Test boolean accepts `true`/`false`, rejects strings. Null accepts `null`, rejects `undefined`.
84
-
85
- ### 7. Handle enum
86
-
87
- Convert `{ enum: ["a", "b", "c"] }` to `Type.Union(values.map(v => Type.Literal(v)))`.
88
-
89
- TDD: Test valid enum values accepted, invalid values rejected.
90
-
91
- ### 8. Handle oneOf and anyOf
92
-
93
- Convert `{ oneOf: [...] }` and `{ anyOf: [...] }` to `Type.Union(schemas.map(s => jsonSchemaToTypeBox(s)))`.
94
-
95
- TDD: Test union of string and number accepts both types, rejects others.
96
-
97
- ### 9. Handle allOf
98
-
99
- Convert `{ allOf: [...] }` to `Type.Intersect(schemas.map(s => jsonSchemaToTypeBox(s)))`.
100
-
101
- TDD: Test intersection of two object schemas requires properties from both.
102
-
103
- ### 10. Handle unknown/unsupported schemas
104
-
105
- Any schema that does not match a known type falls through to `Type.Unknown()`, which accepts any value.
106
-
107
- TDD: Test empty schema `{}` accepts any value.
108
-
109
- ## Acceptance Criteria
110
-
111
- - [x] `object` with properties converts to `Type.Object()` with correct required/optional handling
112
- - [x] `object` without properties converts to `Type.Record(Type.String(), Type.Unknown())`
113
- - [x] `array` with items converts to `Type.Array()` with recursive item conversion
114
- - [x] `array` without items converts to `Type.Array(Type.Unknown())`
115
- - [x] `string` converts to `Type.String()` with `minLength`/`maxLength`/`pattern`/`format` passthrough
116
- - [x] `integer` converts to `Type.Integer()` with numeric constraint passthrough
117
- - [x] `number` converts to `Type.Number()` with numeric constraint passthrough
118
- - [x] `boolean` converts to `Type.Boolean()`
119
- - [x] `null` converts to `Type.Null()`
120
- - [x] `enum` converts to `Type.Union(Type.Literal(...))` for each value
121
- - [x] `oneOf`/`anyOf` convert to `Type.Union()`
122
- - [x] `allOf` converts to `Type.Intersect()`
123
- - [x] Unknown schemas convert to `Type.Unknown()`
124
- - [x] All generated TypeBox schemas pass `Value.Check()` validation correctly
125
- - [x] All tests pass with `vitest`
126
-
127
- ## Dependencies
128
-
129
- - types-and-annotations (for `TSchema` type from TypeBox)
130
-
131
- ## Estimated Time
132
-
133
- 3 hours
@@ -1,160 +0,0 @@
1
- # Task: Types and Annotations
2
-
3
- ## Goal
4
-
5
- Define the core type interfaces, enums, and annotation merging utilities that form the foundation of the schema system. All other schema tasks depend on these types.
6
-
7
- ## Files Involved
8
-
9
- - `src/schema/types.ts` -- `SchemaDefinition`, `ResolvedSchema`, `SchemaStrategy`, `ExportProfile`, `SchemaValidationErrorDetail`, `SchemaValidationResult`, `LLMExtensions`, `validationResultToError()`
10
- - `src/schema/annotations.ts` -- `mergeAnnotations()`, `mergeExamples()`, `mergeMetadata()`
11
-
12
- ## Steps
13
-
14
- ### 1. Define SchemaStrategy enum
15
-
16
- ```typescript
17
- export enum SchemaStrategy {
18
- YamlFirst = 'yaml_first',
19
- NativeFirst = 'native_first',
20
- YamlOnly = 'yaml_only',
21
- }
22
- ```
23
-
24
- TDD: Write tests asserting enum values match the expected string representations.
25
-
26
- ### 2. Define ExportProfile enum
27
-
28
- ```typescript
29
- export enum ExportProfile {
30
- MCP = 'mcp',
31
- OpenAI = 'openai',
32
- Anthropic = 'anthropic',
33
- Generic = 'generic',
34
- }
35
- ```
36
-
37
- TDD: Write tests asserting all four profiles are available and have correct string values.
38
-
39
- ### 3. Define SchemaDefinition interface
40
-
41
- ```typescript
42
- export interface SchemaDefinition {
43
- moduleId: string;
44
- description: string;
45
- inputSchema: Record<string, unknown>;
46
- outputSchema: Record<string, unknown>;
47
- errorSchema?: Record<string, unknown> | null;
48
- definitions: Record<string, unknown>;
49
- version: string;
50
- documentation?: string | null;
51
- schemaUrl?: string | null;
52
- }
53
- ```
54
-
55
- TDD: Create a conforming object and verify all fields are accessible with correct types.
56
-
57
- ### 4. Define ResolvedSchema interface
58
-
59
- ```typescript
60
- import type { TSchema } from '@sinclair/typebox';
61
-
62
- export interface ResolvedSchema {
63
- jsonSchema: Record<string, unknown>;
64
- schema: TSchema;
65
- moduleId: string;
66
- direction: string;
67
- }
68
- ```
69
-
70
- TDD: Create a `ResolvedSchema` with `Type.Object({})` and verify `schema` field is a valid `TSchema`.
71
-
72
- ### 5. Define validation result types
73
-
74
- ```typescript
75
- export interface SchemaValidationErrorDetail {
76
- path: string;
77
- message: string;
78
- constraint?: string | null;
79
- expected?: unknown;
80
- actual?: unknown;
81
- }
82
-
83
- export interface SchemaValidationResult {
84
- valid: boolean;
85
- errors: SchemaValidationErrorDetail[];
86
- }
87
- ```
88
-
89
- TDD: Create valid and invalid results, verify field access.
90
-
91
- ### 6. Implement validationResultToError()
92
-
93
- ```typescript
94
- export function validationResultToError(result: SchemaValidationResult): SchemaValidationError {
95
- if (result.valid) {
96
- throw new Error('Cannot convert valid result to error');
97
- }
98
- const errorDicts = result.errors.map((e) => ({
99
- path: e.path,
100
- message: e.message,
101
- constraint: e.constraint ?? null,
102
- expected: e.expected ?? null,
103
- actual: e.actual ?? null,
104
- }));
105
- return new SchemaValidationError('Schema validation failed', errorDicts);
106
- }
107
- ```
108
-
109
- TDD: Verify conversion from `SchemaValidationResult` to `SchemaValidationError`, and verify throwing on valid result.
110
-
111
- ### 7. Define LLMExtensions interface
112
-
113
- ```typescript
114
- export interface LLMExtensions {
115
- llmDescription?: string | null;
116
- examples?: unknown[] | null;
117
- sensitive: boolean;
118
- constraints?: string | null;
119
- deprecated?: Record<string, unknown> | null;
120
- }
121
- ```
122
-
123
- ### 8. Implement mergeAnnotations()
124
-
125
- Merges YAML-defined and code-defined module annotations with YAML-wins precedence over code, and code-wins precedence over defaults. Operates on the `ANNOTATION_FIELDS` list: `readonly`, `destructive`, `idempotent`, `requiresApproval`, `openWorld`.
126
-
127
- TDD: Test default-only, code-only, YAML-only, and YAML-overrides-code scenarios.
128
-
129
- ### 9. Implement mergeExamples()
130
-
131
- YAML examples override code examples entirely. If no YAML examples, fall back to code examples. If neither, return empty array. YAML examples are mapped from raw records to `ModuleExample` objects.
132
-
133
- TDD: Test YAML-wins, code-fallback, and empty scenarios.
134
-
135
- ### 10. Implement mergeMetadata()
136
-
137
- Shallow merge with YAML overrides. Start from code metadata (or empty), then `Object.assign()` YAML metadata on top.
138
-
139
- TDD: Test merge behavior with overlapping keys.
140
-
141
- ## Acceptance Criteria
142
-
143
- - [x] `SchemaStrategy` enum has `YamlFirst`, `NativeFirst`, `YamlOnly` members
144
- - [x] `ExportProfile` enum has `MCP`, `OpenAI`, `Anthropic`, `Generic` members
145
- - [x] `SchemaDefinition` interface includes all required and optional fields
146
- - [x] `ResolvedSchema` interface includes `jsonSchema`, `schema` (TSchema), `moduleId`, `direction`
147
- - [x] `SchemaValidationErrorDetail` includes `path`, `message`, optional `constraint`/`expected`/`actual`
148
- - [x] `validationResultToError()` converts invalid results and throws on valid results
149
- - [x] `mergeAnnotations()` respects YAML > code > defaults precedence
150
- - [x] `mergeExamples()` respects YAML-wins-all precedence
151
- - [x] `mergeMetadata()` performs shallow merge with YAML overrides
152
- - [x] All types compile with `tsc --noEmit` under strict mode
153
-
154
- ## Dependencies
155
-
156
- - None (foundation task)
157
-
158
- ## Estimated Time
159
-
160
- 2 hours
@@ -1,149 +0,0 @@
1
- # Task: SchemaValidator
2
-
3
- ## Goal
4
-
5
- Implement the `SchemaValidator` class for runtime validation of data against TypeBox `TSchema` objects. Supports a coercion toggle (`Value.Decode` vs `Value.Check`), detailed error collection via `Value.Errors()`, and separate `validateInput()`/`validateOutput()` entry points that return validated data or throw `SchemaValidationError`.
6
-
7
- ## Files Involved
8
-
9
- - `src/schema/validator.ts` -- `SchemaValidator` class
10
- - `src/schema/types.ts` -- `SchemaValidationResult`, `SchemaValidationErrorDetail`, `validationResultToError()`
11
- - `src/errors.ts` -- `SchemaValidationError`
12
- - `tests/schema/test-validator.test.ts` -- Unit tests
13
-
14
- ## Steps
15
-
16
- ### 1. Implement constructor with coercion toggle
17
-
18
- ```typescript
19
- export class SchemaValidator {
20
- private _coerceTypes: boolean;
21
-
22
- constructor(coerceTypes: boolean = true) {
23
- this._coerceTypes = coerceTypes;
24
- }
25
- }
26
- ```
27
-
28
- TDD: Verify default `coerceTypes` is `true`. Verify explicit `false` disables coercion.
29
-
30
- ### 2. Implement validate() method
31
-
32
- When coercion is enabled, attempt `Value.Decode()`. If it succeeds, return `{ valid: true, errors: [] }`. If it throws, collect errors and return `{ valid: false, errors: [...] }`.
33
-
34
- When coercion is disabled, use `Value.Check()`. If it returns `true`, return valid result. Otherwise, collect errors.
35
-
36
- ```typescript
37
- validate(data: Record<string, unknown>, schema: TSchema): SchemaValidationResult {
38
- if (this._coerceTypes) {
39
- try {
40
- Value.Decode(schema, data);
41
- return { valid: true, errors: [] };
42
- } catch {
43
- return { valid: false, errors: this._collectErrors(schema, data) };
44
- }
45
- }
46
-
47
- if (Value.Check(schema, data)) {
48
- return { valid: true, errors: [] };
49
- }
50
- return { valid: false, errors: this._collectErrors(schema, data) };
51
- }
52
- ```
53
-
54
- TDD: Test valid data returns `{ valid: true }`. Test invalid data returns `{ valid: false }` with non-empty errors array.
55
-
56
- ### 3. Implement _collectErrors() private method
57
-
58
- Iterate over `Value.Errors(schema, data)` and map each `ValueError` to a `SchemaValidationErrorDetail`.
59
-
60
- ```typescript
61
- private _collectErrors(schema: TSchema, data: unknown): SchemaValidationErrorDetail[] {
62
- const errors: SchemaValidationErrorDetail[] = [];
63
- for (const error of Value.Errors(schema, data)) {
64
- errors.push(this._typeboxErrorToDetail(error));
65
- }
66
- return errors;
67
- }
68
- ```
69
-
70
- TDD: Verify errors have populated `path` and `message` fields.
71
-
72
- ### 4. Implement _typeboxErrorToDetail() mapping
73
-
74
- Map TypeBox `ValueError` fields to `SchemaValidationErrorDetail`:
75
- - `error.path` -> `path` (defaults to `'/'` if empty)
76
- - `error.message` -> `message`
77
- - `error.type` -> `constraint` (stringified)
78
- - `error.schema` -> `expected`
79
- - `error.value` -> `actual`
80
-
81
- TDD: Verify detail mapping for nested object errors includes correct JSON path.
82
-
83
- ### 5. Implement validateInput() method
84
-
85
- Call `_validateAndReturn()`. On success, return the (potentially coerced) data. On failure, throw `SchemaValidationError` via `validationResultToError()`.
86
-
87
- ```typescript
88
- validateInput(data: Record<string, unknown>, schema: TSchema): Record<string, unknown> {
89
- return this._validateAndReturn(data, schema);
90
- }
91
- ```
92
-
93
- TDD: Test valid input returns data. Test invalid input throws `SchemaValidationError`.
94
-
95
- ### 6. Implement validateOutput() method
96
-
97
- Same as `validateInput()` -- delegates to `_validateAndReturn()`. Separate method for semantic clarity in the executor pipeline (step 5 vs step 8).
98
-
99
- TDD: Test valid output returns data. Test invalid output throws `SchemaValidationError`.
100
-
101
- ### 7. Implement _validateAndReturn() private method
102
-
103
- Shared logic for `validateInput()` and `validateOutput()`. With coercion, use `Value.Decode()` and return the decoded value. Without coercion, use `Value.Check()` and return the original data. On failure, collect errors and throw.
104
-
105
- ```typescript
106
- private _validateAndReturn(data: Record<string, unknown>, schema: TSchema): Record<string, unknown> {
107
- if (this._coerceTypes) {
108
- try {
109
- return Value.Decode(schema, data) as Record<string, unknown>;
110
- } catch {
111
- const result: SchemaValidationResult = {
112
- valid: false,
113
- errors: this._collectErrors(schema, data),
114
- };
115
- throw validationResultToError(result);
116
- }
117
- }
118
- if (Value.Check(schema, data)) {
119
- return data;
120
- }
121
- const result: SchemaValidationResult = {
122
- valid: false,
123
- errors: this._collectErrors(schema, data),
124
- };
125
- throw validationResultToError(result);
126
- }
127
- ```
128
-
129
- TDD: Test both coercion and strict paths for valid and invalid data.
130
-
131
- ## Acceptance Criteria
132
-
133
- - [x] `validate()` returns `{ valid: true, errors: [] }` for conforming data
134
- - [x] `validate()` returns `{ valid: false, errors: [...] }` for non-conforming data with detailed errors
135
- - [x] Coercion mode (`coerceTypes: true`) uses `Value.Decode()` for type coercion
136
- - [x] Strict mode (`coerceTypes: false`) uses `Value.Check()` for exact type matching
137
- - [x] `validateInput()` returns data on success, throws `SchemaValidationError` on failure
138
- - [x] `validateOutput()` returns data on success, throws `SchemaValidationError` on failure
139
- - [x] Error details include `path`, `message`, `constraint`, `expected`, `actual`
140
- - [x] Nested object errors include correct JSON path (e.g., `/nested/x`)
141
- - [x] All tests pass with `vitest`
142
-
143
- ## Dependencies
144
-
145
- - types-and-annotations (for `SchemaValidationResult`, `SchemaValidationErrorDetail`, `validationResultToError()`)
146
-
147
- ## Estimated Time
148
-
149
- 2 hours