@contractspec/example.kb-update-pipeline 0.0.0-canary-20260113162409
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/.turbo/turbo-build$colon$bundle.log +55 -0
- package/.turbo/turbo-build.log +56 -0
- package/CHANGELOG.md +342 -0
- package/LICENSE +21 -0
- package/README.md +28 -0
- package/dist/docs/index.d.ts +1 -0
- package/dist/docs/index.js +1 -0
- package/dist/docs/kb-update-pipeline.docblock.d.ts +1 -0
- package/dist/docs/kb-update-pipeline.docblock.js +31 -0
- package/dist/docs/kb-update-pipeline.docblock.js.map +1 -0
- package/dist/entities/index.d.ts +2 -0
- package/dist/entities/index.js +3 -0
- package/dist/entities/models.d.ts +61 -0
- package/dist/entities/models.d.ts.map +1 -0
- package/dist/entities/models.js +74 -0
- package/dist/entities/models.js.map +1 -0
- package/dist/events.d.ts +74 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +150 -0
- package/dist/events.js.map +1 -0
- package/dist/example.d.ts +7 -0
- package/dist/example.d.ts.map +1 -0
- package/dist/example.js +50 -0
- package/dist/example.js.map +1 -0
- package/dist/handlers/index.d.ts +2 -0
- package/dist/handlers/index.js +3 -0
- package/dist/handlers/memory.handlers.d.ts +68 -0
- package/dist/handlers/memory.handlers.d.ts.map +1 -0
- package/dist/handlers/memory.handlers.js +93 -0
- package/dist/handlers/memory.handlers.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +12 -0
- package/dist/kb-update-pipeline.feature.d.ts +7 -0
- package/dist/kb-update-pipeline.feature.d.ts.map +1 -0
- package/dist/kb-update-pipeline.feature.js +142 -0
- package/dist/kb-update-pipeline.feature.js.map +1 -0
- package/dist/operations/index.d.ts +2 -0
- package/dist/operations/index.js +3 -0
- package/dist/operations/pipeline.d.ts +137 -0
- package/dist/operations/pipeline.d.ts.map +1 -0
- package/dist/operations/pipeline.js +183 -0
- package/dist/operations/pipeline.js.map +1 -0
- package/dist/presentations.d.ts +9 -0
- package/dist/presentations.d.ts.map +1 -0
- package/dist/presentations.js +71 -0
- package/dist/presentations.js.map +1 -0
- package/dist/tests/operations.test-spec.d.ts +9 -0
- package/dist/tests/operations.test-spec.d.ts.map +1 -0
- package/dist/tests/operations.test-spec.js +94 -0
- package/dist/tests/operations.test-spec.js.map +1 -0
- package/example.ts +1 -0
- package/package.json +74 -0
- package/src/docs/index.ts +1 -0
- package/src/docs/kb-update-pipeline.docblock.ts +30 -0
- package/src/entities/index.ts +1 -0
- package/src/entities/models.ts +53 -0
- package/src/events.ts +134 -0
- package/src/example.ts +34 -0
- package/src/handlers/index.ts +1 -0
- package/src/handlers/memory.handlers.test.ts +81 -0
- package/src/handlers/memory.handlers.ts +186 -0
- package/src/index.ts +15 -0
- package/src/kb-update-pipeline.feature.ts +59 -0
- package/src/operations/index.ts +1 -0
- package/src/operations/pipeline.ts +159 -0
- package/src/presentations.ts +68 -0
- package/src/tests/operations.test-spec.ts +82 -0
- package/tsconfig.json +19 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/tsdown.config.js +17 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { ScalarTypeEnum, defineEnum, defineSchemaModel } from "@contractspec/lib.schema";
|
|
2
|
+
|
|
3
|
+
//#region src/entities/models.ts
|
|
4
|
+
const ChangeRiskLevelEnum = defineEnum("ChangeRiskLevel", [
|
|
5
|
+
"low",
|
|
6
|
+
"medium",
|
|
7
|
+
"high"
|
|
8
|
+
]);
|
|
9
|
+
const ReviewAssignedRoleEnum = defineEnum("ReviewAssignedRole", ["curator", "expert"]);
|
|
10
|
+
const ReviewDecisionEnum = defineEnum("ReviewDecision", ["approve", "reject"]);
|
|
11
|
+
const ChangeCandidateModel = defineSchemaModel({
|
|
12
|
+
name: "ChangeCandidate",
|
|
13
|
+
description: "Candidate change detected in a source document.",
|
|
14
|
+
fields: {
|
|
15
|
+
id: {
|
|
16
|
+
type: ScalarTypeEnum.String_unsecure(),
|
|
17
|
+
isOptional: false
|
|
18
|
+
},
|
|
19
|
+
sourceDocumentId: {
|
|
20
|
+
type: ScalarTypeEnum.String_unsecure(),
|
|
21
|
+
isOptional: false
|
|
22
|
+
},
|
|
23
|
+
detectedAt: {
|
|
24
|
+
type: ScalarTypeEnum.DateTime(),
|
|
25
|
+
isOptional: false
|
|
26
|
+
},
|
|
27
|
+
diffSummary: {
|
|
28
|
+
type: ScalarTypeEnum.String_unsecure(),
|
|
29
|
+
isOptional: false
|
|
30
|
+
},
|
|
31
|
+
riskLevel: {
|
|
32
|
+
type: ChangeRiskLevelEnum,
|
|
33
|
+
isOptional: false
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
const ReviewTaskModel = defineSchemaModel({
|
|
38
|
+
name: "ReviewTask",
|
|
39
|
+
description: "Human verification task for a change candidate.",
|
|
40
|
+
fields: {
|
|
41
|
+
id: {
|
|
42
|
+
type: ScalarTypeEnum.String_unsecure(),
|
|
43
|
+
isOptional: false
|
|
44
|
+
},
|
|
45
|
+
changeCandidateId: {
|
|
46
|
+
type: ScalarTypeEnum.String_unsecure(),
|
|
47
|
+
isOptional: false
|
|
48
|
+
},
|
|
49
|
+
status: {
|
|
50
|
+
type: ScalarTypeEnum.String_unsecure(),
|
|
51
|
+
isOptional: false
|
|
52
|
+
},
|
|
53
|
+
assignedRole: {
|
|
54
|
+
type: ReviewAssignedRoleEnum,
|
|
55
|
+
isOptional: false
|
|
56
|
+
},
|
|
57
|
+
decision: {
|
|
58
|
+
type: ReviewDecisionEnum,
|
|
59
|
+
isOptional: true
|
|
60
|
+
},
|
|
61
|
+
decidedAt: {
|
|
62
|
+
type: ScalarTypeEnum.DateTime(),
|
|
63
|
+
isOptional: true
|
|
64
|
+
},
|
|
65
|
+
decidedBy: {
|
|
66
|
+
type: ScalarTypeEnum.String_unsecure(),
|
|
67
|
+
isOptional: true
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
//#endregion
|
|
73
|
+
export { ChangeCandidateModel, ChangeRiskLevelEnum, ReviewAssignedRoleEnum, ReviewDecisionEnum, ReviewTaskModel };
|
|
74
|
+
//# sourceMappingURL=models.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"models.js","names":[],"sources":["../../src/entities/models.ts"],"sourcesContent":["import {\n ScalarTypeEnum,\n defineEnum,\n defineSchemaModel,\n} from '@contractspec/lib.schema';\n\nexport const ChangeRiskLevelEnum = defineEnum('ChangeRiskLevel', [\n 'low',\n 'medium',\n 'high',\n]);\n\nexport const ReviewAssignedRoleEnum = defineEnum('ReviewAssignedRole', [\n 'curator',\n 'expert',\n]);\n\nexport const ReviewDecisionEnum = defineEnum('ReviewDecision', [\n 'approve',\n 'reject',\n]);\n\nexport const ChangeCandidateModel = defineSchemaModel({\n name: 'ChangeCandidate',\n description: 'Candidate change detected in a source document.',\n fields: {\n id: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },\n sourceDocumentId: {\n type: ScalarTypeEnum.String_unsecure(),\n isOptional: false,\n },\n detectedAt: { type: ScalarTypeEnum.DateTime(), isOptional: false },\n diffSummary: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },\n riskLevel: { type: ChangeRiskLevelEnum, isOptional: false },\n },\n});\n\nexport const ReviewTaskModel = defineSchemaModel({\n name: 'ReviewTask',\n description: 'Human verification task for a change candidate.',\n fields: {\n id: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },\n changeCandidateId: {\n type: ScalarTypeEnum.String_unsecure(),\n isOptional: false,\n },\n status: { type: ScalarTypeEnum.String_unsecure(), isOptional: false }, // open|decided\n assignedRole: { type: ReviewAssignedRoleEnum, isOptional: false },\n decision: { type: ReviewDecisionEnum, isOptional: true },\n decidedAt: { type: ScalarTypeEnum.DateTime(), isOptional: true },\n decidedBy: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },\n },\n});\n"],"mappings":";;;AAMA,MAAa,sBAAsB,WAAW,mBAAmB;CAC/D;CACA;CACA;CACD,CAAC;AAEF,MAAa,yBAAyB,WAAW,sBAAsB,CACrE,WACA,SACD,CAAC;AAEF,MAAa,qBAAqB,WAAW,kBAAkB,CAC7D,WACA,SACD,CAAC;AAEF,MAAa,uBAAuB,kBAAkB;CACpD,MAAM;CACN,aAAa;CACb,QAAQ;EACN,IAAI;GAAE,MAAM,eAAe,iBAAiB;GAAE,YAAY;GAAO;EACjE,kBAAkB;GAChB,MAAM,eAAe,iBAAiB;GACtC,YAAY;GACb;EACD,YAAY;GAAE,MAAM,eAAe,UAAU;GAAE,YAAY;GAAO;EAClE,aAAa;GAAE,MAAM,eAAe,iBAAiB;GAAE,YAAY;GAAO;EAC1E,WAAW;GAAE,MAAM;GAAqB,YAAY;GAAO;EAC5D;CACF,CAAC;AAEF,MAAa,kBAAkB,kBAAkB;CAC/C,MAAM;CACN,aAAa;CACb,QAAQ;EACN,IAAI;GAAE,MAAM,eAAe,iBAAiB;GAAE,YAAY;GAAO;EACjE,mBAAmB;GACjB,MAAM,eAAe,iBAAiB;GACtC,YAAY;GACb;EACD,QAAQ;GAAE,MAAM,eAAe,iBAAiB;GAAE,YAAY;GAAO;EACrE,cAAc;GAAE,MAAM;GAAwB,YAAY;GAAO;EACjE,UAAU;GAAE,MAAM;GAAoB,YAAY;GAAM;EACxD,WAAW;GAAE,MAAM,eAAe,UAAU;GAAE,YAAY;GAAM;EAChE,WAAW;GAAE,MAAM,eAAe,iBAAiB;GAAE,YAAY;GAAM;EACxE;CACF,CAAC"}
|
package/dist/events.d.ts
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import * as _contractspec_lib_contracts0 from "@contractspec/lib.contracts";
|
|
2
|
+
import * as _contractspec_lib_schema0 from "@contractspec/lib.schema";
|
|
3
|
+
|
|
4
|
+
//#region src/events.d.ts
|
|
5
|
+
declare const KbChangeDetectedEvent: _contractspec_lib_contracts0.EventSpec<_contractspec_lib_schema0.SchemaModel<{
|
|
6
|
+
changeCandidateId: {
|
|
7
|
+
type: _contractspec_lib_schema0.FieldType<string, string>;
|
|
8
|
+
isOptional: false;
|
|
9
|
+
};
|
|
10
|
+
sourceDocumentId: {
|
|
11
|
+
type: _contractspec_lib_schema0.FieldType<string, string>;
|
|
12
|
+
isOptional: false;
|
|
13
|
+
};
|
|
14
|
+
riskLevel: {
|
|
15
|
+
type: _contractspec_lib_schema0.FieldType<string, string>;
|
|
16
|
+
isOptional: false;
|
|
17
|
+
};
|
|
18
|
+
}>>;
|
|
19
|
+
declare const KbChangeSummarizedEvent: _contractspec_lib_contracts0.EventSpec<_contractspec_lib_schema0.SchemaModel<{
|
|
20
|
+
changeCandidateId: {
|
|
21
|
+
type: _contractspec_lib_schema0.FieldType<string, string>;
|
|
22
|
+
isOptional: false;
|
|
23
|
+
};
|
|
24
|
+
summary: {
|
|
25
|
+
type: _contractspec_lib_schema0.FieldType<string, string>;
|
|
26
|
+
isOptional: false;
|
|
27
|
+
};
|
|
28
|
+
riskLevel: {
|
|
29
|
+
type: _contractspec_lib_schema0.FieldType<string, string>;
|
|
30
|
+
isOptional: false;
|
|
31
|
+
};
|
|
32
|
+
}>>;
|
|
33
|
+
declare const KbPatchProposedEvent: _contractspec_lib_contracts0.EventSpec<_contractspec_lib_schema0.SchemaModel<{
|
|
34
|
+
changeCandidateId: {
|
|
35
|
+
type: _contractspec_lib_schema0.FieldType<string, string>;
|
|
36
|
+
isOptional: false;
|
|
37
|
+
};
|
|
38
|
+
proposedRuleVersionIds: {
|
|
39
|
+
type: _contractspec_lib_schema0.FieldType<string, string>;
|
|
40
|
+
isArray: true;
|
|
41
|
+
isOptional: false;
|
|
42
|
+
};
|
|
43
|
+
}>>;
|
|
44
|
+
declare const KbReviewRequestedEvent: _contractspec_lib_contracts0.EventSpec<_contractspec_lib_schema0.SchemaModel<{
|
|
45
|
+
reviewTaskId: {
|
|
46
|
+
type: _contractspec_lib_schema0.FieldType<string, string>;
|
|
47
|
+
isOptional: false;
|
|
48
|
+
};
|
|
49
|
+
changeCandidateId: {
|
|
50
|
+
type: _contractspec_lib_schema0.FieldType<string, string>;
|
|
51
|
+
isOptional: false;
|
|
52
|
+
};
|
|
53
|
+
assignedRole: {
|
|
54
|
+
type: _contractspec_lib_schema0.FieldType<string, string>;
|
|
55
|
+
isOptional: false;
|
|
56
|
+
};
|
|
57
|
+
}>>;
|
|
58
|
+
declare const KbReviewDecidedEvent: _contractspec_lib_contracts0.EventSpec<_contractspec_lib_schema0.SchemaModel<{
|
|
59
|
+
reviewTaskId: {
|
|
60
|
+
type: _contractspec_lib_schema0.FieldType<string, string>;
|
|
61
|
+
isOptional: false;
|
|
62
|
+
};
|
|
63
|
+
decision: {
|
|
64
|
+
type: _contractspec_lib_schema0.FieldType<string, string>;
|
|
65
|
+
isOptional: false;
|
|
66
|
+
};
|
|
67
|
+
decidedBy: {
|
|
68
|
+
type: _contractspec_lib_schema0.FieldType<string, string>;
|
|
69
|
+
isOptional: false;
|
|
70
|
+
};
|
|
71
|
+
}>>;
|
|
72
|
+
//#endregion
|
|
73
|
+
export { KbChangeDetectedEvent, KbChangeSummarizedEvent, KbPatchProposedEvent, KbReviewDecidedEvent, KbReviewRequestedEvent };
|
|
74
|
+
//# sourceMappingURL=events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","names":[],"sources":["../src/events.ts"],"sourcesContent":[],"mappings":";;;;cAuBa,uBAAqB,4BAAA,CAAA,oCAAA;;UAUhC,yBAAA,CAAA;;EAVW,CAAA;EAUX,gBAAA,EAAA;;;;EAVgC,SAAA,EAAA;IAAA,IAAA,qCAAA,CAAA,MAAA,EAAA,MAAA,CAAA;IAyBrB,UAAA,EAAA,KAAA;EAUX,CAAA;;cAVW,yBAAuB,4BAAA,CAAA,oCAAA;;IAAA,IAAA,EAUlC,yBAAA,CAAA,SAVkC,CAAA,MAAA,EAAA,MAAA,CAAA;IAAA,UAAA,EAAA,KAAA;EA4BvB,CAAA;EAUX,OAAA,EAAA;;;EAV+B,CAAA;EAAA,SAAA,EAAA;IAyBpB,IAAA,qCAUX,CAAA,MAAA,EAAA,MAAA,CAAA;IAAA,UAAA,EAAA,KAAA;;;cAnCW,oBAyBsB,EAzBF,4BAAA,CAAA,SAyBE,2BAzBF,WAyBE,CAAA;EAAA,iBAAA,EAAA;IAAA,IAAA,EAfjC,yBAAA,CAAA,SAeiC,CAAA,MAAA,EAAA,MAAA,CAAA;IAsBtB,UAAA,EAAA,KAAA;EAUX,CAAA;;;;IAV+B,UAAA,EAAA,KAAA;EAAA,CAAA;;cAtBpB,wBAAsB,4BAAA,CAAA,oCAAA;;UAUjC,yBAAA,CAAA;;;;;;;;;;;;cAYW,sBAAoB,4BAAA,CAAA,oCAAA;;UAU/B,yBAAA,CAAA"}
|
package/dist/events.js
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { StabilityEnum, defineEvent, defineSchemaModel } from "@contractspec/lib.contracts";
|
|
2
|
+
import { ScalarTypeEnum } from "@contractspec/lib.schema";
|
|
3
|
+
|
|
4
|
+
//#region src/events.ts
|
|
5
|
+
const KbChangeDetectedPayload = defineSchemaModel({
|
|
6
|
+
name: "KbChangeDetectedPayload",
|
|
7
|
+
description: "Emitted when a source change is detected.",
|
|
8
|
+
fields: {
|
|
9
|
+
changeCandidateId: {
|
|
10
|
+
type: ScalarTypeEnum.String_unsecure(),
|
|
11
|
+
isOptional: false
|
|
12
|
+
},
|
|
13
|
+
sourceDocumentId: {
|
|
14
|
+
type: ScalarTypeEnum.String_unsecure(),
|
|
15
|
+
isOptional: false
|
|
16
|
+
},
|
|
17
|
+
riskLevel: {
|
|
18
|
+
type: ScalarTypeEnum.String_unsecure(),
|
|
19
|
+
isOptional: false
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
const KbChangeDetectedEvent = defineEvent({
|
|
24
|
+
meta: {
|
|
25
|
+
key: "kb.change.detected",
|
|
26
|
+
version: "1.0.0",
|
|
27
|
+
description: "KB source change detected.",
|
|
28
|
+
stability: StabilityEnum.Experimental,
|
|
29
|
+
owners: [],
|
|
30
|
+
tags: []
|
|
31
|
+
},
|
|
32
|
+
payload: KbChangeDetectedPayload
|
|
33
|
+
});
|
|
34
|
+
const KbChangeSummarizedPayload = defineSchemaModel({
|
|
35
|
+
name: "KbChangeSummarizedPayload",
|
|
36
|
+
description: "Emitted when a change summary is produced.",
|
|
37
|
+
fields: {
|
|
38
|
+
changeCandidateId: {
|
|
39
|
+
type: ScalarTypeEnum.String_unsecure(),
|
|
40
|
+
isOptional: false
|
|
41
|
+
},
|
|
42
|
+
summary: {
|
|
43
|
+
type: ScalarTypeEnum.String_unsecure(),
|
|
44
|
+
isOptional: false
|
|
45
|
+
},
|
|
46
|
+
riskLevel: {
|
|
47
|
+
type: ScalarTypeEnum.String_unsecure(),
|
|
48
|
+
isOptional: false
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
const KbChangeSummarizedEvent = defineEvent({
|
|
53
|
+
meta: {
|
|
54
|
+
key: "kb.change.summarized",
|
|
55
|
+
version: "1.0.0",
|
|
56
|
+
description: "KB change summarized.",
|
|
57
|
+
stability: StabilityEnum.Experimental,
|
|
58
|
+
owners: [],
|
|
59
|
+
tags: []
|
|
60
|
+
},
|
|
61
|
+
payload: KbChangeSummarizedPayload
|
|
62
|
+
});
|
|
63
|
+
const KbPatchProposedPayload = defineSchemaModel({
|
|
64
|
+
name: "KbPatchProposedPayload",
|
|
65
|
+
description: "Emitted when draft rule patches are proposed.",
|
|
66
|
+
fields: {
|
|
67
|
+
changeCandidateId: {
|
|
68
|
+
type: ScalarTypeEnum.String_unsecure(),
|
|
69
|
+
isOptional: false
|
|
70
|
+
},
|
|
71
|
+
proposedRuleVersionIds: {
|
|
72
|
+
type: ScalarTypeEnum.String_unsecure(),
|
|
73
|
+
isArray: true,
|
|
74
|
+
isOptional: false
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
const KbPatchProposedEvent = defineEvent({
|
|
79
|
+
meta: {
|
|
80
|
+
key: "kb.patch.proposed",
|
|
81
|
+
version: "1.0.0",
|
|
82
|
+
description: "KB rule patch proposed (draft versions created).",
|
|
83
|
+
stability: StabilityEnum.Experimental,
|
|
84
|
+
owners: [],
|
|
85
|
+
tags: []
|
|
86
|
+
},
|
|
87
|
+
payload: KbPatchProposedPayload
|
|
88
|
+
});
|
|
89
|
+
const KbReviewRequestedPayload = defineSchemaModel({
|
|
90
|
+
name: "KbReviewRequestedPayload",
|
|
91
|
+
description: "Emitted when a review is requested.",
|
|
92
|
+
fields: {
|
|
93
|
+
reviewTaskId: {
|
|
94
|
+
type: ScalarTypeEnum.String_unsecure(),
|
|
95
|
+
isOptional: false
|
|
96
|
+
},
|
|
97
|
+
changeCandidateId: {
|
|
98
|
+
type: ScalarTypeEnum.String_unsecure(),
|
|
99
|
+
isOptional: false
|
|
100
|
+
},
|
|
101
|
+
assignedRole: {
|
|
102
|
+
type: ScalarTypeEnum.String_unsecure(),
|
|
103
|
+
isOptional: false
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
const KbReviewRequestedEvent = defineEvent({
|
|
108
|
+
meta: {
|
|
109
|
+
key: "kb.review.requested",
|
|
110
|
+
version: "1.0.0",
|
|
111
|
+
description: "KB review requested.",
|
|
112
|
+
stability: StabilityEnum.Experimental,
|
|
113
|
+
owners: [],
|
|
114
|
+
tags: []
|
|
115
|
+
},
|
|
116
|
+
payload: KbReviewRequestedPayload
|
|
117
|
+
});
|
|
118
|
+
const KbReviewDecidedPayload = defineSchemaModel({
|
|
119
|
+
name: "KbReviewDecidedPayload",
|
|
120
|
+
description: "Emitted when a review task is decided.",
|
|
121
|
+
fields: {
|
|
122
|
+
reviewTaskId: {
|
|
123
|
+
type: ScalarTypeEnum.String_unsecure(),
|
|
124
|
+
isOptional: false
|
|
125
|
+
},
|
|
126
|
+
decision: {
|
|
127
|
+
type: ScalarTypeEnum.String_unsecure(),
|
|
128
|
+
isOptional: false
|
|
129
|
+
},
|
|
130
|
+
decidedBy: {
|
|
131
|
+
type: ScalarTypeEnum.String_unsecure(),
|
|
132
|
+
isOptional: false
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
const KbReviewDecidedEvent = defineEvent({
|
|
137
|
+
meta: {
|
|
138
|
+
key: "kb.review.decided",
|
|
139
|
+
version: "1.0.0",
|
|
140
|
+
description: "KB review decided.",
|
|
141
|
+
stability: StabilityEnum.Experimental,
|
|
142
|
+
owners: [],
|
|
143
|
+
tags: []
|
|
144
|
+
},
|
|
145
|
+
payload: KbReviewDecidedPayload
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
//#endregion
|
|
149
|
+
export { KbChangeDetectedEvent, KbChangeSummarizedEvent, KbPatchProposedEvent, KbReviewDecidedEvent, KbReviewRequestedEvent };
|
|
150
|
+
//# sourceMappingURL=events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.js","names":[],"sources":["../src/events.ts"],"sourcesContent":["import {\n defineEvent,\n defineSchemaModel,\n StabilityEnum,\n} from '@contractspec/lib.contracts';\nimport { ScalarTypeEnum } from '@contractspec/lib.schema';\n\nconst KbChangeDetectedPayload = defineSchemaModel({\n name: 'KbChangeDetectedPayload',\n description: 'Emitted when a source change is detected.',\n fields: {\n changeCandidateId: {\n type: ScalarTypeEnum.String_unsecure(),\n isOptional: false,\n },\n sourceDocumentId: {\n type: ScalarTypeEnum.String_unsecure(),\n isOptional: false,\n },\n riskLevel: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },\n },\n});\n\nexport const KbChangeDetectedEvent = defineEvent({\n meta: {\n key: 'kb.change.detected',\n version: '1.0.0',\n description: 'KB source change detected.',\n stability: StabilityEnum.Experimental,\n owners: [],\n tags: [],\n },\n payload: KbChangeDetectedPayload,\n});\n\nconst KbChangeSummarizedPayload = defineSchemaModel({\n name: 'KbChangeSummarizedPayload',\n description: 'Emitted when a change summary is produced.',\n fields: {\n changeCandidateId: {\n type: ScalarTypeEnum.String_unsecure(),\n isOptional: false,\n },\n summary: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },\n riskLevel: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },\n },\n});\n\nexport const KbChangeSummarizedEvent = defineEvent({\n meta: {\n key: 'kb.change.summarized',\n version: '1.0.0',\n description: 'KB change summarized.',\n stability: StabilityEnum.Experimental,\n owners: [],\n tags: [],\n },\n payload: KbChangeSummarizedPayload,\n});\n\nconst KbPatchProposedPayload = defineSchemaModel({\n name: 'KbPatchProposedPayload',\n description: 'Emitted when draft rule patches are proposed.',\n fields: {\n changeCandidateId: {\n type: ScalarTypeEnum.String_unsecure(),\n isOptional: false,\n },\n proposedRuleVersionIds: {\n type: ScalarTypeEnum.String_unsecure(),\n isArray: true,\n isOptional: false,\n },\n },\n});\n\nexport const KbPatchProposedEvent = defineEvent({\n meta: {\n key: 'kb.patch.proposed',\n version: '1.0.0',\n description: 'KB rule patch proposed (draft versions created).',\n stability: StabilityEnum.Experimental,\n owners: [],\n tags: [],\n },\n payload: KbPatchProposedPayload,\n});\n\nconst KbReviewRequestedPayload = defineSchemaModel({\n name: 'KbReviewRequestedPayload',\n description: 'Emitted when a review is requested.',\n fields: {\n reviewTaskId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },\n changeCandidateId: {\n type: ScalarTypeEnum.String_unsecure(),\n isOptional: false,\n },\n assignedRole: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },\n },\n});\n\nexport const KbReviewRequestedEvent = defineEvent({\n meta: {\n key: 'kb.review.requested',\n version: '1.0.0',\n description: 'KB review requested.',\n stability: StabilityEnum.Experimental,\n owners: [],\n tags: [],\n },\n payload: KbReviewRequestedPayload,\n});\n\nconst KbReviewDecidedPayload = defineSchemaModel({\n name: 'KbReviewDecidedPayload',\n description: 'Emitted when a review task is decided.',\n fields: {\n reviewTaskId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },\n decision: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },\n decidedBy: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },\n },\n});\n\nexport const KbReviewDecidedEvent = defineEvent({\n meta: {\n key: 'kb.review.decided',\n version: '1.0.0',\n description: 'KB review decided.',\n stability: StabilityEnum.Experimental,\n owners: [],\n tags: [],\n },\n payload: KbReviewDecidedPayload,\n});\n"],"mappings":";;;;AAOA,MAAM,0BAA0B,kBAAkB;CAChD,MAAM;CACN,aAAa;CACb,QAAQ;EACN,mBAAmB;GACjB,MAAM,eAAe,iBAAiB;GACtC,YAAY;GACb;EACD,kBAAkB;GAChB,MAAM,eAAe,iBAAiB;GACtC,YAAY;GACb;EACD,WAAW;GAAE,MAAM,eAAe,iBAAiB;GAAE,YAAY;GAAO;EACzE;CACF,CAAC;AAEF,MAAa,wBAAwB,YAAY;CAC/C,MAAM;EACJ,KAAK;EACL,SAAS;EACT,aAAa;EACb,WAAW,cAAc;EACzB,QAAQ,EAAE;EACV,MAAM,EAAE;EACT;CACD,SAAS;CACV,CAAC;AAEF,MAAM,4BAA4B,kBAAkB;CAClD,MAAM;CACN,aAAa;CACb,QAAQ;EACN,mBAAmB;GACjB,MAAM,eAAe,iBAAiB;GACtC,YAAY;GACb;EACD,SAAS;GAAE,MAAM,eAAe,iBAAiB;GAAE,YAAY;GAAO;EACtE,WAAW;GAAE,MAAM,eAAe,iBAAiB;GAAE,YAAY;GAAO;EACzE;CACF,CAAC;AAEF,MAAa,0BAA0B,YAAY;CACjD,MAAM;EACJ,KAAK;EACL,SAAS;EACT,aAAa;EACb,WAAW,cAAc;EACzB,QAAQ,EAAE;EACV,MAAM,EAAE;EACT;CACD,SAAS;CACV,CAAC;AAEF,MAAM,yBAAyB,kBAAkB;CAC/C,MAAM;CACN,aAAa;CACb,QAAQ;EACN,mBAAmB;GACjB,MAAM,eAAe,iBAAiB;GACtC,YAAY;GACb;EACD,wBAAwB;GACtB,MAAM,eAAe,iBAAiB;GACtC,SAAS;GACT,YAAY;GACb;EACF;CACF,CAAC;AAEF,MAAa,uBAAuB,YAAY;CAC9C,MAAM;EACJ,KAAK;EACL,SAAS;EACT,aAAa;EACb,WAAW,cAAc;EACzB,QAAQ,EAAE;EACV,MAAM,EAAE;EACT;CACD,SAAS;CACV,CAAC;AAEF,MAAM,2BAA2B,kBAAkB;CACjD,MAAM;CACN,aAAa;CACb,QAAQ;EACN,cAAc;GAAE,MAAM,eAAe,iBAAiB;GAAE,YAAY;GAAO;EAC3E,mBAAmB;GACjB,MAAM,eAAe,iBAAiB;GACtC,YAAY;GACb;EACD,cAAc;GAAE,MAAM,eAAe,iBAAiB;GAAE,YAAY;GAAO;EAC5E;CACF,CAAC;AAEF,MAAa,yBAAyB,YAAY;CAChD,MAAM;EACJ,KAAK;EACL,SAAS;EACT,aAAa;EACb,WAAW,cAAc;EACzB,QAAQ,EAAE;EACV,MAAM,EAAE;EACT;CACD,SAAS;CACV,CAAC;AAEF,MAAM,yBAAyB,kBAAkB;CAC/C,MAAM;CACN,aAAa;CACb,QAAQ;EACN,cAAc;GAAE,MAAM,eAAe,iBAAiB;GAAE,YAAY;GAAO;EAC3E,UAAU;GAAE,MAAM,eAAe,iBAAiB;GAAE,YAAY;GAAO;EACvE,WAAW;GAAE,MAAM,eAAe,iBAAiB;GAAE,YAAY;GAAO;EACzE;CACF,CAAC;AAEF,MAAa,uBAAuB,YAAY;CAC9C,MAAM;EACJ,KAAK;EACL,SAAS;EACT,aAAa;EACb,WAAW,cAAc;EACzB,QAAQ,EAAE;EACV,MAAM,EAAE;EACT;CACD,SAAS;CACV,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"example.d.ts","names":[],"sources":["../src/example.ts"],"sourcesContent":[],"mappings":";;;cAEM,SA6BJ,4BAAA,CA7BW"}
|
package/dist/example.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { defineExample } from "@contractspec/lib.contracts";
|
|
2
|
+
|
|
3
|
+
//#region src/example.ts
|
|
4
|
+
const example = defineExample({
|
|
5
|
+
meta: {
|
|
6
|
+
key: "kb-update-pipeline",
|
|
7
|
+
version: "1.0.0",
|
|
8
|
+
title: "KB Update Pipeline",
|
|
9
|
+
description: "Automation proposes KB updates; humans verify; everything audited and notified.",
|
|
10
|
+
kind: "knowledge",
|
|
11
|
+
visibility: "public",
|
|
12
|
+
stability: "experimental",
|
|
13
|
+
owners: ["@platform.core"],
|
|
14
|
+
tags: [
|
|
15
|
+
"knowledge",
|
|
16
|
+
"pipeline",
|
|
17
|
+
"hitl",
|
|
18
|
+
"audit"
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
docs: { rootDocId: "docs.examples.kb-update-pipeline" },
|
|
22
|
+
entrypoints: {
|
|
23
|
+
packageName: "@contractspec/example.kb-update-pipeline",
|
|
24
|
+
feature: "./feature",
|
|
25
|
+
contracts: "./contracts",
|
|
26
|
+
handlers: "./handlers",
|
|
27
|
+
docs: "./docs"
|
|
28
|
+
},
|
|
29
|
+
surfaces: {
|
|
30
|
+
templates: true,
|
|
31
|
+
sandbox: {
|
|
32
|
+
enabled: true,
|
|
33
|
+
modes: [
|
|
34
|
+
"markdown",
|
|
35
|
+
"specs",
|
|
36
|
+
"builder"
|
|
37
|
+
]
|
|
38
|
+
},
|
|
39
|
+
studio: {
|
|
40
|
+
enabled: true,
|
|
41
|
+
installable: true
|
|
42
|
+
},
|
|
43
|
+
mcp: { enabled: true }
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
var example_default = example;
|
|
47
|
+
|
|
48
|
+
//#endregion
|
|
49
|
+
export { example_default as default };
|
|
50
|
+
//# sourceMappingURL=example.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"example.js","names":[],"sources":["../src/example.ts"],"sourcesContent":["import { defineExample } from '@contractspec/lib.contracts';\n\nconst example = defineExample({\n meta: {\n key: 'kb-update-pipeline',\n version: '1.0.0',\n title: 'KB Update Pipeline',\n description:\n 'Automation proposes KB updates; humans verify; everything audited and notified.',\n kind: 'knowledge',\n visibility: 'public',\n stability: 'experimental',\n owners: ['@platform.core'],\n tags: ['knowledge', 'pipeline', 'hitl', 'audit'],\n },\n docs: {\n rootDocId: 'docs.examples.kb-update-pipeline',\n },\n entrypoints: {\n packageName: '@contractspec/example.kb-update-pipeline',\n feature: './feature',\n contracts: './contracts',\n handlers: './handlers',\n docs: './docs',\n },\n surfaces: {\n templates: true,\n sandbox: { enabled: true, modes: ['markdown', 'specs', 'builder'] },\n studio: { enabled: true, installable: true },\n mcp: { enabled: true },\n },\n});\n\nexport default example;\n"],"mappings":";;;AAEA,MAAM,UAAU,cAAc;CAC5B,MAAM;EACJ,KAAK;EACL,SAAS;EACT,OAAO;EACP,aACE;EACF,MAAM;EACN,YAAY;EACZ,WAAW;EACX,QAAQ,CAAC,iBAAiB;EAC1B,MAAM;GAAC;GAAa;GAAY;GAAQ;GAAQ;EACjD;CACD,MAAM,EACJ,WAAW,oCACZ;CACD,aAAa;EACX,aAAa;EACb,SAAS;EACT,WAAW;EACX,UAAU;EACV,MAAM;EACP;CACD,UAAU;EACR,WAAW;EACX,SAAS;GAAE,SAAS;GAAM,OAAO;IAAC;IAAY;IAAS;IAAU;GAAE;EACnE,QAAQ;GAAE,SAAS;GAAM,aAAa;GAAM;EAC5C,KAAK,EAAE,SAAS,MAAM;EACvB;CACF,CAAC;AAEF,sBAAe"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
//#region src/handlers/memory.handlers.d.ts
|
|
2
|
+
interface ChangeCandidate {
|
|
3
|
+
id: string;
|
|
4
|
+
sourceDocumentId: string;
|
|
5
|
+
detectedAt: Date;
|
|
6
|
+
diffSummary: string;
|
|
7
|
+
riskLevel: 'low' | 'medium' | 'high';
|
|
8
|
+
}
|
|
9
|
+
interface ReviewTask {
|
|
10
|
+
id: string;
|
|
11
|
+
changeCandidateId: string;
|
|
12
|
+
status: 'open' | 'decided';
|
|
13
|
+
assignedRole: 'curator' | 'expert';
|
|
14
|
+
decision?: 'approve' | 'reject';
|
|
15
|
+
decidedAt?: Date;
|
|
16
|
+
decidedBy?: string;
|
|
17
|
+
}
|
|
18
|
+
interface PipelineMemoryStore {
|
|
19
|
+
candidates: Map<string, ChangeCandidate>;
|
|
20
|
+
reviewTasks: Map<string, ReviewTask>;
|
|
21
|
+
proposedRuleVersionIdsByCandidate: Map<string, string[]>;
|
|
22
|
+
approvedRuleVersionIds: Set<string>;
|
|
23
|
+
notifications: {
|
|
24
|
+
kind: 'kb.review.requested';
|
|
25
|
+
reviewTaskId: string;
|
|
26
|
+
changeCandidateId: string;
|
|
27
|
+
assignedRole: 'curator' | 'expert';
|
|
28
|
+
createdAt: Date;
|
|
29
|
+
}[];
|
|
30
|
+
}
|
|
31
|
+
declare function createPipelineMemoryStore(): PipelineMemoryStore;
|
|
32
|
+
interface PipelineMemoryHandlers {
|
|
33
|
+
runWatch(input: {
|
|
34
|
+
jurisdiction: string;
|
|
35
|
+
}): Promise<{
|
|
36
|
+
candidates: ChangeCandidate[];
|
|
37
|
+
}>;
|
|
38
|
+
createReviewTask(input: {
|
|
39
|
+
changeCandidateId: string;
|
|
40
|
+
}): Promise<ReviewTask>;
|
|
41
|
+
proposeRulePatch(input: {
|
|
42
|
+
changeCandidateId: string;
|
|
43
|
+
proposedRuleVersionIds: string[];
|
|
44
|
+
}): Promise<{
|
|
45
|
+
proposedRuleVersionIds: string[];
|
|
46
|
+
}>;
|
|
47
|
+
markRuleVersionApproved(input: {
|
|
48
|
+
ruleVersionId: string;
|
|
49
|
+
}): Promise<{
|
|
50
|
+
ruleVersionId: string;
|
|
51
|
+
}>;
|
|
52
|
+
submitDecision(input: {
|
|
53
|
+
reviewTaskId: string;
|
|
54
|
+
decision: 'approve' | 'reject';
|
|
55
|
+
decidedBy: string;
|
|
56
|
+
decidedByRole: 'curator' | 'expert';
|
|
57
|
+
}): Promise<ReviewTask>;
|
|
58
|
+
publishIfReady(input: {
|
|
59
|
+
jurisdiction: string;
|
|
60
|
+
}): Promise<{
|
|
61
|
+
published: boolean;
|
|
62
|
+
reason?: string;
|
|
63
|
+
}>;
|
|
64
|
+
}
|
|
65
|
+
declare function createPipelineMemoryHandlers(store: PipelineMemoryStore): PipelineMemoryHandlers;
|
|
66
|
+
//#endregion
|
|
67
|
+
export { PipelineMemoryHandlers, PipelineMemoryStore, createPipelineMemoryHandlers, createPipelineMemoryStore };
|
|
68
|
+
//# sourceMappingURL=memory.handlers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.handlers.d.ts","names":[],"sources":["../../src/handlers/memory.handlers.ts"],"sourcesContent":[],"mappings":";UAAU,eAAA;EAAA,EAAA,EAAA,MAAA;EAQA,gBAAU,EAAA,MAAA;EAUH,UAAA,EAfH,IAeG;EACS,WAAA,EAAA,MAAA;EAAZ,SAAA,EAAA,KAAA,GAAA,QAAA,GAAA,MAAA;;UAXJ,UAAA,CAYK;EACsB,EAAA,EAAA,MAAA;EACX,iBAAA,EAAA,MAAA;EAMX,MAAA,EAAA,MAAA,GAAA,SAAA;EAAI,YAAA,EAAA,SAAA,GAAA,QAAA;EAIH,QAAA,CAAA,EAAA,SAAA,GAAA,QAAyB;EAcxB,SAAA,CAAA,EAhCH,IAgCG;EAGW,SAAA,CAAA,EAAA,MAAA;;AACsC,UAhCjD,mBAAA,CAgCiD;EAAR,UAAA,EA/B5C,GA+B4C,CAAA,MAAA,EA/BhC,eA+BgC,CAAA;EAIpD,WAAA,EAlCS,GAkCT,CAAA,MAAA,EAlCqB,UAkCrB,CAAA;EAGA,iCAAA,EApC+B,GAoC/B,CAAA,MAAA,EAAA,MAAA,EAAA,CAAA;EAMQ,sBAAA,EAzCY,GAyCZ,CAAA,MAAA,CAAA;EAAR,aAAA,EAAA;IAGA,IAAA,EAAA,qBAAA;IAAO,YAAA,EAAA,MAAA;IAGG,iBAAA,EAAA,MAAA;;eAzCD;;;iBAIC,yBAAA,CAAA,GAA6B;UAc5B,sBAAA;;;MAGX;gBAAsB;;;;MAC8B,QAAQ;;;;MAI5D;;;;;MAGA;;;;;;;;MAMA,QAAQ;;;MAGR;;;;;iBAGU,4BAAA,QACP,sBACN"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
//#region src/handlers/memory.handlers.ts
|
|
2
|
+
function createPipelineMemoryStore() {
|
|
3
|
+
return {
|
|
4
|
+
candidates: /* @__PURE__ */ new Map(),
|
|
5
|
+
reviewTasks: /* @__PURE__ */ new Map(),
|
|
6
|
+
proposedRuleVersionIdsByCandidate: /* @__PURE__ */ new Map(),
|
|
7
|
+
approvedRuleVersionIds: /* @__PURE__ */ new Set(),
|
|
8
|
+
notifications: []
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
function stableId(prefix, value) {
|
|
12
|
+
return `${prefix}_${value.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
|
|
13
|
+
}
|
|
14
|
+
function createPipelineMemoryHandlers(store) {
|
|
15
|
+
async function runWatch(input) {
|
|
16
|
+
return { candidates: [...store.candidates.values()].filter((c) => c.sourceDocumentId.startsWith(`${input.jurisdiction}_`) || true) };
|
|
17
|
+
}
|
|
18
|
+
async function createReviewTask(input) {
|
|
19
|
+
const candidate = store.candidates.get(input.changeCandidateId);
|
|
20
|
+
if (!candidate) throw new Error("CHANGE_CANDIDATE_NOT_FOUND");
|
|
21
|
+
const assignedRole = candidate.riskLevel === "high" ? "expert" : "curator";
|
|
22
|
+
const id = stableId("review", input.changeCandidateId);
|
|
23
|
+
const task = {
|
|
24
|
+
id,
|
|
25
|
+
changeCandidateId: input.changeCandidateId,
|
|
26
|
+
status: "open",
|
|
27
|
+
assignedRole,
|
|
28
|
+
decision: void 0,
|
|
29
|
+
decidedAt: void 0,
|
|
30
|
+
decidedBy: void 0
|
|
31
|
+
};
|
|
32
|
+
store.reviewTasks.set(id, task);
|
|
33
|
+
store.notifications.push({
|
|
34
|
+
kind: "kb.review.requested",
|
|
35
|
+
reviewTaskId: id,
|
|
36
|
+
changeCandidateId: input.changeCandidateId,
|
|
37
|
+
assignedRole,
|
|
38
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
39
|
+
});
|
|
40
|
+
return task;
|
|
41
|
+
}
|
|
42
|
+
async function proposeRulePatch(input) {
|
|
43
|
+
if (!store.candidates.has(input.changeCandidateId)) throw new Error("CHANGE_CANDIDATE_NOT_FOUND");
|
|
44
|
+
store.proposedRuleVersionIdsByCandidate.set(input.changeCandidateId, [...input.proposedRuleVersionIds]);
|
|
45
|
+
return { proposedRuleVersionIds: [...input.proposedRuleVersionIds] };
|
|
46
|
+
}
|
|
47
|
+
async function markRuleVersionApproved(input) {
|
|
48
|
+
store.approvedRuleVersionIds.add(input.ruleVersionId);
|
|
49
|
+
return { ruleVersionId: input.ruleVersionId };
|
|
50
|
+
}
|
|
51
|
+
async function submitDecision(input) {
|
|
52
|
+
const task = store.reviewTasks.get(input.reviewTaskId);
|
|
53
|
+
if (!task) throw new Error("REVIEW_TASK_NOT_FOUND");
|
|
54
|
+
const candidate = store.candidates.get(task.changeCandidateId);
|
|
55
|
+
if (!candidate) throw new Error("CHANGE_CANDIDATE_NOT_FOUND");
|
|
56
|
+
if (candidate.riskLevel === "high" && input.decision === "approve") {
|
|
57
|
+
if (input.decidedByRole !== "expert") throw new Error("FORBIDDEN_ROLE");
|
|
58
|
+
}
|
|
59
|
+
const decided = {
|
|
60
|
+
...task,
|
|
61
|
+
status: "decided",
|
|
62
|
+
decision: input.decision,
|
|
63
|
+
decidedAt: /* @__PURE__ */ new Date(),
|
|
64
|
+
decidedBy: input.decidedBy
|
|
65
|
+
};
|
|
66
|
+
store.reviewTasks.set(decided.id, decided);
|
|
67
|
+
return decided;
|
|
68
|
+
}
|
|
69
|
+
async function publishIfReady(_input) {
|
|
70
|
+
if ([...store.reviewTasks.values()].filter((t) => t.status !== "decided").length) throw new Error("NOT_READY");
|
|
71
|
+
if ([...store.reviewTasks.values()].some((t) => t.decision === "reject")) return {
|
|
72
|
+
published: false,
|
|
73
|
+
reason: "REJECTED"
|
|
74
|
+
};
|
|
75
|
+
for (const task of store.reviewTasks.values()) {
|
|
76
|
+
if (task.decision !== "approve") continue;
|
|
77
|
+
if ((store.proposedRuleVersionIdsByCandidate.get(task.changeCandidateId) ?? []).filter((id) => !store.approvedRuleVersionIds.has(id)).length) throw new Error("NOT_READY");
|
|
78
|
+
}
|
|
79
|
+
return { published: true };
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
runWatch,
|
|
83
|
+
createReviewTask,
|
|
84
|
+
proposeRulePatch,
|
|
85
|
+
markRuleVersionApproved,
|
|
86
|
+
submitDecision,
|
|
87
|
+
publishIfReady
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
//#endregion
|
|
92
|
+
export { createPipelineMemoryHandlers, createPipelineMemoryStore };
|
|
93
|
+
//# sourceMappingURL=memory.handlers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.handlers.js","names":[],"sources":["../../src/handlers/memory.handlers.ts"],"sourcesContent":["interface ChangeCandidate {\n id: string;\n sourceDocumentId: string;\n detectedAt: Date;\n diffSummary: string;\n riskLevel: 'low' | 'medium' | 'high';\n}\n\ninterface ReviewTask {\n id: string;\n changeCandidateId: string;\n status: 'open' | 'decided';\n assignedRole: 'curator' | 'expert';\n decision?: 'approve' | 'reject';\n decidedAt?: Date;\n decidedBy?: string;\n}\n\nexport interface PipelineMemoryStore {\n candidates: Map<string, ChangeCandidate>;\n reviewTasks: Map<string, ReviewTask>;\n proposedRuleVersionIdsByCandidate: Map<string, string[]>;\n approvedRuleVersionIds: Set<string>;\n notifications: {\n kind: 'kb.review.requested';\n reviewTaskId: string;\n changeCandidateId: string;\n assignedRole: 'curator' | 'expert';\n createdAt: Date;\n }[];\n}\n\nexport function createPipelineMemoryStore(): PipelineMemoryStore {\n return {\n candidates: new Map(),\n reviewTasks: new Map(),\n proposedRuleVersionIdsByCandidate: new Map(),\n approvedRuleVersionIds: new Set(),\n notifications: [],\n };\n}\n\nfunction stableId(prefix: string, value: string): string {\n return `${prefix}_${value.replace(/[^a-zA-Z0-9_-]/g, '_')}`;\n}\n\nexport interface PipelineMemoryHandlers {\n runWatch(input: {\n jurisdiction: string;\n }): Promise<{ candidates: ChangeCandidate[] }>;\n createReviewTask(input: { changeCandidateId: string }): Promise<ReviewTask>;\n proposeRulePatch(input: {\n changeCandidateId: string;\n proposedRuleVersionIds: string[];\n }): Promise<{ proposedRuleVersionIds: string[] }>;\n markRuleVersionApproved(input: {\n ruleVersionId: string;\n }): Promise<{ ruleVersionId: string }>;\n submitDecision(input: {\n reviewTaskId: string;\n decision: 'approve' | 'reject';\n decidedBy: string;\n decidedByRole: 'curator' | 'expert';\n }): Promise<ReviewTask>;\n publishIfReady(input: {\n jurisdiction: string;\n }): Promise<{ published: boolean; reason?: string }>;\n}\n\nexport function createPipelineMemoryHandlers(\n store: PipelineMemoryStore\n): PipelineMemoryHandlers {\n async function runWatch(input: { jurisdiction: string }) {\n // demo: always returns empty unless caller pre-seeds candidates\n const candidates = [...store.candidates.values()].filter(\n (c) => c.sourceDocumentId.startsWith(`${input.jurisdiction}_`) || true\n );\n return { candidates };\n }\n\n async function createReviewTask(input: { changeCandidateId: string }) {\n const candidate = store.candidates.get(input.changeCandidateId);\n if (!candidate) throw new Error('CHANGE_CANDIDATE_NOT_FOUND');\n const assignedRole = candidate.riskLevel === 'high' ? 'expert' : 'curator';\n const id = stableId('review', input.changeCandidateId);\n const task: ReviewTask = {\n id,\n changeCandidateId: input.changeCandidateId,\n status: 'open',\n assignedRole,\n decision: undefined,\n decidedAt: undefined,\n decidedBy: undefined,\n };\n store.reviewTasks.set(id, task);\n store.notifications.push({\n kind: 'kb.review.requested',\n reviewTaskId: id,\n changeCandidateId: input.changeCandidateId,\n assignedRole,\n createdAt: new Date(),\n });\n return task;\n }\n\n async function proposeRulePatch(input: {\n changeCandidateId: string;\n proposedRuleVersionIds: string[];\n }): Promise<{ proposedRuleVersionIds: string[] }> {\n if (!store.candidates.has(input.changeCandidateId)) {\n throw new Error('CHANGE_CANDIDATE_NOT_FOUND');\n }\n store.proposedRuleVersionIdsByCandidate.set(input.changeCandidateId, [\n ...input.proposedRuleVersionIds,\n ]);\n return { proposedRuleVersionIds: [...input.proposedRuleVersionIds] };\n }\n\n async function markRuleVersionApproved(input: {\n ruleVersionId: string;\n }): Promise<{ ruleVersionId: string }> {\n store.approvedRuleVersionIds.add(input.ruleVersionId);\n return { ruleVersionId: input.ruleVersionId };\n }\n\n async function submitDecision(input: {\n reviewTaskId: string;\n decision: 'approve' | 'reject';\n decidedBy: string;\n decidedByRole: 'curator' | 'expert';\n }) {\n const task = store.reviewTasks.get(input.reviewTaskId);\n if (!task) throw new Error('REVIEW_TASK_NOT_FOUND');\n const candidate = store.candidates.get(task.changeCandidateId);\n if (!candidate) throw new Error('CHANGE_CANDIDATE_NOT_FOUND');\n if (candidate.riskLevel === 'high' && input.decision === 'approve') {\n if (input.decidedByRole !== 'expert') throw new Error('FORBIDDEN_ROLE');\n }\n const decided: ReviewTask = {\n ...task,\n status: 'decided',\n decision: input.decision,\n decidedAt: new Date(),\n decidedBy: input.decidedBy,\n };\n store.reviewTasks.set(decided.id, decided);\n return decided;\n }\n\n async function publishIfReady(_input: { jurisdiction: string }) {\n const openTasks = [...store.reviewTasks.values()].filter(\n (t) => t.status !== 'decided'\n );\n if (openTasks.length) {\n throw new Error('NOT_READY');\n }\n const rejected = [...store.reviewTasks.values()].some(\n (t) => t.decision === 'reject'\n );\n if (rejected) return { published: false, reason: 'REJECTED' };\n\n // Ensure every proposed rule version is approved before publishing.\n for (const task of store.reviewTasks.values()) {\n if (task.decision !== 'approve') continue;\n const proposed =\n store.proposedRuleVersionIdsByCandidate.get(task.changeCandidateId) ??\n [];\n const unapproved = proposed.filter(\n (id) => !store.approvedRuleVersionIds.has(id)\n );\n if (unapproved.length) {\n throw new Error('NOT_READY');\n }\n }\n return { published: true };\n }\n\n return {\n runWatch,\n createReviewTask,\n proposeRulePatch,\n markRuleVersionApproved,\n submitDecision,\n publishIfReady,\n };\n}\n"],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ChangeCandidateModel, ChangeRiskLevelEnum, ReviewAssignedRoleEnum, ReviewDecisionEnum, ReviewTaskModel } from "./entities/models.js";
|
|
2
|
+
import "./entities/index.js";
|
|
3
|
+
import { KbChangeDetectedEvent, KbChangeSummarizedEvent, KbPatchProposedEvent, KbReviewDecidedEvent, KbReviewRequestedEvent } from "./events.js";
|
|
4
|
+
import example from "./example.js";
|
|
5
|
+
import { PipelineMemoryHandlers, PipelineMemoryStore, createPipelineMemoryHandlers, createPipelineMemoryStore } from "./handlers/memory.handlers.js";
|
|
6
|
+
import { KbPipelineCreateReviewTaskContract, KbPipelinePublishIfReadyContract, KbPipelineRunWatchContract, KbPipelineSubmitDecisionContract } from "./operations/pipeline.js";
|
|
7
|
+
import "./operations/index.js";
|
|
8
|
+
import { KbUpdatePipelineFeature } from "./kb-update-pipeline.feature.js";
|
|
9
|
+
import { KbDashboardPresentation, KbReviewFormPresentation, KbReviewListPresentation } from "./presentations.js";
|
|
10
|
+
export { ChangeCandidateModel, ChangeRiskLevelEnum, KbChangeDetectedEvent, KbChangeSummarizedEvent, KbDashboardPresentation, KbPatchProposedEvent, KbPipelineCreateReviewTaskContract, KbPipelinePublishIfReadyContract, KbPipelineRunWatchContract, KbPipelineSubmitDecisionContract, KbReviewDecidedEvent, KbReviewFormPresentation, KbReviewListPresentation, KbReviewRequestedEvent, KbUpdatePipelineFeature, PipelineMemoryHandlers, PipelineMemoryStore, ReviewAssignedRoleEnum, ReviewDecisionEnum, ReviewTaskModel, createPipelineMemoryHandlers, createPipelineMemoryStore, example };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { KbChangeDetectedEvent, KbChangeSummarizedEvent, KbPatchProposedEvent, KbReviewDecidedEvent, KbReviewRequestedEvent } from "./events.js";
|
|
2
|
+
import example_default from "./example.js";
|
|
3
|
+
import { ChangeCandidateModel, ChangeRiskLevelEnum, ReviewAssignedRoleEnum, ReviewDecisionEnum, ReviewTaskModel } from "./entities/models.js";
|
|
4
|
+
import "./entities/index.js";
|
|
5
|
+
import { KbPipelineCreateReviewTaskContract, KbPipelinePublishIfReadyContract, KbPipelineRunWatchContract, KbPipelineSubmitDecisionContract } from "./operations/pipeline.js";
|
|
6
|
+
import "./operations/index.js";
|
|
7
|
+
import { createPipelineMemoryHandlers, createPipelineMemoryStore } from "./handlers/memory.handlers.js";
|
|
8
|
+
import { KbUpdatePipelineFeature } from "./kb-update-pipeline.feature.js";
|
|
9
|
+
import { KbDashboardPresentation, KbReviewFormPresentation, KbReviewListPresentation } from "./presentations.js";
|
|
10
|
+
import "./docs/index.js";
|
|
11
|
+
|
|
12
|
+
export { ChangeCandidateModel, ChangeRiskLevelEnum, KbChangeDetectedEvent, KbChangeSummarizedEvent, KbDashboardPresentation, KbPatchProposedEvent, KbPipelineCreateReviewTaskContract, KbPipelinePublishIfReadyContract, KbPipelineRunWatchContract, KbPipelineSubmitDecisionContract, KbReviewDecidedEvent, KbReviewFormPresentation, KbReviewListPresentation, KbReviewRequestedEvent, KbUpdatePipelineFeature, ReviewAssignedRoleEnum, ReviewDecisionEnum, ReviewTaskModel, createPipelineMemoryHandlers, createPipelineMemoryStore, example_default as example };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as _contractspec_lib_contracts8 from "@contractspec/lib.contracts";
|
|
2
|
+
|
|
3
|
+
//#region src/kb-update-pipeline.feature.d.ts
|
|
4
|
+
declare const KbUpdatePipelineFeature: _contractspec_lib_contracts8.FeatureModuleSpec;
|
|
5
|
+
//#endregion
|
|
6
|
+
export { KbUpdatePipelineFeature };
|
|
7
|
+
//# sourceMappingURL=kb-update-pipeline.feature.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kb-update-pipeline.feature.d.ts","names":[],"sources":["../src/kb-update-pipeline.feature.ts"],"sourcesContent":[],"mappings":";;;cAEa,yBAwDX,4BAAA,CAxDkC"}
|