@company-semantics/contracts 0.126.0 → 0.128.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@company-semantics/contracts",
3
- "version": "0.126.0",
3
+ "version": "0.128.0",
4
4
  "private": false,
5
5
  "repository": {
6
6
  "type": "git",
@@ -0,0 +1,40 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://company-semantics.dev/schemas/repo-ci-result.json",
4
+ "title": "RepoCiResult",
5
+ "description": "Per-repo result of a cross-repo CI health aggregation run (e.g. pnpm ci:all). Denormalized view of guard-result.schema.json: the top-level errors and warnings are scalar counts; guardResult is the full tiered detail. The scalars MUST equal the aggregated totals in guardResult.results when guardResult is present. Producers derive the scalars from guardResult, never the reverse.",
6
+ "type": "object",
7
+ "required": ["repo", "status", "errors", "warnings", "durationMs"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "repo": {
11
+ "type": "string",
12
+ "minLength": 1,
13
+ "description": "Sibling repo name without the company-semantics- prefix (e.g. 'backend', 'contracts')."
14
+ },
15
+ "status": {
16
+ "type": "string",
17
+ "enum": ["pass", "fail"],
18
+ "description": "pass when the repo's ci:local exited 0 and the guard artifact was produced; fail otherwise."
19
+ },
20
+ "errors": {
21
+ "type": "integer",
22
+ "minimum": 0,
23
+ "description": "Total errors across all guard tiers. MUST equal the sum of guardResult.results[tier].errors.length across all tiers when guardResult is present."
24
+ },
25
+ "warnings": {
26
+ "type": "integer",
27
+ "minimum": 0,
28
+ "description": "Total warnings across all guard tiers. MUST equal the sum of guardResult.results[tier].warnings.length across all tiers when guardResult is present."
29
+ },
30
+ "durationMs": {
31
+ "type": "integer",
32
+ "minimum": 0,
33
+ "description": "Wall-clock duration of the repo's ci:local run in milliseconds."
34
+ },
35
+ "guardResult": {
36
+ "$ref": "guard-result.schema.json",
37
+ "description": "Optional full guard orchestrator output for the repo. When present, errors and warnings MUST be derived from it."
38
+ }
39
+ }
40
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * CI Results Vocabulary Barrel
3
+ *
4
+ * Re-exports the per-repo cross-repo CI aggregation result vocabulary.
5
+ * Import from '@company-semantics/contracts/ci-results' or '@company-semantics/contracts'.
6
+ *
7
+ * @see ADR-CONT-033 for contracts boundary rationale
8
+ */
9
+
10
+ export type {
11
+ GuardTier,
12
+ GuardResultPayload,
13
+ RepoCiResult,
14
+ } from './repo-ci-result';
15
+
16
+ export { assertRepoCiResultConsistent } from './repo-ci-result';
@@ -0,0 +1,94 @@
1
+ /**
2
+ * RepoCiResult — per-repo result of a cross-repo CI health aggregation run.
3
+ *
4
+ * Mirrors schemas/repo-ci-result.schema.json. The JSON schema is the source
5
+ * of truth; this file is the TypeScript projection.
6
+ */
7
+
8
+ export type GuardTier =
9
+ | 'structural'
10
+ | 'behavioral'
11
+ | 'invariants'
12
+ | 'evolution'
13
+ | 'meta';
14
+
15
+ /**
16
+ * Minimal structural shape of a guard orchestrator result payload.
17
+ * The full shape is described by guard-result.schema.json; this is the
18
+ * subset assertRepoCiResultConsistent needs to cross-check against the
19
+ * RepoCiResult scalars.
20
+ */
21
+ export interface GuardResultPayload {
22
+ readonly results: Readonly<
23
+ Record<
24
+ GuardTier,
25
+ { readonly errors: readonly unknown[]; readonly warnings: readonly unknown[] }
26
+ >
27
+ >;
28
+ }
29
+
30
+ /**
31
+ * Per-repo result of a cross-repo CI health aggregation run.
32
+ *
33
+ * Load-bearing invariant: when guardResult is present, errors and warnings
34
+ * MUST equal the aggregated counts across all tiers in guardResult.results.
35
+ * Producers derive the scalars from guardResult, never the reverse.
36
+ * Consumers can enforce this at runtime via assertRepoCiResultConsistent.
37
+ */
38
+ export interface RepoCiResult {
39
+ /** Sibling repo name without the 'company-semantics-' prefix. */
40
+ readonly repo: string;
41
+ /** pass when ci:local exited 0 and the guard artifact was produced; fail otherwise. */
42
+ readonly status: 'pass' | 'fail';
43
+ /**
44
+ * Total errors across all guard tiers.
45
+ * MUST equal the sum of guardResult.results[tier].errors.length across
46
+ * all tiers when guardResult is present.
47
+ */
48
+ readonly errors: number;
49
+ /**
50
+ * Total warnings across all guard tiers.
51
+ * MUST equal the sum of guardResult.results[tier].warnings.length across
52
+ * all tiers when guardResult is present.
53
+ */
54
+ readonly warnings: number;
55
+ /** Wall-clock duration of ci:local in milliseconds. */
56
+ readonly durationMs: number;
57
+ /** Optional full guard orchestrator output. */
58
+ readonly guardResult?: GuardResultPayload;
59
+ }
60
+
61
+ const TIERS: readonly GuardTier[] = [
62
+ 'structural',
63
+ 'behavioral',
64
+ 'invariants',
65
+ 'evolution',
66
+ 'meta',
67
+ ];
68
+
69
+ /**
70
+ * Throws when result.guardResult is present and its aggregated tier counts
71
+ * do not match result.errors / result.warnings. Enforces the load-bearing
72
+ * derivation invariant of the RepoCiResult contract at runtime.
73
+ */
74
+ export function assertRepoCiResultConsistent(result: RepoCiResult): void {
75
+ if (!result.guardResult) return;
76
+ let errorSum = 0;
77
+ let warningSum = 0;
78
+ for (const tier of TIERS) {
79
+ const tierResult = result.guardResult.results[tier];
80
+ if (!tierResult) continue;
81
+ errorSum += tierResult.errors.length;
82
+ warningSum += tierResult.warnings.length;
83
+ }
84
+ if (errorSum !== result.errors) {
85
+ throw new Error(
86
+ `RepoCiResult invariant violation: repo=${result.repo} errors=${result.errors} but guardResult aggregates to ${errorSum}`,
87
+ );
88
+ }
89
+ if (warningSum !== result.warnings) {
90
+ throw new Error(
91
+ `RepoCiResult invariant violation: repo=${result.repo} warnings=${result.warnings} but guardResult aggregates to ${warningSum}`,
92
+ );
93
+ }
94
+ }
@@ -157,6 +157,7 @@ export {
157
157
  ExecutionTimelineResponseSchema,
158
158
  ConfirmExecutionResponseSchema,
159
159
  RejectExecutionResponseSchema,
160
+ StartExecutionResponseSchema,
160
161
  } from './schemas'
161
162
 
162
163
  export type {
@@ -166,4 +167,5 @@ export type {
166
167
  ExecutionTimelineResponse,
167
168
  ConfirmExecutionResponse,
168
169
  RejectExecutionResponse,
170
+ StartExecutionResponse,
169
171
  } from './schemas'
@@ -93,3 +93,10 @@ export const RejectExecutionResponseSchema = z.object({
93
93
  })
94
94
 
95
95
  export type RejectExecutionResponse = z.infer<typeof RejectExecutionResponseSchema>
96
+
97
+ export const StartExecutionResponseSchema = z.object({
98
+ executionId: z.string().uuid(),
99
+ redirectUrl: z.string().optional(),
100
+ })
101
+
102
+ export type StartExecutionResponse = z.infer<typeof StartExecutionResponseSchema>
@@ -42,6 +42,8 @@ export {
42
42
  AccountDeleteResponseSchema,
43
43
  AccountConfirmDeletionResponseSchema,
44
44
  AccountCancelDeletionResponseSchema,
45
+ BannerDismissedListResponseSchema,
46
+ BannerDismissResponseSchema,
45
47
  } from './schemas';
46
48
  export type {
47
49
  MeResponse,
@@ -55,4 +57,6 @@ export type {
55
57
  AccountDeleteResponse,
56
58
  AccountConfirmDeletionResponse,
57
59
  AccountCancelDeletionResponse,
60
+ BannerDismissedListResponse,
61
+ BannerDismissResponse,
58
62
  } from './schemas';
@@ -222,3 +222,23 @@ export const AccountCancelDeletionResponseSchema = z.object({
222
222
  });
223
223
 
224
224
  export type AccountCancelDeletionResponse = z.infer<typeof AccountCancelDeletionResponseSchema>;
225
+
226
+ // ---------------------------------------------------------------------------
227
+ // GET /api/user/preferences/dismissed-banners
228
+ // ---------------------------------------------------------------------------
229
+
230
+ export const BannerDismissedListResponseSchema = z.object({
231
+ bannerIds: z.array(z.string()),
232
+ });
233
+
234
+ export type BannerDismissedListResponse = z.infer<typeof BannerDismissedListResponseSchema>;
235
+
236
+ // ---------------------------------------------------------------------------
237
+ // POST /api/user/preferences/dismissed-banners/:bannerId
238
+ // ---------------------------------------------------------------------------
239
+
240
+ export const BannerDismissResponseSchema = z.object({
241
+ success: z.literal(true),
242
+ });
243
+
244
+ export type BannerDismissResponse = z.infer<typeof BannerDismissResponseSchema>;
package/src/index.ts CHANGED
@@ -98,6 +98,17 @@ export {
98
98
  SOC2_SCHEMA_VERSION,
99
99
  } from './guards/index'
100
100
 
101
+ // Cross-repo CI aggregation vocabulary
102
+ // @see ADR-CONT-033 for contracts boundary rationale
103
+ // Note: GuardTier is already exported above from './guards/index' (structurally
104
+ // identical); not re-exported here to avoid a duplicate-identifier collision.
105
+ export type {
106
+ GuardResultPayload,
107
+ RepoCiResult,
108
+ } from './ci-results/index'
109
+
110
+ export { assertRepoCiResultConsistent } from './ci-results/index'
111
+
101
112
  // Compatibility manifest (CI guard vocabulary)
102
113
  // @see ADR-2025-12-011 for design rationale
103
114
  export { COMPATIBILITY } from './compatibility'
@@ -133,6 +144,8 @@ export {
133
144
  AccountDeleteResponseSchema,
134
145
  AccountConfirmDeletionResponseSchema,
135
146
  AccountCancelDeletionResponseSchema,
147
+ BannerDismissedListResponseSchema,
148
+ BannerDismissResponseSchema,
136
149
  } from './identity/index'
137
150
  export type {
138
151
  MeResponse,
@@ -145,6 +158,8 @@ export type {
145
158
  AccountDeleteResponse,
146
159
  AccountConfirmDeletionResponse,
147
160
  AccountCancelDeletionResponse,
161
+ BannerDismissedListResponse,
162
+ BannerDismissResponse,
148
163
  } from './identity/index'
149
164
 
150
165
  // Auth domain types