@company-semantics/contracts 0.8.0 → 0.9.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.8.0",
3
+ "version": "0.9.0",
4
4
  "private": false,
5
5
  "repository": {
6
6
  "type": "git",
@@ -12,6 +12,10 @@
12
12
  "types": "./src/index.ts",
13
13
  "default": "./src/index.ts"
14
14
  },
15
+ "./guards": {
16
+ "types": "./src/guards/index.ts",
17
+ "default": "./src/guards/index.ts"
18
+ },
15
19
  "./schemas/guard-result.schema.json": "./schemas/guard-result.schema.json"
16
20
  },
17
21
  "types": "./src/index.ts",
@@ -33,14 +37,15 @@
33
37
  "guard:export:json": "npx tsx scripts/ci/export-guard.ts --json",
34
38
  "guard:vocabulary": "npx tsx scripts/ci/vocabulary-guard.ts",
35
39
  "guard:vocabulary:json": "npx tsx scripts/ci/vocabulary-guard.ts --json",
36
- "guard:test": "vitest run scripts/ci/__tests__"
40
+ "guard:test": "vitest run scripts/ci/__tests__",
41
+ "test": "vitest run scripts/ci/__tests__"
37
42
  },
38
43
  "packageManager": "pnpm@10.25.0",
39
44
  "devDependencies": {
40
45
  "@types/node": "^25.0.3",
41
46
  "husky": "^9",
42
- "lint-staged": "^15",
43
- "markdownlint-cli2": "^0.17",
47
+ "lint-staged": "^16.2.7",
48
+ "markdownlint-cli2": "^0.20.0",
44
49
  "tsx": "^4.21.0",
45
50
  "typescript": "^5",
46
51
  "vitest": "^4.0.16"
@@ -2,7 +2,7 @@
2
2
  "$schema": "http://json-schema.org/draft-07/schema#",
3
3
  "$id": "https://company-semantics.dev/schemas/guard-result.json",
4
4
  "title": "Guard Result",
5
- "description": "JSON output envelope for CI guard --json mode. schemaVersion reflects the JSON schema version, not the guard tool version.",
5
+ "description": "JSON output envelope for CI guard --json mode (v2.0.0). Results are tiered, not flattened.",
6
6
  "type": "object",
7
7
  "required": ["tool", "schemaVersion", "timestamp", "results"],
8
8
  "properties": {
@@ -12,7 +12,7 @@
12
12
  },
13
13
  "schemaVersion": {
14
14
  "type": "string",
15
- "description": "Schema version (not tool version). Bump on breaking schema changes.",
15
+ "description": "Schema version (not tool version). v2.0.0 introduces tiered results.",
16
16
  "pattern": "^\\d+\\.\\d+\\.\\d+$"
17
17
  },
18
18
  "timestamp": {
@@ -21,29 +21,18 @@
21
21
  "description": "ISO 8601 timestamp of when the guard ran"
22
22
  },
23
23
  "results": {
24
- "type": "object",
25
- "description": "Flat structure: all errors/warnings from all tiers are aggregated here",
26
- "required": ["errors", "warnings"],
27
- "properties": {
28
- "errors": {
29
- "type": "array",
30
- "items": { "$ref": "#/definitions/GuardMessage" }
31
- },
32
- "warnings": {
33
- "type": "array",
34
- "items": { "$ref": "#/definitions/GuardMessage" }
35
- }
36
- }
24
+ "$ref": "#/definitions/GuardResults"
37
25
  }
38
26
  },
