felenova-backlog 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.
Files changed (147) hide show
  1. package/README.md +58 -0
  2. package/bin/backlog.js +2 -0
  3. package/dist/_core/criteria.d.ts +13 -0
  4. package/dist/_core/criteria.js +44 -0
  5. package/dist/_core/criteria.js.map +1 -0
  6. package/dist/_core/errors.d.ts +53 -0
  7. package/dist/_core/errors.js +91 -0
  8. package/dist/_core/errors.js.map +1 -0
  9. package/dist/_core/index.d.ts +24 -0
  10. package/dist/_core/index.js +27 -0
  11. package/dist/_core/index.js.map +1 -0
  12. package/dist/_core/loop.d.ts +73 -0
  13. package/dist/_core/loop.js +46 -0
  14. package/dist/_core/loop.js.map +1 -0
  15. package/dist/_core/markdown/items.d.ts +35 -0
  16. package/dist/_core/markdown/items.js +256 -0
  17. package/dist/_core/markdown/items.js.map +1 -0
  18. package/dist/_core/markdown/matrix.d.ts +20 -0
  19. package/dist/_core/markdown/matrix.js +147 -0
  20. package/dist/_core/markdown/matrix.js.map +1 -0
  21. package/dist/_core/markdown/track.d.ts +71 -0
  22. package/dist/_core/markdown/track.js +79 -0
  23. package/dist/_core/markdown/track.js.map +1 -0
  24. package/dist/_core/matrix-status.d.ts +9 -0
  25. package/dist/_core/matrix-status.js +31 -0
  26. package/dist/_core/matrix-status.js.map +1 -0
  27. package/dist/_core/matrix.d.ts +46 -0
  28. package/dist/_core/matrix.js +0 -0
  29. package/dist/_core/matrix.js.map +1 -0
  30. package/dist/_core/permissions.d.ts +14 -0
  31. package/dist/_core/permissions.js +87 -0
  32. package/dist/_core/permissions.js.map +1 -0
  33. package/dist/_core/promote.d.ts +20 -0
  34. package/dist/_core/promote.js +47 -0
  35. package/dist/_core/promote.js.map +1 -0
  36. package/dist/_core/ready.d.ts +8 -0
  37. package/dist/_core/ready.js +22 -0
  38. package/dist/_core/ready.js.map +1 -0
  39. package/dist/_core/review.d.ts +49 -0
  40. package/dist/_core/review.js +137 -0
  41. package/dist/_core/review.js.map +1 -0
  42. package/dist/_core/schema.d.ts +636 -0
  43. package/dist/_core/schema.js +304 -0
  44. package/dist/_core/schema.js.map +1 -0
  45. package/dist/_core/ship.d.ts +23 -0
  46. package/dist/_core/ship.js +31 -0
  47. package/dist/_core/ship.js.map +1 -0
  48. package/dist/_core/spec-diff.d.ts +19 -0
  49. package/dist/_core/spec-diff.js +25 -0
  50. package/dist/_core/spec-diff.js.map +1 -0
  51. package/dist/_core/status.d.ts +7 -0
  52. package/dist/_core/status.js +25 -0
  53. package/dist/_core/status.js.map +1 -0
  54. package/dist/_core/util/deep-equal.d.ts +8 -0
  55. package/dist/_core/util/deep-equal.js +31 -0
  56. package/dist/_core/util/deep-equal.js.map +1 -0
  57. package/dist/api.d.ts +46 -0
  58. package/dist/api.js +104 -0
  59. package/dist/api.js.map +1 -0
  60. package/dist/cache.d.ts +53 -0
  61. package/dist/cache.js +114 -0
  62. package/dist/cache.js.map +1 -0
  63. package/dist/commands/common.d.ts +59 -0
  64. package/dist/commands/common.js +94 -0
  65. package/dist/commands/common.js.map +1 -0
  66. package/dist/commands/export.d.ts +20 -0
  67. package/dist/commands/export.js +56 -0
  68. package/dist/commands/export.js.map +1 -0
  69. package/dist/commands/matrix.d.ts +16 -0
  70. package/dist/commands/matrix.js +48 -0
  71. package/dist/commands/matrix.js.map +1 -0
  72. package/dist/commands/next.d.ts +14 -0
  73. package/dist/commands/next.js +30 -0
  74. package/dist/commands/next.js.map +1 -0
  75. package/dist/commands/promote.d.ts +15 -0
  76. package/dist/commands/promote.js +172 -0
  77. package/dist/commands/promote.js.map +1 -0
  78. package/dist/commands/report.d.ts +18 -0
  79. package/dist/commands/report.js +45 -0
  80. package/dist/commands/report.js.map +1 -0
  81. package/dist/commands/ship.d.ts +15 -0
  82. package/dist/commands/ship.js +231 -0
  83. package/dist/commands/ship.js.map +1 -0
  84. package/dist/commands/status.d.ts +13 -0
  85. package/dist/commands/status.js +141 -0
  86. package/dist/commands/status.js.map +1 -0
  87. package/dist/commands/sync.d.ts +17 -0
  88. package/dist/commands/sync.js +90 -0
  89. package/dist/commands/sync.js.map +1 -0
  90. package/dist/conductor/registry.d.ts +45 -0
  91. package/dist/conductor/registry.js +164 -0
  92. package/dist/conductor/registry.js.map +1 -0
  93. package/dist/config.d.ts +47 -0
  94. package/dist/config.js +137 -0
  95. package/dist/config.js.map +1 -0
  96. package/dist/doctor.d.ts +28 -0
  97. package/dist/doctor.js +377 -0
  98. package/dist/doctor.js.map +1 -0
  99. package/dist/errors.d.ts +23 -0
  100. package/dist/errors.js +114 -0
  101. package/dist/errors.js.map +1 -0
  102. package/dist/export.d.ts +1 -0
  103. package/dist/export.js +9 -0
  104. package/dist/export.js.map +1 -0
  105. package/dist/import.d.ts +3 -0
  106. package/dist/import.js +89 -0
  107. package/dist/import.js.map +1 -0
  108. package/dist/index.d.ts +1 -0
  109. package/dist/index.js +183 -0
  110. package/dist/index.js.map +1 -0
  111. package/dist/init/auth.d.ts +85 -0
  112. package/dist/init/auth.js +194 -0
  113. package/dist/init/auth.js.map +1 -0
  114. package/dist/init/claudemd.d.ts +16 -0
  115. package/dist/init/claudemd.js +62 -0
  116. package/dist/init/claudemd.js.map +1 -0
  117. package/dist/init/index.d.ts +47 -0
  118. package/dist/init/index.js +159 -0
  119. package/dist/init/index.js.map +1 -0
  120. package/dist/init/mcp.d.ts +18 -0
  121. package/dist/init/mcp.js +97 -0
  122. package/dist/init/mcp.js.map +1 -0
  123. package/dist/init/plugin.d.ts +60 -0
  124. package/dist/init/plugin.js +120 -0
  125. package/dist/init/plugin.js.map +1 -0
  126. package/dist/init/scaffold.d.ts +19 -0
  127. package/dist/init/scaffold.js +46 -0
  128. package/dist/init/scaffold.js.map +1 -0
  129. package/dist/init/templates.d.ts +48 -0
  130. package/dist/init/templates.js +147 -0
  131. package/dist/init/templates.js.map +1 -0
  132. package/dist/plugin/.claude-plugin/plugin.json +11 -0
  133. package/dist/plugin/README.md +117 -0
  134. package/dist/plugin/commands/next.md +28 -0
  135. package/dist/plugin/commands/promote.md +30 -0
  136. package/dist/plugin/commands/report.md +26 -0
  137. package/dist/plugin/commands/ship.md +30 -0
  138. package/dist/plugin/skills/backlog-management/SKILL.md +63 -0
  139. package/dist/plugin/skills/backlog-query/SKILL.md +57 -0
  140. package/dist/plugin/skills/feature-kickoff/SKILL.md +112 -0
  141. package/dist/snapshot.d.ts +24 -0
  142. package/dist/snapshot.js +2 -0
  143. package/dist/snapshot.js.map +1 -0
  144. package/dist/token.d.ts +29 -0
  145. package/dist/token.js +99 -0
  146. package/dist/token.js.map +1 -0
  147. package/package.json +52 -0
