@lssm/example.kb-update-pipeline 0.0.0-canary-20251213172311 → 0.0.0-canary-20251215220103

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.
@@ -1,6 +1,6 @@
1
1
  $ bun build:bundle && bun build:types
2
2
  $ tsdown
3
- ℹ tsdown v0.17.0 powered by rolldown v1.0.0-beta.53
3
+ ℹ tsdown v0.17.4 powered by rolldown v1.0.0-beta.53
4
4
  ℹ config file: /home/runner/work/contractspec/contractspec/packages/examples/kb-update-pipeline/tsdown.config.js
5
5
  ℹ entry: src/events.ts, src/example.ts, src/feature.ts, src/index.ts, src/contracts/index.ts, src/contracts/pipeline.ts, src/docs/index.ts, src/docs/kb-update-pipeline.docblock.ts, src/entities/index.ts, src/entities/models.ts, src/handlers/index.ts, src/handlers/memory.handlers.ts
6
6
  ℹ target: esnext
@@ -19,5 +19,5 @@ $ tsdown
19
19
  ℹ dist/handlers/index.js 0.17 kB │ gzip: 0.11 kB
20
20
  ℹ dist/docs/index.js 0.04 kB │ gzip: 0.06 kB
21
21
  ℹ 12 files, total: 13.72 kB
22
- ✔ Build complete in 53ms
22
+ ✔ Build complete in 80ms
23
23
  $ tsc --noEmit
package/CHANGELOG.md CHANGED
@@ -1,11 +1,11 @@
1
1
  # @lssm/example.kb-update-pipeline
2
2
 
3
- ## 0.0.0-canary-20251213172311
3
+ ## 0.0.0-canary-20251215220103
4
4
 
5
5
  ### Patch Changes
6
6
 
7
7
  - Updated dependencies [3086383]