39
27
  "definitions": {
40
28
  "GuardMessage": {
41
29
  "type": "object",
30
+ "description": "A single guard message (error or warning)",
42
31
  "required": ["file", "message"],
43
32
  "properties": {
44
33
  "file": {
45
34
  "type": "string",
46
- "description": "Path to the file with the issue"
35
+ "description": "Path to the file with the issue (relative to repo root)"
47
36
  },
48
37
  "message": {
49
38
  "type": "string",
@@ -51,11 +40,49 @@
51
40
  },
52
41
  "line": {
53
42
  "type": "number",
54
- "description": "Optional line number (when available)"
43
+ "description": "Line number where the issue occurs (when available)"
55
44
  },
56
45
  "rule": {
57
46
  "type": "string",
58
- "description": "Optional rule identifier (when available)"
47
+ "description": "Rule identifier that triggered this message (e.g., 'file-size', 'readme')"
48
+ }
49
+ }
50
+ },
51
+ "GuardTierResult": {
52
+ "type": "object",
53
+ "description": "Result for a single tier (errors + warnings)",
54
+ "required": ["errors", "warnings"],
55
+ "properties": {
56
+ "errors": {
57
+ "type": "array",
58
+ "items": { "$ref": "#/definitions/GuardMessage" }
59
+ },
60
+ "warnings": {
61
+ "type": "array",
62
+ "items": { "$ref": "#/definitions/GuardMessage" }
63
+ }
64
+ }
65
+ },
66
+ "GuardResults": {
67
+ "type": "object",
68
+ "description": "Full guard results organized by tier. Tier awareness is preserved end-to-end.",
69
+ "required": ["structural", "behavioral", "invariants", "evolution"],
70
+ "properties": {
71
+ "structural": {
72
+ "$ref": "#/definitions/GuardTierResult",
73
+ "description": "File sizes, READMEs, naming (fast, syntactic)"
74
+ },
75
+ "behavioral": {
76
+ "$ref": "#/definitions/GuardTierResult",
77
+ "description": "Import layers, dependencies (semantic)"
78
+ },
79
+ "invariants": {
80
+ "$ref": "#/definitions/GuardTierResult",
81
+ "description": "Domain rules, trust boundaries (business logic)"
82
+ },
83
+ "evolution": {
84
+ "$ref": "#/definitions/GuardTierResult",
85
+ "description": "Uncovered patterns, growth tracking (observational)"
59
86
  }
60
87
  }
61
88
  }
@@ -0,0 +1,52 @@
1
+ # Guard Types
2
+
3
+ Canonical type vocabulary for CI guard systems across all Company Semantics repos.
4
+
5
+ ## Purpose
6
+
7
+ Defines the contract between guard implementations (in workspace scripts) and consumers (backend, site).
8
+ This module exports **types only** — runtime helper functions live in the workspace-level guard library.
9
+
10
+ ## Invariants
11
+
12
+ - **Tier awareness preserved**: Results are always structured by tier, never flattened
13
+ - **Types only**: No runtime code (functions, classes) per contracts policy
14
+ - **Schema alignment**: Types match `schemas/guard-result.schema.json` exactly
15
+ - **Backward compatibility**: Breaking changes require major version bump
16
+
17
+ ## Public API
18
+
19
+ ### Message Types
20
+
21
+ - `GuardMessage` — Single error/warning with file, message, optional line/rule
22
+ - `GuardTierResult` — Errors + warnings for one tier
23
+ - `GuardResults` — Full results organized by tier
24
+ - `GuardOutput` — JSON envelope for `--json` mode
25
+
26
+ ### Tier Types
27
+
28
+ - `GuardTier` — `'structural' | 'behavioral' | 'invariants' | 'evolution'`
29
+ - `GUARD_TIERS` — Ordered array for iteration
30
+
31
+ ### Check Types
32
+
33
+ - `CheckResult` — Return type from individual guard checks
34
+ - `GuardCheck` — Function signature `(root, config) => Promise<CheckResult>`
35
+ - `GuardCheckFactory` — Factory signature `(overrides?) => GuardCheck`
36
+
37
+ ### Config Types
38
+
39
+ - `RoleLimit` — Three-tier limit (target, warning, hard)
40
+ - `GuardConfig` — Polymorphic configuration for guards
41
+
42
+ ### Constants
43
+
44
+ - `GUARD_SCHEMA_VERSION` — `'2.0.0'` current schema version
45
+ - `DEFAULT_SKIP_DIRECTORIES` — Standard dirs to skip
46
+ - `DEFAULT_DOMAIN_SECTIONS` — Required README sections for domains
47
+ - `DEFAULT_INFRA_SECTIONS` — Required README sections for infra
48
+
49
+ ## Dependencies
50
+
51
+ - No external dependencies (types only)
52
+ - Consumed by: backend `scripts/ci/`, site `scripts/ci/`, workspace `scripts/ci/`
@@ -0,0 +1,163 @@
1
+ /**
2
+ * Guard Configuration Vocabulary
3
+ *
4
+ * Polymorphic configuration types that allow guard implementations
5
+ * to be reused across repos with different settings.
6
+ *
7
+ * Design principle: Configuration is data, not code.
8
+ * Each repo provides its own config values; shared guards consume them.
9
+ */
10
+
11
+ import type { GuardTier, CheckResult } from './types.js';
12
+
13
+ // =============================================================================
14
+ // Size Limits
15
+ // =============================================================================
16
+
17
+ /**
18
+ * Three-tier size limit for a file role.
19
+ * - target: Ideal maximum (for new code)
20
+ * - warning: Soft limit (CI warns but passes)
21
+ * - hard: Hard limit (CI fails)
22
+ */
23
+ export interface RoleLimit {
24
+ target: number;
25
+ warning: number;
26
+ hard: number;
27
+ }
28
+
29
+ // =============================================================================
30
+ // Guard Configuration
31
+ // =============================================================================
32
+
33
+ /**
34
+ * Configuration for guard checks.
35
+ * Repos provide their own values; shared guards consume polymorphically.
36
+ */
37
+ export interface GuardConfig {
38
+ /**
39
+ * File size limits by role name.
40
+ * Keys are role names (e.g., 'Service', 'Component', 'Handler').
41
+ */
42
+ limits: Record<string, RoleLimit>;
43
+
44
+ /**
45
+ * Role detection patterns.
46
+ * Keys are role names, values are regex patterns as strings.
47
+ * Example: { 'Service': 'Service\\.ts$', 'Handler': 'Handler\\.ts$' }
48
+ */
49
+ rolePatterns: Record<string, string>;
50
+
51
+ /**
52
+ * Glob patterns for auto-exempt files.
53
+ * Files matching these are skipped by size/complexity checks.
54
+ * Example: ['index.ts', '*.generated.ts', '*.schema.ts']
55
+ */
56
+ exemptPatterns: string[];
57
+
58
+ /**
59
+ * README section requirements by semantic root role.
60
+ * Keys are role names (e.g., 'domain', 'infra').
61
+ * Values are required section headers.
62
+ */
63
+ semanticRootSections: Record<string, string[]>;
64
+
65
+ /**
66
+ * Universal size limit for files without a detected role.
67
+ * Applied when no rolePattern matches.
68
+ */
69
+ universalSizeLimit: number;
70
+
71
+ /**
72
+ * Universal warning threshold.
73
+ * Files above this but below universalSizeLimit get warnings.
74
+ */
75
+ universalWarningThreshold: number;
76
+
77
+ /**
78
+ * Export complexity thresholds.
79
+ * Files with more exports than these limits are flagged.
80
+ */
81
+ exportLimits?: {
82
+ warning: number;
83
+ error: number;
84
+ };
85
+
86
+ /**
87
+ * Import fanout thresholds.
88
+ * Files with more imports than these limits are flagged.
89
+ */
90
+ importLimits?: {
91
+ warning: number;
92
+ error: number;
93
+ };
94
+
95
+ /**
96
+ * Domain directories to check for READMEs.
97
+ * Example: ['src/domain', 'src/providers', 'src/interfaces']
98
+ */
99
+ domainDirectories?: string[];
100
+
101
+ /**
102
+ * Directories to skip when walking the file tree.
103
+ * Example: ['node_modules', 'dist', '.git']
104
+ */
105
+ skipDirectories?: string[];
106
+ }
107
+
108
+ // =============================================================================
109
+ // Guard Check Signature
110
+ // =============================================================================
111
+
112
+ /**
113
+ * Signature for a guard check function.
114
+ * Guards receive the repo root and config, return structured results.
115
+ */
116
+ export type GuardCheck = (
117
+ repoRoot: string,
118
+ config: GuardConfig
119
+ ) => Promise<CheckResult>;
120
+
121
+ /**
122
+ * Signature for a guard check factory.
123
+ * Factories create check functions with optional overrides.
124
+ */
125
+ export type GuardCheckFactory = (
126
+ overrides?: Partial<GuardConfig>
127
+ ) => GuardCheck;
128
+
129
+ // =============================================================================
130
+ // Default Values
131
+ // =============================================================================
132
+
133
+ /**
134
+ * Default directories to skip when walking file trees.
135
+ */
136
+ export const DEFAULT_SKIP_DIRECTORIES = [
137
+ 'node_modules',
138
+ 'dist',
139
+ '.git',
140
+ '.next',
141
+ 'coverage',
142
+ '.tsbuild',
143
+ ];
144
+
145
+ /**
146
+ * Default README sections for domain directories.
147
+ */
148
+ export const DEFAULT_DOMAIN_SECTIONS = [
149
+ 'Purpose',
150
+ 'Invariants',
151
+ 'Public API',
152
+ 'Dependencies',
153
+ ];
154
+
155
+ /**
156
+ * Default README sections for infrastructure directories.
157
+ */
158
+ export const DEFAULT_INFRA_SECTIONS = [
159
+ 'Purpose',
160
+ 'How it works',
161
+ 'Integration',
162
+ 'Maintenance',
163
+ ];
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Guard Types Barrel
3
+ *
4
+ * Re-exports all guard vocabulary types.
5
+ * Import from '@company-semantics/contracts/guards' or '@company-semantics/contracts'.
6
+ *
7
+ * Note: This module exports types only (no runtime code per contracts policy).
8
+ * Helper functions for working with these types live in workspace scripts.
9
+ */
10
+
11
+ // Types
12
+ export type {
13
+ GuardMessage,
14
+ GuardTierResult,
15
+ GuardTier,
16
+ GuardResults,
17
+ CheckResult,
18
+ GuardOutput,
19
+ } from './types.js';
20
+
21
+ // Constants (these are type-level, not runtime)
22
+ export { GUARD_SCHEMA_VERSION, GUARD_TIERS } from './types.js';
23
+
24
+ // Config types
25
+ export type {
26
+ RoleLimit,
27
+ GuardConfig,
28
+ GuardCheck,
29
+ GuardCheckFactory,
30
+ } from './config.js';
31
+
32
+ // Config constants (type-level defaults)
33
+ export {
34
+ DEFAULT_SKIP_DIRECTORIES,
35
+ DEFAULT_DOMAIN_SECTIONS,
36
+ DEFAULT_INFRA_SECTIONS,
37
+ } from './config.js';
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Guard Type Vocabulary (v2.0.0)
3
+ *
4
+ * Canonical types for CI guard output across all Company Semantics repos.
5
+ * These types define the contract between guard implementations and consumers.
6
+ *
7
+ * Design invariants:
8
+ * - Tier awareness is preserved end-to-end (no flattening)
9
+ * - CheckResult shape matches aggregation needs (errors/warnings separated)
10
+ * - GuardOutput envelope is JSON-serializable for CI integration
11
+ *
12
+ * @see schemas/guard-result.schema.json for JSON Schema
13
+ */
14
+
15
+ // =============================================================================
16
+ // Message Types
17
+ // =============================================================================
18
+
19
+ /**
20
+ * A single guard message (error or warning).
21
+ * The atomic unit of guard output.
22
+ */
23
+ export interface GuardMessage {
24
+ /** Path to the file with the issue (relative to repo root) */
25
+ file: string;
26
+ /** Human-readable description of the issue */
27
+ message: string;
28
+ /** Line number where the issue occurs (when available) */
29
+ line?: number;
30
+ /** Rule identifier that triggered this message (e.g., 'file-size', 'readme') */
31
+ rule?: string;
32
+ }
33
+
34
+ // =============================================================================
35
+ // Tier Types
36
+ // =============================================================================
37
+
38
+ /**
39
+ * Result for a single tier (errors + warnings).
40
+ */
41
+ export interface GuardTierResult {
42
+ errors: GuardMessage[];
43
+ warnings: GuardMessage[];
44
+ }
45
+
46
+ /**
47
+ * Guard tier names.
48
+ * Ordered by enforcement phase:
49
+ * - structural: file sizes, READMEs, naming (fast, syntactic)
50
+ * - behavioral: import layers, dependencies (semantic)
51
+ * - invariants: domain rules, trust boundaries (business logic)
52
+ * - evolution: uncovered patterns, growth tracking (observational)
53
+ */
54
+ export type GuardTier = 'structural' | 'behavioral' | 'invariants' | 'evolution';
55
+
56
+ /**
57
+ * Full guard results, organized by tier.
58
+ * Preserves tier awareness for reporting and filtering.
59
+ */
60
+ export type GuardResults = {
61
+ [K in GuardTier]: GuardTierResult;
62
+ };
63
+
64
+ // =============================================================================
65
+ // Check Types (for guard implementations)
66
+ // =============================================================================
67
+
68
+ /**
69
+ * Result from a single guard check.
70
+ * Designed for clean aggregation into GuardResults.
71
+ */
72
+ export interface CheckResult {
73
+ /** Which tier this check belongs to */
74
+ tier: GuardTier;
75
+ /** Rule identifier (e.g., 'file-size', 'readme-sections') */
76
+ rule: string;
77
+ /** Errors that should fail CI */
78
+ errors: GuardMessage[];
79
+ /** Warnings that should be reported but not fail CI */
80
+ warnings: GuardMessage[];
81
+ /** Informational messages (optional, for observability) */
82
+ info?: GuardMessage[];
83
+ }
84
+
85
+ // =============================================================================
86
+ // JSON Output Envelope
87
+ // =============================================================================
88
+
89
+ /**
90
+ * JSON output envelope for --json mode.
91
+ * This is the top-level structure emitted by guard tools.
92
+ *
93
+ * Invariant: results are tiered, not flattened.
94
+ */
95
+ export interface GuardOutput {
96
+ /** Guard tool name (e.g., 'architecture-guard', 'vocabulary-guard') */
97
+ tool: string;
98
+ /** Schema version (not tool version). Bump on breaking schema changes. */
99
+ schemaVersion: string;
100
+ /** ISO 8601 timestamp of when the guard ran */
101
+ timestamp: string;
102
+ /** Tiered results preserving full structure */
103
+ results: GuardResults;
104
+ }
105
+
106
+ /**
107
+ * Current schema version.
108
+ * v2.0.0: Tiered results (breaking change from v1.x flattened structure)
109
+ */
110
+ export const GUARD_SCHEMA_VERSION = '2.0.0';
111
+
112
+ /**
113
+ * All guard tiers in order.
114
+ * Useful for iteration when aggregating results.
115
+ */
116
+ export const GUARD_TIERS: readonly GuardTier[] = [
117
+ 'structural',
118
+ 'behavioral',
119
+ 'invariants',
120
+ 'evolution',
121
+ ] as const;
package/src/index.ts CHANGED
@@ -39,3 +39,26 @@ export type {
39
39
  DiagramSpec,
40
40
  DiagramSnapshot,
41
41
  } from './system/index.js'
42
+
43
+ // Guard types (CI guard vocabulary)
44
+ // @see schemas/guard-result.schema.json for JSON Schema
45
+ export type {
46
+ GuardMessage,
47
+ GuardTierResult,
48
+ GuardTier,
49
+ GuardResults,
50
+ CheckResult,
51
+ GuardOutput,
52
+ RoleLimit,
53
+ GuardConfig,
54
+ GuardCheck,
55
+ GuardCheckFactory,
56
+ } from './guards/index.js'
57
+
58
+ export {
59
+ GUARD_SCHEMA_VERSION,
60
+ GUARD_TIERS,
61
+ DEFAULT_SKIP_DIRECTORIES,
62
+ DEFAULT_DOMAIN_SECTIONS,
63
+ DEFAULT_INFRA_SECTIONS,
64
+ } from './guards/index.js'