@adrkit/core 0.1.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.
- package/README.md +22 -0
- package/dist/LICENSE +201 -0
- package/dist/NOTICE +11 -0
- package/dist/affects/catalog.d.ts +14 -0
- package/dist/affects/index.d.ts +30 -0
- package/dist/affects/inert.d.ts +8 -0
- package/dist/affects/matchers/package.d.ts +20 -0
- package/dist/affects/matchers/path.d.ts +5 -0
- package/dist/check/index.d.ts +46 -0
- package/dist/graph/build.d.ts +18 -0
- package/dist/import/classify.d.ts +13 -0
- package/dist/import/fingerprint.d.ts +2 -0
- package/dist/import/index.d.ts +32 -0
- package/dist/import/madr.d.ts +21 -0
- package/dist/import/merge.d.ts +21 -0
- package/dist/import/status.d.ts +11 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +1768 -0
- package/dist/load/corpus.d.ts +20 -0
- package/dist/parse/frontmatter.d.ts +10 -0
- package/dist/scaffold/new.d.ts +26 -0
- package/dist/schema/adr.schema.d.ts +416 -0
- package/dist/schema/adr.schema.js +182 -0
- package/dist/schema/emit.cli.d.ts +1 -0
- package/dist/schema/emit.d.ts +6 -0
- package/dist/schema/emit.js +200 -0
- package/dist/schema/index.d.ts +2 -0
- package/dist/schema/index.js +220 -0
- package/dist/validate/contract.d.ts +9 -0
- package/dist/validate/corpus-invariants.d.ts +3 -0
- package/dist/validate/findings.d.ts +19 -0
- package/dist/validate/import-incomplete.d.ts +3 -0
- package/dist/validate/index.d.ts +13 -0
- package/package.json +76 -0
- package/src/affects/catalog.ts +17 -0
- package/src/affects/index.ts +240 -0
- package/src/affects/inert.ts +63 -0
- package/src/affects/matchers/package.ts +102 -0
- package/src/affects/matchers/path.ts +37 -0
- package/src/check/index.ts +121 -0
- package/src/graph/build.ts +94 -0
- package/src/import/classify.ts +53 -0
- package/src/import/fingerprint.ts +10 -0
- package/src/import/index.ts +240 -0
- package/src/import/madr.ts +117 -0
- package/src/import/merge.ts +321 -0
- package/src/import/status.ts +48 -0
- package/src/index.ts +13 -0
- package/src/load/corpus.ts +101 -0
- package/src/parse/frontmatter.ts +73 -0
- package/src/scaffold/new.ts +208 -0
- package/src/schema/adr.schema.ts +338 -0
- package/src/schema/emit.cli.ts +9 -0
- package/src/schema/emit.ts +55 -0
- package/src/schema/index.ts +2 -0
- package/src/validate/contract.ts +120 -0
- package/src/validate/corpus-invariants.ts +77 -0
- package/src/validate/findings.ts +51 -0
- package/src/validate/import-incomplete.ts +23 -0
- package/src/validate/index.ts +68 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type Adr } from '../schema/adr.schema.js';
|
|
2
|
+
export declare const RECORD_FILE_PATTERN: RegExp;
|
|
3
|
+
export declare const TEMPLATE_FILE_NAME = "0000-template.md";
|
|
4
|
+
export interface ParsedAdrFile {
|
|
5
|
+
data: unknown;
|
|
6
|
+
body: string;
|
|
7
|
+
path: string;
|
|
8
|
+
absolutePath: string;
|
|
9
|
+
}
|
|
10
|
+
export interface Corpus {
|
|
11
|
+
records: Adr[];
|
|
12
|
+
byId: Map<string, Adr>;
|
|
13
|
+
}
|
|
14
|
+
export declare function isRecordFileName(fileName: string): boolean;
|
|
15
|
+
export declare function normalizeDisplayPath(path: string, cwd?: string): string;
|
|
16
|
+
export declare function discoverAdrFiles(dir?: string, cwd?: string): Promise<string[]>;
|
|
17
|
+
export declare function expandRecordInputs(paths: string[] | undefined, dir?: string, cwd?: string): Promise<string[]>;
|
|
18
|
+
export declare function parseAdrFile(path: string, cwd?: string): Promise<ParsedAdrFile>;
|
|
19
|
+
export declare function loadAdrFile(path: string, cwd?: string): Promise<Adr>;
|
|
20
|
+
export declare function loadCorpus(dir?: string, cwd?: string): Promise<Corpus>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type FrontmatterErrorCode = 'missing-frontmatter' | 'unterminated-frontmatter' | 'invalid-yaml';
|
|
2
|
+
export declare class FrontmatterError extends Error {
|
|
3
|
+
readonly code: FrontmatterErrorCode;
|
|
4
|
+
constructor(code: FrontmatterErrorCode, message: string);
|
|
5
|
+
}
|
|
6
|
+
export interface ParsedFrontmatter {
|
|
7
|
+
data: unknown;
|
|
8
|
+
body: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function parseFrontmatter(source: string): ParsedFrontmatter;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export interface NewAdrOptions {
|
|
2
|
+
title: string;
|
|
3
|
+
status?: string;
|
|
4
|
+
dir?: string;
|
|
5
|
+
cwd?: string;
|
|
6
|
+
date?: string;
|
|
7
|
+
write?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface NewAdrResult {
|
|
10
|
+
id: string;
|
|
11
|
+
path: string;
|
|
12
|
+
content: string;
|
|
13
|
+
}
|
|
14
|
+
export declare class ScaffoldError extends Error {
|
|
15
|
+
readonly code: 'usage' | 'exists';
|
|
16
|
+
constructor(code: 'usage' | 'exists', message: string);
|
|
17
|
+
}
|
|
18
|
+
export declare function slugifyTitle(title: string): string;
|
|
19
|
+
export declare function nextSequentialId(dir: string, cwd: string): Promise<string>;
|
|
20
|
+
export declare function renderAdrRecord(options: {
|
|
21
|
+
id: string;
|
|
22
|
+
title: string;
|
|
23
|
+
status: string;
|
|
24
|
+
date: string;
|
|
25
|
+
}): string;
|
|
26
|
+
export declare function createAdr(options: NewAdrOptions): Promise<NewAdrResult>;
|
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @adrkit/core — ADR frontmatter schema
|
|
3
|
+
*
|
|
4
|
+
* Single source of truth for the typed half of a decision record. The JSON
|
|
5
|
+
* Schema in ./adr.schema.json is generated from this file (`bun run schema:emit`)
|
|
6
|
+
* so non-TS consumers — editors, CI in other languages, IDP plugins — get the
|
|
7
|
+
* same contract.
|
|
8
|
+
*
|
|
9
|
+
* Targets Zod 4. Deliberately avoids `.brand()` and other Zod-only constructs
|
|
10
|
+
* in the public shapes so the JSON Schema emit stays lossless.
|
|
11
|
+
*/
|
|
12
|
+
import { z } from 'zod';
|
|
13
|
+
export declare const SCHEMA_VERSION: "0.1.0";
|
|
14
|
+
/** `@handle`, `team:platform`, or an email address. */
|
|
15
|
+
export declare const Identity: z.ZodString;
|
|
16
|
+
/** `0042` (same log) or `payments:0012` (federated). */
|
|
17
|
+
export declare const AdrRef: z.ZodString;
|
|
18
|
+
/**
|
|
19
|
+
* `rejected` is retained on purpose. The decision *not* to do something is the
|
|
20
|
+
* one most often re-litigated, and the graveyard is where "we tried that in
|
|
21
|
+
* 2023" knowledge lives.
|
|
22
|
+
*/
|
|
23
|
+
export declare const Status: z.ZodEnum<{
|
|
24
|
+
draft: "draft";
|
|
25
|
+
proposed: "proposed";
|
|
26
|
+
accepted: "accepted";
|
|
27
|
+
rejected: "rejected";
|
|
28
|
+
superseded: "superseded";
|
|
29
|
+
deprecated: "deprecated";
|
|
30
|
+
}>;
|
|
31
|
+
export declare const Scope: z.ZodEnum<{
|
|
32
|
+
component: "component";
|
|
33
|
+
domain: "domain";
|
|
34
|
+
org: "org";
|
|
35
|
+
}>;
|
|
36
|
+
export declare const Reversibility: z.ZodEnum<{
|
|
37
|
+
"two-way-door": "two-way-door";
|
|
38
|
+
"one-way-door": "one-way-door";
|
|
39
|
+
unknown: "unknown";
|
|
40
|
+
}>;
|
|
41
|
+
export declare const BlastRadius: z.ZodEnum<{
|
|
42
|
+
component: "component";
|
|
43
|
+
org: "org";
|
|
44
|
+
team: "team";
|
|
45
|
+
"cross-team": "cross-team";
|
|
46
|
+
}>;
|
|
47
|
+
export declare const ReviewTier: z.ZodEnum<{
|
|
48
|
+
auto: "auto";
|
|
49
|
+
async: "async";
|
|
50
|
+
arb: "arb";
|
|
51
|
+
}>;
|
|
52
|
+
export declare const Severity: z.ZodEnum<{
|
|
53
|
+
error: "error";
|
|
54
|
+
warn: "warn";
|
|
55
|
+
info: "info";
|
|
56
|
+
}>;
|
|
57
|
+
export declare const EscalationReason: z.ZodEnum<{
|
|
58
|
+
"one-way-door": "one-way-door";
|
|
59
|
+
"cost-threshold": "cost-threshold";
|
|
60
|
+
"security-surface": "security-surface";
|
|
61
|
+
"data-residency": "data-residency";
|
|
62
|
+
regulatory: "regulatory";
|
|
63
|
+
"contradicts-accepted-adr": "contradicts-accepted-adr";
|
|
64
|
+
"low-confidence": "low-confidence";
|
|
65
|
+
"pass-disagreement": "pass-disagreement";
|
|
66
|
+
"agent-authored-production": "agent-authored-production";
|
|
67
|
+
"novel-no-precedent": "novel-no-precedent";
|
|
68
|
+
"human-requested": "human-requested";
|
|
69
|
+
}>;
|
|
70
|
+
export declare const AffectsType: z.ZodEnum<{
|
|
71
|
+
path: "path";
|
|
72
|
+
entity: "entity";
|
|
73
|
+
package: "package";
|
|
74
|
+
resource: "resource";
|
|
75
|
+
api: "api";
|
|
76
|
+
data: "data";
|
|
77
|
+
}>;
|
|
78
|
+
export declare const AffectsMatcher: z.ZodObject<{
|
|
79
|
+
type: z.ZodEnum<{
|
|
80
|
+
path: "path";
|
|
81
|
+
entity: "entity";
|
|
82
|
+
package: "package";
|
|
83
|
+
resource: "resource";
|
|
84
|
+
api: "api";
|
|
85
|
+
data: "data";
|
|
86
|
+
}>;
|
|
87
|
+
pattern: z.ZodString;
|
|
88
|
+
repo: z.ZodOptional<z.ZodString>;
|
|
89
|
+
negate: z.ZodDefault<z.ZodBoolean>;
|
|
90
|
+
note: z.ZodOptional<z.ZodString>;
|
|
91
|
+
}, z.core.$strict>;
|
|
92
|
+
export declare const Assertion: z.ZodObject<{
|
|
93
|
+
id: z.ZodString;
|
|
94
|
+
description: z.ZodOptional<z.ZodString>;
|
|
95
|
+
engine: z.ZodEnum<{
|
|
96
|
+
custom: "custom";
|
|
97
|
+
rego: "rego";
|
|
98
|
+
jsonpath: "jsonpath";
|
|
99
|
+
grep: "grep";
|
|
100
|
+
}>;
|
|
101
|
+
expression: z.ZodOptional<z.ZodString>;
|
|
102
|
+
expressionFile: z.ZodOptional<z.ZodString>;
|
|
103
|
+
input: z.ZodDefault<z.ZodEnum<{
|
|
104
|
+
custom: "custom";
|
|
105
|
+
source: "source";
|
|
106
|
+
"iac-plan": "iac-plan";
|
|
107
|
+
sbom: "sbom";
|
|
108
|
+
openapi: "openapi";
|
|
109
|
+
catalog: "catalog";
|
|
110
|
+
}>>;
|
|
111
|
+
severity: z.ZodEnum<{
|
|
112
|
+
error: "error";
|
|
113
|
+
warn: "warn";
|
|
114
|
+
info: "info";
|
|
115
|
+
}>;
|
|
116
|
+
}, z.core.$strict>;
|
|
117
|
+
export declare const Provenance: z.ZodObject<{
|
|
118
|
+
authoredBy: z.ZodDefault<z.ZodEnum<{
|
|
119
|
+
human: "human";
|
|
120
|
+
agent: "agent";
|
|
121
|
+
"agent-drafted": "agent-drafted";
|
|
122
|
+
}>>;
|
|
123
|
+
agent: z.ZodOptional<z.ZodObject<{
|
|
124
|
+
name: z.ZodOptional<z.ZodString>;
|
|
125
|
+
model: z.ZodOptional<z.ZodString>;
|
|
126
|
+
harness: z.ZodOptional<z.ZodString>;
|
|
127
|
+
runId: z.ZodOptional<z.ZodString>;
|
|
128
|
+
}, z.core.$strict>>;
|
|
129
|
+
ratifiedBy: z.ZodOptional<z.ZodString>;
|
|
130
|
+
sourceArtifact: z.ZodOptional<z.ZodString>;
|
|
131
|
+
importedFrom: z.ZodOptional<z.ZodObject<{
|
|
132
|
+
sourceKind: z.ZodEnum<{
|
|
133
|
+
madr: "madr";
|
|
134
|
+
"agent-log": "agent-log";
|
|
135
|
+
"plan-artifact": "plan-artifact";
|
|
136
|
+
other: "other";
|
|
137
|
+
}>;
|
|
138
|
+
sourceRef: z.ZodString;
|
|
139
|
+
fingerprint: z.ZodString;
|
|
140
|
+
importedAt: z.ZodOptional<z.ZodString>;
|
|
141
|
+
}, z.core.$strict>>;
|
|
142
|
+
}, z.core.$strict>;
|
|
143
|
+
export declare const Objection: z.ZodObject<{
|
|
144
|
+
by: z.ZodString;
|
|
145
|
+
summary: z.ZodOptional<z.ZodString>;
|
|
146
|
+
resolved: z.ZodDefault<z.ZodBoolean>;
|
|
147
|
+
}, z.core.$strict>;
|
|
148
|
+
export declare const Review: z.ZodObject<{
|
|
149
|
+
tier: z.ZodOptional<z.ZodEnum<{
|
|
150
|
+
auto: "auto";
|
|
151
|
+
async: "async";
|
|
152
|
+
arb: "arb";
|
|
153
|
+
}>>;
|
|
154
|
+
tierReason: z.ZodOptional<z.ZodString>;
|
|
155
|
+
queuedAt: z.ZodOptional<z.ZodString>;
|
|
156
|
+
slaDays: z.ZodOptional<z.ZodNumber>;
|
|
157
|
+
escalatedAt: z.ZodOptional<z.ZodString>;
|
|
158
|
+
decidedAt: z.ZodOptional<z.ZodString>;
|
|
159
|
+
quorum: z.ZodOptional<z.ZodNumber>;
|
|
160
|
+
approvals: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
161
|
+
objections: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
162
|
+
by: z.ZodString;
|
|
163
|
+
summary: z.ZodOptional<z.ZodString>;
|
|
164
|
+
resolved: z.ZodDefault<z.ZodBoolean>;
|
|
165
|
+
}, z.core.$strict>>>;
|
|
166
|
+
}, z.core.$strict>;
|
|
167
|
+
export declare const DeterministicFinding: z.ZodObject<{
|
|
168
|
+
rule: z.ZodString;
|
|
169
|
+
severity: z.ZodEnum<{
|
|
170
|
+
error: "error";
|
|
171
|
+
warn: "warn";
|
|
172
|
+
info: "info";
|
|
173
|
+
}>;
|
|
174
|
+
message: z.ZodOptional<z.ZodString>;
|
|
175
|
+
adr: z.ZodOptional<z.ZodString>;
|
|
176
|
+
}, z.core.$strict>;
|
|
177
|
+
export declare const Evaluation: z.ZodObject<{
|
|
178
|
+
ranAt: z.ZodOptional<z.ZodString>;
|
|
179
|
+
evaluatorVersion: z.ZodOptional<z.ZodString>;
|
|
180
|
+
rubricVersion: z.ZodOptional<z.ZodString>;
|
|
181
|
+
scores: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNumber>>;
|
|
182
|
+
confidence: z.ZodOptional<z.ZodNumber>;
|
|
183
|
+
escalate: z.ZodOptional<z.ZodBoolean>;
|
|
184
|
+
escalationReasons: z.ZodDefault<z.ZodArray<z.ZodEnum<{
|
|
185
|
+
"one-way-door": "one-way-door";
|
|
186
|
+
"cost-threshold": "cost-threshold";
|
|
187
|
+
"security-surface": "security-surface";
|
|
188
|
+
"data-residency": "data-residency";
|
|
189
|
+
regulatory: "regulatory";
|
|
190
|
+
"contradicts-accepted-adr": "contradicts-accepted-adr";
|
|
191
|
+
"low-confidence": "low-confidence";
|
|
192
|
+
"pass-disagreement": "pass-disagreement";
|
|
193
|
+
"agent-authored-production": "agent-authored-production";
|
|
194
|
+
"novel-no-precedent": "novel-no-precedent";
|
|
195
|
+
"human-requested": "human-requested";
|
|
196
|
+
}>>>;
|
|
197
|
+
deterministicFindings: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
198
|
+
rule: z.ZodString;
|
|
199
|
+
severity: z.ZodEnum<{
|
|
200
|
+
error: "error";
|
|
201
|
+
warn: "warn";
|
|
202
|
+
info: "info";
|
|
203
|
+
}>;
|
|
204
|
+
message: z.ZodOptional<z.ZodString>;
|
|
205
|
+
adr: z.ZodOptional<z.ZodString>;
|
|
206
|
+
}, z.core.$strict>>>;
|
|
207
|
+
}, z.core.$strict>;
|
|
208
|
+
export declare const ExternalRef: z.ZodObject<{
|
|
209
|
+
type: z.ZodEnum<{
|
|
210
|
+
other: "other";
|
|
211
|
+
issue: "issue";
|
|
212
|
+
pr: "pr";
|
|
213
|
+
rfc: "rfc";
|
|
214
|
+
incident: "incident";
|
|
215
|
+
doc: "doc";
|
|
216
|
+
meeting: "meeting";
|
|
217
|
+
control: "control";
|
|
218
|
+
}>;
|
|
219
|
+
id: z.ZodOptional<z.ZodString>;
|
|
220
|
+
url: z.ZodString;
|
|
221
|
+
label: z.ZodOptional<z.ZodString>;
|
|
222
|
+
}, z.core.$strict>;
|
|
223
|
+
export declare const AdrFrontmatter: z.ZodObject<{
|
|
224
|
+
schemaVersion: z.ZodDefault<z.ZodString>;
|
|
225
|
+
id: z.ZodString;
|
|
226
|
+
title: z.ZodString;
|
|
227
|
+
status: z.ZodEnum<{
|
|
228
|
+
draft: "draft";
|
|
229
|
+
proposed: "proposed";
|
|
230
|
+
accepted: "accepted";
|
|
231
|
+
rejected: "rejected";
|
|
232
|
+
superseded: "superseded";
|
|
233
|
+
deprecated: "deprecated";
|
|
234
|
+
}>;
|
|
235
|
+
date: z.ZodString;
|
|
236
|
+
created: z.ZodOptional<z.ZodString>;
|
|
237
|
+
deciders: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
238
|
+
consulted: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
239
|
+
informed: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
240
|
+
tags: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
241
|
+
scope: z.ZodDefault<z.ZodEnum<{
|
|
242
|
+
component: "component";
|
|
243
|
+
domain: "domain";
|
|
244
|
+
org: "org";
|
|
245
|
+
}>>;
|
|
246
|
+
domain: z.ZodOptional<z.ZodString>;
|
|
247
|
+
reversibility: z.ZodDefault<z.ZodEnum<{
|
|
248
|
+
"two-way-door": "two-way-door";
|
|
249
|
+
"one-way-door": "one-way-door";
|
|
250
|
+
unknown: "unknown";
|
|
251
|
+
}>>;
|
|
252
|
+
blastRadius: z.ZodDefault<z.ZodEnum<{
|
|
253
|
+
component: "component";
|
|
254
|
+
org: "org";
|
|
255
|
+
team: "team";
|
|
256
|
+
"cross-team": "cross-team";
|
|
257
|
+
}>>;
|
|
258
|
+
supersedes: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
259
|
+
supersededBy: z.ZodOptional<z.ZodString>;
|
|
260
|
+
relatesTo: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
261
|
+
conflictsWith: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
262
|
+
affects: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
263
|
+
type: z.ZodEnum<{
|
|
264
|
+
path: "path";
|
|
265
|
+
entity: "entity";
|
|
266
|
+
package: "package";
|
|
267
|
+
resource: "resource";
|
|
268
|
+
api: "api";
|
|
269
|
+
data: "data";
|
|
270
|
+
}>;
|
|
271
|
+
pattern: z.ZodString;
|
|
272
|
+
repo: z.ZodOptional<z.ZodString>;
|
|
273
|
+
negate: z.ZodDefault<z.ZodBoolean>;
|
|
274
|
+
note: z.ZodOptional<z.ZodString>;
|
|
275
|
+
}, z.core.$strict>>>;
|
|
276
|
+
assertions: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
277
|
+
id: z.ZodString;
|
|
278
|
+
description: z.ZodOptional<z.ZodString>;
|
|
279
|
+
engine: z.ZodEnum<{
|
|
280
|
+
custom: "custom";
|
|
281
|
+
rego: "rego";
|
|
282
|
+
jsonpath: "jsonpath";
|
|
283
|
+
grep: "grep";
|
|
284
|
+
}>;
|
|
285
|
+
expression: z.ZodOptional<z.ZodString>;
|
|
286
|
+
expressionFile: z.ZodOptional<z.ZodString>;
|
|
287
|
+
input: z.ZodDefault<z.ZodEnum<{
|
|
288
|
+
custom: "custom";
|
|
289
|
+
source: "source";
|
|
290
|
+
"iac-plan": "iac-plan";
|
|
291
|
+
sbom: "sbom";
|
|
292
|
+
openapi: "openapi";
|
|
293
|
+
catalog: "catalog";
|
|
294
|
+
}>>;
|
|
295
|
+
severity: z.ZodEnum<{
|
|
296
|
+
error: "error";
|
|
297
|
+
warn: "warn";
|
|
298
|
+
info: "info";
|
|
299
|
+
}>;
|
|
300
|
+
}, z.core.$strict>>>;
|
|
301
|
+
provenance: z.ZodOptional<z.ZodObject<{
|
|
302
|
+
authoredBy: z.ZodDefault<z.ZodEnum<{
|
|
303
|
+
human: "human";
|
|
304
|
+
agent: "agent";
|
|
305
|
+
"agent-drafted": "agent-drafted";
|
|
306
|
+
}>>;
|
|
307
|
+
agent: z.ZodOptional<z.ZodObject<{
|
|
308
|
+
name: z.ZodOptional<z.ZodString>;
|
|
309
|
+
model: z.ZodOptional<z.ZodString>;
|
|
310
|
+
harness: z.ZodOptional<z.ZodString>;
|
|
311
|
+
runId: z.ZodOptional<z.ZodString>;
|
|
312
|
+
}, z.core.$strict>>;
|
|
313
|
+
ratifiedBy: z.ZodOptional<z.ZodString>;
|
|
314
|
+
sourceArtifact: z.ZodOptional<z.ZodString>;
|
|
315
|
+
importedFrom: z.ZodOptional<z.ZodObject<{
|
|
316
|
+
sourceKind: z.ZodEnum<{
|
|
317
|
+
madr: "madr";
|
|
318
|
+
"agent-log": "agent-log";
|
|
319
|
+
"plan-artifact": "plan-artifact";
|
|
320
|
+
other: "other";
|
|
321
|
+
}>;
|
|
322
|
+
sourceRef: z.ZodString;
|
|
323
|
+
fingerprint: z.ZodString;
|
|
324
|
+
importedAt: z.ZodOptional<z.ZodString>;
|
|
325
|
+
}, z.core.$strict>>;
|
|
326
|
+
}, z.core.$strict>>;
|
|
327
|
+
review: z.ZodOptional<z.ZodObject<{
|
|
328
|
+
tier: z.ZodOptional<z.ZodEnum<{
|
|
329
|
+
auto: "auto";
|
|
330
|
+
async: "async";
|
|
331
|
+
arb: "arb";
|
|
332
|
+
}>>;
|
|
333
|
+
tierReason: z.ZodOptional<z.ZodString>;
|
|
334
|
+
queuedAt: z.ZodOptional<z.ZodString>;
|
|
335
|
+
slaDays: z.ZodOptional<z.ZodNumber>;
|
|
336
|
+
escalatedAt: z.ZodOptional<z.ZodString>;
|
|
337
|
+
decidedAt: z.ZodOptional<z.ZodString>;
|
|
338
|
+
quorum: z.ZodOptional<z.ZodNumber>;
|
|
339
|
+
approvals: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
340
|
+
objections: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
341
|
+
by: z.ZodString;
|
|
342
|
+
summary: z.ZodOptional<z.ZodString>;
|
|
343
|
+
resolved: z.ZodDefault<z.ZodBoolean>;
|
|
344
|
+
}, z.core.$strict>>>;
|
|
345
|
+
}, z.core.$strict>>;
|
|
346
|
+
evaluation: z.ZodOptional<z.ZodObject<{
|
|
347
|
+
ranAt: z.ZodOptional<z.ZodString>;
|
|
348
|
+
evaluatorVersion: z.ZodOptional<z.ZodString>;
|
|
349
|
+
rubricVersion: z.ZodOptional<z.ZodString>;
|
|
350
|
+
scores: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNumber>>;
|
|
351
|
+
confidence: z.ZodOptional<z.ZodNumber>;
|
|
352
|
+
escalate: z.ZodOptional<z.ZodBoolean>;
|
|
353
|
+
escalationReasons: z.ZodDefault<z.ZodArray<z.ZodEnum<{
|
|
354
|
+
"one-way-door": "one-way-door";
|
|
355
|
+
"cost-threshold": "cost-threshold";
|
|
356
|
+
"security-surface": "security-surface";
|
|
357
|
+
"data-residency": "data-residency";
|
|
358
|
+
regulatory: "regulatory";
|
|
359
|
+
"contradicts-accepted-adr": "contradicts-accepted-adr";
|
|
360
|
+
"low-confidence": "low-confidence";
|
|
361
|
+
"pass-disagreement": "pass-disagreement";
|
|
362
|
+
"agent-authored-production": "agent-authored-production";
|
|
363
|
+
"novel-no-precedent": "novel-no-precedent";
|
|
364
|
+
"human-requested": "human-requested";
|
|
365
|
+
}>>>;
|
|
366
|
+
deterministicFindings: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
367
|
+
rule: z.ZodString;
|
|
368
|
+
severity: z.ZodEnum<{
|
|
369
|
+
error: "error";
|
|
370
|
+
warn: "warn";
|
|
371
|
+
info: "info";
|
|
372
|
+
}>;
|
|
373
|
+
message: z.ZodOptional<z.ZodString>;
|
|
374
|
+
adr: z.ZodOptional<z.ZodString>;
|
|
375
|
+
}, z.core.$strict>>>;
|
|
376
|
+
}, z.core.$strict>>;
|
|
377
|
+
externalRefs: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
378
|
+
type: z.ZodEnum<{
|
|
379
|
+
other: "other";
|
|
380
|
+
issue: "issue";
|
|
381
|
+
pr: "pr";
|
|
382
|
+
rfc: "rfc";
|
|
383
|
+
incident: "incident";
|
|
384
|
+
doc: "doc";
|
|
385
|
+
meeting: "meeting";
|
|
386
|
+
control: "control";
|
|
387
|
+
}>;
|
|
388
|
+
id: z.ZodOptional<z.ZodString>;
|
|
389
|
+
url: z.ZodString;
|
|
390
|
+
label: z.ZodOptional<z.ZodString>;
|
|
391
|
+
}, z.core.$strict>>>;
|
|
392
|
+
complianceControls: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
393
|
+
reviewBy: z.ZodOptional<z.ZodString>;
|
|
394
|
+
}, z.core.$strict>;
|
|
395
|
+
export type AdrFrontmatter = z.infer<typeof AdrFrontmatter>;
|
|
396
|
+
export interface Adr {
|
|
397
|
+
frontmatter: AdrFrontmatter;
|
|
398
|
+
/** Raw markdown body below the frontmatter. */
|
|
399
|
+
body: string;
|
|
400
|
+
/** Repo-relative path, e.g. docs/adr/0042-use-postgres-for-the-index.md */
|
|
401
|
+
path: string;
|
|
402
|
+
/** Log name for federated corpora; undefined for single-repo. */
|
|
403
|
+
log?: string;
|
|
404
|
+
}
|
|
405
|
+
export type AdrRef = z.infer<typeof AdrRef>;
|
|
406
|
+
export type AffectsType = z.infer<typeof AffectsType>;
|
|
407
|
+
export type AffectsMatcher = z.infer<typeof AffectsMatcher>;
|
|
408
|
+
export type Assertion = z.infer<typeof Assertion>;
|
|
409
|
+
export type Severity = z.infer<typeof Severity>;
|
|
410
|
+
export type EscalationReason = z.infer<typeof EscalationReason>;
|
|
411
|
+
export type DeterministicFinding = z.infer<typeof DeterministicFinding>;
|
|
412
|
+
export type Evaluation = z.infer<typeof Evaluation>;
|
|
413
|
+
export type Status = z.infer<typeof Status>;
|
|
414
|
+
export type Scope = z.infer<typeof Scope>;
|
|
415
|
+
export type Reversibility = z.infer<typeof Reversibility>;
|
|
416
|
+
export type BlastRadius = z.infer<typeof BlastRadius>;
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
// src/schema/adr.schema.ts
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
var SCHEMA_VERSION = "0.1.0";
|
|
4
|
+
var Identity = z.string().regex(/^(@[A-Za-z0-9-]+|team:[a-z0-9-]+|[^@\s]+@[^@\s]+\.[^@\s]+)$/, "Expected @handle, team:slug, or an email address");
|
|
5
|
+
var AdrRef = z.string().regex(/^(([a-z0-9][a-z0-9-]*):)?([0-9]{4,}|[0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{26})$/, "Expected an ADR id, optionally prefixed with a log name");
|
|
6
|
+
var IsoDate = z.string().date();
|
|
7
|
+
var IsoDateTime = z.string().datetime({ offset: true });
|
|
8
|
+
var Slug = z.string().regex(/^[a-z0-9][a-z0-9-]*$/);
|
|
9
|
+
var strictObject = (shape) => z.strictObject(shape);
|
|
10
|
+
var uniqueArray = (item) => z.array(item).refine((xs) => new Set(xs.map((x) => JSON.stringify(x))).size === xs.length, {
|
|
11
|
+
message: "Items must be unique"
|
|
12
|
+
}).meta({ uniqueItems: true });
|
|
13
|
+
var Status = z.enum([
|
|
14
|
+
"draft",
|
|
15
|
+
"proposed",
|
|
16
|
+
"accepted",
|
|
17
|
+
"rejected",
|
|
18
|
+
"superseded",
|
|
19
|
+
"deprecated"
|
|
20
|
+
]);
|
|
21
|
+
var Scope = z.enum(["component", "domain", "org"]);
|
|
22
|
+
var Reversibility = z.enum(["two-way-door", "one-way-door", "unknown"]);
|
|
23
|
+
var BlastRadius = z.enum(["component", "team", "cross-team", "org"]);
|
|
24
|
+
var ReviewTier = z.enum(["auto", "async", "arb"]);
|
|
25
|
+
var Severity = z.enum(["error", "warn", "info"]);
|
|
26
|
+
var EscalationReason = z.enum([
|
|
27
|
+
"one-way-door",
|
|
28
|
+
"cost-threshold",
|
|
29
|
+
"security-surface",
|
|
30
|
+
"data-residency",
|
|
31
|
+
"regulatory",
|
|
32
|
+
"contradicts-accepted-adr",
|
|
33
|
+
"low-confidence",
|
|
34
|
+
"pass-disagreement",
|
|
35
|
+
"agent-authored-production",
|
|
36
|
+
"novel-no-precedent",
|
|
37
|
+
"human-requested"
|
|
38
|
+
]);
|
|
39
|
+
var AffectsType = z.enum([
|
|
40
|
+
"path",
|
|
41
|
+
"entity",
|
|
42
|
+
"package",
|
|
43
|
+
"resource",
|
|
44
|
+
"api",
|
|
45
|
+
"data"
|
|
46
|
+
]);
|
|
47
|
+
var AffectsMatcher = strictObject({
|
|
48
|
+
type: AffectsType,
|
|
49
|
+
pattern: z.string().min(1),
|
|
50
|
+
repo: z.string().optional(),
|
|
51
|
+
negate: z.boolean().default(false),
|
|
52
|
+
note: z.string().optional()
|
|
53
|
+
});
|
|
54
|
+
var Assertion = strictObject({
|
|
55
|
+
id: Slug,
|
|
56
|
+
description: z.string().optional(),
|
|
57
|
+
engine: z.enum(["rego", "jsonpath", "grep", "custom"]),
|
|
58
|
+
expression: z.string().optional(),
|
|
59
|
+
expressionFile: z.string().optional(),
|
|
60
|
+
input: z.enum(["source", "iac-plan", "sbom", "openapi", "catalog", "custom"]).default("source"),
|
|
61
|
+
severity: Severity
|
|
62
|
+
});
|
|
63
|
+
var Provenance = strictObject({
|
|
64
|
+
authoredBy: z.enum(["human", "agent", "agent-drafted"]).default("human"),
|
|
65
|
+
agent: strictObject({
|
|
66
|
+
name: z.string().optional(),
|
|
67
|
+
model: z.string().optional(),
|
|
68
|
+
harness: z.string().optional(),
|
|
69
|
+
runId: z.string().optional()
|
|
70
|
+
}).optional(),
|
|
71
|
+
ratifiedBy: Identity.optional(),
|
|
72
|
+
sourceArtifact: z.string().optional(),
|
|
73
|
+
importedFrom: strictObject({
|
|
74
|
+
sourceKind: z.enum(["madr", "agent-log", "plan-artifact", "other"]),
|
|
75
|
+
sourceRef: z.string(),
|
|
76
|
+
fingerprint: z.string(),
|
|
77
|
+
importedAt: IsoDateTime.optional()
|
|
78
|
+
}).optional()
|
|
79
|
+
});
|
|
80
|
+
var Objection = strictObject({
|
|
81
|
+
by: Identity,
|
|
82
|
+
summary: z.string().optional(),
|
|
83
|
+
resolved: z.boolean().default(false)
|
|
84
|
+
});
|
|
85
|
+
var Review = strictObject({
|
|
86
|
+
tier: ReviewTier.optional(),
|
|
87
|
+
tierReason: z.string().optional(),
|
|
88
|
+
queuedAt: IsoDateTime.optional(),
|
|
89
|
+
slaDays: z.number().int().min(0).optional(),
|
|
90
|
+
escalatedAt: IsoDateTime.optional(),
|
|
91
|
+
decidedAt: IsoDateTime.optional(),
|
|
92
|
+
quorum: z.number().int().min(1).optional(),
|
|
93
|
+
approvals: z.array(Identity).default([]),
|
|
94
|
+
objections: z.array(Objection).default([])
|
|
95
|
+
});
|
|
96
|
+
var DeterministicFinding = strictObject({
|
|
97
|
+
rule: z.string(),
|
|
98
|
+
severity: Severity,
|
|
99
|
+
message: z.string().optional(),
|
|
100
|
+
adr: AdrRef.optional()
|
|
101
|
+
});
|
|
102
|
+
var Evaluation = strictObject({
|
|
103
|
+
ranAt: IsoDateTime.optional(),
|
|
104
|
+
evaluatorVersion: z.string().optional(),
|
|
105
|
+
rubricVersion: z.string().optional(),
|
|
106
|
+
scores: z.record(z.string(), z.number().min(0).max(4)).optional(),
|
|
107
|
+
confidence: z.number().min(0).max(1).optional(),
|
|
108
|
+
escalate: z.boolean().optional(),
|
|
109
|
+
escalationReasons: z.array(EscalationReason).default([]),
|
|
110
|
+
deterministicFindings: z.array(DeterministicFinding).default([])
|
|
111
|
+
});
|
|
112
|
+
var ExternalRef = strictObject({
|
|
113
|
+
type: z.enum(["issue", "pr", "rfc", "incident", "doc", "meeting", "control", "other"]),
|
|
114
|
+
id: z.string().optional(),
|
|
115
|
+
url: z.string().url(),
|
|
116
|
+
label: z.string().optional()
|
|
117
|
+
});
|
|
118
|
+
var AdrFrontmatter = strictObject({
|
|
119
|
+
schemaVersion: z.string().regex(/^\d+\.\d+\.\d+$/).default(SCHEMA_VERSION),
|
|
120
|
+
id: z.string().regex(/^([0-9]{4,}|[0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{26})$/),
|
|
121
|
+
title: z.string().min(3).max(120),
|
|
122
|
+
status: Status,
|
|
123
|
+
date: IsoDate,
|
|
124
|
+
created: IsoDate.optional(),
|
|
125
|
+
deciders: z.array(Identity).default([]),
|
|
126
|
+
consulted: z.array(Identity).default([]),
|
|
127
|
+
informed: z.array(Identity).default([]),
|
|
128
|
+
tags: uniqueArray(Slug).default([]),
|
|
129
|
+
scope: Scope.default("component"),
|
|
130
|
+
domain: z.string().optional(),
|
|
131
|
+
reversibility: Reversibility.default("unknown"),
|
|
132
|
+
blastRadius: BlastRadius.default("component"),
|
|
133
|
+
supersedes: uniqueArray(AdrRef).default([]),
|
|
134
|
+
supersededBy: AdrRef.optional(),
|
|
135
|
+
relatesTo: uniqueArray(AdrRef).default([]),
|
|
136
|
+
conflictsWith: z.array(AdrRef).default([]),
|
|
137
|
+
affects: z.array(AffectsMatcher).default([]),
|
|
138
|
+
assertions: z.array(Assertion).default([]),
|
|
139
|
+
provenance: Provenance.optional(),
|
|
140
|
+
review: Review.optional(),
|
|
141
|
+
evaluation: Evaluation.optional(),
|
|
142
|
+
externalRefs: z.array(ExternalRef).default([]),
|
|
143
|
+
complianceControls: uniqueArray(z.string()).default([]),
|
|
144
|
+
reviewBy: IsoDate.optional()
|
|
145
|
+
}).refine((a) => a.status === "superseded" ? Boolean(a.supersededBy) : true, {
|
|
146
|
+
message: 'status "superseded" requires supersededBy',
|
|
147
|
+
path: ["supersededBy"]
|
|
148
|
+
}).refine((a) => a.supersededBy ? a.status === "superseded" : true, {
|
|
149
|
+
message: 'supersededBy is set but status is not "superseded"',
|
|
150
|
+
path: ["status"]
|
|
151
|
+
}).refine((a) => a.status !== "accepted" || a.deciders.length > 0 || Boolean(a.provenance?.importedFrom), {
|
|
152
|
+
message: "an accepted decision must name at least one decider, unless it was imported",
|
|
153
|
+
path: ["deciders"]
|
|
154
|
+
}).refine((a) => a.status !== "accepted" || a.provenance?.authoredBy !== "agent" || Boolean(a.provenance?.ratifiedBy), {
|
|
155
|
+
message: 'an agent-authored record cannot reach "accepted" without a named human ratifier',
|
|
156
|
+
path: ["provenance", "ratifiedBy"]
|
|
157
|
+
}).refine((a) => !(a.reversibility === "one-way-door" && a.review?.tier === "auto"), {
|
|
158
|
+
message: "one-way-door decisions may not take the auto-approve fast path",
|
|
159
|
+
path: ["review", "tier"]
|
|
160
|
+
});
|
|
161
|
+
export {
|
|
162
|
+
Status,
|
|
163
|
+
Severity,
|
|
164
|
+
Scope,
|
|
165
|
+
SCHEMA_VERSION,
|
|
166
|
+
ReviewTier,
|
|
167
|
+
Review,
|
|
168
|
+
Reversibility,
|
|
169
|
+
Provenance,
|
|
170
|
+
Objection,
|
|
171
|
+
Identity,
|
|
172
|
+
ExternalRef,
|
|
173
|
+
Evaluation,
|
|
174
|
+
EscalationReason,
|
|
175
|
+
DeterministicFinding,
|
|
176
|
+
BlastRadius,
|
|
177
|
+
Assertion,
|
|
178
|
+
AffectsType,
|
|
179
|
+
AffectsMatcher,
|
|
180
|
+
AdrRef,
|
|
181
|
+
AdrFrontmatter
|
|
182
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const ADR_SCHEMA_ID: string;
|
|
2
|
+
export type JsonValue = null | boolean | number | string | JsonValue[] | {
|
|
3
|
+
[key: string]: JsonValue;
|
|
4
|
+
};
|
|
5
|
+
export declare function emitJsonSchema(): JsonValue;
|
|
6
|
+
export declare function stringifyJsonSchema(schema?: JsonValue): string;
|