@sigloch/contracts 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/LICENSE +21 -0
  2. package/dist/harness/index.d.ts +185 -0
  3. package/dist/harness/index.js +185 -0
  4. package/dist/index.d.ts +13 -0
  5. package/dist/index.js +14 -0
  6. package/dist/se/ao-rules.d.ts +59 -0
  7. package/dist/se/ao-rules.js +341 -0
  8. package/dist/se/conformance-rules.d.ts +64 -0
  9. package/dist/se/conformance-rules.js +364 -0
  10. package/dist/se/cr-quality-rules.d.ts +8 -0
  11. package/dist/se/cr-quality-rules.js +141 -0
  12. package/dist/se/evaluate-all.d.ts +17 -0
  13. package/dist/se/evaluate-all.js +50 -0
  14. package/dist/se/fchain-quality-rules.d.ts +10 -0
  15. package/dist/se/fchain-quality-rules.js +105 -0
  16. package/dist/se/fmea-rules.d.ts +17 -0
  17. package/dist/se/fmea-rules.js +137 -0
  18. package/dist/se/format-e-parser.d.ts +28 -0
  19. package/dist/se/format-e-parser.js +217 -0
  20. package/dist/se/index.d.ts +28 -0
  21. package/dist/se/index.js +28 -0
  22. package/dist/se/meta-model.d.ts +26 -0
  23. package/dist/se/meta-model.js +60 -0
  24. package/dist/se/metric-rules.d.ts +45 -0
  25. package/dist/se/metric-rules.js +208 -0
  26. package/dist/se/near-duplicate-rules.d.ts +44 -0
  27. package/dist/se/near-duplicate-rules.js +106 -0
  28. package/dist/se/ontology.d.ts +327 -0
  29. package/dist/se/ontology.js +216 -0
  30. package/dist/se/quality-rules.d.ts +28 -0
  31. package/dist/se/quality-rules.js +206 -0
  32. package/dist/se/readiness.d.ts +62 -0
  33. package/dist/se/readiness.js +79 -0
  34. package/dist/se/rules.d.ts +159 -0
  35. package/dist/se/rules.js +854 -0
  36. package/dist/se/schema-quality-rules.d.ts +11 -0
  37. package/dist/se/schema-quality-rules.js +73 -0
  38. package/dist/se/semantic-id.d.ts +30 -0
  39. package/dist/se/semantic-id.js +90 -0
  40. package/dist/se/uc-quality-rules.d.ts +13 -0
  41. package/dist/se/uc-quality-rules.js +123 -0
  42. package/dist/se/view-rules.d.ts +11 -0
  43. package/dist/se/view-rules.js +56 -0
  44. package/package.json +51 -0