@@ -0,0 +1,304 @@
1
+ import { z } from 'zod';
2
+ import { SPEC_FIELDS } from './criteria.js';
3
+ // ---- enums (PRODUCT-SPEC §3, §5.2, §5.3, §5.6) -------------------------------
4
+ export const STATUSES = [
5
+ 'backlog',
6
+ 'scheduled',
7
+ 'promoted',
8
+ 'in-progress',
9
+ 'shipped',
10
+ 'rejected',
11
+ ];
12
+ export const CRITERIA_STATUSES = ['draft', 'reviewed', 'locked'];
13
+ export const MATRIX_STATUSES = ['☐', '🟡', '✅', '🔬', '🚀', '⏭️'];
14
+ export const ROLES = ['owner', 'product', 'engineer', 'qa', 'viewer'];
15
+ export const PRIORITIES = ['P0', 'P1', 'P2', 'P3', 'P4'];
16
+ export const TEST_TYPES = [
17
+ 'Unit',
18
+ 'Integration',
19
+ 'E2E',
20
+ 'Code review',
21
+ 'Manual',
22
+ 'Infra',
23
+ 'Telemetry',
24
+ ];
25
+ export const Status = z.enum(STATUSES);
26
+ export const CriteriaStatus = z.enum(CRITERIA_STATUSES);
27
+ export const MatrixStatus = z.enum(MATRIX_STATUSES);
28
+ export const Role = z.enum(ROLES);
29
+ export const Priority = z.enum(PRIORITIES);
30
+ export const TestType = z.enum(TEST_TYPES);
31
+ // ---- ids ----------------------------------------------------------------------
32
+ const ITEM_ID = /^[A-Z][A-Z0-9]*-\d{3,}$/;
33
+ export function isItemId(s) {
34
+ return ITEM_ID.test(s);
35
+ }
36
+ export const ItemId = z.string().regex(ITEM_ID, 'expected PREFIX-NNN');
37
+ const IsoDate = z.string().regex(/^\d{4}-\d{2}-\d{2}$/, 'expected YYYY-MM-DD');
38
+ // ---- item ---------------------------------------------------------------------
39
+ export const Criterion = z.object({
40
+ index: z.number().int().positive(), // AC{n}, stable
41
+ text: z.string().min(1),
42
+ done: z.boolean(),
43
+ });
44
+ /** A body section the schema does not name (e.g. `## Estimated effort`). Kept so canonical export loses nothing. */
45
+ export const ExtraSection = z.object({ heading: z.string().min(1), text: z.string() });
46
+ export const Item = z
47
+ .object({
48
+ id: ItemId,
49
+ title: z.string().min(1),
50
+ status: Status,
51
+ domain: z.string().min(1),
52
+ priority: Priority,
53
+ origin: z.string(),
54
+ created: IsoDate,
55
+ updated: IsoDate,
56
+ prerequisites: z.array(ItemId),
57
+ blocks: z.array(ItemId),
58
+ criteria_status: CriteriaStatus,
59
+ criteria_version: z.number().int().positive().default(1),
60
+ revisit_when: z.string(),
61
+ track: z.string().nullable(),
62
+ shipped_commit: z.string().nullable(),
63
+ production_date: IsoDate.nullable(),
64
+ rejected_reason: z.string().nullable().default(null),
65
+ // body (markdown)
66
+ what: z.string(),
67
+ why: z.string(),
68
+ criteria: z.array(Criterion),
69
+ /** Prose inside `## Acceptance criteria` that is not a checkbox (AI-001's `*Pending — …*`). */
70
+ criteria_notes: z.string().default(''),
71
+ critique: z.string(),
72
+ out_of_scope: z.string(),
73
+ dependencies_note: z.string(),
74
+ extra_sections: z.array(ExtraSection).default([]),
75
+ /** Prose before the first `## ` heading (liblib-meet WL-001 has some). Kept verbatim in canonical export. */
76
+ preamble: z.string().default(''),
77
+ })
78
+ .superRefine((it, ctx) => {
79
+ if (it.status === 'rejected' && !it.rejected_reason) {
80
+ ctx.addIssue({
81
+ code: 'custom',
82
+ path: ['rejected_reason'],
83
+ message: 'rejected_reason is required when status is rejected',
84
+ });
85
+ }
86
+ if (it.status === 'shipped' && (!it.shipped_commit || !it.production_date)) {
87
+ ctx.addIssue({
88
+ code: 'custom',
89
+ path: ['status'],
90
+ message: 'shipped requires shipped_commit and production_date',
91
+ });
92
+ }
93
+ });
94
+ // ---- track --------------------------------------------------------------------
95
+ /** How hard §5.6's ship gate bites: the closed set `Track.qa_enforcement` is derived from. */
96
+ export const QA_ENFORCEMENTS = ['permissive', 'strict'];
97
+ export const Shipment = z.object({
98
+ commit: z.string().min(1),
99
+ production_date: IsoDate,
100
+ shipped_by: z.string(),
101
+ });
102
+ export const Track = z.object({
103
+ slug: z.string().min(1),
104
+ type: z.string().min(1),
105
+ backlog_ids: z.array(ItemId),
106
+ follow_up_backlog: z.array(ItemId).default([]),
107
+ qa_doc: z.string().nullable().default(null),
108
+ qa_enforcement: z.enum(QA_ENFORCEMENTS).default('permissive'),
109
+ spec_drift: z.boolean().default(false),
110
+ shipment: Shipment.nullable().default(null),
111
+ });
112
+ // ---- matrix -------------------------------------------------------------------
113
+ export const LinkedCriterion = z.union([
114
+ z.object({ item: ItemId, ac: z.number().int().positive() }),
115
+ /** Legacy `A1`/`B2` rows link to a README rule, not a criterion (MIG-001 critique). */
116
+ z.object({ legacy: z.string().min(1) }),
117
+ ]);
118
+ export const Evidence = z.object({
119
+ path: z.string().min(1),
120
+ content_type: z.string(),
121
+ uploaded_by: z.string(),
122
+ uploaded_at: z.string(),
123
+ });
124
+ export const MatrixRow = z.object({
125
+ id: z.string().min(1), // `{ITEM}-AC{n}.M{m}` or legacy `A1`
126
+ what_to_verify: z.string(),
127
+ how_to_verify: z.string(),
128
+ /** Free text on import (legacy: "Unit · Manual"); MCP-004 enforces TestType for new rows. */
129
+ test_type: z.string(),
130
+ linked_criterion: LinkedCriterion,
131
+ /** The original "Linked criterion" cell text, so a regenerated file keeps the human-readable link. */
132
+ linked_text: z.string().default(''),
133
+ environment: z.string().nullable().default(null),
134
+ /** null = the cell was not a recognised symbol on import (kept in status_raw). */
135
+ status: MatrixStatus.nullable(),
136
+ status_raw: z.string().default(''),
137
+ notes: z.string(),
138
+ evidence: z.array(Evidence).default([]),
139
+ });
140
+ // ---- org ----------------------------------------------------------------------
141
+ export const Member = z.object({ user_id: z.string().min(1), org: z.string().min(1), role: Role });
142
+ export const Token = z.object({
143
+ id: z.string().min(1),
144
+ user_id: z.string().min(1),
145
+ scope: z.enum(['full', 'read_only']),
146
+ expires_at: z.string().nullable(),
147
+ hash: z.string().min(1),
148
+ });
149
+ export const AuditEvent = z.object({
150
+ who: z.string().min(1),
151
+ via: z.enum(['web', 'cli', 'mcp']),
152
+ actor_kind: z.enum(['human', 'agent']).default('human'),
153
+ when: z.string().min(1),
154
+ action: z.string().min(1),
155
+ target: z.string().min(1),
156
+ before: z.unknown().nullable(),
157
+ after: z.unknown().nullable(),
158
+ reason: z.string().nullable().default(null),
159
+ });
160
+ export const Decision = z.object({
161
+ anchor: z.string().min(1),
162
+ title: z.string(),
163
+ blocks: z.array(z.string()),
164
+ next_step: z.string(),
165
+ status: z.enum(['open', 'resolved']).default('open'),
166
+ });
167
+ // ---- review layer (docs/service/review-layer.md) --------------------------------
168
+ export const SUGGESTION_STATUSES = [
169
+ 'open',
170
+ 'accepted',
171
+ 'declined',
172
+ 'withdrawn',
173
+ 'superseded',
174
+ ];
175
+ export const REVISION_SOURCES = ['edit', 'unlock', 'suggestion_accept', 'ship_reconcile'];
176
+ export const SuggestionStatus = z.enum(SUGGESTION_STATUSES);
177
+ export const RevisionSource = z.enum(REVISION_SOURCES);
178
+ /** §12: "QA owns the text, Engineer proposes via comment" needs a target that can be a matrix row. */
179
+ export const CommentTarget = z.discriminatedUnion('kind', [
180
+ z.object({ kind: z.literal('item') }),
181
+ z.object({ kind: z.literal('criterion'), ac: z.number().int().positive() }),
182
+ z.object({ kind: z.literal('matrix_row'), row_id: z.string().min(1) }),
183
+ ]);
184
+ /** Discussion. Immutable once posted — no edit, no delete; if you were wrong, post another. */
185
+ export const Comment = z.object({
186
+ id: z.string().min(1),
187
+ item_id: ItemId,
188
+ target: CommentTarget.default({ kind: 'item' }),
189
+ body: z.string().min(1),
190
+ created_by: z.string().min(1),
191
+ created_at: z.string().min(1),
192
+ });
193
+ /** A proposed change to a **locked** item, held until Product rules on it (§5.4 rule 4). */
194
+ export const Suggestion = z.object({
195
+ id: z.string().min(1),
196
+ item_id: ItemId,
197
+ /** The version it was filed against — what makes `superseded` mechanical. */
198
+ criteria_version: z.number().int().positive(),
199
+ target: CommentTarget.default({ kind: 'item' }),
200
+ text: z.string().min(1),
201
+ rationale: z.string().min(1),
202
+ status: SuggestionStatus.default('open'),
203
+ created_by: z.string().min(1),
204
+ created_at: z.string().min(1),
205
+ resolved_by: z.string().nullable().default(null),
206
+ resolved_at: z.string().nullable().default(null),
207
+ resolution_note: z.string().nullable().default(null),
208
+ });
209
+ export const RevisionField = z.object({
210
+ field: z.enum(SPEC_FIELDS),
211
+ before: z.unknown(),
212
+ after: z.unknown(),
213
+ });
214
+ /**
215
+ * The record of a spec-field change that already happened. Field-level diffs, never a whole item
216
+ * (SVC-004 critique). `id` is null until the store assigns one — core builds revisions, it does
217
+ * not number them.
218
+ */
219
+ export const Revision = z.object({
220
+ id: z.string().min(1).nullable().default(null),
221
+ item_id: ItemId,
222
+ version_before: z.number().int().positive(),
223
+ version_after: z.number().int().positive(),
224
+ fields: z.array(RevisionField),
225
+ source: RevisionSource,
226
+ reason: z.string().nullable().default(null),
227
+ changed_by: z.string().min(1),
228
+ changed_at: z.string().min(1),
229
+ });
230
+ // ---- matrix, DB-shaped (MCP-004) ------------------------------------------------
231
+ // Additive: the `MatrixRow`/`Evidence` above are the markdown-era shapes the importer round-trips
232
+ // (free-text `test_type`, nullable `status`, legacy links). The records below are what
233
+ // `backlog.matrix_rows` / `backlog.evidence` hold — every field constrained, nothing legacy.
234
+ /** A matrix row always links to a real criterion here: the legacy `A1` form has no DB home. */
235
+ export const MatrixCriterionRef = z.object({ item: ItemId, ac: z.number().int().positive() });
236
+ export const EvidenceRecord = z.object({
237
+ id: z.string().min(1),
238
+ path: z.string().min(1),
239
+ filename: z.string().min(1),
240
+ content_type: z.string().min(1),
241
+ size_bytes: z.number().int().positive(),
242
+ uploaded_by: z.string().min(1),
243
+ created_at: z.string().min(1),
244
+ /** Null until the object is confirmed against Storage (DECISION-019's second step). */
245
+ uploaded_at: z.string().nullable().default(null),
246
+ });
247
+ export const MatrixRowRecord = z.object({
248
+ /** The row's uuid; `row_id` is the human `{ITEM}-AC{n}.M{m}` id, unique within the track. */
249
+ id: z.string().min(1),
250
+ track: z.string().min(1),
251
+ row_id: z.string().min(1),
252
+ linked_criterion: MatrixCriterionRef,
253
+ /** The criterion text as it read when the row was written — the drift comparand. */
254
+ linked_text: z.string(),
255
+ criteria_version: z.number().int().positive(),
256
+ what_to_verify: z.string(),
257
+ how_to_verify: z.string().default(''),
258
+ test_type: TestType,
259
+ environment: z.string().nullable().default(null),
260
+ status: MatrixStatus,
261
+ notes: z.string().default(''),
262
+ evidence: z.array(EvidenceRecord).default([]),
263
+ updated_by: z.string().nullable().default(null),
264
+ updated_at: z.string().min(1),
265
+ });
266
+ /** What `scaffoldMatrix` emits: a row the store has not numbered or timestamped yet. */
267
+ export const NewMatrixRow = z.object({
268
+ row_id: z.string().min(1),
269
+ linked_criterion: MatrixCriterionRef,
270
+ linked_text: z.string(),
271
+ criteria_version: z.number().int().positive(),
272
+ what_to_verify: z.string(),
273
+ how_to_verify: z.string().default(''),
274
+ test_type: TestType.default('Manual'),
275
+ environment: z.string().nullable().default(null),
276
+ status: MatrixStatus.default('☐'),
277
+ notes: z.string().default(''),
278
+ });
279
+ /**
280
+ * What scaffolding needs about an existing row: which criterion, which M, whether the row is
281
+ * live — and the criterion text it quotes, because a `⏭️` row keeps covering *that* text and
282
+ * nothing else.
283
+ */
284
+ export const MatrixRowRef = z.object({
285
+ row_id: z.string().min(1),
286
+ linked_criterion: MatrixCriterionRef,
287
+ /** The criterion text the row was written against; `''` never matches a live criterion. */
288
+ linked_text: z.string(),
289
+ status: MatrixStatus,
290
+ });
291
+ /** DECISION-020: the QA queue is grouped `track → environment → rows`, Viewer-readable. */
292
+ export const QaQueueGroup = z.object({
293
+ track: z.string().min(1),
294
+ /** `'any'` stands in for a row with no environment. */
295
+ environment: z.string().min(1),
296
+ rows: z.array(MatrixRowRecord),
297
+ });
298
+ export const QaQueue = z.object({
299
+ /** `✅` — implemented, waiting to be verified on staging. */
300
+ waiting_staging: z.array(QaQueueGroup),
301
+ /** `🔬` — verified on staging, waiting to be verified in production. */
302
+ waiting_production: z.array(QaQueueGroup),
303
+ });
304
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,iFAAiF;AACjF,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,SAAS;IACT,WAAW;IACX,UAAU;IACV,aAAa;IACb,SAAS;IACT,UAAU;CACF,CAAC;AACX,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,OAAO,EAAE,UAAU,EAAE,QAAQ,CAAU,CAAC;AAC1E,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAU,CAAC;AAC3E,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,CAAU,CAAC;AAC/E,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAU,CAAC;AAClE,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,MAAM;IACN,aAAa;IACb,KAAK;IACL,aAAa;IACb,QAAQ;IACR,OAAO;IACP,WAAW;CACH,CAAC;AAEX,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AACvC,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;AACxD,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;AACpD,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAClC,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AAC3C,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AAS3C,kFAAkF;AAClF,MAAM,OAAO,GAAG,yBAAyB,CAAC;AAC1C,MAAM,UAAU,QAAQ,CAAC,CAAS;IAChC,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACzB,CAAC;AACD,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,qBAAqB,CAAC,CAAC;AACvE,MAAM,OAAO,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,qBAAqB,EAAE,qBAAqB,CAAC,CAAC;AAE/E,kFAAkF;AAClF,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC;IAChC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,EAAE,gBAAgB;IACpD,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE;CAClB,CAAC,CAAC;AAGH,oHAAoH;AACpH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAGvF,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC;KAClB,MAAM,CAAC;IACN,EAAE,EAAE,MAAM;IACV,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACxB,MAAM,EAAE,MAAM;IACd,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACzB,QAAQ,EAAE,QAAQ;IAClB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;IAClB,OAAO,EAAE,OAAO;IAChB,OAAO,EAAE,OAAO;IAChB,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC;IAC9B,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC;IACvB,eAAe,EAAE,cAAc;IAC/B,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IACxD,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;IACxB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACrC,eAAe,EAAE,OAAO,CAAC,QAAQ,EAAE;IACnC,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IACpD,kBAAkB;IAClB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;IACf,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC;IAC5B,+FAA+F;IAC/F,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IACtC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;IACxB,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE;IAC7B,cAAc,EAAE,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACjD,6GAA6G;IAC7G,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;CACjC,CAAC;KACD,WAAW,CAAC,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE;IACvB,IAAI,EAAE,CAAC,MAAM,KAAK,UAAU,IAAI,CAAC,EAAE,CAAC,eAAe,EAAE,CAAC;QACpD,GAAG,CAAC,QAAQ,CAAC;YACX,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,CAAC,iBAAiB,CAAC;YACzB,OAAO,EAAE,qDAAqD;SAC/D,CAAC,CAAC;IACL,CAAC;IACD,IAAI,EAAE,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,CAAC,EAAE,CAAC,cAAc,IAAI,CAAC,EAAE,CAAC,eAAe,CAAC,EAAE,CAAC;QAC3E,GAAG,CAAC,QAAQ,CAAC;YACX,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,CAAC,QAAQ,CAAC;YAChB,OAAO,EAAE,qDAAqD;SAC/D,CAAC,CAAC;IACL,CAAC;AACH,CAAC,CAAC,CAAC;AAGL,kFAAkF;AAClF,8FAA8F;AAC9F,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,YAAY,EAAE,QAAQ,CAAU,CAAC;AAGjE,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/B,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACzB,eAAe,EAAE,OAAO;IACxB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;CACvB,CAAC,CAAC;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC;IAC5B,iBAAiB,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IAC9C,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAC3C,cAAc,EAAE,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC;IAC7D,UAAU,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;IACtC,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;CAC5C,CAAC,CAAC;AAGH,kFAAkF;AAClF,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC;IACrC,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC;IAC3D,uFAAuF;IACvF,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;CACxC,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;IACxB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;CACxB,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC;IAChC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,qCAAqC;IAC5D,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE;IAC1B,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE;IACzB,6FAA6F;IAC7F,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,gBAAgB,EAAE,eAAe;IACjC,sGAAsG;IACtG,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IACnC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAChD,kFAAkF;IAClF,MAAM,EAAE,YAAY,CAAC,QAAQ,EAAE;IAC/B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IAClC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;CACxC,CAAC,CAAC;AAGH,kFAAkF;AAClF,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;AAGnG,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5B,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACrB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1B,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACpC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACjC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CACxB,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC;IACjC,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACtB,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IAClC,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;IACvD,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACzB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACzB,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAC9B,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAC7B,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;CAC5C,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/B,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACzB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAC3B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;CACrD,CAAC,CAAC;AAGH,oFAAoF;AACpF,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,MAAM;IACN,UAAU;IACV,UAAU;IACV,WAAW;IACX,YAAY;CACJ,CAAC;AACX,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,mBAAmB,EAAE,gBAAgB,CAAU,CAAC;AAEnG,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;AAC5D,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;AAIvD,sGAAsG;AACtG,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC,kBAAkB,CAAC,MAAM,EAAE;IACxD,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;IACrC,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC;IAC3E,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;CACvE,CAAC,CAAC;AAGH,+FAA+F;AAC/F,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9B,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACrB,OAAO,EAAE,MAAM;IACf,MAAM,EAAE,aAAa,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAC/C,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CAC9B,CAAC,CAAC;AAGH,4FAA4F;AAC5F,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC;IACjC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACrB,OAAO,EAAE,MAAM;IACf,6EAA6E;IAC7E,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IAC7C,MAAM,EAAE,aAAa,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAC/C,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5B,MAAM,EAAE,gBAAgB,CAAC,OAAO,CAAC,MAAM,CAAC;IACxC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7B,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAChD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAChD,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;CACrD,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC;IACpC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC;IAC1B,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE;IACnB,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE;CACnB,CAAC,CAAC;AAGH;;;;GAIG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/B,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAC9C,OAAO,EAAE,MAAM;IACf,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IAC3C,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IAC1C,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC;IAC9B,MAAM,EAAE,cAAc;IACtB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAC3C,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CAC9B,CAAC,CAAC;AAGH,oFAAoF;AACpF,kGAAkG;AAClG,uFAAuF;AACvF,6FAA6F;AAE7F,+FAA+F;AAC/F,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;AAG9F,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IACrC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACrB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3B,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC/B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IACvC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7B,uFAAuF;IACvF,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;CACjD,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC;IACtC,6FAA6F;IAC7F,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACrB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACxB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACzB,gBAAgB,EAAE,kBAAkB;IACpC,oFAAoF;IACpF,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IAC7C,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE;IAC1B,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IACrC,SAAS,EAAE,QAAQ;IACnB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAChD,MAAM,EAAE,YAAY;IACpB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IAC7B,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IAC7C,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAC/C,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CAC9B,CAAC,CAAC;AAGH,wFAAwF;AACxF,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IACnC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACzB,gBAAgB,EAAE,kBAAkB;IACpC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IAC7C,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE;IAC1B,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IACrC,SAAS,EAAE,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC;IACrC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAChD,MAAM,EAAE,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC;IACjC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;CAC9B,CAAC,CAAC;AAGH;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IACnC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACzB,gBAAgB,EAAE,kBAAkB;IACpC,2FAA2F;IAC3F,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,MAAM,EAAE,YAAY;CACrB,CAAC,CAAC;AAGH,2FAA2F;AAC3F,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IACnC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACxB,uDAAuD;IACvD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9B,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC;CAC/B,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9B,4DAA4D;IAC5D,eAAe,EAAE,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC;IACtC,wEAAwE;IACxE,kBAAkB,EAAE,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC;CAC1C,CAAC,CAAC"}
@@ -0,0 +1,23 @@
1
+ import type { LoopState } from './loop.js';
2
+ import type { Item, Role } from './schema.js';
3
+ export interface ShipGateInput {
4
+ items: readonly Item[];
5
+ lastReport: LoopState | null;
6
+ /** §3.1 Ship is Product+, but only the Owner may ship without a COMPLETE loop, and must say why. */
7
+ override?: {
8
+ reason: string;
9
+ role: Role;
10
+ };
11
+ }
12
+ export type ShipGateResult = {
13
+ ok: true;
14
+ } | {
15
+ ok: false;
16
+ reasons: string[];
17
+ };
18
+ /**
19
+ * The gate `ship_track` runs before writing a commit and a production date: every item is on the
20
+ * track (promoted or in-progress) and the loop reached `COMPLETE`. Returns every refusal, not the
21
+ * first — a caller that has to fix three things should learn all three at once.
22
+ */
23
+ export declare function shipGate(input: ShipGateInput): ShipGateResult;
@@ -0,0 +1,31 @@
1
+ /**
2
+ * The gate `ship_track` runs before writing a commit and a production date: every item is on the
3
+ * track (promoted or in-progress) and the loop reached `COMPLETE`. Returns every refusal, not the
4
+ * first — a caller that has to fix three things should learn all three at once.
5
+ */
6
+ export function shipGate(input) {
7
+ const reasons = [];
8
+ if (input.items.length === 0)
9
+ reasons.push('the track has no items');
10
+ for (const it of input.items) {
11
+ if (it.status !== 'promoted' && it.status !== 'in-progress')
12
+ reasons.push(`${it.id} is ${it.status}, not promoted/in-progress`);
13
+ }
14
+ const complete = input.lastReport?.step === 'COMPLETE' && input.lastReport?.status === 'COMPLETE';
15
+ if (!complete) {
16
+ const ov = input.override;
17
+ if (ov === undefined) {
18
+ reasons.push(input.lastReport === null
19
+ ? 'the track has no progress report; the loop must reach COMPLETE (or an Owner must override)'
20
+ : `the last progress report is ${input.lastReport.step}/${input.lastReport.status}, not COMPLETE/COMPLETE`);
21
+ }
22
+ else {
23
+ if (ov.role !== 'owner')
24
+ reasons.push(`only the owner may override the ship gate, not ${ov.role}`);
25
+ if (!ov.reason.trim())
26
+ reasons.push('a ship-gate override requires a non-empty reason');
27
+ }
28
+ }
29
+ return reasons.length === 0 ? { ok: true } : { ok: false, reasons };
30
+ }
31
+ //# sourceMappingURL=ship.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ship.js","sourceRoot":"","sources":["../src/ship.ts"],"names":[],"mappings":"AAWA;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAoB;IAC3C,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;IACrE,KAAK,MAAM,EAAE,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAC7B,IAAI,EAAE,CAAC,MAAM,KAAK,UAAU,IAAI,EAAE,CAAC,MAAM,KAAK,aAAa;YACzD,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,MAAM,4BAA4B,CAAC,CAAC;IACvE,CAAC;IAED,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU,EAAE,IAAI,KAAK,UAAU,IAAI,KAAK,CAAC,UAAU,EAAE,MAAM,KAAK,UAAU,CAAC;IAClG,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,EAAE,GAAG,KAAK,CAAC,QAAQ,CAAC;QAC1B,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;YACrB,OAAO,CAAC,IAAI,CACV,KAAK,CAAC,UAAU,KAAK,IAAI;gBACvB,CAAC,CAAC,4FAA4F;gBAC9F,CAAC,CAAC,+BAA+B,KAAK,CAAC,UAAU,CAAC,IAAI,IAAI,KAAK,CAAC,UAAU,CAAC,MAAM,yBAAyB,CAC7G,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,IAAI,EAAE,CAAC,IAAI,KAAK,OAAO;gBACrB,OAAO,CAAC,IAAI,CAAC,kDAAkD,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;YAC5E,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE;gBAAE,OAAO,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC;QAC1F,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AACtE,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { type SpecField } from './criteria.js';
2
+ import type { Item } from './schema.js';
3
+ export interface FieldChange {
4
+ before: unknown;
5
+ after: unknown;
6
+ }
7
+ export type SpecDiff = Partial<Record<SpecField, FieldChange>>;
8
+ /**
9
+ * Field-level diff over `SPEC_FIELDS` only — never the whole item, never a non-spec column.
10
+ * `criteria` is an array of objects, so it is compared structurally (`deepEqual`): an item that
11
+ * has been through `jsonb` and back must not read as changed.
12
+ */
13
+ export declare function specDiff(before: Item, after: Item): SpecDiff;
14
+ /** The same diff in `Revision.fields` shape, in `SPEC_FIELDS` order. */
15
+ export declare function specDiffFields(before: Item, after: Item): Array<{
16
+ field: SpecField;
17
+ before: unknown;
18
+ after: unknown;
19
+ }>;
@@ -0,0 +1,25 @@
1
+ import { SPEC_FIELDS } from './criteria.js';
2
+ import { deepEqual } from './util/deep-equal.js';
3
+ /**
4
+ * Field-level diff over `SPEC_FIELDS` only — never the whole item, never a non-spec column.
5
+ * `criteria` is an array of objects, so it is compared structurally (`deepEqual`): an item that
6
+ * has been through `jsonb` and back must not read as changed.
7
+ */
8
+ export function specDiff(before, after) {
9
+ const out = {};
10
+ for (const field of SPEC_FIELDS) {
11
+ if (!deepEqual(before[field], after[field]))
12
+ out[field] = { before: before[field], after: after[field] };
13
+ }
14
+ return out;
15
+ }
16
+ /** The same diff in `Revision.fields` shape, in `SPEC_FIELDS` order. */
17
+ export function specDiffFields(before, after) {
18
+ const diff = specDiff(before, after);
19
+ return SPEC_FIELDS.filter((f) => diff[f] !== undefined).map((field) => ({
20
+ field,
21
+ before: diff[field].before,
22
+ after: diff[field].after,
23
+ }));
24
+ }
25
+ //# sourceMappingURL=spec-diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spec-diff.js","sourceRoot":"","sources":["../src/spec-diff.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAkB,MAAM,eAAe,CAAC;AAE5D,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAQjD;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAC,MAAY,EAAE,KAAW;IAChD,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,KAAK,IAAI,WAAW,EAAE,CAAC;QAChC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;YACzC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;IAChE,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,cAAc,CAC5B,MAAY,EACZ,KAAW;IAEX,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACrC,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACtE,KAAK;QACL,MAAM,EAAG,IAAI,CAAC,KAAK,CAAiB,CAAC,MAAM;QAC3C,KAAK,EAAG,IAAI,CAAC,KAAK,CAAiB,CAAC,KAAK;KAC1C,CAAC,CAAC,CAAC;AACN,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { Item, Status } from './schema.js';
2
+ /** PRODUCT-SPEC §5.3 — one-way except scheduled→backlog; rejected only from backlog/scheduled. */
3
+ export declare const STATUS_TRANSITIONS: ReadonlyArray<readonly [Status, Status]>;
4
+ export declare function canTransitionStatus(from: Status, to: Status): boolean;
5
+ export declare function transitionStatus(item: Item, to: Status, opts?: {
6
+ rejected_reason?: string;
7
+ }): Item;
@@ -0,0 +1,25 @@
1
+ import { ReasonRequiredError, TransitionError } from './errors.js';
2
+ /** PRODUCT-SPEC §5.3 — one-way except scheduled→backlog; rejected only from backlog/scheduled. */
3
+ export const STATUS_TRANSITIONS = [
4
+ ['backlog', 'scheduled'],
5
+ ['scheduled', 'promoted'],
6
+ ['promoted', 'in-progress'],
7
+ ['in-progress', 'shipped'],
8
+ ['scheduled', 'backlog'],
9
+ ['backlog', 'rejected'],
10
+ ['scheduled', 'rejected'],
11
+ ];
12
+ export function canTransitionStatus(from, to) {
13
+ return STATUS_TRANSITIONS.some(([f, t]) => f === from && t === to);
14
+ }
15
+ export function transitionStatus(item, to, opts = {}) {
16
+ if (!canTransitionStatus(item.status, to))
17
+ throw new TransitionError('status', item.status, to);
18
+ if (to === 'rejected') {
19
+ if (!opts.rejected_reason?.trim())
20
+ throw new ReasonRequiredError('reject');
21
+ return { ...item, status: to, rejected_reason: opts.rejected_reason };
22
+ }
23
+ return { ...item, status: to };
24
+ }
25
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAGnE,kGAAkG;AAClG,MAAM,CAAC,MAAM,kBAAkB,GAA6C;IAC1E,CAAC,SAAS,EAAE,WAAW,CAAC;IACxB,CAAC,WAAW,EAAE,UAAU,CAAC;IACzB,CAAC,UAAU,EAAE,aAAa,CAAC;IAC3B,CAAC,aAAa,EAAE,SAAS,CAAC;IAC1B,CAAC,WAAW,EAAE,SAAS,CAAC;IACxB,CAAC,SAAS,EAAE,UAAU,CAAC;IACvB,CAAC,WAAW,EAAE,UAAU,CAAC;CAC1B,CAAC;AAEF,MAAM,UAAU,mBAAmB,CAAC,IAAY,EAAE,EAAU;IAC1D,OAAO,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,IAAU,EACV,EAAU,EACV,OAAqC,EAAE;IAEvC,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;QAAE,MAAM,IAAI,eAAe,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAChG,IAAI,EAAE,KAAK,UAAU,EAAE,CAAC;QACtB,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,IAAI,EAAE;YAAE,MAAM,IAAI,mBAAmB,CAAC,QAAQ,CAAC,CAAC;QAC3E,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,eAAe,EAAE,IAAI,CAAC,eAAe,EAAE,CAAC;IACxE,CAAC;IACD,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;AACjC,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Structural equality: key-order-insensitive for plain objects, order-sensitive for arrays.
3
+ *
4
+ * `JSON.stringify(a) === JSON.stringify(b)` is not usable for "is this object still pristine?":
5
+ * once a value has been through Postgres `jsonb` its key order is whatever Postgres chose, so a
6
+ * byte-identical item would compare unequal and be silently re-emitted in canonical form.
7
+ */
8
+ export declare function deepEqual(a: unknown, b: unknown): boolean;
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Structural equality: key-order-insensitive for plain objects, order-sensitive for arrays.
3
+ *
4
+ * `JSON.stringify(a) === JSON.stringify(b)` is not usable for "is this object still pristine?":
5
+ * once a value has been through Postgres `jsonb` its key order is whatever Postgres chose, so a
6
+ * byte-identical item would compare unequal and be silently re-emitted in canonical form.
7
+ */
8
+ export function deepEqual(a, b) {
9
+ if (Object.is(a, b))
10
+ return true;
11
+ if (typeof a !== typeof b)
12
+ return false;
13
+ if (a === null || b === null || typeof a !== 'object')
14
+ return false;
15
+ const aArr = Array.isArray(a);
16
+ if (aArr !== Array.isArray(b))
17
+ return false;
18
+ if (aArr) {
19
+ const x = a;
20
+ const y = b;
21
+ return x.length === y.length && x.every((v, i) => deepEqual(v, y[i]));
22
+ }
23
+ const x = a;
24
+ const y = b;
25
+ const ka = Object.keys(x);
26
+ const kb = Object.keys(y);
27
+ if (ka.length !== kb.length)
28
+ return false;
29
+ return ka.every((k) => Object.hasOwn(y, k) && deepEqual(x[k], y[k]));
30
+ }
31
+ //# sourceMappingURL=deep-equal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deep-equal.js","sourceRoot":"","sources":["../../src/util/deep-equal.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,CAAU,EAAE,CAAU;IAC9C,IAAI,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACjC,IAAI,OAAO,CAAC,KAAK,OAAO,CAAC;QAAE,OAAO,KAAK,CAAC;IACxC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACpE,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAC9B,IAAI,IAAI,KAAK,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAC5C,IAAI,IAAI,EAAE,CAAC;QACT,MAAM,CAAC,GAAG,CAAc,CAAC;QACzB,MAAM,CAAC,GAAG,CAAc,CAAC;QACzB,OAAO,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACxE,CAAC;IACD,MAAM,CAAC,GAAG,CAA4B,CAAC;IACvC,MAAM,CAAC,GAAG,CAA4B,CAAC;IACvC,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC1B,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC1B,IAAI,EAAE,CAAC,MAAM,KAAK,EAAE,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAC1C,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,EAAG,CAA6B,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACpG,CAAC"}
package/dist/api.d.ts ADDED
@@ -0,0 +1,46 @@
1
+ /**
2
+ * The single HTTP call site in the CLI (DECISION-025). The CLI speaks REST `/v1` with a PAT:
3
+ * one call per command, the same `{ error, message }` refusal contract as `/mcp`, and no
4
+ * retries — every write in the register is non-idempotent.
5
+ *
6
+ * `src/no-stray-fetch.test.ts` fails the build if any other module calls `fetch`.
7
+ */
8
+ export type HttpMethod = 'GET' | 'POST' | 'PATCH' | 'DELETE';
9
+ /** A refusal the CLI can render. `status: 0` means the request never reached the service. */
10
+ export declare class ApiError extends Error {
11
+ readonly status: number;
12
+ readonly code: string;
13
+ constructor(status: number, code: string, message: string);
14
+ }
15
+ export interface RequestConfig {
16
+ url: string;
17
+ /** Present for symmetry with `BacklogConfig`; the request itself never needs it. */
18
+ project?: string | undefined;
19
+ fetchImpl?: typeof fetch | undefined;
20
+ timeoutMs?: number | undefined;
21
+ }
22
+ /**
23
+ * One request. A 2xx JSON body is parsed and returned (`204` and an empty body are `null`);
24
+ * anything else throws `ApiError` built from the service's `{ error, message }`, and a body
25
+ * that is not that shape is `internal`. A transport failure is `status: 0`/`unreachable`.
26
+ */
27
+ export declare function request(cfg: RequestConfig, token: string | null, method: HttpMethod, path: string, body?: unknown): Promise<unknown>;
28
+ export declare const get: (cfg: RequestConfig, token: string | null, path: string) => Promise<unknown>;
29
+ export declare const post: (cfg: RequestConfig, token: string | null, path: string, body?: unknown) => Promise<unknown>;
30
+ export declare const patch: (cfg: RequestConfig, token: string | null, path: string, body?: unknown) => Promise<unknown>;
31
+ export declare const del: (cfg: RequestConfig, token: string | null, path: string) => Promise<unknown>;
32
+ export interface ApiClient {
33
+ url: string;
34
+ get(path: string): Promise<unknown>;
35
+ post(path: string, body?: unknown): Promise<unknown>;
36
+ patch(path: string, body?: unknown): Promise<unknown>;
37
+ del(path: string): Promise<unknown>;
38
+ }
39
+ /** A config + token bound once, so a command never handles the token itself. */
40
+ export declare function createClient(opts: {
41
+ url: string;
42
+ token: string | null;
43
+ project?: string | undefined;
44
+ fetchImpl?: typeof fetch | undefined;
45
+ timeoutMs?: number | undefined;
46
+ }): ApiClient;