8
- - @lssm/lib.contracts@0.0.0-canary-20251213172311
9
- - @lssm/lib.schema@0.0.0-canary-20251213172311
10
- - @lssm/lib.identity-rbac@0.0.0-canary-20251213172311
11
- - @lssm/module.notifications@0.0.0-canary-20251213172311
8
+ - @lssm/lib.contracts@0.0.0-canary-20251215220103
9
+ - @lssm/lib.schema@0.0.0-canary-20251215220103
10
+ - @lssm/lib.identity-rbac@0.0.0-canary-20251215220103
11
+ - @lssm/module.notifications@0.0.0-canary-20251215220103
package/README.md CHANGED
@@ -16,3 +16,4 @@ bun test
16
16
  ```
17
17
 
18
18
 
19
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lssm/example.kb-update-pipeline",
3
- "version": "0.0.0-canary-20251213172311",
3
+ "version": "0.0.0-canary-20251215220103",
4
4
  "description": "Example: KB update automation pipeline with HITL review and auditability.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -42,7 +42,7 @@
42
42
  "devDependencies": {
43
43
  "@lssm/tool.tsdown": "workspace:*",
44
44
  "@lssm/tool.typescript": "workspace:*",
45
- "tsdown": "^0.17.0",
45
+ "tsdown": "^0.17.4",
46
46
  "typescript": "^5.9.3"
47
47
  },
48
48
  "publishConfig": {
@@ -1,3 +1 @@
1
1
  export * from './pipeline';
2
-
3
-
@@ -1,7 +1,11 @@
1
1
  import { defineCommand } from '@lssm/lib.contracts';
2
2
  import { ScalarTypeEnum, defineSchemaModel } from '@lssm/lib.schema';
3
3
 
4
- import { ChangeCandidateModel, ReviewDecisionEnum, ReviewTaskModel } from '../entities/models';
4
+ import {
5
+ ChangeCandidateModel,
6
+ ReviewDecisionEnum,
7
+ ReviewTaskModel,
8
+ } from '../entities/models';
5
9
 
6
10
  const RunWatchInput = defineSchemaModel({
7
11
  name: 'KbPipelineRunWatchInput',
@@ -15,7 +19,11 @@ const RunWatchOutput = defineSchemaModel({
15
19
  name: 'KbPipelineRunWatchOutput',
16
20
  description: 'Output containing detected changes.',
17
21
  fields: {
18
- candidates: { type: ChangeCandidateModel, isArray: true, isOptional: false },
22
+ candidates: {
23
+ type: ChangeCandidateModel,
24
+ isArray: true,
25
+ isOptional: false,
26
+ },
19
27
  },
20
28
  });
21
29
 
@@ -23,7 +31,10 @@ const CreateReviewTaskInput = defineSchemaModel({
23
31
  name: 'KbPipelineCreateReviewTaskInput',
24
32
  description: 'Create a review task for a change candidate.',
25
33
  fields: {
26
- changeCandidateId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
34
+ changeCandidateId: {
35
+ type: ScalarTypeEnum.String_unsecure(),
36
+ isOptional: false,
37
+ },
27
38
  },
28
39
  });
29
40
 
@@ -34,13 +45,17 @@ const SubmitDecisionInput = defineSchemaModel({
34
45
  reviewTaskId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
35
46
  decision: { type: ReviewDecisionEnum, isOptional: false },
36
47
  decidedBy: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
37
- decidedByRole: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
48
+ decidedByRole: {
49
+ type: ScalarTypeEnum.String_unsecure(),
50
+ isOptional: false,
51
+ },
38
52
  },
39
53
  });
40
54
 
41
55
  const PublishIfReadyInput = defineSchemaModel({
42
56
  name: 'KbPipelinePublishIfReadyInput',
43
- description: 'Publish snapshot if approvals are satisfied for a jurisdiction.',
57
+ description:
58
+ 'Publish snapshot if approvals are satisfied for a jurisdiction.',
44
59
  fields: {
45
60
  jurisdiction: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
46
61
  },
@@ -142,5 +157,3 @@ export const KbPipelinePublishIfReadyContract = defineCommand({
142
157
  },
143
158
  policy: { auth: 'user' },
144
159
  });
145
-
146
-
package/src/docs/index.ts CHANGED
@@ -1,3 +1 @@
1
1
  import './kb-update-pipeline.docblock';
2
-
3
-
@@ -17,7 +17,8 @@ const docBlocks: DocBlock[] = [
17
17
  {
18
18
  id: 'docs.examples.kb-update-pipeline.reference',
19
19
  title: 'KB Update Pipeline — Reference',
20
- summary: 'Entities, contracts, and events for the KB update pipeline example.',
20
+ summary:
21
+ 'Entities, contracts, and events for the KB update pipeline example.',
21
22
  kind: 'reference',
22
23
  visibility: 'public',
23
24
  route: '/docs/examples/kb-update-pipeline',
@@ -27,5 +28,3 @@ const docBlocks: DocBlock[] = [
27
28
  ];
28
29
 
29
30
  registerDocBlocks(docBlocks);
30
-
31
-
@@ -1,3 +1 @@
1
1
  export * from './models';
2
-
3
-
@@ -1,4 +1,8 @@
1
- import { ScalarTypeEnum, defineEnum, defineSchemaModel } from '@lssm/lib.schema';
1
+ import {
2
+ ScalarTypeEnum,
3
+ defineEnum,
4
+ defineSchemaModel,
5
+ } from '@lssm/lib.schema';
2
6
 
3
7
  export const ChangeRiskLevelEnum = defineEnum('ChangeRiskLevel', [
4
8
  'low',
@@ -21,7 +25,10 @@ export const ChangeCandidateModel = defineSchemaModel({
21
25
  description: 'Candidate change detected in a source document.',
22
26
  fields: {
23
27
  id: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
24
- sourceDocumentId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
28
+ sourceDocumentId: {
29
+ type: ScalarTypeEnum.String_unsecure(),
30
+ isOptional: false,
31
+ },
25
32
  detectedAt: { type: ScalarTypeEnum.DateTime(), isOptional: false },
26
33
  diffSummary: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
27
34
  riskLevel: { type: ChangeRiskLevelEnum, isOptional: false },
@@ -33,7 +40,10 @@ export const ReviewTaskModel = defineSchemaModel({
33
40
  description: 'Human verification task for a change candidate.',
34
41
  fields: {
35
42
  id: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
36
- changeCandidateId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
43
+ changeCandidateId: {
44
+ type: ScalarTypeEnum.String_unsecure(),
45
+ isOptional: false,
46
+ },
37
47
  status: { type: ScalarTypeEnum.String_unsecure(), isOptional: false }, // open|decided
38
48
  assignedRole: { type: ReviewAssignedRoleEnum, isOptional: false },
39
49
  decision: { type: ReviewDecisionEnum, isOptional: true },
@@ -41,5 +51,3 @@ export const ReviewTaskModel = defineSchemaModel({
41
51
  decidedBy: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
42
52
  },
43
53
  });
44
-
45
-
package/src/events.ts CHANGED
@@ -5,8 +5,14 @@ const KbChangeDetectedPayload = defineSchemaModel({
5
5
  name: 'KbChangeDetectedPayload',
6
6
  description: 'Emitted when a source change is detected.',
7
7
  fields: {
8
- changeCandidateId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
9
- sourceDocumentId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
8
+ changeCandidateId: {
9
+ type: ScalarTypeEnum.String_unsecure(),
10
+ isOptional: false,
11
+ },
12
+ sourceDocumentId: {
13
+ type: ScalarTypeEnum.String_unsecure(),
14
+ isOptional: false,
15
+ },
10
16
  riskLevel: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
11
17
  },
12
18
  });
@@ -22,7 +28,10 @@ const KbChangeSummarizedPayload = defineSchemaModel({
22
28
  name: 'KbChangeSummarizedPayload',
23
29
  description: 'Emitted when a change summary is produced.',
24
30
  fields: {
25
- changeCandidateId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
31
+ changeCandidateId: {
32
+ type: ScalarTypeEnum.String_unsecure(),
33
+ isOptional: false,
34
+ },
26
35
  summary: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
27
36
  riskLevel: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
28
37
  },
@@ -39,7 +48,10 @@ const KbPatchProposedPayload = defineSchemaModel({
39
48
  name: 'KbPatchProposedPayload',
40
49
  description: 'Emitted when draft rule patches are proposed.',
41
50
  fields: {
42
- changeCandidateId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
51
+ changeCandidateId: {
52
+ type: ScalarTypeEnum.String_unsecure(),
53
+ isOptional: false,
54
+ },
43
55
  proposedRuleVersionIds: {
44
56
  type: ScalarTypeEnum.String_unsecure(),
45
57
  isArray: true,
@@ -60,7 +72,10 @@ const KbReviewRequestedPayload = defineSchemaModel({
60
72
  description: 'Emitted when a review is requested.',
61
73
  fields: {
62
74
  reviewTaskId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
63
- changeCandidateId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
75
+ changeCandidateId: {
76
+ type: ScalarTypeEnum.String_unsecure(),
77
+ isOptional: false,
78
+ },
64
79
  assignedRole: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
65
80
  },
66
81
  });
@@ -88,5 +103,3 @@ export const KbReviewDecidedEvent = defineEvent({
88
103
  description: 'KB review decided.',
89
104
  payload: KbReviewDecidedPayload,
90
105
  });
91
-
92
-
package/src/example.ts CHANGED
@@ -25,5 +25,3 @@ const example = {
25
25
  } as const;
26
26
 
27
27
  export default example;
28
-
29
-
package/src/feature.ts CHANGED
@@ -35,5 +35,3 @@ export const KbUpdatePipelineFeature: FeatureModuleSpec = {
35
35
  ],
36
36
  },
37
37
  };
38
-
39
-
@@ -1,3 +1 @@
1
1
  export * from './memory.handlers';
2
-
3
-
@@ -1,6 +1,9 @@
1
1
  import { describe, expect, it } from 'bun:test';
2
2
 
3
- import { createPipelineMemoryHandlers, createPipelineMemoryStore } from './memory.handlers';
3
+ import {
4
+ createPipelineMemoryHandlers,
5
+ createPipelineMemoryStore,
6
+ } from './memory.handlers';
4
7
 
5
8
  describe('@lssm/example.kb-update-pipeline memory handlers', () => {
6
9
  it('high-risk change cannot be approved by curator role', async () => {
@@ -76,5 +79,3 @@ describe('@lssm/example.kb-update-pipeline memory handlers', () => {
76
79
  ).rejects.toThrow('NOT_READY');
77
80
  });
78
81
  });
79
-
80
-
@@ -1,12 +1,12 @@
1
- type ChangeCandidate = {
1
+ interface ChangeCandidate {
2
2
  id: string;
3
3
  sourceDocumentId: string;
4
4
  detectedAt: Date;
5
5
  diffSummary: string;
6
6
  riskLevel: 'low' | 'medium' | 'high';
7
- };
7
+ }
8
8
 
9
- type ReviewTask = {
9
+ interface ReviewTask {
10
10
  id: string;
11
11
  changeCandidateId: string;
12
12
  status: 'open' | 'decided';
@@ -14,20 +14,20 @@ type ReviewTask = {
14
14
  decision?: 'approve' | 'reject';
15
15
  decidedAt?: Date;
16
16
  decidedBy?: string;
17
- };
17
+ }
18
18
 
19
19
  export interface PipelineMemoryStore {
20
20
  candidates: Map<string, ChangeCandidate>;
21
21
  reviewTasks: Map<string, ReviewTask>;
22
22
  proposedRuleVersionIdsByCandidate: Map<string, string[]>;
23
23
  approvedRuleVersionIds: Set<string>;
24
- notifications: Array<{
24
+ notifications: {
25
25
  kind: 'kb.review.requested';
26
26
  reviewTaskId: string;
27
27
  changeCandidateId: string;
28
28
  assignedRole: 'curator' | 'expert';
29
29
  createdAt: Date;
30
- }>;
30
+ }[];
31
31
  }
32
32
 
33
33
  export function createPipelineMemoryStore(): PipelineMemoryStore {
@@ -45,20 +45,26 @@ function stableId(prefix: string, value: string): string {
45
45
  }
46
46
 
47
47
  export interface PipelineMemoryHandlers {
48
- runWatch(input: { jurisdiction: string }): Promise<{ candidates: ChangeCandidate[] }>;
48
+ runWatch(input: {
49
+ jurisdiction: string;
50
+ }): Promise<{ candidates: ChangeCandidate[] }>;
49
51
  createReviewTask(input: { changeCandidateId: string }): Promise<ReviewTask>;
50
52
  proposeRulePatch(input: {
51
53
  changeCandidateId: string;
52
54
  proposedRuleVersionIds: string[];
53
55
  }): Promise<{ proposedRuleVersionIds: string[] }>;
54
- markRuleVersionApproved(input: { ruleVersionId: string }): Promise<{ ruleVersionId: string }>;
56
+ markRuleVersionApproved(input: {
57
+ ruleVersionId: string;
58
+ }): Promise<{ ruleVersionId: string }>;
55
59
  submitDecision(input: {
56
60
  reviewTaskId: string;
57
61
  decision: 'approve' | 'reject';
58
62
  decidedBy: string;
59
63
  decidedByRole: 'curator' | 'expert';
60
64
  }): Promise<ReviewTask>;
61
- publishIfReady(input: { jurisdiction: string }): Promise<{ published: boolean; reason?: string }>;
65
+ publishIfReady(input: {
66
+ jurisdiction: string;
67
+ }): Promise<{ published: boolean; reason?: string }>;
62
68
  }
63
69
 
64
70
  export function createPipelineMemoryHandlers(
@@ -104,10 +110,9 @@ export function createPipelineMemoryHandlers(
104
110
  if (!store.candidates.has(input.changeCandidateId)) {
105
111
  throw new Error('CHANGE_CANDIDATE_NOT_FOUND');
106
112
  }
107
- store.proposedRuleVersionIdsByCandidate.set(
108
- input.changeCandidateId,
109
- [...input.proposedRuleVersionIds]
110
- );
113
+ store.proposedRuleVersionIdsByCandidate.set(input.changeCandidateId, [
114
+ ...input.proposedRuleVersionIds,
115
+ ]);
111
116
  return { proposedRuleVersionIds: [...input.proposedRuleVersionIds] };
112
117
  }
113
118
 
@@ -158,8 +163,11 @@ export function createPipelineMemoryHandlers(
158
163
  for (const task of store.reviewTasks.values()) {
159
164
  if (task.decision !== 'approve') continue;
160
165
  const proposed =
161
- store.proposedRuleVersionIdsByCandidate.get(task.changeCandidateId) ?? [];
162
- const unapproved = proposed.filter((id) => !store.approvedRuleVersionIds.has(id));
166
+ store.proposedRuleVersionIdsByCandidate.get(task.changeCandidateId) ??
167
+ [];
168
+ const unapproved = proposed.filter(
169
+ (id) => !store.approvedRuleVersionIds.has(id)
170
+ );
163
171
  if (unapproved.length) {
164
172
  throw new Error('NOT_READY');
165
173
  }
@@ -176,5 +184,3 @@ export function createPipelineMemoryHandlers(
176
184
  publishIfReady,
177
185
  };
178
186
  }
179
-
180
-
package/src/index.ts CHANGED
@@ -11,5 +11,3 @@ export * from './feature';
11
11
  export { default as example } from './example';
12
12
 
13
13
  import './docs';
14
-
15
-
package/tsconfig.json CHANGED
@@ -9,3 +9,4 @@
9
9
  }
10
10
 
11
11
 
12
+