@@ -0,0 +1,11 @@
1
+ /**
2
+ * SC-01..SC-03 — Schema Quality rules (CR-122).
3
+ * Complement V3 structural rules with content checks on SCHEMA elements.
4
+ */
5
+ import type { OntologyGraph } from './ontology.js';
6
+ import type { RuleDefinition, RuleViolation } from './rules.js';
7
+ export declare function sc01HasDefinition(graph: OntologyGraph): RuleViolation[];
8
+ export declare function sc02IsReferenced(graph: OntologyGraph): RuleViolation[];
9
+ export declare function sc03IsImplemented(graph: OntologyGraph): RuleViolation[];
10
+ export declare const SC_RULES: RuleDefinition[];
11
+ export declare function evaluateSCRules(graph: OntologyGraph): RuleViolation[];
@@ -0,0 +1,73 @@
1
+ // ---------------------------------------------------------------------------
2
+ // SC-01: SCHEMA must have zodDefinition attribute
3
+ // ---------------------------------------------------------------------------
4
+ export function sc01HasDefinition(graph) {
5
+ return graph.elements
6
+ .filter(e => e.type === 'SCHEMA')
7
+ .filter(s => {
8
+ const def = s.attributes?.zodDefinition;
9
+ return !def || (typeof def === 'string' && def.trim().length === 0);
10
+ })
11
+ .map(s => ({
12
+ rule_id: 'SC-01',
13
+ severity: 'warning',
14
+ element_id: s.id,
15
+ message: `${s.id} has no zodDefinition attribute`,
16
+ fix_hint: 'Add zodDefinition attribute with Zod schema string',
17
+ context: {
18
+ element_type: s.type,
19
+ element_name: s.name,
20
+ },
21
+ }));
22
+ }
23
+ // ---------------------------------------------------------------------------
24
+ // SC-02: SCHEMA must be referenced by at least one FLOW via relation trace
25
+ // ---------------------------------------------------------------------------
26
+ export function sc02IsReferenced(graph) {
27
+ const flows = graph.elements.filter(e => e.type === 'FLOW');
28
+ return graph.elements
29
+ .filter(e => e.type === 'SCHEMA')
30
+ .filter(s => !graph.traces.some(t => t.target === s.id && t.type === 'relation'))
31
+ .map(s => ({
32
+ rule_id: 'SC-02',
33
+ severity: 'warning',
34
+ element_id: s.id,
35
+ message: `${s.id} not referenced by any FLOW`,
36
+ fix_hint: 'Link at least one FLOW to this SCHEMA via relation trace',
37
+ context: {
38
+ element_type: s.type,
39
+ element_name: s.name,
40
+ candidate_targets: flows.map(f => ({ id: f.id, type: f.type, name: f.name })),
41
+ },
42
+ }));
43
+ }
44
+ // ---------------------------------------------------------------------------
45
+ // SC-03: SCHEMA should have sourceFile (implementation marker)
46
+ // ---------------------------------------------------------------------------
47
+ export function sc03IsImplemented(graph) {
48
+ return graph.elements
49
+ .filter(e => e.type === 'SCHEMA')
50
+ .filter(s => !s.attributes?.sourceFile && !s.attributes?.sourceExport)
51
+ .map(s => ({
52
+ rule_id: 'SC-03',
53
+ severity: 'info',
54
+ element_id: s.id,
55
+ message: `${s.id} has no sourceFile/sourceExport (not implemented yet)`,
56
+ fix_hint: 'Implement the Zod schema in code and set sourceFile/sourceExport',
57
+ context: {
58
+ element_type: s.type,
59
+ element_name: s.name,
60
+ },
61
+ }));
62
+ }
63
+ // ---------------------------------------------------------------------------
64
+ // Aggregated array & convenience runner
65
+ // ---------------------------------------------------------------------------
66
+ export const SC_RULES = [
67
+ { id: 'SC-01', name: 'Schema has definition', severity: 'warning', evaluate: sc01HasDefinition },
68
+ { id: 'SC-02', name: 'Schema referenced by FLOW', severity: 'warning', evaluate: sc02IsReferenced },
69
+ { id: 'SC-03', name: 'Schema is implemented', severity: 'info', evaluate: sc03IsImplemented },
70
+ ];
71
+ export function evaluateSCRules(graph) {
72
+ return SC_RULES.flatMap(rule => rule.evaluate(graph));
73
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * SemanticId — Format-E canonical element ID schema.
3
+ * Aligned with graphengine CR-052/CR-053.
4
+ *
5
+ * Format: {Name}.{TypeAbbr}.{Counter}
6
+ * Example: ObserveSessions.UC.001
7
+ *
8
+ * @sigloch/contracts/se
9
+ */
10
+ import { z } from 'zod/v4';
11
+ import type { ElementType } from './ontology.js';
12
+ /** 2-char abbreviation → full ElementType. */
13
+ export declare const ABBREV_TO_TYPE: Record<string, ElementType>;
14
+ /** Full ElementType → 2-char abbreviation. */
15
+ export declare const TYPE_TO_ABBREV: Record<string, string>;
16
+ /** SemanticId: `Name.TypeAbbr.Counter` where Counter is 3-digit or 6-char alphanumeric. */
17
+ export declare const SemanticId: z.ZodString;
18
+ export type SemanticId = z.infer<typeof SemanticId>;
19
+ /** Check if a string is a valid SemanticId. */
20
+ export declare function isSemanticId(s: string): boolean;
21
+ /** Extract name, type, and counter from a SemanticId. */
22
+ export declare function extractFromSemanticId(semanticId: string): {
23
+ name: string;
24
+ type: ElementType;
25
+ counter: string;
26
+ };
27
+ /** Build a SemanticId from parts. */
28
+ export declare function toSemanticId(name: string, type: ElementType, counter: string): string;
29
+ /** Get the 2-char abbreviation for an ElementType. */
30
+ export declare function getTypeAbbreviation(type: ElementType): string;
@@ -0,0 +1,90 @@
1
+ /**
2
+ * SemanticId — Format-E canonical element ID schema.
3
+ * Aligned with graphengine CR-052/CR-053.
4
+ *
5
+ * Format: {Name}.{TypeAbbr}.{Counter}
6
+ * Example: ObserveSessions.UC.001
7
+ *
8
+ * @sigloch/contracts/se
9
+ */
10
+ import { z } from 'zod/v4';
11
+ // ---------------------------------------------------------------------------
12
+ // Type abbreviation maps (aligned with graphengine semantic-id.ts)
13
+ // ---------------------------------------------------------------------------
14
+ /** 2-char abbreviation → full ElementType. */
15
+ export const ABBREV_TO_TYPE = {
16
+ SY: 'SYS',
17
+ UC: 'UC',
18
+ RQ: 'REQ',
19
+ FN: 'FUNC',
20
+ FC: 'FCHAIN',
21
+ FL: 'FLOW',
22
+ AC: 'ACTOR',
23
+ MD: 'MOD',
24
+ TC: 'TEST',
25
+ TS: 'TEST', // legacy alias
26
+ SC: 'SCHEMA',
27
+ CR: 'CR',
28
+ MS: 'MS',
29
+ };
30
+ /** Full ElementType → 2-char abbreviation. */
31
+ export const TYPE_TO_ABBREV = {
32
+ SYS: 'SY',
33
+ UC: 'UC',
34
+ REQ: 'RQ',
35
+ FUNC: 'FN',
36
+ FCHAIN: 'FC',
37
+ FLOW: 'FL',
38
+ ACTOR: 'AC',
39
+ MOD: 'MD',
40
+ TEST: 'TC',
41
+ SCHEMA: 'SC',
42
+ SESSION: 'SE',
43
+ CR: 'CR',
44
+ MS: 'MS',
45
+ };
46
+ // ---------------------------------------------------------------------------
47
+ // Zod schema
48
+ // ---------------------------------------------------------------------------
49
+ /** SemanticId: `Name.TypeAbbr.Counter` where Counter is 3-digit or 6-char alphanumeric. */
50
+ export const SemanticId = z.string().regex(/^[A-Za-z][A-Za-z0-9_+]{0,49}\.[A-Z]{2}\.[a-z0-9]{3,6}$/, 'SemanticId must match {Name}.{TypeAbbr}.{Counter}');
51
+ // ---------------------------------------------------------------------------
52
+ // Pure functions
53
+ // ---------------------------------------------------------------------------
54
+ /** Check if a string is a valid SemanticId. */
55
+ export function isSemanticId(s) {
56
+ return SemanticId.safeParse(s).success;
57
+ }
58
+ /** Extract name, type, and counter from a SemanticId. */
59
+ export function extractFromSemanticId(semanticId) {
60
+ const parts = semanticId.split('.');
61
+ if (parts.length < 3) {
62
+ throw new Error(`Invalid semanticId: "${semanticId}" — expected Name.TypeAbbr.Counter`);
63
+ }
64
+ const name = parts[0];
65
+ const typeAbbr = parts[1];
66
+ const type = ABBREV_TO_TYPE[typeAbbr];
67
+ if (!type) {
68
+ throw new Error(`Unknown type abbreviation "${typeAbbr}" in: "${semanticId}"`);
69
+ }
70
+ return { name, type, counter: parts[2] };
71
+ }
72
+ /** Build a SemanticId from parts. */
73
+ export function toSemanticId(name, type, counter) {
74
+ const abbr = TYPE_TO_ABBREV[type];
75
+ if (!abbr)
76
+ throw new Error(`No abbreviation for type: ${type}`);
77
+ const sanitized = sanitizeName(name);
78
+ return `${sanitized}.${abbr}.${counter}`;
79
+ }
80
+ /** Get the 2-char abbreviation for an ElementType. */
81
+ export function getTypeAbbreviation(type) {
82
+ return TYPE_TO_ABBREV[type] ?? type.slice(0, 2).toUpperCase();
83
+ }
84
+ // ---------------------------------------------------------------------------
85
+ // Helpers
86
+ // ---------------------------------------------------------------------------
87
+ /** Sanitize a name for SemanticId: PascalCase, only alnum + underscore + plus, max 50 chars. */
88
+ function sanitizeName(name) {
89
+ return name.replace(/[^a-zA-Z0-9_+]/g, '').slice(0, 50);
90
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * UC-01..UC-06 — Use Case quality rules (CR-121 Phase 1).
3
+ */
4
+ import type { OntologyGraph } from './ontology.js';
5
+ import type { RuleDefinition, RuleViolation } from './rules.js';
6
+ export declare function uc01HasRequirements(graph: OntologyGraph): RuleViolation[];
7
+ export declare function uc02HasActor(graph: OntologyGraph): RuleViolation[];
8
+ export declare function uc03HasScenario(graph: OntologyGraph): RuleViolation[];
9
+ export declare function uc04GoalDefined(graph: OntologyGraph): RuleViolation[];
10
+ export declare function uc05HasPostcondition(graph: OntologyGraph): RuleViolation[];
11
+ export declare function uc06HasPrecondition(graph: OntologyGraph): RuleViolation[];
12
+ export declare const UC_RULES: RuleDefinition[];
13
+ export declare function evaluateUCRules(graph: OntologyGraph): RuleViolation[];
@@ -0,0 +1,123 @@
1
+ // ---------------------------------------------------------------------------
2
+ // UC-01: UC must have compose→REQ trace (CR-165: satisfy UC→REQ is invalid per meta-model)
3
+ // ---------------------------------------------------------------------------
4
+ export function uc01HasRequirements(graph) {
5
+ return graph.elements
6
+ .filter(e => e.type === 'UC')
7
+ .filter(uc => !graph.traces.some(t => t.source === uc.id && t.type === 'compose' && graph.elements.some(e => e.id === t.target && e.type === 'REQ')))
8
+ .map(uc => ({
9
+ rule_id: 'UC-01',
10
+ severity: 'error',
11
+ element_id: uc.id,
12
+ message: `${uc.id} has no requirements (compose→REQ)`,
13
+ fix_hint: 'Add at least one REQ via compose trace',
14
+ context: { element_type: uc.type, element_name: uc.name },
15
+ }));
16
+ }
17
+ // ---------------------------------------------------------------------------
18
+ // UC-02: UC FCHAIN must have an ACTOR with io trace
19
+ // ---------------------------------------------------------------------------
20
+ export function uc02HasActor(graph) {
21
+ return graph.elements
22
+ .filter(e => e.type === 'UC')
23
+ .filter(uc => {
24
+ // Check if any ACTOR has io trace to this UC or to a FCHAIN/FLOW in this UC
25
+ return !graph.traces.some(t => t.type === 'io' &&
26
+ graph.elements.some(e => e.id === t.source && e.type === 'ACTOR') &&
27
+ (t.target === uc.id || graph.traces.some(ct => ct.source === uc.id && ct.type === 'compose' && ct.target === t.target)));
28
+ })
29
+ .map(uc => ({
30
+ rule_id: 'UC-02',
31
+ severity: 'error',
32
+ element_id: uc.id,
33
+ message: `${uc.id} has no ACTOR with io trace`,
34
+ fix_hint: 'Link an ACTOR via io trace to this UC or its FCHAIN',
35
+ context: { element_type: uc.type, element_name: uc.name },
36
+ }));
37
+ }
38
+ // ---------------------------------------------------------------------------
39
+ // UC-03: UC must have compose→FCHAIN (scenario)
40
+ // ---------------------------------------------------------------------------
41
+ export function uc03HasScenario(graph) {
42
+ return graph.elements
43
+ .filter(e => e.type === 'UC')
44
+ .filter(uc => !graph.traces.some(t => t.source === uc.id && t.type === 'compose' &&
45
+ graph.elements.some(e => e.id === t.target && e.type === 'FCHAIN')))
46
+ .map(uc => ({
47
+ rule_id: 'UC-03',
48
+ severity: 'warning',
49
+ element_id: uc.id,
50
+ message: `${uc.id} has no FCHAIN scenario`,
51
+ fix_hint: 'Add a FCHAIN via compose trace to define behavioral scenario',
52
+ context: { element_type: uc.type, element_name: uc.name },
53
+ }));
54
+ }
55
+ // ---------------------------------------------------------------------------
56
+ // UC-04: UC must have meaningful description (CR-150: description = goal)
57
+ // ---------------------------------------------------------------------------
58
+ const UC_DESC_MIN_LEN = 10;
59
+ const PLACEHOLDER_RE = /\b(tbd|todo|fixme|placeholder|xxx)\b/i;
60
+ export function uc04GoalDefined(graph) {
61
+ return graph.elements
62
+ .filter(e => e.type === 'UC')
63
+ .filter(uc => {
64
+ const d = uc.description?.trim() ?? '';
65
+ return d.length < UC_DESC_MIN_LEN || PLACEHOLDER_RE.test(d);
66
+ })
67
+ .map(uc => ({
68
+ rule_id: 'UC-04',
69
+ severity: 'warning',
70
+ element_id: uc.id,
71
+ message: `${uc.id} description is missing or contains placeholders (description = goal per CR-150)`,
72
+ fix_hint: `Provide a meaningful description (min ${UC_DESC_MIN_LEN} chars, no TBD/TODO)`,
73
+ context: { element_type: uc.type, element_name: uc.name },
74
+ }));
75
+ }
76
+ // ---------------------------------------------------------------------------
77
+ // UC-05: UC should have postcondition REQ (CR-165: compose only, satisfy UC→REQ invalid)
78
+ // ---------------------------------------------------------------------------
79
+ export function uc05HasPostcondition(graph) {
80
+ return graph.elements
81
+ .filter(e => e.type === 'UC')
82
+ .filter(uc => !graph.traces.some(t => t.source === uc.id && t.type === 'compose' &&
83
+ graph.elements.some(e => e.id === t.target && e.type === 'REQ' && e.kinds?.includes('postcondition'))))
84
+ .map(uc => ({
85
+ rule_id: 'UC-05',
86
+ severity: 'info',
87
+ element_id: uc.id,
88
+ message: `${uc.id} has no postcondition requirement`,
89
+ fix_hint: 'Add a REQ with kinds=["postcondition"] via compose trace',
90
+ context: { element_type: uc.type, element_name: uc.name },
91
+ }));
92
+ }
93
+ // ---------------------------------------------------------------------------
94
+ // UC-06: UC should have precondition REQ (CR-165: compose only, satisfy UC→REQ invalid)
95
+ // ---------------------------------------------------------------------------
96
+ export function uc06HasPrecondition(graph) {
97
+ return graph.elements
98
+ .filter(e => e.type === 'UC')
99
+ .filter(uc => !graph.traces.some(t => t.source === uc.id && t.type === 'compose' &&
100
+ graph.elements.some(e => e.id === t.target && e.type === 'REQ' && e.kinds?.includes('precondition'))))
101
+ .map(uc => ({
102
+ rule_id: 'UC-06',
103
+ severity: 'info',
104
+ element_id: uc.id,
105
+ message: `${uc.id} has no precondition requirement`,
106
+ fix_hint: 'Add a REQ with kinds=["precondition"] via compose trace',
107
+ context: { element_type: uc.type, element_name: uc.name },
108
+ }));
109
+ }
110
+ // ---------------------------------------------------------------------------
111
+ // Aggregated
112
+ // ---------------------------------------------------------------------------
113
+ export const UC_RULES = [
114
+ { id: 'UC-01', name: 'UC has requirements', severity: 'error', evaluate: uc01HasRequirements },
115
+ { id: 'UC-02', name: 'UC has actor', severity: 'error', evaluate: uc02HasActor },
116
+ { id: 'UC-03', name: 'UC has scenario', severity: 'warning', evaluate: uc03HasScenario },
117
+ { id: 'UC-04', name: 'UC has goal', severity: 'warning', evaluate: uc04GoalDefined },
118
+ { id: 'UC-05', name: 'UC has postcondition', severity: 'info', evaluate: uc05HasPostcondition },
119
+ { id: 'UC-06', name: 'UC has precondition', severity: 'info', evaluate: uc06HasPrecondition },
120
+ ];
121
+ export function evaluateUCRules(graph) {
122
+ return UC_RULES.flatMap(rule => rule.evaluate(graph));
123
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * CR-184: View-related quality rules.
3
+ * VR-01: TEST without testResult attribute (info).
4
+ * CL-01: ACTOR without UCs in at least 2 distinct operatingModes (warning).
5
+ */
6
+ import type { OntologyGraph } from './ontology.js';
7
+ import type { RuleViolation, RuleDefinition } from './rules.js';
8
+ export declare function vr01TestNoResult(graph: OntologyGraph): RuleViolation[];
9
+ export declare function cl01ConopsCompleteness(graph: OntologyGraph): RuleViolation[];
10
+ export declare const VIEW_RULES: RuleDefinition[];
11
+ export declare function evaluateViewRules(graph: OntologyGraph): RuleViolation[];
@@ -0,0 +1,56 @@
1
+ // ---------------------------------------------------------------------------
2
+ // VR-01: TEST without testResult
3
+ // ---------------------------------------------------------------------------
4
+ export function vr01TestNoResult(graph) {
5
+ return graph.elements
6
+ .filter(e => e.type === 'TEST' && e.attributes?.['testResult'] == null)
7
+ .map(e => ({
8
+ rule_id: 'VR-01',
9
+ severity: 'info',
10
+ element_id: e.id,
11
+ message: `${e.id} has no testResult — assumed pending`,
12
+ }));
13
+ }
14
+ // ---------------------------------------------------------------------------
15
+ // CL-01: ACTOR without UCs in >= 2 distinct operatingModes
16
+ // ---------------------------------------------------------------------------
17
+ export function cl01ConopsCompleteness(graph) {
18
+ // Only fire when at least one UC has an operatingMode attribute
19
+ const anyUcHasMode = graph.elements.some(e => e.type === 'UC' && e.attributes?.['operatingMode'] != null);
20
+ if (!anyUcHasMode)
21
+ return [];
22
+ const actors = graph.elements.filter(e => e.type === 'ACTOR');
23
+ const violations = [];
24
+ for (const actor of actors) {
25
+ // Find all UCs linked via io trace
26
+ const ucIds = graph.traces
27
+ .filter(t => t.type === 'io' && t.source === actor.id)
28
+ .map(t => t.target);
29
+ const modes = new Set();
30
+ for (const ucId of ucIds) {
31
+ const uc = graph.elements.find(e => e.id === ucId && e.type === 'UC');
32
+ const mode = uc?.attributes?.['operatingMode'];
33
+ if (mode != null)
34
+ modes.add(String(mode));
35
+ }
36
+ if (modes.size < 2) {
37
+ violations.push({
38
+ rule_id: 'CL-01',
39
+ severity: 'warning',
40
+ element_id: actor.id,
41
+ message: `${actor.id} has UCs in only ${modes.size} distinct operatingMode(s) — expected at least 2`,
42
+ });
43
+ }
44
+ }
45
+ return violations;
46
+ }
47
+ // ---------------------------------------------------------------------------
48
+ // Aggregated array & convenience runner
49
+ // ---------------------------------------------------------------------------
50
+ export const VIEW_RULES = [
51
+ { id: 'VR-01', name: 'TestNoResult', severity: 'info', evaluate: vr01TestNoResult },
52
+ { id: 'CL-01', name: 'ConopsCompleteness', severity: 'warning', evaluate: cl01ConopsCompleteness },
53
+ ];
54
+ export function evaluateViewRules(graph) {
55
+ return VIEW_RULES.flatMap(rule => rule.evaluate(graph));
56
+ }
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@sigloch/contracts",
3
+ "version": "0.7.0",
4
+ "type": "module",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist",
9
+ "LICENSE"
10
+ ],
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "default": "./dist/index.js"
15
+ },
16
+ "./se": {
17
+ "types": "./dist/se/index.d.ts",
18
+ "default": "./dist/se/index.js"
19
+ },
20
+ "./harness": {
21
+ "types": "./dist/harness/index.d.ts",
22
+ "default": "./dist/harness/index.js"
23
+ }
24
+ },
25
+ "scripts": {
26
+ "build": "rm -rf dist && tsc",
27
+ "test": "vitest run",
28
+ "prepublishOnly": "npm run build && npm run test"
29
+ },
30
+ "dependencies": {
31
+ "zod": "^4.3.6"
32
+ },
33
+ "license": "MIT",
34
+ "description": "Zod contracts for the SE model layer — ontology, rules and harness schemas (single source of truth)",
35
+ "author": "sigloch-consulting",
36
+ "repository": {
37
+ "type": "git",
38
+ "url": "git+https://github.com/andreassigloch/sigloch-modules.git",
39
+ "directory": "packages/contracts"
40
+ },
41
+ "homepage": "https://github.com/andreassigloch/sigloch-modules#readme",
42
+ "bugs": {
43
+ "url": "https://github.com/andreassigloch/sigloch-modules/issues"
44
+ },
45
+ "engines": {
46
+ "node": ">=22"
47
+ },
48
+ "publishConfig": {
49
+ "access": "public"
50
+ }
51
+ }