@lucern/pack-host 0.1.0-alpha.2
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/README.md +64 -0
- package/dist/contracts.d.ts +77 -0
- package/dist/contracts.js +21 -0
- package/dist/contracts.js.map +1 -0
- package/dist/convex.config.d.ts +5 -0
- package/dist/convex.config.js +9 -0
- package/dist/convex.config.js.map +1 -0
- package/dist/dependencyResolution.d.ts +18 -0
- package/dist/dependencyResolution.js +131 -0
- package/dist/dependencyResolution.js.map +1 -0
- package/dist/domain-pack/authoring.d.ts +172 -0
- package/dist/domain-pack/authoring.js +1896 -0
- package/dist/domain-pack/authoring.js.map +1 -0
- package/dist/domain-pack/contracts.d.ts +183 -0
- package/dist/domain-pack/contracts.js +65 -0
- package/dist/domain-pack/contracts.js.map +1 -0
- package/dist/domain-pack/index.d.ts +8 -0
- package/dist/domain-pack/index.js +3813 -0
- package/dist/domain-pack/index.js.map +1 -0
- package/dist/domain-pack/ontology/software-entities-v1.d.ts +102 -0
- package/dist/domain-pack/ontology/software-entities-v1.js +104 -0
- package/dist/domain-pack/ontology/software-entities-v1.js.map +1 -0
- package/dist/domain-pack/packs/developer-reasoning.d.ts +14 -0
- package/dist/domain-pack/packs/developer-reasoning.js +339 -0
- package/dist/domain-pack/packs/developer-reasoning.js.map +1 -0
- package/dist/domain-pack/packs/engineering-accelerator.d.ts +11 -0
- package/dist/domain-pack/packs/engineering-accelerator.js +1348 -0
- package/dist/domain-pack/packs/engineering-accelerator.js.map +1 -0
- package/dist/domain-pack/packs/index.d.ts +18 -0
- package/dist/domain-pack/packs/index.js +2653 -0
- package/dist/domain-pack/packs/index.js.map +1 -0
- package/dist/domain-pack/shaping.d.ts +54 -0
- package/dist/domain-pack/shaping.js +1013 -0
- package/dist/domain-pack/shaping.js.map +1 -0
- package/dist/domain-pack/validation.d.ts +26 -0
- package/dist/domain-pack/validation.js +775 -0
- package/dist/domain-pack/validation.js.map +1 -0
- package/dist/domain-pack.d.ts +8 -0
- package/dist/domain-pack.js +3813 -0
- package/dist/domain-pack.js.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.js +5520 -0
- package/dist/index.js.map +1 -0
- package/dist/lifecycle.d.ts +27 -0
- package/dist/lifecycle.js +98 -0
- package/dist/lifecycle.js.map +1 -0
- package/dist/manifestValidation.d.ts +28 -0
- package/dist/manifestValidation.js +253 -0
- package/dist/manifestValidation.js.map +1 -0
- package/dist/manifests/chat-v1.d.ts +10 -0
- package/dist/manifests/chat-v1.js +87 -0
- package/dist/manifests/chat-v1.js.map +1 -0
- package/dist/manifests/deals-v1.d.ts +10 -0
- package/dist/manifests/deals-v1.js +107 -0
- package/dist/manifests/deals-v1.js.map +1 -0
- package/dist/manifests/decisions-v1.d.ts +10 -0
- package/dist/manifests/decisions-v1.js +103 -0
- package/dist/manifests/decisions-v1.js.map +1 -0
- package/dist/manifests/documents-v1.d.ts +10 -0
- package/dist/manifests/documents-v1.js +88 -0
- package/dist/manifests/documents-v1.js.map +1 -0
- package/dist/manifests/epistemic-algorithms-v1.d.ts +10 -0
- package/dist/manifests/epistemic-algorithms-v1.js +107 -0
- package/dist/manifests/epistemic-algorithms-v1.js.map +1 -0
- package/dist/manifests/graph-visualization-v1.d.ts +10 -0
- package/dist/manifests/graph-visualization-v1.js +88 -0
- package/dist/manifests/graph-visualization-v1.js.map +1 -0
- package/dist/manifests/index.d.ts +23 -0
- package/dist/manifests/index.js +955 -0
- package/dist/manifests/index.js.map +1 -0
- package/dist/manifests/news-v1.d.ts +10 -0
- package/dist/manifests/news-v1.js +93 -0
- package/dist/manifests/news-v1.js.map +1 -0
- package/dist/manifests/philosophy-mode-v1.d.ts +10 -0
- package/dist/manifests/philosophy-mode-v1.js +100 -0
- package/dist/manifests/philosophy-mode-v1.js.map +1 -0
- package/dist/manifests/task-management-v1.d.ts +10 -0
- package/dist/manifests/task-management-v1.js +86 -0
- package/dist/manifests/task-management-v1.js.map +1 -0
- package/dist/manifests/team-analysis-v1.d.ts +10 -0
- package/dist/manifests/team-analysis-v1.js +93 -0
- package/dist/manifests/team-analysis-v1.js.map +1 -0
- package/dist/manifests/themes-v1.d.ts +10 -0
- package/dist/manifests/themes-v1.js +118 -0
- package/dist/manifests/themes-v1.js.map +1 -0
- package/dist/manifests/user-profiles-v1.d.ts +10 -0
- package/dist/manifests/user-profiles-v1.js +100 -0
- package/dist/manifests/user-profiles-v1.js.map +1 -0
- package/dist/manifests.d.ts +14 -0
- package/dist/manifests.js +955 -0
- package/dist/manifests.js.map +1 -0
- package/dist/namespacePolicy.d.ts +26 -0
- package/dist/namespacePolicy.js +129 -0
- package/dist/namespacePolicy.js.map +1 -0
- package/dist/registry.d.ts +13 -0
- package/dist/registry.js +1710 -0
- package/dist/registry.js.map +1 -0
- package/dist/runtime.d.ts +19 -0
- package/dist/runtime.js +638 -0
- package/dist/runtime.js.map +1 -0
- package/dist/serviceContracts.d.ts +18 -0
- package/dist/serviceContracts.js +64 -0
- package/dist/serviceContracts.js.map +1 -0
- package/package.json +48 -0
|
@@ -0,0 +1,3813 @@
|
|
|
1
|
+
// src/domain-pack/contracts.ts
|
|
2
|
+
function dedupeStrings(values) {
|
|
3
|
+
return Array.from(
|
|
4
|
+
new Set(values.map((v) => v.trim()).filter((v) => v.length > 0))
|
|
5
|
+
);
|
|
6
|
+
}
|
|
7
|
+
function normalizeRuntimeTargets(values) {
|
|
8
|
+
return values ? dedupeStrings(values) : void 0;
|
|
9
|
+
}
|
|
10
|
+
function normalizeOntologyBinding(binding) {
|
|
11
|
+
return {
|
|
12
|
+
...binding,
|
|
13
|
+
requiredEntityTypes: binding.requiredEntityTypes ? dedupeStrings(binding.requiredEntityTypes) : void 0,
|
|
14
|
+
requiredEdgeTypes: binding.requiredEdgeTypes ? dedupeStrings(binding.requiredEdgeTypes) : void 0
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function normalizeOperatingSystem(layer) {
|
|
18
|
+
if (!layer) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
prompts: layer.prompts?.map((prompt) => ({
|
|
23
|
+
...prompt,
|
|
24
|
+
runtimeTargets: normalizeRuntimeTargets(prompt.runtimeTargets)
|
|
25
|
+
})),
|
|
26
|
+
tools: layer.tools?.map((tool) => ({
|
|
27
|
+
...tool,
|
|
28
|
+
runtimeTargets: normalizeRuntimeTargets(tool.runtimeTargets)
|
|
29
|
+
})),
|
|
30
|
+
setupAssets: layer.setupAssets?.map((asset) => ({
|
|
31
|
+
...asset,
|
|
32
|
+
runtimeTargets: normalizeRuntimeTargets(asset.runtimeTargets)
|
|
33
|
+
})),
|
|
34
|
+
topicTemplates: layer.topicTemplates,
|
|
35
|
+
installProfiles: layer.installProfiles?.map((profile) => ({
|
|
36
|
+
...profile,
|
|
37
|
+
promptIds: dedupeStrings(profile.promptIds),
|
|
38
|
+
toolIds: dedupeStrings(profile.toolIds),
|
|
39
|
+
assetIds: dedupeStrings(profile.assetIds),
|
|
40
|
+
defaultTopicSlugs: dedupeStrings(profile.defaultTopicSlugs)
|
|
41
|
+
}))
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
function defineDomainPack(input) {
|
|
45
|
+
return {
|
|
46
|
+
...input,
|
|
47
|
+
ontologyBindings: input.ontologyBindings.map(normalizeOntologyBinding),
|
|
48
|
+
appPackKeys: input.appPackKeys ? dedupeStrings(input.appPackKeys) : void 0,
|
|
49
|
+
operatingSystem: normalizeOperatingSystem(input.operatingSystem),
|
|
50
|
+
workflows: input.workflows.map((w) => ({
|
|
51
|
+
...w,
|
|
52
|
+
requiredArtifacts: dedupeStrings(w.requiredArtifacts),
|
|
53
|
+
gateCheckpoints: dedupeStrings(w.gateCheckpoints),
|
|
54
|
+
steps: w.steps.map((s) => ({
|
|
55
|
+
...s,
|
|
56
|
+
requiredRoles: dedupeStrings(s.requiredRoles),
|
|
57
|
+
produces: s.produces ? dedupeStrings(s.produces) : void 0
|
|
58
|
+
}))
|
|
59
|
+
}))
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// src/domain-pack/validation.ts
|
|
64
|
+
function issue(code, message, path, severity = "error") {
|
|
65
|
+
return { code, severity, message, path };
|
|
66
|
+
}
|
|
67
|
+
var KEBAB_CASE = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
|
|
68
|
+
var SEMVER = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
|
|
69
|
+
var SHAPING_QUESTION_TYPES = /* @__PURE__ */ new Set([
|
|
70
|
+
"validation",
|
|
71
|
+
"falsification",
|
|
72
|
+
"assumption_probe",
|
|
73
|
+
"counterfactual",
|
|
74
|
+
"scope",
|
|
75
|
+
"comparison",
|
|
76
|
+
"mechanism",
|
|
77
|
+
"general"
|
|
78
|
+
]);
|
|
79
|
+
var RUNTIME_TARGETS = /* @__PURE__ */ new Set(["claude-code", "codex", "hybrid", "portable"]);
|
|
80
|
+
var ONTOLOGY_PROVISION_MODES = /* @__PURE__ */ new Set(["bind", "seed", "extend"]);
|
|
81
|
+
function validateStringArray(values, path, label) {
|
|
82
|
+
if (!values) {
|
|
83
|
+
return [];
|
|
84
|
+
}
|
|
85
|
+
return values.flatMap((value, index) => {
|
|
86
|
+
if (!value?.trim()) {
|
|
87
|
+
return [
|
|
88
|
+
issue(
|
|
89
|
+
"INVALID_SHAPING_CONDITION",
|
|
90
|
+
`${label} must not contain empty strings`,
|
|
91
|
+
`${path}[${index}]`
|
|
92
|
+
)
|
|
93
|
+
];
|
|
94
|
+
}
|
|
95
|
+
return [];
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
function validateRuntimeTargets(values, path) {
|
|
99
|
+
const issues = validateStringArray(values, path, "runtimeTargets");
|
|
100
|
+
for (const [index, value] of (values || []).entries()) {
|
|
101
|
+
if (!RUNTIME_TARGETS.has(value)) {
|
|
102
|
+
issues.push(
|
|
103
|
+
issue(
|
|
104
|
+
"INVALID_RUNTIME_TARGET",
|
|
105
|
+
`Unsupported runtime target "${value}"`,
|
|
106
|
+
`${path}[${index}]`
|
|
107
|
+
)
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return issues;
|
|
112
|
+
}
|
|
113
|
+
function validatePromptBinding(prompt, index) {
|
|
114
|
+
const path = `operatingSystem.prompts[${index}]`;
|
|
115
|
+
const issues = [];
|
|
116
|
+
if (!prompt.promptId?.trim()) {
|
|
117
|
+
issues.push(
|
|
118
|
+
issue(
|
|
119
|
+
"MISSING_PROMPT_ID",
|
|
120
|
+
"prompt binding requires promptId",
|
|
121
|
+
`${path}.promptId`
|
|
122
|
+
)
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
if (!prompt.ref?.trim()) {
|
|
126
|
+
issues.push(
|
|
127
|
+
issue("MISSING_PROMPT_REF", "prompt binding requires ref", `${path}.ref`)
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
issues.push(
|
|
131
|
+
...validateRuntimeTargets(prompt.runtimeTargets, `${path}.runtimeTargets`)
|
|
132
|
+
);
|
|
133
|
+
return issues;
|
|
134
|
+
}
|
|
135
|
+
function validateToolBinding(tool, index) {
|
|
136
|
+
const path = `operatingSystem.tools[${index}]`;
|
|
137
|
+
const issues = [];
|
|
138
|
+
if (!tool.toolId?.trim()) {
|
|
139
|
+
issues.push(
|
|
140
|
+
issue("MISSING_TOOL_ID", "tool binding requires toolId", `${path}.toolId`)
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
if (!tool.entrypoint?.trim()) {
|
|
144
|
+
issues.push(
|
|
145
|
+
issue(
|
|
146
|
+
"MISSING_TOOL_ENTRYPOINT",
|
|
147
|
+
"tool binding requires entrypoint",
|
|
148
|
+
`${path}.entrypoint`
|
|
149
|
+
)
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
issues.push(
|
|
153
|
+
...validateRuntimeTargets(tool.runtimeTargets, `${path}.runtimeTargets`)
|
|
154
|
+
);
|
|
155
|
+
return issues;
|
|
156
|
+
}
|
|
157
|
+
function validateSetupAsset(asset, index) {
|
|
158
|
+
const path = `operatingSystem.setupAssets[${index}]`;
|
|
159
|
+
const issues = [];
|
|
160
|
+
if (!asset.assetId?.trim()) {
|
|
161
|
+
issues.push(
|
|
162
|
+
issue(
|
|
163
|
+
"MISSING_SETUP_ASSET_ID",
|
|
164
|
+
"setup asset requires assetId",
|
|
165
|
+
`${path}.assetId`
|
|
166
|
+
)
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
if (!asset.path?.trim()) {
|
|
170
|
+
issues.push(
|
|
171
|
+
issue(
|
|
172
|
+
"MISSING_SETUP_ASSET_PATH",
|
|
173
|
+
"setup asset requires path",
|
|
174
|
+
`${path}.path`
|
|
175
|
+
)
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
issues.push(
|
|
179
|
+
...validateRuntimeTargets(asset.runtimeTargets, `${path}.runtimeTargets`)
|
|
180
|
+
);
|
|
181
|
+
return issues;
|
|
182
|
+
}
|
|
183
|
+
function validateQuestionTemplate(template, index) {
|
|
184
|
+
const path = `inquiryShaping.questionTemplates[${index}]`;
|
|
185
|
+
const issues = [];
|
|
186
|
+
if (!template.templateId?.trim()) {
|
|
187
|
+
issues.push(
|
|
188
|
+
issue(
|
|
189
|
+
"MISSING_SHAPING_TEMPLATE_ID",
|
|
190
|
+
"question template requires templateId",
|
|
191
|
+
`${path}.templateId`
|
|
192
|
+
)
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
if (!template.template?.trim()) {
|
|
196
|
+
issues.push(
|
|
197
|
+
issue(
|
|
198
|
+
"MISSING_SHAPING_TEMPLATE",
|
|
199
|
+
"question template requires template text",
|
|
200
|
+
`${path}.template`
|
|
201
|
+
)
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
if (!SHAPING_QUESTION_TYPES.has(template.questionType)) {
|
|
205
|
+
issues.push(
|
|
206
|
+
issue(
|
|
207
|
+
"INVALID_SHAPING_QUESTION_TYPE",
|
|
208
|
+
`Unsupported questionType "${template.questionType}"`,
|
|
209
|
+
`${path}.questionType`
|
|
210
|
+
)
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
issues.push(
|
|
214
|
+
...validateStringArray(
|
|
215
|
+
template.whenObjectiveIncludes,
|
|
216
|
+
`${path}.whenObjectiveIncludes`,
|
|
217
|
+
"whenObjectiveIncludes"
|
|
218
|
+
)
|
|
219
|
+
);
|
|
220
|
+
return issues;
|
|
221
|
+
}
|
|
222
|
+
function validateTaskTemplate(template, index) {
|
|
223
|
+
const path = `inquiryShaping.taskTemplates[${index}]`;
|
|
224
|
+
const issues = [];
|
|
225
|
+
if (!template.templateId?.trim()) {
|
|
226
|
+
issues.push(
|
|
227
|
+
issue(
|
|
228
|
+
"MISSING_TASK_GENERATOR_ID",
|
|
229
|
+
"task template requires templateId",
|
|
230
|
+
`${path}.templateId`
|
|
231
|
+
)
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
if (!template.title?.trim()) {
|
|
235
|
+
issues.push(
|
|
236
|
+
issue(
|
|
237
|
+
"MISSING_TASK_GENERATOR_TITLE",
|
|
238
|
+
"task template requires title",
|
|
239
|
+
`${path}.title`
|
|
240
|
+
)
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
issues.push(
|
|
244
|
+
...validateStringArray(
|
|
245
|
+
template.whenObjectiveIncludes,
|
|
246
|
+
`${path}.whenObjectiveIncludes`,
|
|
247
|
+
"whenObjectiveIncludes"
|
|
248
|
+
)
|
|
249
|
+
);
|
|
250
|
+
issues.push(
|
|
251
|
+
...validateStringArray(
|
|
252
|
+
template.whenQuestionTypes,
|
|
253
|
+
`${path}.whenQuestionTypes`,
|
|
254
|
+
"whenQuestionTypes"
|
|
255
|
+
)
|
|
256
|
+
);
|
|
257
|
+
for (const [questionTypeIndex, questionType] of (template.whenQuestionTypes || []).entries()) {
|
|
258
|
+
if (!SHAPING_QUESTION_TYPES.has(questionType)) {
|
|
259
|
+
issues.push(
|
|
260
|
+
issue(
|
|
261
|
+
"INVALID_TASK_GENERATOR_QUESTION_TYPE",
|
|
262
|
+
`Unsupported whenQuestionTypes value "${questionType}"`,
|
|
263
|
+
`${path}.whenQuestionTypes[${questionTypeIndex}]`
|
|
264
|
+
)
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return issues;
|
|
269
|
+
}
|
|
270
|
+
function validateFrameworkHint(hint, index) {
|
|
271
|
+
const path = `inquiryShaping.frameworkHints[${index}]`;
|
|
272
|
+
const issues = [];
|
|
273
|
+
if (!hint.frameworkName?.trim()) {
|
|
274
|
+
issues.push(
|
|
275
|
+
issue(
|
|
276
|
+
"MISSING_FRAMEWORK_HOOK_NAME",
|
|
277
|
+
"framework hint requires frameworkName",
|
|
278
|
+
`${path}.frameworkName`
|
|
279
|
+
)
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
if (hint.boost != null && (!Number.isFinite(hint.boost) || hint.boost < 0)) {
|
|
283
|
+
issues.push(
|
|
284
|
+
issue(
|
|
285
|
+
"INVALID_FRAMEWORK_HOOK_BOOST",
|
|
286
|
+
"framework hint boost must be a non-negative number",
|
|
287
|
+
`${path}.boost`
|
|
288
|
+
)
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
issues.push(
|
|
292
|
+
...validateStringArray(
|
|
293
|
+
hint.whenObjectiveIncludes,
|
|
294
|
+
`${path}.whenObjectiveIncludes`,
|
|
295
|
+
"whenObjectiveIncludes"
|
|
296
|
+
)
|
|
297
|
+
);
|
|
298
|
+
issues.push(
|
|
299
|
+
...validateStringArray(
|
|
300
|
+
hint.whenQuestionTypes,
|
|
301
|
+
`${path}.whenQuestionTypes`,
|
|
302
|
+
"whenQuestionTypes"
|
|
303
|
+
)
|
|
304
|
+
);
|
|
305
|
+
for (const [questionTypeIndex, questionType] of (hint.whenQuestionTypes || []).entries()) {
|
|
306
|
+
if (!SHAPING_QUESTION_TYPES.has(questionType)) {
|
|
307
|
+
issues.push(
|
|
308
|
+
issue(
|
|
309
|
+
"INVALID_FRAMEWORK_HOOK_QUESTION_TYPE",
|
|
310
|
+
`Unsupported whenQuestionTypes value "${questionType}"`,
|
|
311
|
+
`${path}.whenQuestionTypes[${questionTypeIndex}]`
|
|
312
|
+
)
|
|
313
|
+
);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
return issues;
|
|
317
|
+
}
|
|
318
|
+
function validateTopicTemplate(template, index, knownTopicSlugs) {
|
|
319
|
+
const path = `operatingSystem.topicTemplates[${index}]`;
|
|
320
|
+
const issues = [];
|
|
321
|
+
if (!template.slug?.trim()) {
|
|
322
|
+
issues.push(
|
|
323
|
+
issue(
|
|
324
|
+
"MISSING_TOPIC_TEMPLATE_SLUG",
|
|
325
|
+
"topic template requires slug",
|
|
326
|
+
`${path}.slug`
|
|
327
|
+
)
|
|
328
|
+
);
|
|
329
|
+
} else if (!KEBAB_CASE.test(template.slug)) {
|
|
330
|
+
issues.push(
|
|
331
|
+
issue(
|
|
332
|
+
"INVALID_TOPIC_TEMPLATE_SLUG",
|
|
333
|
+
`topic template slug "${template.slug}" must be kebab-case`,
|
|
334
|
+
`${path}.slug`
|
|
335
|
+
)
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
if (!template.name?.trim()) {
|
|
339
|
+
issues.push(
|
|
340
|
+
issue(
|
|
341
|
+
"MISSING_TOPIC_TEMPLATE_NAME",
|
|
342
|
+
"topic template requires name",
|
|
343
|
+
`${path}.name`
|
|
344
|
+
)
|
|
345
|
+
);
|
|
346
|
+
}
|
|
347
|
+
if (!template.description?.trim()) {
|
|
348
|
+
issues.push(
|
|
349
|
+
issue(
|
|
350
|
+
"MISSING_TOPIC_TEMPLATE_DESCRIPTION",
|
|
351
|
+
"topic template requires description",
|
|
352
|
+
`${path}.description`
|
|
353
|
+
)
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
if (template.parentSlug && !knownTopicSlugs.has(template.parentSlug)) {
|
|
357
|
+
issues.push(
|
|
358
|
+
issue(
|
|
359
|
+
"UNKNOWN_TOPIC_PARENT",
|
|
360
|
+
`topic template references unknown parent "${template.parentSlug}"`,
|
|
361
|
+
`${path}.parentSlug`
|
|
362
|
+
)
|
|
363
|
+
);
|
|
364
|
+
}
|
|
365
|
+
return issues;
|
|
366
|
+
}
|
|
367
|
+
function validateInstallProfile(profile, index, knownPromptIds, knownToolIds, knownAssetIds, knownTopicSlugs) {
|
|
368
|
+
const path = `operatingSystem.installProfiles[${index}]`;
|
|
369
|
+
const issues = [];
|
|
370
|
+
if (!profile.profileId?.trim()) {
|
|
371
|
+
issues.push(
|
|
372
|
+
issue(
|
|
373
|
+
"MISSING_INSTALL_PROFILE_ID",
|
|
374
|
+
"install profile requires profileId",
|
|
375
|
+
`${path}.profileId`
|
|
376
|
+
)
|
|
377
|
+
);
|
|
378
|
+
}
|
|
379
|
+
if (!profile.name?.trim()) {
|
|
380
|
+
issues.push(
|
|
381
|
+
issue(
|
|
382
|
+
"MISSING_INSTALL_PROFILE_NAME",
|
|
383
|
+
"install profile requires name",
|
|
384
|
+
`${path}.name`
|
|
385
|
+
)
|
|
386
|
+
);
|
|
387
|
+
}
|
|
388
|
+
if (!profile.description?.trim()) {
|
|
389
|
+
issues.push(
|
|
390
|
+
issue(
|
|
391
|
+
"MISSING_INSTALL_PROFILE_DESCRIPTION",
|
|
392
|
+
"install profile requires description",
|
|
393
|
+
`${path}.description`
|
|
394
|
+
)
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
if (!RUNTIME_TARGETS.has(profile.runtimeTarget)) {
|
|
398
|
+
issues.push(
|
|
399
|
+
issue(
|
|
400
|
+
"INVALID_RUNTIME_TARGET",
|
|
401
|
+
`Unsupported runtime target "${profile.runtimeTarget}"`,
|
|
402
|
+
`${path}.runtimeTarget`
|
|
403
|
+
)
|
|
404
|
+
);
|
|
405
|
+
}
|
|
406
|
+
for (const [promptIndex, promptId] of profile.promptIds.entries()) {
|
|
407
|
+
if (!knownPromptIds.has(promptId)) {
|
|
408
|
+
issues.push(
|
|
409
|
+
issue(
|
|
410
|
+
"UNKNOWN_PROMPT_REF",
|
|
411
|
+
`install profile references unknown prompt "${promptId}"`,
|
|
412
|
+
`${path}.promptIds[${promptIndex}]`
|
|
413
|
+
)
|
|
414
|
+
);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
for (const [toolIndex, toolId] of profile.toolIds.entries()) {
|
|
418
|
+
if (!knownToolIds.has(toolId)) {
|
|
419
|
+
issues.push(
|
|
420
|
+
issue(
|
|
421
|
+
"UNKNOWN_TOOL_REF",
|
|
422
|
+
`install profile references unknown tool "${toolId}"`,
|
|
423
|
+
`${path}.toolIds[${toolIndex}]`
|
|
424
|
+
)
|
|
425
|
+
);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
for (const [assetIndex, assetId] of profile.assetIds.entries()) {
|
|
429
|
+
if (!knownAssetIds.has(assetId)) {
|
|
430
|
+
issues.push(
|
|
431
|
+
issue(
|
|
432
|
+
"UNKNOWN_SETUP_ASSET_REF",
|
|
433
|
+
`install profile references unknown setup asset "${assetId}"`,
|
|
434
|
+
`${path}.assetIds[${assetIndex}]`
|
|
435
|
+
)
|
|
436
|
+
);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
for (const [topicIndex, topicSlug] of profile.defaultTopicSlugs.entries()) {
|
|
440
|
+
if (!knownTopicSlugs.has(topicSlug)) {
|
|
441
|
+
issues.push(
|
|
442
|
+
issue(
|
|
443
|
+
"UNKNOWN_TOPIC_REF",
|
|
444
|
+
`install profile references unknown topic "${topicSlug}"`,
|
|
445
|
+
`${path}.defaultTopicSlugs[${topicIndex}]`
|
|
446
|
+
)
|
|
447
|
+
);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
return issues;
|
|
451
|
+
}
|
|
452
|
+
function checkDuplicateIds(items, idField, path) {
|
|
453
|
+
const issues = [];
|
|
454
|
+
const seen = /* @__PURE__ */ new Set();
|
|
455
|
+
for (const item of items) {
|
|
456
|
+
const id = item[idField];
|
|
457
|
+
if (seen.has(id)) {
|
|
458
|
+
issues.push(
|
|
459
|
+
issue(
|
|
460
|
+
"DUPLICATE_ID",
|
|
461
|
+
`Duplicate ${idField} "${id}"`,
|
|
462
|
+
`${path}.${idField}`
|
|
463
|
+
)
|
|
464
|
+
);
|
|
465
|
+
}
|
|
466
|
+
seen.add(id);
|
|
467
|
+
}
|
|
468
|
+
return issues;
|
|
469
|
+
}
|
|
470
|
+
function validateDomainPack(pack) {
|
|
471
|
+
const issues = [];
|
|
472
|
+
if (!pack.packId || !pack.packId.trim()) {
|
|
473
|
+
issues.push(issue("MISSING_PACK_ID", "packId is required", "packId"));
|
|
474
|
+
} else if (!KEBAB_CASE.test(pack.packId)) {
|
|
475
|
+
issues.push(
|
|
476
|
+
issue(
|
|
477
|
+
"INVALID_PACK_ID",
|
|
478
|
+
`packId "${pack.packId}" must be kebab-case`,
|
|
479
|
+
"packId"
|
|
480
|
+
)
|
|
481
|
+
);
|
|
482
|
+
}
|
|
483
|
+
if (!pack.name || !pack.name.trim()) {
|
|
484
|
+
issues.push(issue("MISSING_NAME", "name is required", "name"));
|
|
485
|
+
}
|
|
486
|
+
if (!pack.version || !pack.version.trim()) {
|
|
487
|
+
issues.push(issue("MISSING_VERSION", "version is required", "version"));
|
|
488
|
+
} else if (!SEMVER.test(pack.version)) {
|
|
489
|
+
issues.push(
|
|
490
|
+
issue(
|
|
491
|
+
"INVALID_VERSION",
|
|
492
|
+
`version "${pack.version}" must be valid semver`,
|
|
493
|
+
"version"
|
|
494
|
+
)
|
|
495
|
+
);
|
|
496
|
+
}
|
|
497
|
+
if (!pack.ontologyBindings || pack.ontologyBindings.length === 0) {
|
|
498
|
+
issues.push(
|
|
499
|
+
issue(
|
|
500
|
+
"MISSING_ONTOLOGY_BINDINGS",
|
|
501
|
+
"At least one ontologyBinding is required",
|
|
502
|
+
"ontologyBindings"
|
|
503
|
+
)
|
|
504
|
+
);
|
|
505
|
+
} else {
|
|
506
|
+
for (const [i, binding] of pack.ontologyBindings.entries()) {
|
|
507
|
+
if (!binding.ontologyId?.trim()) {
|
|
508
|
+
issues.push(
|
|
509
|
+
issue(
|
|
510
|
+
"MISSING_ONTOLOGY_ID",
|
|
511
|
+
`ontologyBinding[${i}].ontologyId is required`,
|
|
512
|
+
`ontologyBindings[${i}].ontologyId`
|
|
513
|
+
)
|
|
514
|
+
);
|
|
515
|
+
}
|
|
516
|
+
if (!binding.versionConstraint?.trim()) {
|
|
517
|
+
issues.push(
|
|
518
|
+
issue(
|
|
519
|
+
"MISSING_VERSION_CONSTRAINT",
|
|
520
|
+
`ontologyBinding[${i}].versionConstraint is required`,
|
|
521
|
+
`ontologyBindings[${i}].versionConstraint`
|
|
522
|
+
)
|
|
523
|
+
);
|
|
524
|
+
}
|
|
525
|
+
if (binding.provisionMode && !ONTOLOGY_PROVISION_MODES.has(binding.provisionMode)) {
|
|
526
|
+
issues.push(
|
|
527
|
+
issue(
|
|
528
|
+
"INVALID_ONTOLOGY_PROVISION_MODE",
|
|
529
|
+
`Unsupported provisionMode "${binding.provisionMode}"`,
|
|
530
|
+
`ontologyBindings[${i}].provisionMode`
|
|
531
|
+
)
|
|
532
|
+
);
|
|
533
|
+
}
|
|
534
|
+
if (binding.provisionMode && binding.provisionMode !== "bind" && !binding.seedRef?.trim()) {
|
|
535
|
+
issues.push(
|
|
536
|
+
issue(
|
|
537
|
+
"MISSING_ONTOLOGY_SEED_REF",
|
|
538
|
+
`ontologyBinding[${i}] requires seedRef when provisionMode is "${binding.provisionMode}"`,
|
|
539
|
+
`ontologyBindings[${i}].seedRef`
|
|
540
|
+
)
|
|
541
|
+
);
|
|
542
|
+
}
|
|
543
|
+
issues.push(
|
|
544
|
+
...validateStringArray(
|
|
545
|
+
binding.requiredEntityTypes,
|
|
546
|
+
`ontologyBindings[${i}].requiredEntityTypes`,
|
|
547
|
+
"requiredEntityTypes"
|
|
548
|
+
),
|
|
549
|
+
...validateStringArray(
|
|
550
|
+
binding.requiredEdgeTypes,
|
|
551
|
+
`ontologyBindings[${i}].requiredEdgeTypes`,
|
|
552
|
+
"requiredEdgeTypes"
|
|
553
|
+
)
|
|
554
|
+
);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
if (!pack.topicRoots || pack.topicRoots.length === 0) {
|
|
558
|
+
issues.push(
|
|
559
|
+
issue(
|
|
560
|
+
"MISSING_TOPIC_ROOTS",
|
|
561
|
+
"At least one topicRoot is required",
|
|
562
|
+
"topicRoots"
|
|
563
|
+
)
|
|
564
|
+
);
|
|
565
|
+
} else {
|
|
566
|
+
issues.push(
|
|
567
|
+
...checkDuplicateIds(
|
|
568
|
+
pack.topicRoots,
|
|
569
|
+
"slug",
|
|
570
|
+
"topicRoots"
|
|
571
|
+
)
|
|
572
|
+
);
|
|
573
|
+
}
|
|
574
|
+
if (pack.operatingSystem) {
|
|
575
|
+
const knownRootSlugs = new Set(
|
|
576
|
+
pack.topicRoots?.map((topic) => topic.slug) ?? []
|
|
577
|
+
);
|
|
578
|
+
if (pack.operatingSystem.prompts) {
|
|
579
|
+
issues.push(
|
|
580
|
+
...checkDuplicateIds(
|
|
581
|
+
pack.operatingSystem.prompts,
|
|
582
|
+
"promptId",
|
|
583
|
+
"operatingSystem.prompts"
|
|
584
|
+
)
|
|
585
|
+
);
|
|
586
|
+
pack.operatingSystem.prompts.forEach((prompt, index) => {
|
|
587
|
+
issues.push(...validatePromptBinding(prompt, index));
|
|
588
|
+
});
|
|
589
|
+
}
|
|
590
|
+
if (pack.operatingSystem.tools) {
|
|
591
|
+
issues.push(
|
|
592
|
+
...checkDuplicateIds(
|
|
593
|
+
pack.operatingSystem.tools,
|
|
594
|
+
"toolId",
|
|
595
|
+
"operatingSystem.tools"
|
|
596
|
+
)
|
|
597
|
+
);
|
|
598
|
+
pack.operatingSystem.tools.forEach((tool, index) => {
|
|
599
|
+
issues.push(...validateToolBinding(tool, index));
|
|
600
|
+
});
|
|
601
|
+
}
|
|
602
|
+
if (pack.operatingSystem.setupAssets) {
|
|
603
|
+
issues.push(
|
|
604
|
+
...checkDuplicateIds(
|
|
605
|
+
pack.operatingSystem.setupAssets,
|
|
606
|
+
"assetId",
|
|
607
|
+
"operatingSystem.setupAssets"
|
|
608
|
+
)
|
|
609
|
+
);
|
|
610
|
+
pack.operatingSystem.setupAssets.forEach((asset, index) => {
|
|
611
|
+
issues.push(...validateSetupAsset(asset, index));
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
const templateSlugs = /* @__PURE__ */ new Set();
|
|
615
|
+
if (pack.operatingSystem.topicTemplates) {
|
|
616
|
+
issues.push(
|
|
617
|
+
...checkDuplicateIds(
|
|
618
|
+
pack.operatingSystem.topicTemplates,
|
|
619
|
+
"slug",
|
|
620
|
+
"operatingSystem.topicTemplates"
|
|
621
|
+
)
|
|
622
|
+
);
|
|
623
|
+
pack.operatingSystem.topicTemplates.forEach((template) => {
|
|
624
|
+
if (template.slug) {
|
|
625
|
+
templateSlugs.add(template.slug);
|
|
626
|
+
}
|
|
627
|
+
});
|
|
628
|
+
const knownTopicSlugs = /* @__PURE__ */ new Set([...knownRootSlugs, ...templateSlugs]);
|
|
629
|
+
pack.operatingSystem.topicTemplates.forEach((template, index) => {
|
|
630
|
+
issues.push(...validateTopicTemplate(template, index, knownTopicSlugs));
|
|
631
|
+
});
|
|
632
|
+
}
|
|
633
|
+
if (pack.operatingSystem.installProfiles) {
|
|
634
|
+
issues.push(
|
|
635
|
+
...checkDuplicateIds(
|
|
636
|
+
pack.operatingSystem.installProfiles,
|
|
637
|
+
"profileId",
|
|
638
|
+
"operatingSystem.installProfiles"
|
|
639
|
+
)
|
|
640
|
+
);
|
|
641
|
+
const knownPromptIds = new Set(
|
|
642
|
+
pack.operatingSystem.prompts?.map((prompt) => prompt.promptId) ?? []
|
|
643
|
+
);
|
|
644
|
+
const knownToolIds = new Set(
|
|
645
|
+
pack.operatingSystem.tools?.map((tool) => tool.toolId) ?? []
|
|
646
|
+
);
|
|
647
|
+
const knownAssetIds = new Set(
|
|
648
|
+
pack.operatingSystem.setupAssets?.map((asset) => asset.assetId) ?? []
|
|
649
|
+
);
|
|
650
|
+
const knownTopicSlugs = /* @__PURE__ */ new Set([...knownRootSlugs, ...templateSlugs]);
|
|
651
|
+
pack.operatingSystem.installProfiles.forEach((profile, index) => {
|
|
652
|
+
issues.push(
|
|
653
|
+
...validateInstallProfile(
|
|
654
|
+
profile,
|
|
655
|
+
index,
|
|
656
|
+
knownPromptIds,
|
|
657
|
+
knownToolIds,
|
|
658
|
+
knownAssetIds,
|
|
659
|
+
knownTopicSlugs
|
|
660
|
+
)
|
|
661
|
+
);
|
|
662
|
+
});
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
if (!pack.roles || pack.roles.length === 0) {
|
|
666
|
+
issues.push(
|
|
667
|
+
issue("MISSING_ROLES", "At least one reasoning role is required", "roles")
|
|
668
|
+
);
|
|
669
|
+
} else {
|
|
670
|
+
issues.push(
|
|
671
|
+
...checkDuplicateIds(
|
|
672
|
+
pack.roles,
|
|
673
|
+
"roleId",
|
|
674
|
+
"roles"
|
|
675
|
+
)
|
|
676
|
+
);
|
|
677
|
+
}
|
|
678
|
+
const knownGateIds = new Set(pack.gates?.map((g) => g.gateId) ?? []);
|
|
679
|
+
const knownArtifactIds = new Set(
|
|
680
|
+
pack.artifacts?.map((a) => a.artifactId) ?? []
|
|
681
|
+
);
|
|
682
|
+
const knownRoleIds = new Set(pack.roles?.map((r) => r.roleId) ?? []);
|
|
683
|
+
if (pack.gates) {
|
|
684
|
+
issues.push(
|
|
685
|
+
...checkDuplicateIds(
|
|
686
|
+
pack.gates,
|
|
687
|
+
"gateId",
|
|
688
|
+
"gates"
|
|
689
|
+
)
|
|
690
|
+
);
|
|
691
|
+
for (const [i, gate] of pack.gates.entries()) {
|
|
692
|
+
if (!gate.criteria || gate.criteria.length === 0) {
|
|
693
|
+
issues.push(
|
|
694
|
+
issue(
|
|
695
|
+
"EMPTY_GATE_CRITERIA",
|
|
696
|
+
`Gate "${gate.gateId}" has no criteria`,
|
|
697
|
+
`gates[${i}].criteria`,
|
|
698
|
+
"warning"
|
|
699
|
+
)
|
|
700
|
+
);
|
|
701
|
+
} else {
|
|
702
|
+
issues.push(
|
|
703
|
+
...checkDuplicateIds(
|
|
704
|
+
gate.criteria,
|
|
705
|
+
"criterionId",
|
|
706
|
+
`gates[${i}].criteria`
|
|
707
|
+
)
|
|
708
|
+
);
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
if (pack.artifacts) {
|
|
713
|
+
issues.push(
|
|
714
|
+
...checkDuplicateIds(
|
|
715
|
+
pack.artifacts,
|
|
716
|
+
"artifactId",
|
|
717
|
+
"artifacts"
|
|
718
|
+
)
|
|
719
|
+
);
|
|
720
|
+
}
|
|
721
|
+
if (pack.workflows) {
|
|
722
|
+
issues.push(
|
|
723
|
+
...checkDuplicateIds(
|
|
724
|
+
pack.workflows,
|
|
725
|
+
"workflowId",
|
|
726
|
+
"workflows"
|
|
727
|
+
)
|
|
728
|
+
);
|
|
729
|
+
for (const [wi, workflow] of pack.workflows.entries()) {
|
|
730
|
+
for (const gateId of workflow.gateCheckpoints) {
|
|
731
|
+
if (!knownGateIds.has(gateId)) {
|
|
732
|
+
issues.push(
|
|
733
|
+
issue(
|
|
734
|
+
"UNKNOWN_GATE_REF",
|
|
735
|
+
`Workflow "${workflow.workflowId}" references unknown gate "${gateId}"`,
|
|
736
|
+
`workflows[${wi}].gateCheckpoints`
|
|
737
|
+
)
|
|
738
|
+
);
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
for (const artifactId of workflow.requiredArtifacts) {
|
|
742
|
+
if (!knownArtifactIds.has(artifactId)) {
|
|
743
|
+
issues.push(
|
|
744
|
+
issue(
|
|
745
|
+
"UNKNOWN_ARTIFACT_REF",
|
|
746
|
+
`Workflow "${workflow.workflowId}" references unknown artifact "${artifactId}"`,
|
|
747
|
+
`workflows[${wi}].requiredArtifacts`
|
|
748
|
+
)
|
|
749
|
+
);
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
for (const [si, step] of workflow.steps.entries()) {
|
|
753
|
+
for (const roleId of step.requiredRoles) {
|
|
754
|
+
if (!knownRoleIds.has(roleId)) {
|
|
755
|
+
issues.push(
|
|
756
|
+
issue(
|
|
757
|
+
"UNKNOWN_ROLE_REF",
|
|
758
|
+
`Step "${step.stepId}" references unknown role "${roleId}"`,
|
|
759
|
+
`workflows[${wi}].steps[${si}].requiredRoles`
|
|
760
|
+
)
|
|
761
|
+
);
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
if (step.gateId && !knownGateIds.has(step.gateId)) {
|
|
765
|
+
issues.push(
|
|
766
|
+
issue(
|
|
767
|
+
"UNKNOWN_GATE_REF",
|
|
768
|
+
`Step "${step.stepId}" references unknown gate "${step.gateId}"`,
|
|
769
|
+
`workflows[${wi}].steps[${si}].gateId`
|
|
770
|
+
)
|
|
771
|
+
);
|
|
772
|
+
}
|
|
773
|
+
if (step.produces) {
|
|
774
|
+
for (const artifactId of step.produces) {
|
|
775
|
+
if (!knownArtifactIds.has(artifactId)) {
|
|
776
|
+
issues.push(
|
|
777
|
+
issue(
|
|
778
|
+
"UNKNOWN_ARTIFACT_REF",
|
|
779
|
+
`Step "${step.stepId}" references unknown artifact "${artifactId}"`,
|
|
780
|
+
`workflows[${wi}].steps[${si}].produces`
|
|
781
|
+
)
|
|
782
|
+
);
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
if (pack.inquiryShaping) {
|
|
790
|
+
if (pack.inquiryShaping.questionTemplates) {
|
|
791
|
+
issues.push(
|
|
792
|
+
...checkDuplicateIds(
|
|
793
|
+
pack.inquiryShaping.questionTemplates,
|
|
794
|
+
"templateId",
|
|
795
|
+
"inquiryShaping.questionTemplates"
|
|
796
|
+
)
|
|
797
|
+
);
|
|
798
|
+
pack.inquiryShaping.questionTemplates.forEach((template, index) => {
|
|
799
|
+
issues.push(...validateQuestionTemplate(template, index));
|
|
800
|
+
});
|
|
801
|
+
}
|
|
802
|
+
if (pack.inquiryShaping.taskTemplates) {
|
|
803
|
+
issues.push(
|
|
804
|
+
...checkDuplicateIds(
|
|
805
|
+
pack.inquiryShaping.taskTemplates,
|
|
806
|
+
"templateId",
|
|
807
|
+
"inquiryShaping.taskTemplates"
|
|
808
|
+
)
|
|
809
|
+
);
|
|
810
|
+
pack.inquiryShaping.taskTemplates.forEach((template, index) => {
|
|
811
|
+
issues.push(...validateTaskTemplate(template, index));
|
|
812
|
+
});
|
|
813
|
+
}
|
|
814
|
+
if (pack.inquiryShaping.frameworkHints) {
|
|
815
|
+
issues.push(
|
|
816
|
+
...checkDuplicateIds(
|
|
817
|
+
pack.inquiryShaping.frameworkHints.map((hint) => ({
|
|
818
|
+
frameworkName: hint.frameworkName
|
|
819
|
+
})),
|
|
820
|
+
"frameworkName",
|
|
821
|
+
"inquiryShaping.frameworkHints"
|
|
822
|
+
)
|
|
823
|
+
);
|
|
824
|
+
pack.inquiryShaping.frameworkHints.forEach((hint, index) => {
|
|
825
|
+
issues.push(...validateFrameworkHint(hint, index));
|
|
826
|
+
});
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
return {
|
|
830
|
+
valid: issues.filter((i) => i.severity === "error").length === 0,
|
|
831
|
+
issues
|
|
832
|
+
};
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
// src/domain-pack/authoring.ts
|
|
836
|
+
var DOMAIN_PACK_MANIFEST_KIND = "lucern-domain-pack-manifest";
|
|
837
|
+
var CURRENT_MANIFEST_VERSION = "1.0.0";
|
|
838
|
+
var KEBAB_CASE2 = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
|
|
839
|
+
var SEMVER2 = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
|
|
840
|
+
var LEGACY_PUBLIC_KEYS = /* @__PURE__ */ new Set([
|
|
841
|
+
"project",
|
|
842
|
+
"projects",
|
|
843
|
+
"projectId",
|
|
844
|
+
"projectIds"
|
|
845
|
+
]);
|
|
846
|
+
var SCHEMA_EXTENSION_TARGETS = /* @__PURE__ */ new Set([
|
|
847
|
+
"artifact",
|
|
848
|
+
"workflow",
|
|
849
|
+
"gate",
|
|
850
|
+
"prompt",
|
|
851
|
+
"tool",
|
|
852
|
+
"install-profile",
|
|
853
|
+
"topic-template"
|
|
854
|
+
]);
|
|
855
|
+
var ONTOLOGY_CONSTRAINT_SEVERITIES = /* @__PURE__ */ new Set([
|
|
856
|
+
"error",
|
|
857
|
+
"warning",
|
|
858
|
+
"informational"
|
|
859
|
+
]);
|
|
860
|
+
var LINEAGE_MODES = /* @__PURE__ */ new Set(["root", "remix", "fork"]);
|
|
861
|
+
var AUTHORING_TOOL_NAMES = {
|
|
862
|
+
validate: "validate_domain_pack_manifest",
|
|
863
|
+
preview: "preview_domain_pack_manifest",
|
|
864
|
+
publish: "publish_domain_pack_manifest"
|
|
865
|
+
};
|
|
866
|
+
function issue2(code, message, path, source, severity = "error") {
|
|
867
|
+
return { code, message, path, severity, source };
|
|
868
|
+
}
|
|
869
|
+
function emptyCounts() {
|
|
870
|
+
return {
|
|
871
|
+
topicRoots: 0,
|
|
872
|
+
workflows: 0,
|
|
873
|
+
gates: 0,
|
|
874
|
+
artifacts: 0,
|
|
875
|
+
roles: 0,
|
|
876
|
+
prompts: 0,
|
|
877
|
+
tools: 0,
|
|
878
|
+
setupAssets: 0,
|
|
879
|
+
installProfiles: 0,
|
|
880
|
+
frameworks: 0,
|
|
881
|
+
schemaExtensions: 0,
|
|
882
|
+
ontologyExtensions: 0
|
|
883
|
+
};
|
|
884
|
+
}
|
|
885
|
+
function isPlainObject(value) {
|
|
886
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype;
|
|
887
|
+
}
|
|
888
|
+
function dedupeStrings2(values) {
|
|
889
|
+
if (!values) {
|
|
890
|
+
return void 0;
|
|
891
|
+
}
|
|
892
|
+
return Array.from(
|
|
893
|
+
new Set(values.map((value) => value.trim()).filter((value) => value.length))
|
|
894
|
+
);
|
|
895
|
+
}
|
|
896
|
+
function normalizeRuntimeTargets2(values) {
|
|
897
|
+
return values ? dedupeStrings2(values) : void 0;
|
|
898
|
+
}
|
|
899
|
+
function normalizeFrameworks(frameworks) {
|
|
900
|
+
if (!frameworks) {
|
|
901
|
+
return void 0;
|
|
902
|
+
}
|
|
903
|
+
return frameworks.map((framework) => ({
|
|
904
|
+
...framework,
|
|
905
|
+
frameworkId: framework.frameworkId.trim(),
|
|
906
|
+
version: framework.version.trim(),
|
|
907
|
+
versionConstraint: framework.versionConstraint?.trim(),
|
|
908
|
+
runtimeTargets: normalizeRuntimeTargets2(framework.runtimeTargets)
|
|
909
|
+
}));
|
|
910
|
+
}
|
|
911
|
+
function normalizeSchemaExtensions(extensions) {
|
|
912
|
+
if (!extensions) {
|
|
913
|
+
return void 0;
|
|
914
|
+
}
|
|
915
|
+
return extensions.map((extension) => ({
|
|
916
|
+
...extension,
|
|
917
|
+
extensionId: extension.extensionId.trim(),
|
|
918
|
+
target: extension.target,
|
|
919
|
+
description: extension.description.trim(),
|
|
920
|
+
version: extension.version.trim(),
|
|
921
|
+
extends: extension.extends?.trim()
|
|
922
|
+
}));
|
|
923
|
+
}
|
|
924
|
+
function normalizeOntologyExtensions(extensions) {
|
|
925
|
+
if (!extensions) {
|
|
926
|
+
return void 0;
|
|
927
|
+
}
|
|
928
|
+
return extensions.map((extension) => ({
|
|
929
|
+
...extension,
|
|
930
|
+
extensionId: extension.extensionId.trim(),
|
|
931
|
+
ontologyId: extension.ontologyId.trim(),
|
|
932
|
+
baseVersionConstraint: extension.baseVersionConstraint.trim(),
|
|
933
|
+
entityTypes: extension.entityTypes?.map((entityType) => ({
|
|
934
|
+
...entityType,
|
|
935
|
+
value: entityType.value.trim(),
|
|
936
|
+
label: entityType.label.trim(),
|
|
937
|
+
description: entityType.description?.trim(),
|
|
938
|
+
subtypes: dedupeStrings2(entityType.subtypes)
|
|
939
|
+
})),
|
|
940
|
+
edgeTypes: extension.edgeTypes?.map((edgeType) => ({
|
|
941
|
+
...edgeType,
|
|
942
|
+
value: edgeType.value.trim(),
|
|
943
|
+
label: edgeType.label.trim(),
|
|
944
|
+
description: edgeType.description?.trim(),
|
|
945
|
+
sourceTypes: dedupeStrings2(edgeType.sourceTypes),
|
|
946
|
+
targetTypes: dedupeStrings2(edgeType.targetTypes)
|
|
947
|
+
}))
|
|
948
|
+
}));
|
|
949
|
+
}
|
|
950
|
+
function normalizeLineage(lineage) {
|
|
951
|
+
if (!lineage) {
|
|
952
|
+
return { mode: "root" };
|
|
953
|
+
}
|
|
954
|
+
return {
|
|
955
|
+
mode: lineage.mode,
|
|
956
|
+
parentPackId: lineage.parentPackId?.trim(),
|
|
957
|
+
parentVersion: lineage.parentVersion?.trim(),
|
|
958
|
+
parentManifestDigest: lineage.parentManifestDigest?.trim(),
|
|
959
|
+
supersedesPackId: lineage.supersedesPackId?.trim(),
|
|
960
|
+
notes: lineage.notes?.trim()
|
|
961
|
+
};
|
|
962
|
+
}
|
|
963
|
+
function normalizeMetadata(metadata) {
|
|
964
|
+
if (!metadata) {
|
|
965
|
+
return void 0;
|
|
966
|
+
}
|
|
967
|
+
return {
|
|
968
|
+
description: metadata.description?.trim(),
|
|
969
|
+
owner: metadata.owner?.trim(),
|
|
970
|
+
tags: dedupeStrings2(metadata.tags)
|
|
971
|
+
};
|
|
972
|
+
}
|
|
973
|
+
function toDomainPack(pack) {
|
|
974
|
+
return defineDomainPack(pack);
|
|
975
|
+
}
|
|
976
|
+
function defineDomainPackAuthoringManifest(input) {
|
|
977
|
+
return {
|
|
978
|
+
kind: input.kind ?? DOMAIN_PACK_MANIFEST_KIND,
|
|
979
|
+
manifestVersion: input.manifestVersion?.trim() || CURRENT_MANIFEST_VERSION,
|
|
980
|
+
pack: toDomainPack(input.pack),
|
|
981
|
+
frameworks: normalizeFrameworks(input.frameworks),
|
|
982
|
+
schemaExtensions: normalizeSchemaExtensions(input.schemaExtensions),
|
|
983
|
+
ontologyExtensions: normalizeOntologyExtensions(input.ontologyExtensions),
|
|
984
|
+
lineage: normalizeLineage(input.lineage),
|
|
985
|
+
metadata: normalizeMetadata(input.metadata)
|
|
986
|
+
};
|
|
987
|
+
}
|
|
988
|
+
function countManifestArtifacts(manifest) {
|
|
989
|
+
if (!manifest) {
|
|
990
|
+
return emptyCounts();
|
|
991
|
+
}
|
|
992
|
+
return {
|
|
993
|
+
topicRoots: manifest.pack.topicRoots.length,
|
|
994
|
+
workflows: manifest.pack.workflows.length,
|
|
995
|
+
gates: manifest.pack.gates.length,
|
|
996
|
+
artifacts: manifest.pack.artifacts.length,
|
|
997
|
+
roles: manifest.pack.roles.length,
|
|
998
|
+
prompts: manifest.pack.operatingSystem?.prompts?.length ?? 0,
|
|
999
|
+
tools: manifest.pack.operatingSystem?.tools?.length ?? 0,
|
|
1000
|
+
setupAssets: manifest.pack.operatingSystem?.setupAssets?.length ?? 0,
|
|
1001
|
+
installProfiles: manifest.pack.operatingSystem?.installProfiles?.length ?? 0,
|
|
1002
|
+
frameworks: manifest.frameworks?.length ?? 0,
|
|
1003
|
+
schemaExtensions: manifest.schemaExtensions?.length ?? 0,
|
|
1004
|
+
ontologyExtensions: manifest.ontologyExtensions?.length ?? 0
|
|
1005
|
+
};
|
|
1006
|
+
}
|
|
1007
|
+
function sortJsonValue(value) {
|
|
1008
|
+
if (Array.isArray(value)) {
|
|
1009
|
+
return value.map(sortJsonValue);
|
|
1010
|
+
}
|
|
1011
|
+
if (isPlainObject(value)) {
|
|
1012
|
+
return Object.fromEntries(
|
|
1013
|
+
Object.entries(value).filter(([, entryValue]) => entryValue !== void 0).sort(([left], [right]) => left.localeCompare(right)).map(([key, entryValue]) => [key, sortJsonValue(entryValue)])
|
|
1014
|
+
);
|
|
1015
|
+
}
|
|
1016
|
+
return value;
|
|
1017
|
+
}
|
|
1018
|
+
function escapeYamlString(value) {
|
|
1019
|
+
return JSON.stringify(value);
|
|
1020
|
+
}
|
|
1021
|
+
function toYamlScalar(value) {
|
|
1022
|
+
if (value === null) {
|
|
1023
|
+
return "null";
|
|
1024
|
+
}
|
|
1025
|
+
if (typeof value === "boolean" || typeof value === "number") {
|
|
1026
|
+
return String(value);
|
|
1027
|
+
}
|
|
1028
|
+
return escapeYamlString(String(value));
|
|
1029
|
+
}
|
|
1030
|
+
function renderYaml(value, indent = 0) {
|
|
1031
|
+
const prefix = " ".repeat(indent);
|
|
1032
|
+
if (Array.isArray(value)) {
|
|
1033
|
+
if (value.length === 0) {
|
|
1034
|
+
return [`${prefix}[]`];
|
|
1035
|
+
}
|
|
1036
|
+
return value.flatMap((entry) => {
|
|
1037
|
+
if (Array.isArray(entry) || isPlainObject(entry)) {
|
|
1038
|
+
return [`${prefix}-`, ...renderYaml(entry, indent + 2)];
|
|
1039
|
+
}
|
|
1040
|
+
return [`${prefix}- ${toYamlScalar(entry)}`];
|
|
1041
|
+
});
|
|
1042
|
+
}
|
|
1043
|
+
if (isPlainObject(value)) {
|
|
1044
|
+
const entries = Object.entries(value);
|
|
1045
|
+
if (entries.length === 0) {
|
|
1046
|
+
return [`${prefix}{}`];
|
|
1047
|
+
}
|
|
1048
|
+
return entries.flatMap(([key, entryValue]) => {
|
|
1049
|
+
if (entryValue === void 0) {
|
|
1050
|
+
return [];
|
|
1051
|
+
}
|
|
1052
|
+
if (Array.isArray(entryValue)) {
|
|
1053
|
+
if (entryValue.length === 0) {
|
|
1054
|
+
return [`${prefix}${key}: []`];
|
|
1055
|
+
}
|
|
1056
|
+
return [`${prefix}${key}:`, ...renderYaml(entryValue, indent + 2)];
|
|
1057
|
+
}
|
|
1058
|
+
if (isPlainObject(entryValue)) {
|
|
1059
|
+
if (Object.keys(entryValue).length === 0) {
|
|
1060
|
+
return [`${prefix}${key}: {}`];
|
|
1061
|
+
}
|
|
1062
|
+
return [`${prefix}${key}:`, ...renderYaml(entryValue, indent + 2)];
|
|
1063
|
+
}
|
|
1064
|
+
return [`${prefix}${key}: ${toYamlScalar(entryValue)}`];
|
|
1065
|
+
});
|
|
1066
|
+
}
|
|
1067
|
+
return [`${prefix}${toYamlScalar(value)}`];
|
|
1068
|
+
}
|
|
1069
|
+
function countIndent(line) {
|
|
1070
|
+
return line.length - line.trimStart().length;
|
|
1071
|
+
}
|
|
1072
|
+
function parseYamlScalar(raw) {
|
|
1073
|
+
const value = raw.trim();
|
|
1074
|
+
if (value === "null") {
|
|
1075
|
+
return null;
|
|
1076
|
+
}
|
|
1077
|
+
if (value === "true") {
|
|
1078
|
+
return true;
|
|
1079
|
+
}
|
|
1080
|
+
if (value === "false") {
|
|
1081
|
+
return false;
|
|
1082
|
+
}
|
|
1083
|
+
if (/^-?\d+(?:\.\d+)?$/.test(value)) {
|
|
1084
|
+
return Number(value);
|
|
1085
|
+
}
|
|
1086
|
+
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
1087
|
+
if (value.startsWith("'")) {
|
|
1088
|
+
return value.slice(1, -1).replace(/''/g, "'");
|
|
1089
|
+
}
|
|
1090
|
+
return JSON.parse(value);
|
|
1091
|
+
}
|
|
1092
|
+
if (value === "[]") {
|
|
1093
|
+
return [];
|
|
1094
|
+
}
|
|
1095
|
+
if (value === "{}") {
|
|
1096
|
+
return {};
|
|
1097
|
+
}
|
|
1098
|
+
return value;
|
|
1099
|
+
}
|
|
1100
|
+
function splitYamlKeyValue(trimmed) {
|
|
1101
|
+
const separatorIndex = trimmed.indexOf(":");
|
|
1102
|
+
if (separatorIndex === -1) {
|
|
1103
|
+
throw new Error(`Invalid YAML mapping entry: ${trimmed}`);
|
|
1104
|
+
}
|
|
1105
|
+
const key = trimmed.slice(0, separatorIndex).trim();
|
|
1106
|
+
const value = trimmed.slice(separatorIndex + 1).trim();
|
|
1107
|
+
return { key, value: value.length ? value : null };
|
|
1108
|
+
}
|
|
1109
|
+
function parseYamlDocument(text) {
|
|
1110
|
+
const rawLines = text.replace(/\r\n/g, "\n").split("\n").map((line) => line.replace(/\t/g, " "));
|
|
1111
|
+
const lines = rawLines.filter((line) => {
|
|
1112
|
+
const trimmed = line.trim();
|
|
1113
|
+
return trimmed.length > 0 && trimmed !== "---" && trimmed !== "...";
|
|
1114
|
+
});
|
|
1115
|
+
let index = 0;
|
|
1116
|
+
function parseBlock(indent) {
|
|
1117
|
+
if (index >= lines.length) {
|
|
1118
|
+
return {};
|
|
1119
|
+
}
|
|
1120
|
+
const currentLine = lines[index];
|
|
1121
|
+
const currentIndent = countIndent(currentLine);
|
|
1122
|
+
if (currentIndent < indent) {
|
|
1123
|
+
return {};
|
|
1124
|
+
}
|
|
1125
|
+
if (currentLine.trimStart().startsWith("-")) {
|
|
1126
|
+
return parseArray(indent);
|
|
1127
|
+
}
|
|
1128
|
+
return parseObject(indent);
|
|
1129
|
+
}
|
|
1130
|
+
function parseArray(indent) {
|
|
1131
|
+
const items = [];
|
|
1132
|
+
while (index < lines.length) {
|
|
1133
|
+
const line = lines[index];
|
|
1134
|
+
const currentIndent = countIndent(line);
|
|
1135
|
+
if (currentIndent < indent) {
|
|
1136
|
+
break;
|
|
1137
|
+
}
|
|
1138
|
+
if (currentIndent !== indent) {
|
|
1139
|
+
throw new Error(`Invalid YAML indentation near: ${line.trim()}`);
|
|
1140
|
+
}
|
|
1141
|
+
const trimmed = line.trimStart();
|
|
1142
|
+
if (!trimmed.startsWith("-")) {
|
|
1143
|
+
break;
|
|
1144
|
+
}
|
|
1145
|
+
const rest = trimmed.slice(1).trimStart();
|
|
1146
|
+
index += 1;
|
|
1147
|
+
if (!rest.length) {
|
|
1148
|
+
items.push(parseBlock(indent + 2));
|
|
1149
|
+
continue;
|
|
1150
|
+
}
|
|
1151
|
+
items.push(parseYamlScalar(rest));
|
|
1152
|
+
}
|
|
1153
|
+
return items;
|
|
1154
|
+
}
|
|
1155
|
+
function parseObject(indent) {
|
|
1156
|
+
const objectValue = {};
|
|
1157
|
+
while (index < lines.length) {
|
|
1158
|
+
const line = lines[index];
|
|
1159
|
+
const currentIndent = countIndent(line);
|
|
1160
|
+
if (currentIndent < indent) {
|
|
1161
|
+
break;
|
|
1162
|
+
}
|
|
1163
|
+
if (currentIndent !== indent) {
|
|
1164
|
+
throw new Error(`Invalid YAML indentation near: ${line.trim()}`);
|
|
1165
|
+
}
|
|
1166
|
+
const trimmed = line.trim();
|
|
1167
|
+
if (trimmed.startsWith("-")) {
|
|
1168
|
+
break;
|
|
1169
|
+
}
|
|
1170
|
+
const { key, value } = splitYamlKeyValue(trimmed);
|
|
1171
|
+
index += 1;
|
|
1172
|
+
objectValue[key] = value === null ? parseBlock(indent + 2) : parseYamlScalar(value);
|
|
1173
|
+
}
|
|
1174
|
+
return objectValue;
|
|
1175
|
+
}
|
|
1176
|
+
return parseBlock(0);
|
|
1177
|
+
}
|
|
1178
|
+
function detectDomainPackManifestFormat(source, explicitFormat) {
|
|
1179
|
+
if (explicitFormat) {
|
|
1180
|
+
return explicitFormat;
|
|
1181
|
+
}
|
|
1182
|
+
const trimmed = source.trim();
|
|
1183
|
+
if (trimmed.startsWith("{")) {
|
|
1184
|
+
return "json";
|
|
1185
|
+
}
|
|
1186
|
+
return "yaml";
|
|
1187
|
+
}
|
|
1188
|
+
function serializeDomainPackAuthoringManifest(manifest, format = "json") {
|
|
1189
|
+
const canonicalValue = sortJsonValue(manifest);
|
|
1190
|
+
if (format === "json") {
|
|
1191
|
+
return `${JSON.stringify(canonicalValue, null, 2)}
|
|
1192
|
+
`;
|
|
1193
|
+
}
|
|
1194
|
+
return `${renderYaml(canonicalValue).join("\n")}
|
|
1195
|
+
`;
|
|
1196
|
+
}
|
|
1197
|
+
function parseDomainPackAuthoringManifest(source, format) {
|
|
1198
|
+
const detectedFormat = detectDomainPackManifestFormat(source, format);
|
|
1199
|
+
const parsed = detectedFormat === "json" ? JSON.parse(source) : parseYamlDocument(source);
|
|
1200
|
+
if (!isPlainObject(parsed)) {
|
|
1201
|
+
throw new Error("Domain pack manifest must parse to an object.");
|
|
1202
|
+
}
|
|
1203
|
+
if (!("pack" in parsed)) {
|
|
1204
|
+
throw new Error("Domain pack manifest requires a top-level pack object.");
|
|
1205
|
+
}
|
|
1206
|
+
return defineDomainPackAuthoringManifest({
|
|
1207
|
+
kind: parsed.kind,
|
|
1208
|
+
manifestVersion: parsed.manifestVersion,
|
|
1209
|
+
pack: parsed.pack,
|
|
1210
|
+
frameworks: parsed.frameworks,
|
|
1211
|
+
schemaExtensions: parsed.schemaExtensions,
|
|
1212
|
+
ontologyExtensions: parsed.ontologyExtensions,
|
|
1213
|
+
lineage: parsed.lineage,
|
|
1214
|
+
metadata: parsed.metadata
|
|
1215
|
+
});
|
|
1216
|
+
}
|
|
1217
|
+
function validateFrameworks(frameworks) {
|
|
1218
|
+
if (!frameworks) {
|
|
1219
|
+
return [];
|
|
1220
|
+
}
|
|
1221
|
+
const issues = [];
|
|
1222
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1223
|
+
frameworks.forEach((framework, index) => {
|
|
1224
|
+
const path = `frameworks[${index}]`;
|
|
1225
|
+
if (!framework.frameworkId) {
|
|
1226
|
+
issues.push(
|
|
1227
|
+
issue2(
|
|
1228
|
+
"MISSING_FRAMEWORK_ID",
|
|
1229
|
+
"frameworkId is required",
|
|
1230
|
+
`${path}.frameworkId`,
|
|
1231
|
+
"framework"
|
|
1232
|
+
)
|
|
1233
|
+
);
|
|
1234
|
+
} else if (!KEBAB_CASE2.test(framework.frameworkId)) {
|
|
1235
|
+
issues.push(
|
|
1236
|
+
issue2(
|
|
1237
|
+
"INVALID_FRAMEWORK_ID",
|
|
1238
|
+
`frameworkId "${framework.frameworkId}" must be kebab-case`,
|
|
1239
|
+
`${path}.frameworkId`,
|
|
1240
|
+
"framework"
|
|
1241
|
+
)
|
|
1242
|
+
);
|
|
1243
|
+
} else if (seen.has(framework.frameworkId)) {
|
|
1244
|
+
issues.push(
|
|
1245
|
+
issue2(
|
|
1246
|
+
"DUPLICATE_FRAMEWORK_ID",
|
|
1247
|
+
`Duplicate frameworkId "${framework.frameworkId}"`,
|
|
1248
|
+
`${path}.frameworkId`,
|
|
1249
|
+
"framework"
|
|
1250
|
+
)
|
|
1251
|
+
);
|
|
1252
|
+
} else {
|
|
1253
|
+
seen.add(framework.frameworkId);
|
|
1254
|
+
}
|
|
1255
|
+
if (!framework.version) {
|
|
1256
|
+
issues.push(
|
|
1257
|
+
issue2(
|
|
1258
|
+
"MISSING_FRAMEWORK_VERSION",
|
|
1259
|
+
"version is required",
|
|
1260
|
+
`${path}.version`,
|
|
1261
|
+
"framework"
|
|
1262
|
+
)
|
|
1263
|
+
);
|
|
1264
|
+
} else if (!SEMVER2.test(framework.version)) {
|
|
1265
|
+
issues.push(
|
|
1266
|
+
issue2(
|
|
1267
|
+
"INVALID_FRAMEWORK_VERSION",
|
|
1268
|
+
`framework version "${framework.version}" must be valid semver`,
|
|
1269
|
+
`${path}.version`,
|
|
1270
|
+
"framework"
|
|
1271
|
+
)
|
|
1272
|
+
);
|
|
1273
|
+
}
|
|
1274
|
+
});
|
|
1275
|
+
return issues;
|
|
1276
|
+
}
|
|
1277
|
+
function validateSchemaExtensions(extensions) {
|
|
1278
|
+
if (!extensions) {
|
|
1279
|
+
return [];
|
|
1280
|
+
}
|
|
1281
|
+
const issues = [];
|
|
1282
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1283
|
+
extensions.forEach((extension, index) => {
|
|
1284
|
+
const path = `schemaExtensions[${index}]`;
|
|
1285
|
+
if (!extension.extensionId) {
|
|
1286
|
+
issues.push(
|
|
1287
|
+
issue2(
|
|
1288
|
+
"MISSING_SCHEMA_EXTENSION_ID",
|
|
1289
|
+
"extensionId is required",
|
|
1290
|
+
`${path}.extensionId`,
|
|
1291
|
+
"schema-extension"
|
|
1292
|
+
)
|
|
1293
|
+
);
|
|
1294
|
+
} else if (!KEBAB_CASE2.test(extension.extensionId)) {
|
|
1295
|
+
issues.push(
|
|
1296
|
+
issue2(
|
|
1297
|
+
"INVALID_SCHEMA_EXTENSION_ID",
|
|
1298
|
+
`extensionId "${extension.extensionId}" must be kebab-case`,
|
|
1299
|
+
`${path}.extensionId`,
|
|
1300
|
+
"schema-extension"
|
|
1301
|
+
)
|
|
1302
|
+
);
|
|
1303
|
+
} else if (seen.has(extension.extensionId)) {
|
|
1304
|
+
issues.push(
|
|
1305
|
+
issue2(
|
|
1306
|
+
"DUPLICATE_SCHEMA_EXTENSION_ID",
|
|
1307
|
+
`Duplicate schema extension "${extension.extensionId}"`,
|
|
1308
|
+
`${path}.extensionId`,
|
|
1309
|
+
"schema-extension"
|
|
1310
|
+
)
|
|
1311
|
+
);
|
|
1312
|
+
} else {
|
|
1313
|
+
seen.add(extension.extensionId);
|
|
1314
|
+
}
|
|
1315
|
+
if (!SCHEMA_EXTENSION_TARGETS.has(extension.target)) {
|
|
1316
|
+
issues.push(
|
|
1317
|
+
issue2(
|
|
1318
|
+
"INVALID_SCHEMA_EXTENSION_TARGET",
|
|
1319
|
+
`Unsupported schema extension target "${extension.target}"`,
|
|
1320
|
+
`${path}.target`,
|
|
1321
|
+
"schema-extension"
|
|
1322
|
+
)
|
|
1323
|
+
);
|
|
1324
|
+
}
|
|
1325
|
+
if (!extension.description) {
|
|
1326
|
+
issues.push(
|
|
1327
|
+
issue2(
|
|
1328
|
+
"MISSING_SCHEMA_EXTENSION_DESCRIPTION",
|
|
1329
|
+
"description is required",
|
|
1330
|
+
`${path}.description`,
|
|
1331
|
+
"schema-extension"
|
|
1332
|
+
)
|
|
1333
|
+
);
|
|
1334
|
+
}
|
|
1335
|
+
if (!SEMVER2.test(extension.version)) {
|
|
1336
|
+
issues.push(
|
|
1337
|
+
issue2(
|
|
1338
|
+
"INVALID_SCHEMA_EXTENSION_VERSION",
|
|
1339
|
+
`schema extension version "${extension.version}" must be valid semver`,
|
|
1340
|
+
`${path}.version`,
|
|
1341
|
+
"schema-extension"
|
|
1342
|
+
)
|
|
1343
|
+
);
|
|
1344
|
+
}
|
|
1345
|
+
if (!isPlainObject(extension.schema)) {
|
|
1346
|
+
issues.push(
|
|
1347
|
+
issue2(
|
|
1348
|
+
"INVALID_SCHEMA_EXTENSION_SCHEMA",
|
|
1349
|
+
"schema extension schema must be a plain object",
|
|
1350
|
+
`${path}.schema`,
|
|
1351
|
+
"schema-extension"
|
|
1352
|
+
)
|
|
1353
|
+
);
|
|
1354
|
+
}
|
|
1355
|
+
});
|
|
1356
|
+
return issues;
|
|
1357
|
+
}
|
|
1358
|
+
function validateOntologyExtensions(extensions) {
|
|
1359
|
+
if (!extensions) {
|
|
1360
|
+
return [];
|
|
1361
|
+
}
|
|
1362
|
+
const issues = [];
|
|
1363
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1364
|
+
extensions.forEach((extension, index) => {
|
|
1365
|
+
const path = `ontologyExtensions[${index}]`;
|
|
1366
|
+
if (!extension.extensionId) {
|
|
1367
|
+
issues.push(
|
|
1368
|
+
issue2(
|
|
1369
|
+
"MISSING_ONTOLOGY_EXTENSION_ID",
|
|
1370
|
+
"extensionId is required",
|
|
1371
|
+
`${path}.extensionId`,
|
|
1372
|
+
"ontology-extension"
|
|
1373
|
+
)
|
|
1374
|
+
);
|
|
1375
|
+
} else if (!KEBAB_CASE2.test(extension.extensionId)) {
|
|
1376
|
+
issues.push(
|
|
1377
|
+
issue2(
|
|
1378
|
+
"INVALID_ONTOLOGY_EXTENSION_ID",
|
|
1379
|
+
`extensionId "${extension.extensionId}" must be kebab-case`,
|
|
1380
|
+
`${path}.extensionId`,
|
|
1381
|
+
"ontology-extension"
|
|
1382
|
+
)
|
|
1383
|
+
);
|
|
1384
|
+
} else if (seen.has(extension.extensionId)) {
|
|
1385
|
+
issues.push(
|
|
1386
|
+
issue2(
|
|
1387
|
+
"DUPLICATE_ONTOLOGY_EXTENSION_ID",
|
|
1388
|
+
`Duplicate ontology extension "${extension.extensionId}"`,
|
|
1389
|
+
`${path}.extensionId`,
|
|
1390
|
+
"ontology-extension"
|
|
1391
|
+
)
|
|
1392
|
+
);
|
|
1393
|
+
} else {
|
|
1394
|
+
seen.add(extension.extensionId);
|
|
1395
|
+
}
|
|
1396
|
+
if (!extension.ontologyId) {
|
|
1397
|
+
issues.push(
|
|
1398
|
+
issue2(
|
|
1399
|
+
"MISSING_ONTOLOGY_EXTENSION_TARGET",
|
|
1400
|
+
"ontologyId is required",
|
|
1401
|
+
`${path}.ontologyId`,
|
|
1402
|
+
"ontology-extension"
|
|
1403
|
+
)
|
|
1404
|
+
);
|
|
1405
|
+
}
|
|
1406
|
+
if (!extension.baseVersionConstraint) {
|
|
1407
|
+
issues.push(
|
|
1408
|
+
issue2(
|
|
1409
|
+
"MISSING_ONTOLOGY_BASE_VERSION",
|
|
1410
|
+
"baseVersionConstraint is required",
|
|
1411
|
+
`${path}.baseVersionConstraint`,
|
|
1412
|
+
"ontology-extension"
|
|
1413
|
+
)
|
|
1414
|
+
);
|
|
1415
|
+
}
|
|
1416
|
+
if (extension.additiveOnly !== true) {
|
|
1417
|
+
issues.push(
|
|
1418
|
+
issue2(
|
|
1419
|
+
"NON_MONOTONIC_ONTOLOGY_EXTENSION",
|
|
1420
|
+
"ontology extensions must set additiveOnly=true",
|
|
1421
|
+
`${path}.additiveOnly`,
|
|
1422
|
+
"ontology-extension"
|
|
1423
|
+
)
|
|
1424
|
+
);
|
|
1425
|
+
}
|
|
1426
|
+
const entityTypeValues = /* @__PURE__ */ new Set();
|
|
1427
|
+
extension.entityTypes?.forEach((entityType, entityTypeIndex) => {
|
|
1428
|
+
const entityPath = `${path}.entityTypes[${entityTypeIndex}]`;
|
|
1429
|
+
if (!entityType.value || !KEBAB_CASE2.test(entityType.value)) {
|
|
1430
|
+
issues.push(
|
|
1431
|
+
issue2(
|
|
1432
|
+
"INVALID_ONTOLOGY_ENTITY_VALUE",
|
|
1433
|
+
"entity extension value must be kebab-case",
|
|
1434
|
+
`${entityPath}.value`,
|
|
1435
|
+
"ontology-extension"
|
|
1436
|
+
)
|
|
1437
|
+
);
|
|
1438
|
+
} else if (entityTypeValues.has(entityType.value)) {
|
|
1439
|
+
issues.push(
|
|
1440
|
+
issue2(
|
|
1441
|
+
"DUPLICATE_ONTOLOGY_ENTITY_VALUE",
|
|
1442
|
+
`Duplicate entity extension value "${entityType.value}"`,
|
|
1443
|
+
`${entityPath}.value`,
|
|
1444
|
+
"ontology-extension"
|
|
1445
|
+
)
|
|
1446
|
+
);
|
|
1447
|
+
} else {
|
|
1448
|
+
entityTypeValues.add(entityType.value);
|
|
1449
|
+
}
|
|
1450
|
+
if (!entityType.label) {
|
|
1451
|
+
issues.push(
|
|
1452
|
+
issue2(
|
|
1453
|
+
"MISSING_ONTOLOGY_ENTITY_LABEL",
|
|
1454
|
+
"entity extension label is required",
|
|
1455
|
+
`${entityPath}.label`,
|
|
1456
|
+
"ontology-extension"
|
|
1457
|
+
)
|
|
1458
|
+
);
|
|
1459
|
+
}
|
|
1460
|
+
});
|
|
1461
|
+
const edgeTypeValues = /* @__PURE__ */ new Set();
|
|
1462
|
+
extension.edgeTypes?.forEach((edgeType, edgeTypeIndex) => {
|
|
1463
|
+
const edgePath = `${path}.edgeTypes[${edgeTypeIndex}]`;
|
|
1464
|
+
if (!edgeType.value || !KEBAB_CASE2.test(edgeType.value)) {
|
|
1465
|
+
issues.push(
|
|
1466
|
+
issue2(
|
|
1467
|
+
"INVALID_ONTOLOGY_EDGE_VALUE",
|
|
1468
|
+
"edge extension value must be kebab-case",
|
|
1469
|
+
`${edgePath}.value`,
|
|
1470
|
+
"ontology-extension"
|
|
1471
|
+
)
|
|
1472
|
+
);
|
|
1473
|
+
} else if (edgeTypeValues.has(edgeType.value)) {
|
|
1474
|
+
issues.push(
|
|
1475
|
+
issue2(
|
|
1476
|
+
"DUPLICATE_ONTOLOGY_EDGE_VALUE",
|
|
1477
|
+
`Duplicate edge extension value "${edgeType.value}"`,
|
|
1478
|
+
`${edgePath}.value`,
|
|
1479
|
+
"ontology-extension"
|
|
1480
|
+
)
|
|
1481
|
+
);
|
|
1482
|
+
} else {
|
|
1483
|
+
edgeTypeValues.add(edgeType.value);
|
|
1484
|
+
}
|
|
1485
|
+
if (!edgeType.label) {
|
|
1486
|
+
issues.push(
|
|
1487
|
+
issue2(
|
|
1488
|
+
"MISSING_ONTOLOGY_EDGE_LABEL",
|
|
1489
|
+
"edge extension label is required",
|
|
1490
|
+
`${edgePath}.label`,
|
|
1491
|
+
"ontology-extension"
|
|
1492
|
+
)
|
|
1493
|
+
);
|
|
1494
|
+
}
|
|
1495
|
+
if (edgeType.constraintSeverity && !ONTOLOGY_CONSTRAINT_SEVERITIES.has(edgeType.constraintSeverity)) {
|
|
1496
|
+
issues.push(
|
|
1497
|
+
issue2(
|
|
1498
|
+
"INVALID_ONTOLOGY_EDGE_SEVERITY",
|
|
1499
|
+
`Unsupported constraint severity "${edgeType.constraintSeverity}"`,
|
|
1500
|
+
`${edgePath}.constraintSeverity`,
|
|
1501
|
+
"ontology-extension"
|
|
1502
|
+
)
|
|
1503
|
+
);
|
|
1504
|
+
}
|
|
1505
|
+
});
|
|
1506
|
+
});
|
|
1507
|
+
return issues;
|
|
1508
|
+
}
|
|
1509
|
+
function validateLineage(lineage, packId) {
|
|
1510
|
+
const issues = [];
|
|
1511
|
+
if (!LINEAGE_MODES.has(lineage.mode)) {
|
|
1512
|
+
issues.push(
|
|
1513
|
+
issue2(
|
|
1514
|
+
"INVALID_LINEAGE_MODE",
|
|
1515
|
+
`Unsupported lineage mode "${lineage.mode}"`,
|
|
1516
|
+
"lineage.mode",
|
|
1517
|
+
"lineage"
|
|
1518
|
+
)
|
|
1519
|
+
);
|
|
1520
|
+
return issues;
|
|
1521
|
+
}
|
|
1522
|
+
if (lineage.mode === "root") {
|
|
1523
|
+
if (lineage.parentPackId || lineage.parentVersion || lineage.supersedesPackId) {
|
|
1524
|
+
issues.push(
|
|
1525
|
+
issue2(
|
|
1526
|
+
"ROOT_LINEAGE_HAS_PARENT",
|
|
1527
|
+
"root lineage cannot declare parent or supersedes metadata",
|
|
1528
|
+
"lineage",
|
|
1529
|
+
"lineage"
|
|
1530
|
+
)
|
|
1531
|
+
);
|
|
1532
|
+
}
|
|
1533
|
+
return issues;
|
|
1534
|
+
}
|
|
1535
|
+
if (!lineage.parentPackId) {
|
|
1536
|
+
issues.push(
|
|
1537
|
+
issue2(
|
|
1538
|
+
"MISSING_LINEAGE_PARENT_PACK",
|
|
1539
|
+
"parentPackId is required for remix or fork lineage",
|
|
1540
|
+
"lineage.parentPackId",
|
|
1541
|
+
"lineage"
|
|
1542
|
+
)
|
|
1543
|
+
);
|
|
1544
|
+
} else if (!KEBAB_CASE2.test(lineage.parentPackId)) {
|
|
1545
|
+
issues.push(
|
|
1546
|
+
issue2(
|
|
1547
|
+
"INVALID_LINEAGE_PARENT_PACK",
|
|
1548
|
+
`parentPackId "${lineage.parentPackId}" must be kebab-case`,
|
|
1549
|
+
"lineage.parentPackId",
|
|
1550
|
+
"lineage"
|
|
1551
|
+
)
|
|
1552
|
+
);
|
|
1553
|
+
}
|
|
1554
|
+
if (!lineage.parentVersion) {
|
|
1555
|
+
issues.push(
|
|
1556
|
+
issue2(
|
|
1557
|
+
"MISSING_LINEAGE_PARENT_VERSION",
|
|
1558
|
+
"parentVersion is required for remix or fork lineage",
|
|
1559
|
+
"lineage.parentVersion",
|
|
1560
|
+
"lineage"
|
|
1561
|
+
)
|
|
1562
|
+
);
|
|
1563
|
+
} else if (!SEMVER2.test(lineage.parentVersion)) {
|
|
1564
|
+
issues.push(
|
|
1565
|
+
issue2(
|
|
1566
|
+
"INVALID_LINEAGE_PARENT_VERSION",
|
|
1567
|
+
`parentVersion "${lineage.parentVersion}" must be valid semver`,
|
|
1568
|
+
"lineage.parentVersion",
|
|
1569
|
+
"lineage"
|
|
1570
|
+
)
|
|
1571
|
+
);
|
|
1572
|
+
}
|
|
1573
|
+
if (lineage.parentPackId && lineage.parentPackId === packId && lineage.parentVersion === void 0) {
|
|
1574
|
+
issues.push(
|
|
1575
|
+
issue2(
|
|
1576
|
+
"SELF_REFERENTIAL_LINEAGE",
|
|
1577
|
+
"lineage parentPackId cannot equal the child packId without an explicit parentVersion",
|
|
1578
|
+
"lineage.parentPackId",
|
|
1579
|
+
"lineage"
|
|
1580
|
+
)
|
|
1581
|
+
);
|
|
1582
|
+
}
|
|
1583
|
+
if (lineage.mode === "remix" && lineage.supersedesPackId) {
|
|
1584
|
+
issues.push(
|
|
1585
|
+
issue2(
|
|
1586
|
+
"REMIX_LINEAGE_SUPERSEDES",
|
|
1587
|
+
"remix lineage cannot declare supersedesPackId",
|
|
1588
|
+
"lineage.supersedesPackId",
|
|
1589
|
+
"lineage"
|
|
1590
|
+
)
|
|
1591
|
+
);
|
|
1592
|
+
}
|
|
1593
|
+
if (lineage.mode === "fork") {
|
|
1594
|
+
if (!lineage.supersedesPackId) {
|
|
1595
|
+
issues.push(
|
|
1596
|
+
issue2(
|
|
1597
|
+
"MISSING_SUPERSEDES_PACK",
|
|
1598
|
+
"fork lineage requires supersedesPackId to model the supersedes edge",
|
|
1599
|
+
"lineage.supersedesPackId",
|
|
1600
|
+
"lineage"
|
|
1601
|
+
)
|
|
1602
|
+
);
|
|
1603
|
+
} else if (!KEBAB_CASE2.test(lineage.supersedesPackId)) {
|
|
1604
|
+
issues.push(
|
|
1605
|
+
issue2(
|
|
1606
|
+
"INVALID_SUPERSEDES_PACK",
|
|
1607
|
+
`supersedesPackId "${lineage.supersedesPackId}" must be kebab-case`,
|
|
1608
|
+
"lineage.supersedesPackId",
|
|
1609
|
+
"lineage"
|
|
1610
|
+
)
|
|
1611
|
+
);
|
|
1612
|
+
}
|
|
1613
|
+
}
|
|
1614
|
+
return issues;
|
|
1615
|
+
}
|
|
1616
|
+
function scanLegacyPublicKeys(value, path = "") {
|
|
1617
|
+
const issues = [];
|
|
1618
|
+
if (Array.isArray(value)) {
|
|
1619
|
+
value.forEach((entry, index) => {
|
|
1620
|
+
issues.push(...scanLegacyPublicKeys(entry, `${path}[${index}]`));
|
|
1621
|
+
});
|
|
1622
|
+
return issues;
|
|
1623
|
+
}
|
|
1624
|
+
if (!isPlainObject(value)) {
|
|
1625
|
+
return issues;
|
|
1626
|
+
}
|
|
1627
|
+
Object.entries(value).forEach(([key, entryValue]) => {
|
|
1628
|
+
const nextPath = path ? `${path}.${key}` : key;
|
|
1629
|
+
if (LEGACY_PUBLIC_KEYS.has(key)) {
|
|
1630
|
+
issues.push(
|
|
1631
|
+
issue2(
|
|
1632
|
+
"LEGACY_PUBLIC_TERM",
|
|
1633
|
+
`Public manifest field "${key}" uses legacy terminology; expose canonical topic/worktree terms instead.`,
|
|
1634
|
+
nextPath,
|
|
1635
|
+
"terminology"
|
|
1636
|
+
)
|
|
1637
|
+
);
|
|
1638
|
+
}
|
|
1639
|
+
issues.push(...scanLegacyPublicKeys(entryValue, nextPath));
|
|
1640
|
+
});
|
|
1641
|
+
return issues;
|
|
1642
|
+
}
|
|
1643
|
+
function createManifestDigest(manifest) {
|
|
1644
|
+
const data = serializeDomainPackAuthoringManifest(manifest, "json");
|
|
1645
|
+
let h1 = 2166136261 | 0;
|
|
1646
|
+
let h2 = 2166136261 | 0;
|
|
1647
|
+
for (let i = 0; i < data.length; i++) {
|
|
1648
|
+
const c = data.charCodeAt(i);
|
|
1649
|
+
h1 = Math.imul(h1 ^ c, 16777619);
|
|
1650
|
+
h2 = Math.imul(h2 ^ (c >>> 4 | c << 4), 16777619);
|
|
1651
|
+
}
|
|
1652
|
+
return (h1 >>> 0).toString(16).padStart(8, "0") + (h2 >>> 0).toString(16).padStart(8, "0");
|
|
1653
|
+
}
|
|
1654
|
+
function evaluateDomainPackAuthoringManifest(manifest, format = null) {
|
|
1655
|
+
const issues = [];
|
|
1656
|
+
if (manifest.kind !== DOMAIN_PACK_MANIFEST_KIND) {
|
|
1657
|
+
issues.push(
|
|
1658
|
+
issue2(
|
|
1659
|
+
"INVALID_MANIFEST_KIND",
|
|
1660
|
+
`kind must be "${DOMAIN_PACK_MANIFEST_KIND}"`,
|
|
1661
|
+
"kind",
|
|
1662
|
+
"manifest"
|
|
1663
|
+
)
|
|
1664
|
+
);
|
|
1665
|
+
}
|
|
1666
|
+
if (!SEMVER2.test(manifest.manifestVersion)) {
|
|
1667
|
+
issues.push(
|
|
1668
|
+
issue2(
|
|
1669
|
+
"INVALID_MANIFEST_VERSION",
|
|
1670
|
+
`manifestVersion "${manifest.manifestVersion}" must be valid semver`,
|
|
1671
|
+
"manifestVersion",
|
|
1672
|
+
"manifest"
|
|
1673
|
+
)
|
|
1674
|
+
);
|
|
1675
|
+
}
|
|
1676
|
+
issues.push(...validateFrameworks(manifest.frameworks));
|
|
1677
|
+
issues.push(...validateSchemaExtensions(manifest.schemaExtensions));
|
|
1678
|
+
issues.push(...validateOntologyExtensions(manifest.ontologyExtensions));
|
|
1679
|
+
issues.push(...validateLineage(manifest.lineage, manifest.pack.packId));
|
|
1680
|
+
issues.push(...scanLegacyPublicKeys(manifest));
|
|
1681
|
+
const packValidation = validateDomainPack(manifest.pack);
|
|
1682
|
+
issues.push(
|
|
1683
|
+
...packValidation.issues.map((packIssue) => ({
|
|
1684
|
+
...packIssue,
|
|
1685
|
+
path: `pack.${packIssue.path}`,
|
|
1686
|
+
source: "pack"
|
|
1687
|
+
}))
|
|
1688
|
+
);
|
|
1689
|
+
return {
|
|
1690
|
+
valid: issues.every((currentIssue) => currentIssue.severity !== "error"),
|
|
1691
|
+
format,
|
|
1692
|
+
manifest,
|
|
1693
|
+
manifestDigest: createManifestDigest(manifest),
|
|
1694
|
+
issues,
|
|
1695
|
+
counts: countManifestArtifacts(manifest)
|
|
1696
|
+
};
|
|
1697
|
+
}
|
|
1698
|
+
function parseFailureResult(error, format) {
|
|
1699
|
+
return {
|
|
1700
|
+
valid: false,
|
|
1701
|
+
format,
|
|
1702
|
+
manifest: null,
|
|
1703
|
+
manifestDigest: null,
|
|
1704
|
+
issues: [
|
|
1705
|
+
issue2(
|
|
1706
|
+
"PARSE_ERROR",
|
|
1707
|
+
error instanceof Error ? error.message : String(error),
|
|
1708
|
+
"manifest",
|
|
1709
|
+
"parse"
|
|
1710
|
+
)
|
|
1711
|
+
],
|
|
1712
|
+
counts: emptyCounts()
|
|
1713
|
+
};
|
|
1714
|
+
}
|
|
1715
|
+
function validateDomainPackAuthoringManifest(manifest) {
|
|
1716
|
+
return evaluateDomainPackAuthoringManifest(
|
|
1717
|
+
defineDomainPackAuthoringManifest(
|
|
1718
|
+
manifest
|
|
1719
|
+
)
|
|
1720
|
+
);
|
|
1721
|
+
}
|
|
1722
|
+
function validateDomainPackAuthoringManifestSource(source, format) {
|
|
1723
|
+
const detectedFormat = detectDomainPackManifestFormat(source, format);
|
|
1724
|
+
try {
|
|
1725
|
+
const manifest = parseDomainPackAuthoringManifest(source, detectedFormat);
|
|
1726
|
+
return evaluateDomainPackAuthoringManifest(manifest, detectedFormat);
|
|
1727
|
+
} catch (error) {
|
|
1728
|
+
return parseFailureResult(error, detectedFormat);
|
|
1729
|
+
}
|
|
1730
|
+
}
|
|
1731
|
+
function collectRuntimeTargets(manifest) {
|
|
1732
|
+
if (!manifest) {
|
|
1733
|
+
return [];
|
|
1734
|
+
}
|
|
1735
|
+
const targets = /* @__PURE__ */ new Set();
|
|
1736
|
+
manifest.frameworks?.forEach(
|
|
1737
|
+
(framework) => framework.runtimeTargets?.forEach((target) => targets.add(target))
|
|
1738
|
+
);
|
|
1739
|
+
manifest.pack.operatingSystem?.prompts?.forEach(
|
|
1740
|
+
(prompt) => prompt.runtimeTargets?.forEach((target) => targets.add(target))
|
|
1741
|
+
);
|
|
1742
|
+
manifest.pack.operatingSystem?.tools?.forEach(
|
|
1743
|
+
(tool) => tool.runtimeTargets?.forEach((target) => targets.add(target))
|
|
1744
|
+
);
|
|
1745
|
+
manifest.pack.operatingSystem?.setupAssets?.forEach(
|
|
1746
|
+
(asset) => asset.runtimeTargets?.forEach((target) => targets.add(target))
|
|
1747
|
+
);
|
|
1748
|
+
manifest.pack.operatingSystem?.installProfiles?.forEach(
|
|
1749
|
+
(profile) => targets.add(profile.runtimeTarget)
|
|
1750
|
+
);
|
|
1751
|
+
return Array.from(targets).sort();
|
|
1752
|
+
}
|
|
1753
|
+
function describeLineage(lineage) {
|
|
1754
|
+
if (!lineage) {
|
|
1755
|
+
return null;
|
|
1756
|
+
}
|
|
1757
|
+
if (lineage.mode === "root") {
|
|
1758
|
+
return "Root pack with no parent lineage.";
|
|
1759
|
+
}
|
|
1760
|
+
if (lineage.mode === "remix") {
|
|
1761
|
+
return `Remix of ${lineage.parentPackId}@${lineage.parentVersion}.`;
|
|
1762
|
+
}
|
|
1763
|
+
return `Fork of ${lineage.parentPackId}@${lineage.parentVersion} that supersedes ${lineage.supersedesPackId}.`;
|
|
1764
|
+
}
|
|
1765
|
+
function previewDomainPackAuthoringManifest(manifest) {
|
|
1766
|
+
const validation = validateDomainPackAuthoringManifest(manifest);
|
|
1767
|
+
return {
|
|
1768
|
+
...validation,
|
|
1769
|
+
readyToPublish: validation.valid,
|
|
1770
|
+
canonicalJson: validation.manifest ? serializeDomainPackAuthoringManifest(validation.manifest, "json") : null,
|
|
1771
|
+
canonicalYaml: validation.manifest ? serializeDomainPackAuthoringManifest(validation.manifest, "yaml") : null,
|
|
1772
|
+
lineageSummary: describeLineage(validation.manifest?.lineage ?? null),
|
|
1773
|
+
requiredRuntimeTargets: collectRuntimeTargets(validation.manifest)
|
|
1774
|
+
};
|
|
1775
|
+
}
|
|
1776
|
+
function previewDomainPackAuthoringManifestSource(source, format) {
|
|
1777
|
+
const validation = validateDomainPackAuthoringManifestSource(source, format);
|
|
1778
|
+
return {
|
|
1779
|
+
...validation,
|
|
1780
|
+
readyToPublish: validation.valid,
|
|
1781
|
+
canonicalJson: validation.manifest ? serializeDomainPackAuthoringManifest(validation.manifest, "json") : null,
|
|
1782
|
+
canonicalYaml: validation.manifest ? serializeDomainPackAuthoringManifest(validation.manifest, "yaml") : null,
|
|
1783
|
+
lineageSummary: describeLineage(validation.manifest?.lineage ?? null),
|
|
1784
|
+
requiredRuntimeTargets: collectRuntimeTargets(validation.manifest)
|
|
1785
|
+
};
|
|
1786
|
+
}
|
|
1787
|
+
function buildLineageEdge(manifest) {
|
|
1788
|
+
const { lineage, pack } = manifest;
|
|
1789
|
+
if (lineage.mode === "root") {
|
|
1790
|
+
return null;
|
|
1791
|
+
}
|
|
1792
|
+
if (lineage.mode === "remix") {
|
|
1793
|
+
return {
|
|
1794
|
+
edgeType: "remixed_from",
|
|
1795
|
+
childPackId: pack.packId,
|
|
1796
|
+
parentPackId: lineage.parentPackId,
|
|
1797
|
+
parentVersion: lineage.parentVersion
|
|
1798
|
+
};
|
|
1799
|
+
}
|
|
1800
|
+
return {
|
|
1801
|
+
edgeType: "supersedes",
|
|
1802
|
+
childPackId: pack.packId,
|
|
1803
|
+
parentPackId: lineage.supersedesPackId,
|
|
1804
|
+
parentVersion: lineage.parentVersion
|
|
1805
|
+
};
|
|
1806
|
+
}
|
|
1807
|
+
function publishDomainPackAuthoringManifest(manifest) {
|
|
1808
|
+
const preview = previewDomainPackAuthoringManifest(manifest);
|
|
1809
|
+
if (!preview.readyToPublish || !preview.manifest || !preview.manifestDigest) {
|
|
1810
|
+
return {
|
|
1811
|
+
published: false,
|
|
1812
|
+
preview,
|
|
1813
|
+
publication: null
|
|
1814
|
+
};
|
|
1815
|
+
}
|
|
1816
|
+
return {
|
|
1817
|
+
published: true,
|
|
1818
|
+
preview,
|
|
1819
|
+
publication: {
|
|
1820
|
+
publicationId: `${preview.manifest.pack.packId}@${preview.manifest.pack.version}`,
|
|
1821
|
+
packId: preview.manifest.pack.packId,
|
|
1822
|
+
version: preview.manifest.pack.version,
|
|
1823
|
+
manifestDigest: preview.manifestDigest,
|
|
1824
|
+
manifest: preview.manifest,
|
|
1825
|
+
lineageEdge: buildLineageEdge(preview.manifest),
|
|
1826
|
+
canonicalJson: preview.canonicalJson,
|
|
1827
|
+
canonicalYaml: preview.canonicalYaml
|
|
1828
|
+
}
|
|
1829
|
+
};
|
|
1830
|
+
}
|
|
1831
|
+
function publishDomainPackAuthoringManifestSource(source, format) {
|
|
1832
|
+
const preview = previewDomainPackAuthoringManifestSource(source, format);
|
|
1833
|
+
if (!preview.readyToPublish || !preview.manifest || !preview.manifestDigest) {
|
|
1834
|
+
return {
|
|
1835
|
+
published: false,
|
|
1836
|
+
preview,
|
|
1837
|
+
publication: null
|
|
1838
|
+
};
|
|
1839
|
+
}
|
|
1840
|
+
return {
|
|
1841
|
+
published: true,
|
|
1842
|
+
preview,
|
|
1843
|
+
publication: {
|
|
1844
|
+
publicationId: `${preview.manifest.pack.packId}@${preview.manifest.pack.version}`,
|
|
1845
|
+
packId: preview.manifest.pack.packId,
|
|
1846
|
+
version: preview.manifest.pack.version,
|
|
1847
|
+
manifestDigest: preview.manifestDigest,
|
|
1848
|
+
manifest: preview.manifest,
|
|
1849
|
+
lineageEdge: buildLineageEdge(preview.manifest),
|
|
1850
|
+
canonicalJson: preview.canonicalJson,
|
|
1851
|
+
canonicalYaml: preview.canonicalYaml
|
|
1852
|
+
}
|
|
1853
|
+
};
|
|
1854
|
+
}
|
|
1855
|
+
function createDomainPackAuthoringTools() {
|
|
1856
|
+
const inputSchema = {
|
|
1857
|
+
type: "object",
|
|
1858
|
+
properties: {
|
|
1859
|
+
manifestText: {
|
|
1860
|
+
type: "string",
|
|
1861
|
+
description: "Domain pack manifest text in JSON or YAML form."
|
|
1862
|
+
},
|
|
1863
|
+
format: {
|
|
1864
|
+
type: "string",
|
|
1865
|
+
enum: ["json", "yaml"],
|
|
1866
|
+
description: "Optional manifest format override."
|
|
1867
|
+
}
|
|
1868
|
+
},
|
|
1869
|
+
required: ["manifestText"],
|
|
1870
|
+
additionalProperties: false
|
|
1871
|
+
};
|
|
1872
|
+
return {
|
|
1873
|
+
validate: {
|
|
1874
|
+
name: AUTHORING_TOOL_NAMES.validate,
|
|
1875
|
+
description: "Validate a domain pack authoring manifest and return structural, lineage, terminology, and extension issues.",
|
|
1876
|
+
inputSchema,
|
|
1877
|
+
execute: (args) => validateDomainPackAuthoringManifestSource(args.manifestText, args.format)
|
|
1878
|
+
},
|
|
1879
|
+
preview: {
|
|
1880
|
+
name: AUTHORING_TOOL_NAMES.preview,
|
|
1881
|
+
description: "Preview a domain pack manifest with canonical JSON/YAML renderings, runtime targets, and publication readiness.",
|
|
1882
|
+
inputSchema,
|
|
1883
|
+
execute: (args) => previewDomainPackAuthoringManifestSource(args.manifestText, args.format)
|
|
1884
|
+
},
|
|
1885
|
+
publish: {
|
|
1886
|
+
name: AUTHORING_TOOL_NAMES.publish,
|
|
1887
|
+
description: "Build a publication-ready domain pack artifact when validation passes, including remix/fork lineage metadata.",
|
|
1888
|
+
inputSchema,
|
|
1889
|
+
execute: (args) => publishDomainPackAuthoringManifestSource(args.manifestText, args.format)
|
|
1890
|
+
}
|
|
1891
|
+
};
|
|
1892
|
+
}
|
|
1893
|
+
|
|
1894
|
+
// src/domain-pack/ontology/software-entities-v1.ts
|
|
1895
|
+
var SOFTWARE_ENTITIES_V1 = {
|
|
1896
|
+
ontologyId: "software-entities",
|
|
1897
|
+
version: "1.0.0",
|
|
1898
|
+
name: "Software Entities",
|
|
1899
|
+
description: "Core software-delivery ontology for repositories, services, modules, changes, incidents, and agent-assisted engineering workflows.",
|
|
1900
|
+
entityTypes: [
|
|
1901
|
+
{
|
|
1902
|
+
value: "repository",
|
|
1903
|
+
label: "Repository",
|
|
1904
|
+
description: "Source repository or monorepo boundary under active ownership."
|
|
1905
|
+
},
|
|
1906
|
+
{
|
|
1907
|
+
value: "service",
|
|
1908
|
+
label: "Service",
|
|
1909
|
+
description: "Deployable service, application, or runtime surface."
|
|
1910
|
+
},
|
|
1911
|
+
{
|
|
1912
|
+
value: "module",
|
|
1913
|
+
label: "Module",
|
|
1914
|
+
description: "Logical code module, package, or subsystem within a service."
|
|
1915
|
+
},
|
|
1916
|
+
{
|
|
1917
|
+
value: "workflow",
|
|
1918
|
+
label: "Workflow",
|
|
1919
|
+
description: "Repeatable engineering workflow such as review, migration, or incident response."
|
|
1920
|
+
},
|
|
1921
|
+
{
|
|
1922
|
+
value: "migration",
|
|
1923
|
+
label: "Migration",
|
|
1924
|
+
description: "Schema, API, or rollout change with sequencing and rollback concerns."
|
|
1925
|
+
},
|
|
1926
|
+
{
|
|
1927
|
+
value: "incident",
|
|
1928
|
+
label: "Incident",
|
|
1929
|
+
description: "Operational incident, outage, or regression requiring triage and mitigation."
|
|
1930
|
+
},
|
|
1931
|
+
{
|
|
1932
|
+
value: "decision_record",
|
|
1933
|
+
label: "Decision Record",
|
|
1934
|
+
description: "Architecture decision, rationale record, or precedent artifact."
|
|
1935
|
+
},
|
|
1936
|
+
{
|
|
1937
|
+
value: "agent",
|
|
1938
|
+
label: "Agent",
|
|
1939
|
+
description: "Configured AI worker or assistant participating in engineering workflows."
|
|
1940
|
+
}
|
|
1941
|
+
],
|
|
1942
|
+
edgeTypes: [
|
|
1943
|
+
{
|
|
1944
|
+
value: "depends_on",
|
|
1945
|
+
label: "Depends On",
|
|
1946
|
+
description: "A repository, service, module, or workflow depends on another surface.",
|
|
1947
|
+
sourceTypes: ["repository", "service", "module", "workflow", "migration"],
|
|
1948
|
+
targetTypes: ["repository", "service", "module", "workflow", "migration"]
|
|
1949
|
+
},
|
|
1950
|
+
{
|
|
1951
|
+
value: "owns",
|
|
1952
|
+
label: "Owns",
|
|
1953
|
+
description: "An agent or service owns a module, workflow, or decision record.",
|
|
1954
|
+
sourceTypes: ["agent", "service"],
|
|
1955
|
+
targetTypes: ["module", "workflow", "decision_record"]
|
|
1956
|
+
},
|
|
1957
|
+
{
|
|
1958
|
+
value: "calls",
|
|
1959
|
+
label: "Calls",
|
|
1960
|
+
description: "A repository, service, or module invokes another service or module.",
|
|
1961
|
+
sourceTypes: ["repository", "service", "module"],
|
|
1962
|
+
targetTypes: ["service", "module"]
|
|
1963
|
+
},
|
|
1964
|
+
{
|
|
1965
|
+
value: "blocks",
|
|
1966
|
+
label: "Blocks",
|
|
1967
|
+
description: "An incident, migration, or workflow blocks another engineering surface.",
|
|
1968
|
+
sourceTypes: ["incident", "migration", "workflow"],
|
|
1969
|
+
targetTypes: ["migration", "workflow", "service", "decision_record"]
|
|
1970
|
+
},
|
|
1971
|
+
{
|
|
1972
|
+
value: "reviews",
|
|
1973
|
+
label: "Reviews",
|
|
1974
|
+
description: "An agent or workflow reviews a change, module, or migration.",
|
|
1975
|
+
sourceTypes: ["agent", "workflow"],
|
|
1976
|
+
targetTypes: ["module", "migration", "decision_record"]
|
|
1977
|
+
},
|
|
1978
|
+
{
|
|
1979
|
+
value: "mitigates",
|
|
1980
|
+
label: "Mitigates",
|
|
1981
|
+
description: "A workflow or migration mitigates an incident or risky change.",
|
|
1982
|
+
sourceTypes: ["workflow", "migration"],
|
|
1983
|
+
targetTypes: ["incident", "service", "module"]
|
|
1984
|
+
},
|
|
1985
|
+
{
|
|
1986
|
+
value: "supersedes",
|
|
1987
|
+
label: "Supersedes",
|
|
1988
|
+
description: "A newer decision record, migration, or workflow replaces an earlier one.",
|
|
1989
|
+
sourceTypes: ["decision_record", "migration", "workflow"],
|
|
1990
|
+
targetTypes: ["decision_record", "migration", "workflow"]
|
|
1991
|
+
}
|
|
1992
|
+
]
|
|
1993
|
+
};
|
|
1994
|
+
|
|
1995
|
+
// src/domain-pack/shaping.ts
|
|
1996
|
+
var QUESTION_PRIORITY_WEIGHT = {
|
|
1997
|
+
critical: 0.12,
|
|
1998
|
+
high: 0.08,
|
|
1999
|
+
medium: 0.04,
|
|
2000
|
+
low: 0.01
|
|
2001
|
+
};
|
|
2002
|
+
var TASK_PRIORITY_WEIGHT = {
|
|
2003
|
+
urgent: 0.12,
|
|
2004
|
+
high: 0.08,
|
|
2005
|
+
medium: 0.04,
|
|
2006
|
+
low: 0.01
|
|
2007
|
+
};
|
|
2008
|
+
function dedupeStrings3(values) {
|
|
2009
|
+
if (!values || values.length === 0) {
|
|
2010
|
+
return void 0;
|
|
2011
|
+
}
|
|
2012
|
+
const normalized = values.map((value) => value.trim()).filter(Boolean);
|
|
2013
|
+
return normalized.length > 0 ? Array.from(new Set(normalized)) : void 0;
|
|
2014
|
+
}
|
|
2015
|
+
function toKebabCase(value) {
|
|
2016
|
+
return value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
2017
|
+
}
|
|
2018
|
+
function normalizeCondition(args) {
|
|
2019
|
+
return {
|
|
2020
|
+
...dedupeStrings3(args.objectiveIncludes) ? { objectiveIncludes: dedupeStrings3(args.objectiveIncludes) } : {},
|
|
2021
|
+
...dedupeStrings3(args.questionTypes) ? { questionTypes: dedupeStrings3(args.questionTypes) } : {}
|
|
2022
|
+
};
|
|
2023
|
+
}
|
|
2024
|
+
function normalizeQuestionType(questionType) {
|
|
2025
|
+
return questionType === "scope" ? "clarification" : questionType;
|
|
2026
|
+
}
|
|
2027
|
+
function questionTemplateToContribution(packId, template) {
|
|
2028
|
+
return {
|
|
2029
|
+
sourcePackId: packId,
|
|
2030
|
+
templateId: template.templateId,
|
|
2031
|
+
questionType: normalizeQuestionType(template.questionType),
|
|
2032
|
+
priority: template.priority,
|
|
2033
|
+
priorityWeight: QUESTION_PRIORITY_WEIGHT[template.priority || "medium"],
|
|
2034
|
+
template: template.template,
|
|
2035
|
+
condition: normalizeCondition({
|
|
2036
|
+
objectiveIncludes: template.whenObjectiveIncludes
|
|
2037
|
+
})
|
|
2038
|
+
};
|
|
2039
|
+
}
|
|
2040
|
+
function taskTemplateToContribution(packId, template) {
|
|
2041
|
+
return {
|
|
2042
|
+
sourcePackId: packId,
|
|
2043
|
+
generatorId: template.templateId,
|
|
2044
|
+
title: template.title,
|
|
2045
|
+
description: template.description,
|
|
2046
|
+
taskType: template.taskType,
|
|
2047
|
+
priority: template.priority,
|
|
2048
|
+
priorityWeight: TASK_PRIORITY_WEIGHT[template.priority || "medium"],
|
|
2049
|
+
condition: normalizeCondition({
|
|
2050
|
+
objectiveIncludes: template.whenObjectiveIncludes,
|
|
2051
|
+
questionTypes: template.whenQuestionTypes
|
|
2052
|
+
})
|
|
2053
|
+
};
|
|
2054
|
+
}
|
|
2055
|
+
function frameworkHintToContribution(packId, hint) {
|
|
2056
|
+
const hookId = `${packId}:${toKebabCase(hint.frameworkName || "framework")}`;
|
|
2057
|
+
return {
|
|
2058
|
+
sourcePackId: packId,
|
|
2059
|
+
hookId,
|
|
2060
|
+
frameworkName: hint.frameworkName,
|
|
2061
|
+
boost: hint.boost || 0,
|
|
2062
|
+
reason: hint.reason,
|
|
2063
|
+
priorityWeight: Math.max(0.02, hint.boost || 0),
|
|
2064
|
+
condition: normalizeCondition({
|
|
2065
|
+
objectiveIncludes: hint.whenObjectiveIncludes,
|
|
2066
|
+
questionTypes: hint.whenQuestionTypes
|
|
2067
|
+
})
|
|
2068
|
+
};
|
|
2069
|
+
}
|
|
2070
|
+
function issue3(code, message, path, severity = "error") {
|
|
2071
|
+
return { code, message, path, severity };
|
|
2072
|
+
}
|
|
2073
|
+
function checkDuplicateIds2(items, idField, path) {
|
|
2074
|
+
const issues = [];
|
|
2075
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2076
|
+
for (const item of items) {
|
|
2077
|
+
const id = item[idField];
|
|
2078
|
+
if (!id) {
|
|
2079
|
+
continue;
|
|
2080
|
+
}
|
|
2081
|
+
if (seen.has(id)) {
|
|
2082
|
+
issues.push(
|
|
2083
|
+
issue3("DUPLICATE_ID", `Duplicate ${idField} "${id}"`, `${path}.${idField}`)
|
|
2084
|
+
);
|
|
2085
|
+
}
|
|
2086
|
+
seen.add(id);
|
|
2087
|
+
}
|
|
2088
|
+
return issues;
|
|
2089
|
+
}
|
|
2090
|
+
function formatRegistrationIssues(packId, issues) {
|
|
2091
|
+
return `Invalid shaping contribution registration for ${packId}: ${issues.map((item) => `${item.code} at ${item.path}`).join("; ")}`;
|
|
2092
|
+
}
|
|
2093
|
+
function buildShapingContribution(pack) {
|
|
2094
|
+
const inquiryShaping = pack.inquiryShaping || {};
|
|
2095
|
+
return {
|
|
2096
|
+
packId: pack.packId,
|
|
2097
|
+
questionTemplates: (inquiryShaping.questionTemplates || []).map(
|
|
2098
|
+
(template) => questionTemplateToContribution(pack.packId, template)
|
|
2099
|
+
),
|
|
2100
|
+
taskGenerators: (inquiryShaping.taskTemplates || []).map(
|
|
2101
|
+
(template) => taskTemplateToContribution(pack.packId, template)
|
|
2102
|
+
),
|
|
2103
|
+
frameworkHooks: (inquiryShaping.frameworkHints || []).map(
|
|
2104
|
+
(hint) => frameworkHintToContribution(pack.packId, hint)
|
|
2105
|
+
)
|
|
2106
|
+
};
|
|
2107
|
+
}
|
|
2108
|
+
function validateShapingContribution(contribution) {
|
|
2109
|
+
const issues = [];
|
|
2110
|
+
if (!contribution.packId?.trim()) {
|
|
2111
|
+
issues.push(issue3("MISSING_PACK_ID", "packId is required", "packId"));
|
|
2112
|
+
}
|
|
2113
|
+
issues.push(
|
|
2114
|
+
...checkDuplicateIds2(
|
|
2115
|
+
contribution.questionTemplates,
|
|
2116
|
+
"templateId",
|
|
2117
|
+
"questionTemplates"
|
|
2118
|
+
)
|
|
2119
|
+
);
|
|
2120
|
+
issues.push(
|
|
2121
|
+
...checkDuplicateIds2(
|
|
2122
|
+
contribution.taskGenerators,
|
|
2123
|
+
"generatorId",
|
|
2124
|
+
"taskGenerators"
|
|
2125
|
+
)
|
|
2126
|
+
);
|
|
2127
|
+
issues.push(
|
|
2128
|
+
...checkDuplicateIds2(
|
|
2129
|
+
contribution.frameworkHooks,
|
|
2130
|
+
"hookId",
|
|
2131
|
+
"frameworkHooks"
|
|
2132
|
+
)
|
|
2133
|
+
);
|
|
2134
|
+
contribution.questionTemplates.forEach((template, index) => {
|
|
2135
|
+
if (!template.templateId?.trim()) {
|
|
2136
|
+
issues.push(
|
|
2137
|
+
issue3(
|
|
2138
|
+
"MISSING_TEMPLATE_ID",
|
|
2139
|
+
"Question template requires templateId",
|
|
2140
|
+
`questionTemplates[${index}].templateId`
|
|
2141
|
+
)
|
|
2142
|
+
);
|
|
2143
|
+
}
|
|
2144
|
+
if (!template.template?.trim()) {
|
|
2145
|
+
issues.push(
|
|
2146
|
+
issue3(
|
|
2147
|
+
"MISSING_TEMPLATE",
|
|
2148
|
+
"Question template requires template text",
|
|
2149
|
+
`questionTemplates[${index}].template`
|
|
2150
|
+
)
|
|
2151
|
+
);
|
|
2152
|
+
}
|
|
2153
|
+
});
|
|
2154
|
+
contribution.taskGenerators.forEach((generator, index) => {
|
|
2155
|
+
if (!generator.generatorId?.trim()) {
|
|
2156
|
+
issues.push(
|
|
2157
|
+
issue3(
|
|
2158
|
+
"MISSING_GENERATOR_ID",
|
|
2159
|
+
"Task generator requires generatorId",
|
|
2160
|
+
`taskGenerators[${index}].generatorId`
|
|
2161
|
+
)
|
|
2162
|
+
);
|
|
2163
|
+
}
|
|
2164
|
+
if (!generator.title?.trim()) {
|
|
2165
|
+
issues.push(
|
|
2166
|
+
issue3(
|
|
2167
|
+
"MISSING_TASK_TITLE",
|
|
2168
|
+
"Task generator requires title",
|
|
2169
|
+
`taskGenerators[${index}].title`
|
|
2170
|
+
)
|
|
2171
|
+
);
|
|
2172
|
+
}
|
|
2173
|
+
});
|
|
2174
|
+
contribution.frameworkHooks.forEach((hook, index) => {
|
|
2175
|
+
if (!hook.frameworkName?.trim()) {
|
|
2176
|
+
issues.push(
|
|
2177
|
+
issue3(
|
|
2178
|
+
"MISSING_FRAMEWORK_NAME",
|
|
2179
|
+
"Framework hook requires frameworkName",
|
|
2180
|
+
`frameworkHooks[${index}].frameworkName`
|
|
2181
|
+
)
|
|
2182
|
+
);
|
|
2183
|
+
}
|
|
2184
|
+
if (!Number.isFinite(hook.boost) || hook.boost < 0) {
|
|
2185
|
+
issues.push(
|
|
2186
|
+
issue3(
|
|
2187
|
+
"INVALID_FRAMEWORK_BOOST",
|
|
2188
|
+
"Framework hook boost must be a non-negative number",
|
|
2189
|
+
`frameworkHooks[${index}].boost`
|
|
2190
|
+
)
|
|
2191
|
+
);
|
|
2192
|
+
}
|
|
2193
|
+
});
|
|
2194
|
+
return {
|
|
2195
|
+
valid: issues.every((item) => item.severity !== "error"),
|
|
2196
|
+
issues
|
|
2197
|
+
};
|
|
2198
|
+
}
|
|
2199
|
+
function createShapingContributionRegistry(packs = []) {
|
|
2200
|
+
const registry = /* @__PURE__ */ new Map();
|
|
2201
|
+
const register = (pack) => {
|
|
2202
|
+
if (registry.has(pack.packId)) {
|
|
2203
|
+
throw new Error(
|
|
2204
|
+
`Duplicate shaping contribution registration for ${pack.packId}`
|
|
2205
|
+
);
|
|
2206
|
+
}
|
|
2207
|
+
const packValidation = validateDomainPack(pack);
|
|
2208
|
+
if (!packValidation.valid) {
|
|
2209
|
+
throw new Error(formatRegistrationIssues(pack.packId, packValidation.issues));
|
|
2210
|
+
}
|
|
2211
|
+
const contribution = buildShapingContribution(pack);
|
|
2212
|
+
const contributionValidation = validateShapingContribution(contribution);
|
|
2213
|
+
if (!contributionValidation.valid) {
|
|
2214
|
+
throw new Error(
|
|
2215
|
+
formatRegistrationIssues(pack.packId, contributionValidation.issues)
|
|
2216
|
+
);
|
|
2217
|
+
}
|
|
2218
|
+
registry.set(pack.packId, contribution);
|
|
2219
|
+
return contribution;
|
|
2220
|
+
};
|
|
2221
|
+
packs.forEach(register);
|
|
2222
|
+
return {
|
|
2223
|
+
register,
|
|
2224
|
+
get(packId) {
|
|
2225
|
+
return registry.get(packId) ?? null;
|
|
2226
|
+
},
|
|
2227
|
+
list() {
|
|
2228
|
+
return Array.from(registry.keys());
|
|
2229
|
+
}
|
|
2230
|
+
};
|
|
2231
|
+
}
|
|
2232
|
+
|
|
2233
|
+
// src/domain-pack/packs/developer-reasoning.ts
|
|
2234
|
+
var DEVELOPER_REASONING_PACK = defineDomainPack({
|
|
2235
|
+
packId: "developer-reasoning",
|
|
2236
|
+
name: "Developer Reasoning",
|
|
2237
|
+
version: "1.0.0",
|
|
2238
|
+
ontologyBindings: [
|
|
2239
|
+
{
|
|
2240
|
+
ontologyId: "software-entities",
|
|
2241
|
+
versionConstraint: "^1.0.0",
|
|
2242
|
+
required: true
|
|
2243
|
+
}
|
|
2244
|
+
],
|
|
2245
|
+
topicRoots: [
|
|
2246
|
+
{
|
|
2247
|
+
slug: "architecture",
|
|
2248
|
+
name: "Architecture",
|
|
2249
|
+
description: "System architecture decisions and trade-offs",
|
|
2250
|
+
ontologyId: "software-entities"
|
|
2251
|
+
},
|
|
2252
|
+
{
|
|
2253
|
+
slug: "implementation",
|
|
2254
|
+
name: "Implementation",
|
|
2255
|
+
description: "Active implementation work and worktrees",
|
|
2256
|
+
ontologyId: "software-entities"
|
|
2257
|
+
},
|
|
2258
|
+
{
|
|
2259
|
+
slug: "operations",
|
|
2260
|
+
name: "Operations",
|
|
2261
|
+
description: "Deployment, observability, and operational concerns"
|
|
2262
|
+
}
|
|
2263
|
+
],
|
|
2264
|
+
workflows: [
|
|
2265
|
+
{
|
|
2266
|
+
workflowId: "worktree-lifecycle",
|
|
2267
|
+
name: "Worktree Lifecycle",
|
|
2268
|
+
description: "Structured development cycle from scoping through implementation and review",
|
|
2269
|
+
steps: [
|
|
2270
|
+
{
|
|
2271
|
+
stepId: "scope",
|
|
2272
|
+
name: "Scope & Context",
|
|
2273
|
+
description: "Read graph context, identify constraints and prior decisions",
|
|
2274
|
+
requiredRoles: ["investigator"],
|
|
2275
|
+
produces: ["scope-artifact"]
|
|
2276
|
+
},
|
|
2277
|
+
{
|
|
2278
|
+
stepId: "plan",
|
|
2279
|
+
name: "Plan",
|
|
2280
|
+
description: "Design implementation approach informed by graph beliefs",
|
|
2281
|
+
requiredRoles: ["investigator", "critic"],
|
|
2282
|
+
produces: ["plan-artifact"],
|
|
2283
|
+
gateId: "plan-reviewed"
|
|
2284
|
+
},
|
|
2285
|
+
{
|
|
2286
|
+
stepId: "build",
|
|
2287
|
+
name: "Build",
|
|
2288
|
+
description: "Implement with in-flight graph writeback",
|
|
2289
|
+
requiredRoles: ["implementer"],
|
|
2290
|
+
produces: ["implementation-artifact"]
|
|
2291
|
+
},
|
|
2292
|
+
{
|
|
2293
|
+
stepId: "review",
|
|
2294
|
+
name: "Review",
|
|
2295
|
+
description: "Validate implementation against plan, tests, and type safety",
|
|
2296
|
+
requiredRoles: ["critic"],
|
|
2297
|
+
produces: ["review-artifact"],
|
|
2298
|
+
gateId: "review-passed"
|
|
2299
|
+
}
|
|
2300
|
+
],
|
|
2301
|
+
requiredArtifacts: ["scope-artifact", "implementation-artifact"],
|
|
2302
|
+
gateCheckpoints: ["plan-reviewed", "review-passed"]
|
|
2303
|
+
}
|
|
2304
|
+
],
|
|
2305
|
+
gates: [
|
|
2306
|
+
{
|
|
2307
|
+
gateId: "plan-reviewed",
|
|
2308
|
+
name: "Plan Reviewed",
|
|
2309
|
+
description: "Implementation plan has been reviewed for feasibility",
|
|
2310
|
+
criteria: [
|
|
2311
|
+
{
|
|
2312
|
+
criterionId: "constraints-checked",
|
|
2313
|
+
description: "Plan respects high-credence beliefs (>= 0.90) as constraints",
|
|
2314
|
+
metric: "constraint_violations",
|
|
2315
|
+
threshold: 0,
|
|
2316
|
+
operator: "eq"
|
|
2317
|
+
},
|
|
2318
|
+
{
|
|
2319
|
+
criterionId: "scope-bounded",
|
|
2320
|
+
description: "Plan stays within declared file and concern scope",
|
|
2321
|
+
metric: "scope_bounded",
|
|
2322
|
+
threshold: 1,
|
|
2323
|
+
operator: "eq"
|
|
2324
|
+
}
|
|
2325
|
+
],
|
|
2326
|
+
severity: "blocking"
|
|
2327
|
+
},
|
|
2328
|
+
{
|
|
2329
|
+
gateId: "review-passed",
|
|
2330
|
+
name: "Review Passed",
|
|
2331
|
+
description: "Implementation passes type checks, tests, and review",
|
|
2332
|
+
criteria: [
|
|
2333
|
+
{
|
|
2334
|
+
criterionId: "types-clean",
|
|
2335
|
+
description: "TypeScript check passes (npx tsc --noEmit)",
|
|
2336
|
+
metric: "tsc_errors",
|
|
2337
|
+
threshold: 0,
|
|
2338
|
+
operator: "eq"
|
|
2339
|
+
},
|
|
2340
|
+
{
|
|
2341
|
+
criterionId: "tests-passing",
|
|
2342
|
+
description: "All relevant tests pass",
|
|
2343
|
+
metric: "test_pass_ratio",
|
|
2344
|
+
threshold: 1,
|
|
2345
|
+
operator: "eq"
|
|
2346
|
+
}
|
|
2347
|
+
],
|
|
2348
|
+
severity: "blocking"
|
|
2349
|
+
}
|
|
2350
|
+
],
|
|
2351
|
+
artifacts: [
|
|
2352
|
+
{
|
|
2353
|
+
artifactId: "scope-artifact",
|
|
2354
|
+
name: "Scope Context",
|
|
2355
|
+
description: "Graph context summary \u2014 beliefs, questions, constraints informing this work",
|
|
2356
|
+
stage: "scope",
|
|
2357
|
+
contentSchema: {
|
|
2358
|
+
type: "object",
|
|
2359
|
+
properties: {
|
|
2360
|
+
beliefs: { type: "array", items: { type: "string" } },
|
|
2361
|
+
questions: { type: "array", items: { type: "string" } },
|
|
2362
|
+
constraints: { type: "array", items: { type: "string" } }
|
|
2363
|
+
},
|
|
2364
|
+
required: ["beliefs", "constraints"]
|
|
2365
|
+
},
|
|
2366
|
+
requiredFields: ["beliefs", "constraints"]
|
|
2367
|
+
},
|
|
2368
|
+
{
|
|
2369
|
+
artifactId: "plan-artifact",
|
|
2370
|
+
name: "Implementation Plan",
|
|
2371
|
+
description: "Files to create/modify, approach, and test strategy",
|
|
2372
|
+
stage: "plan",
|
|
2373
|
+
contentSchema: {
|
|
2374
|
+
type: "object",
|
|
2375
|
+
properties: {
|
|
2376
|
+
files: { type: "array", items: { type: "string" } },
|
|
2377
|
+
approach: { type: "string" },
|
|
2378
|
+
testStrategy: { type: "string" }
|
|
2379
|
+
},
|
|
2380
|
+
required: ["files", "approach"]
|
|
2381
|
+
},
|
|
2382
|
+
requiredFields: ["files", "approach"]
|
|
2383
|
+
},
|
|
2384
|
+
{
|
|
2385
|
+
artifactId: "implementation-artifact",
|
|
2386
|
+
name: "Implementation Summary",
|
|
2387
|
+
description: "What was built, files changed, decisions made",
|
|
2388
|
+
stage: "build",
|
|
2389
|
+
contentSchema: {
|
|
2390
|
+
type: "object",
|
|
2391
|
+
properties: {
|
|
2392
|
+
filesChanged: { type: "array", items: { type: "string" } },
|
|
2393
|
+
decisions: { type: "array", items: { type: "string" } },
|
|
2394
|
+
deferredWork: { type: "array", items: { type: "string" } }
|
|
2395
|
+
},
|
|
2396
|
+
required: ["filesChanged"]
|
|
2397
|
+
},
|
|
2398
|
+
requiredFields: ["filesChanged"]
|
|
2399
|
+
},
|
|
2400
|
+
{
|
|
2401
|
+
artifactId: "review-artifact",
|
|
2402
|
+
name: "Review Summary",
|
|
2403
|
+
description: "Review findings, type check results, test results",
|
|
2404
|
+
stage: "review",
|
|
2405
|
+
contentSchema: {
|
|
2406
|
+
type: "object",
|
|
2407
|
+
properties: {
|
|
2408
|
+
verdict: { type: "string", enum: ["approve", "request-changes"] },
|
|
2409
|
+
findings: { type: "array", items: { type: "string" } },
|
|
2410
|
+
testsPassing: { type: "boolean" },
|
|
2411
|
+
typesClean: { type: "boolean" }
|
|
2412
|
+
},
|
|
2413
|
+
required: ["verdict", "testsPassing", "typesClean"]
|
|
2414
|
+
},
|
|
2415
|
+
requiredFields: ["verdict", "testsPassing", "typesClean"]
|
|
2416
|
+
}
|
|
2417
|
+
],
|
|
2418
|
+
roles: [
|
|
2419
|
+
{
|
|
2420
|
+
roleId: "investigator",
|
|
2421
|
+
name: "Investigator",
|
|
2422
|
+
description: "Reads graph context and identifies relevant prior knowledge",
|
|
2423
|
+
perspective: "Context-aware, evidence-driven scoping",
|
|
2424
|
+
optimizesFor: "thoroughness of context retrieval and constraint identification",
|
|
2425
|
+
mayBlock: false
|
|
2426
|
+
},
|
|
2427
|
+
{
|
|
2428
|
+
roleId: "implementer",
|
|
2429
|
+
name: "Implementer",
|
|
2430
|
+
description: "Writes code and records decisions in the graph",
|
|
2431
|
+
perspective: "Pragmatic, focused on working code within constraints",
|
|
2432
|
+
optimizesFor: "correctness and simplicity",
|
|
2433
|
+
mayBlock: false
|
|
2434
|
+
},
|
|
2435
|
+
{
|
|
2436
|
+
roleId: "critic",
|
|
2437
|
+
name: "Critic",
|
|
2438
|
+
description: "Challenges assumptions, finds edge cases, and surfaces risks",
|
|
2439
|
+
perspective: "Skeptical, detail-oriented, adversarial testing",
|
|
2440
|
+
optimizesFor: "identifying weaknesses before they reach production",
|
|
2441
|
+
mayBlock: true
|
|
2442
|
+
// Epistemic Invariant #13
|
|
2443
|
+
}
|
|
2444
|
+
],
|
|
2445
|
+
inquiryShaping: {
|
|
2446
|
+
questionTemplates: [
|
|
2447
|
+
{
|
|
2448
|
+
templateId: "developer-boundary-falsifier",
|
|
2449
|
+
questionType: "falsification",
|
|
2450
|
+
priority: "high",
|
|
2451
|
+
template: "Which interface, contract, or boundary would fail first if {{objective}} is wrong?",
|
|
2452
|
+
whenObjectiveIncludes: [
|
|
2453
|
+
"build",
|
|
2454
|
+
"implement",
|
|
2455
|
+
"refactor",
|
|
2456
|
+
"integrate",
|
|
2457
|
+
"algorithm",
|
|
2458
|
+
"handler",
|
|
2459
|
+
"workflow"
|
|
2460
|
+
]
|
|
2461
|
+
},
|
|
2462
|
+
{
|
|
2463
|
+
templateId: "developer-regression-counterfactual",
|
|
2464
|
+
questionType: "counterfactual",
|
|
2465
|
+
priority: "high",
|
|
2466
|
+
template: "What existing behavior or verification path would regress if {{hypothesis}} is false?",
|
|
2467
|
+
whenObjectiveIncludes: ["build", "implement", "add", "extend", "support"]
|
|
2468
|
+
}
|
|
2469
|
+
],
|
|
2470
|
+
taskTemplates: [
|
|
2471
|
+
{
|
|
2472
|
+
templateId: "developer-contract-audit",
|
|
2473
|
+
title: "Audit adjacent contracts and invariants for {{objective}}",
|
|
2474
|
+
description: "Inspect the existing MCP, schema, and worktree contracts that constrain {{objective}} before changing runtime behavior.",
|
|
2475
|
+
taskType: "analysis",
|
|
2476
|
+
priority: "high",
|
|
2477
|
+
whenObjectiveIncludes: ["build", "implement", "extend", "support"]
|
|
2478
|
+
},
|
|
2479
|
+
{
|
|
2480
|
+
templateId: "developer-verification-pass",
|
|
2481
|
+
title: "Run focused verification for {{objective}}",
|
|
2482
|
+
description: "Add or update targeted tests and type-safety checks that would fail if {{hypothesis}} is wrong.",
|
|
2483
|
+
taskType: "review",
|
|
2484
|
+
priority: "medium",
|
|
2485
|
+
whenObjectiveIncludes: ["build", "implement", "algorithm", "workflow"],
|
|
2486
|
+
whenQuestionTypes: ["falsification", "counterfactual"]
|
|
2487
|
+
}
|
|
2488
|
+
],
|
|
2489
|
+
frameworkHints: [
|
|
2490
|
+
{
|
|
2491
|
+
frameworkName: "Boundary Audit",
|
|
2492
|
+
whenObjectiveIncludes: ["handler", "contract", "api", "workflow"],
|
|
2493
|
+
boost: 0.25,
|
|
2494
|
+
reason: "Developer reasoning work benefits from explicit boundary checks."
|
|
2495
|
+
},
|
|
2496
|
+
{
|
|
2497
|
+
frameworkName: "Pre-mortem",
|
|
2498
|
+
whenQuestionTypes: ["falsification", "counterfactual"],
|
|
2499
|
+
boost: 0.2,
|
|
2500
|
+
reason: "Stress-testing likely failure modes improves worktree shaping quality."
|
|
2501
|
+
}
|
|
2502
|
+
]
|
|
2503
|
+
},
|
|
2504
|
+
methodologyPackId: "developer"
|
|
2505
|
+
});
|
|
2506
|
+
|
|
2507
|
+
// src/domain-pack/packs/engineering-accelerator.ts
|
|
2508
|
+
var ENGINEERING_ACCELERATOR_PACK = defineDomainPack({
|
|
2509
|
+
packId: "engineering-accelerator",
|
|
2510
|
+
name: "Engineering Accelerator",
|
|
2511
|
+
version: "1.0.0",
|
|
2512
|
+
ontologyBindings: [
|
|
2513
|
+
{
|
|
2514
|
+
ontologyId: "software-entities",
|
|
2515
|
+
versionConstraint: "^1.0.0",
|
|
2516
|
+
required: true,
|
|
2517
|
+
provisionMode: "seed",
|
|
2518
|
+
seedRef: "packages/pack-host/src/domain-pack/ontology/software-entities-v1.ts",
|
|
2519
|
+
requiredEntityTypes: [
|
|
2520
|
+
"repository",
|
|
2521
|
+
"service",
|
|
2522
|
+
"module",
|
|
2523
|
+
"workflow",
|
|
2524
|
+
"incident",
|
|
2525
|
+
"migration",
|
|
2526
|
+
"decision_record",
|
|
2527
|
+
"agent"
|
|
2528
|
+
],
|
|
2529
|
+
requiredEdgeTypes: [
|
|
2530
|
+
"depends_on",
|
|
2531
|
+
"owns",
|
|
2532
|
+
"calls",
|
|
2533
|
+
"blocks",
|
|
2534
|
+
"reviews",
|
|
2535
|
+
"mitigates",
|
|
2536
|
+
"supersedes"
|
|
2537
|
+
]
|
|
2538
|
+
}
|
|
2539
|
+
],
|
|
2540
|
+
topicRoots: [
|
|
2541
|
+
{
|
|
2542
|
+
slug: "migrations",
|
|
2543
|
+
name: "Migrations",
|
|
2544
|
+
description: "Schema, API, and runtime migrations with blast-radius, rollback, and parity memory",
|
|
2545
|
+
ontologyId: "software-entities"
|
|
2546
|
+
},
|
|
2547
|
+
{
|
|
2548
|
+
slug: "reviews",
|
|
2549
|
+
name: "Reviews",
|
|
2550
|
+
description: "Pull-request and change-review workflows grounded in prior rationale and regressions",
|
|
2551
|
+
ontologyId: "software-entities"
|
|
2552
|
+
},
|
|
2553
|
+
{
|
|
2554
|
+
slug: "incidents",
|
|
2555
|
+
name: "Incidents",
|
|
2556
|
+
description: "Incident response driven by competing hypotheses, contradictions, and mitigations",
|
|
2557
|
+
ontologyId: "software-entities"
|
|
2558
|
+
},
|
|
2559
|
+
{
|
|
2560
|
+
slug: "architecture",
|
|
2561
|
+
name: "Architecture",
|
|
2562
|
+
description: "Architecture decisions, interface trade-offs, and precedent-aware rationale recall",
|
|
2563
|
+
ontologyId: "software-entities"
|
|
2564
|
+
},
|
|
2565
|
+
{
|
|
2566
|
+
slug: "decision-memory",
|
|
2567
|
+
name: "Decision Memory",
|
|
2568
|
+
description: "Cross-cutting rationale recall, failed attempts, and analog reuse across engineering work",
|
|
2569
|
+
ontologyId: "software-entities"
|
|
2570
|
+
}
|
|
2571
|
+
],
|
|
2572
|
+
workflows: [
|
|
2573
|
+
{
|
|
2574
|
+
workflowId: "migration-readiness",
|
|
2575
|
+
name: "Migration Readiness",
|
|
2576
|
+
description: "Recall similar migrations, map blast radius, and define rollback before rollout",
|
|
2577
|
+
steps: [
|
|
2578
|
+
{
|
|
2579
|
+
stepId: "recall-history",
|
|
2580
|
+
name: "Recall History",
|
|
2581
|
+
description: "Compile analogous migrations, prior rationale, failed attempts, and compatibility constraints",
|
|
2582
|
+
requiredRoles: ["context-compiler", "migration-owner"],
|
|
2583
|
+
produces: ["memory-brief"],
|
|
2584
|
+
gateId: "memory-grounded"
|
|
2585
|
+
},
|
|
2586
|
+
{
|
|
2587
|
+
stepId: "plan-rollout",
|
|
2588
|
+
name: "Plan Rollout",
|
|
2589
|
+
description: "Define blast radius, sequencing, rollback, and verification checkpoints",
|
|
2590
|
+
requiredRoles: ["migration-owner", "critic"],
|
|
2591
|
+
produces: ["migration-plan"],
|
|
2592
|
+
gateId: "rollback-ready"
|
|
2593
|
+
},
|
|
2594
|
+
{
|
|
2595
|
+
stepId: "verify-rollout",
|
|
2596
|
+
name: "Verify Rollout",
|
|
2597
|
+
description: "Confirm canary, rollback, and parity checks are explicit before execution",
|
|
2598
|
+
requiredRoles: ["reviewer"],
|
|
2599
|
+
produces: ["verification-checklist"],
|
|
2600
|
+
gateId: "verification-covered"
|
|
2601
|
+
}
|
|
2602
|
+
],
|
|
2603
|
+
requiredArtifacts: [
|
|
2604
|
+
"memory-brief",
|
|
2605
|
+
"migration-plan",
|
|
2606
|
+
"verification-checklist"
|
|
2607
|
+
],
|
|
2608
|
+
gateCheckpoints: [
|
|
2609
|
+
"memory-grounded",
|
|
2610
|
+
"rollback-ready",
|
|
2611
|
+
"verification-covered"
|
|
2612
|
+
]
|
|
2613
|
+
},
|
|
2614
|
+
{
|
|
2615
|
+
workflowId: "pull-request-review",
|
|
2616
|
+
name: "Pull Request Review",
|
|
2617
|
+
description: "Use prior rationale, regressions, and verification history to review risky changes faster",
|
|
2618
|
+
steps: [
|
|
2619
|
+
{
|
|
2620
|
+
stepId: "recall-review-context",
|
|
2621
|
+
name: "Recall Review Context",
|
|
2622
|
+
description: "Load earlier decisions, similar diffs, failed attempts, and relevant incidents",
|
|
2623
|
+
requiredRoles: ["context-compiler", "reviewer"],
|
|
2624
|
+
produces: ["review-context"],
|
|
2625
|
+
gateId: "memory-grounded"
|
|
2626
|
+
},
|
|
2627
|
+
{
|
|
2628
|
+
stepId: "inspect-diff",
|
|
2629
|
+
name: "Inspect Diff",
|
|
2630
|
+
description: "Surface risk areas, stale assumptions, and regressions that should block approval",
|
|
2631
|
+
requiredRoles: ["reviewer", "critic"],
|
|
2632
|
+
produces: ["review-findings"],
|
|
2633
|
+
gateId: "review-risks-surfaced"
|
|
2634
|
+
},
|
|
2635
|
+
{
|
|
2636
|
+
stepId: "verify-changes",
|
|
2637
|
+
name: "Verify Changes",
|
|
2638
|
+
description: "Tie approval to explicit typecheck, test, and integration evidence",
|
|
2639
|
+
requiredRoles: ["reviewer"],
|
|
2640
|
+
produces: ["verification-checklist"],
|
|
2641
|
+
gateId: "verification-covered"
|
|
2642
|
+
}
|
|
2643
|
+
],
|
|
2644
|
+
requiredArtifacts: [
|
|
2645
|
+
"review-context",
|
|
2646
|
+
"review-findings",
|
|
2647
|
+
"verification-checklist"
|
|
2648
|
+
],
|
|
2649
|
+
gateCheckpoints: [
|
|
2650
|
+
"memory-grounded",
|
|
2651
|
+
"review-risks-surfaced",
|
|
2652
|
+
"verification-covered"
|
|
2653
|
+
]
|
|
2654
|
+
},
|
|
2655
|
+
{
|
|
2656
|
+
workflowId: "incident-response",
|
|
2657
|
+
name: "Incident Response",
|
|
2658
|
+
description: "Treat incidents as contradiction-heavy reasoning tasks before committing to a root cause",
|
|
2659
|
+
steps: [
|
|
2660
|
+
{
|
|
2661
|
+
stepId: "collect-signal",
|
|
2662
|
+
name: "Collect Signal",
|
|
2663
|
+
description: "Assemble symptoms, recent changes, precedent incidents, and active hypotheses",
|
|
2664
|
+
requiredRoles: ["context-compiler", "incident-commander"],
|
|
2665
|
+
produces: ["incident-brief"],
|
|
2666
|
+
gateId: "memory-grounded"
|
|
2667
|
+
},
|
|
2668
|
+
{
|
|
2669
|
+
stepId: "surface-contradictions",
|
|
2670
|
+
name: "Surface Contradictions",
|
|
2671
|
+
description: "Make competing explanations explicit before mitigation narrows the search space",
|
|
2672
|
+
requiredRoles: ["incident-commander", "critic"],
|
|
2673
|
+
produces: ["contradiction-report"],
|
|
2674
|
+
gateId: "contradictions-surfaced"
|
|
2675
|
+
},
|
|
2676
|
+
{
|
|
2677
|
+
stepId: "plan-mitigation",
|
|
2678
|
+
name: "Plan Mitigation",
|
|
2679
|
+
description: "Choose mitigations with owners, reversibility, and verification paths",
|
|
2680
|
+
requiredRoles: ["incident-commander", "reviewer"],
|
|
2681
|
+
produces: ["mitigation-plan"],
|
|
2682
|
+
gateId: "verification-covered"
|
|
2683
|
+
}
|
|
2684
|
+
],
|
|
2685
|
+
requiredArtifacts: [
|
|
2686
|
+
"incident-brief",
|
|
2687
|
+
"contradiction-report",
|
|
2688
|
+
"mitigation-plan"
|
|
2689
|
+
],
|
|
2690
|
+
gateCheckpoints: [
|
|
2691
|
+
"memory-grounded",
|
|
2692
|
+
"contradictions-surfaced",
|
|
2693
|
+
"verification-covered"
|
|
2694
|
+
]
|
|
2695
|
+
},
|
|
2696
|
+
{
|
|
2697
|
+
workflowId: "architecture-decision",
|
|
2698
|
+
name: "Architecture Decision",
|
|
2699
|
+
description: "Ground architecture choices in cited precedent, explicit alternatives, and follow-up risk",
|
|
2700
|
+
steps: [
|
|
2701
|
+
{
|
|
2702
|
+
stepId: "recall-precedent",
|
|
2703
|
+
name: "Recall Precedent",
|
|
2704
|
+
description: "Gather analogous decisions, trade-offs, reversals, and evidence already in the graph",
|
|
2705
|
+
requiredRoles: ["context-compiler", "architect"],
|
|
2706
|
+
produces: ["decision-brief"],
|
|
2707
|
+
gateId: "memory-grounded"
|
|
2708
|
+
},
|
|
2709
|
+
{
|
|
2710
|
+
stepId: "compare-options",
|
|
2711
|
+
name: "Compare Options",
|
|
2712
|
+
description: "Contrast viable paths, show what changes, and surface objections early",
|
|
2713
|
+
requiredRoles: ["architect", "critic"],
|
|
2714
|
+
produces: ["decision-brief"],
|
|
2715
|
+
gateId: "decision-rationale-citable"
|
|
2716
|
+
},
|
|
2717
|
+
{
|
|
2718
|
+
stepId: "record-decision",
|
|
2719
|
+
name: "Record Decision",
|
|
2720
|
+
description: "Capture the chosen path, cited rationale, and follow-up risks for later recall",
|
|
2721
|
+
requiredRoles: ["architect"],
|
|
2722
|
+
produces: ["decision-record"]
|
|
2723
|
+
}
|
|
2724
|
+
],
|
|
2725
|
+
requiredArtifacts: ["decision-brief", "decision-record"],
|
|
2726
|
+
gateCheckpoints: ["memory-grounded", "decision-rationale-citable"]
|
|
2727
|
+
}
|
|
2728
|
+
],
|
|
2729
|
+
gates: [
|
|
2730
|
+
{
|
|
2731
|
+
gateId: "memory-grounded",
|
|
2732
|
+
name: "Memory Grounded",
|
|
2733
|
+
description: "The workflow is anchored in prior rationale, analogs, and failure memory before action",
|
|
2734
|
+
criteria: [
|
|
2735
|
+
{
|
|
2736
|
+
criterionId: "precedent-cited",
|
|
2737
|
+
description: "At least one prior change, incident, or decision is cited",
|
|
2738
|
+
metric: "precedent_citations",
|
|
2739
|
+
threshold: 1,
|
|
2740
|
+
operator: "gte"
|
|
2741
|
+
},
|
|
2742
|
+
{
|
|
2743
|
+
criterionId: "failure-log-checked",
|
|
2744
|
+
description: "Relevant failed attempts or incident history were checked",
|
|
2745
|
+
metric: "failure_log_checked",
|
|
2746
|
+
threshold: 1,
|
|
2747
|
+
operator: "eq"
|
|
2748
|
+
}
|
|
2749
|
+
],
|
|
2750
|
+
severity: "blocking"
|
|
2751
|
+
},
|
|
2752
|
+
{
|
|
2753
|
+
gateId: "rollback-ready",
|
|
2754
|
+
name: "Rollback Ready",
|
|
2755
|
+
description: "Risky migrations cannot proceed without explicit rollback and blast-radius coverage",
|
|
2756
|
+
criteria: [
|
|
2757
|
+
{
|
|
2758
|
+
criterionId: "blast-radius-scoped",
|
|
2759
|
+
description: "Blast radius is enumerated for the proposed change",
|
|
2760
|
+
metric: "blast_radius_scoped",
|
|
2761
|
+
threshold: 1,
|
|
2762
|
+
operator: "eq"
|
|
2763
|
+
},
|
|
2764
|
+
{
|
|
2765
|
+
criterionId: "rollback-path-defined",
|
|
2766
|
+
description: "Rollback path is explicit and reversible",
|
|
2767
|
+
metric: "rollback_path_defined",
|
|
2768
|
+
threshold: 1,
|
|
2769
|
+
operator: "eq"
|
|
2770
|
+
}
|
|
2771
|
+
],
|
|
2772
|
+
severity: "blocking"
|
|
2773
|
+
},
|
|
2774
|
+
{
|
|
2775
|
+
gateId: "review-risks-surfaced",
|
|
2776
|
+
name: "Review Risks Surfaced",
|
|
2777
|
+
description: "Review must explain what could regress and why approval is still justified",
|
|
2778
|
+
criteria: [
|
|
2779
|
+
{
|
|
2780
|
+
criterionId: "risk-areas-documented",
|
|
2781
|
+
description: "Risk areas and likely regressions are called out explicitly",
|
|
2782
|
+
metric: "risk_areas_documented",
|
|
2783
|
+
threshold: 1,
|
|
2784
|
+
operator: "gte"
|
|
2785
|
+
},
|
|
2786
|
+
{
|
|
2787
|
+
criterionId: "prior-regressions-checked",
|
|
2788
|
+
description: "Reviewer checked analogous regressions or incidents",
|
|
2789
|
+
metric: "prior_regressions_checked",
|
|
2790
|
+
threshold: 1,
|
|
2791
|
+
operator: "eq"
|
|
2792
|
+
}
|
|
2793
|
+
],
|
|
2794
|
+
severity: "blocking"
|
|
2795
|
+
},
|
|
2796
|
+
{
|
|
2797
|
+
gateId: "contradictions-surfaced",
|
|
2798
|
+
name: "Contradictions Surfaced",
|
|
2799
|
+
description: "Incidents should preserve competing hypotheses long enough to avoid false certainty",
|
|
2800
|
+
criteria: [
|
|
2801
|
+
{
|
|
2802
|
+
criterionId: "multiple-hypotheses",
|
|
2803
|
+
description: "At least two plausible hypotheses remain visible",
|
|
2804
|
+
metric: "competing_hypotheses_count",
|
|
2805
|
+
threshold: 2,
|
|
2806
|
+
operator: "gte"
|
|
2807
|
+
},
|
|
2808
|
+
{
|
|
2809
|
+
criterionId: "contradictions-reviewed",
|
|
2810
|
+
description: "Relevant contradictions or tensions were reviewed",
|
|
2811
|
+
metric: "contradictions_reviewed",
|
|
2812
|
+
threshold: 1,
|
|
2813
|
+
operator: "gte"
|
|
2814
|
+
}
|
|
2815
|
+
],
|
|
2816
|
+
severity: "blocking"
|
|
2817
|
+
},
|
|
2818
|
+
{
|
|
2819
|
+
gateId: "decision-rationale-citable",
|
|
2820
|
+
name: "Decision Rationale Citable",
|
|
2821
|
+
description: "Architecture choices should cite prior rationale and compare viable alternatives",
|
|
2822
|
+
criteria: [
|
|
2823
|
+
{
|
|
2824
|
+
criterionId: "options-compared",
|
|
2825
|
+
description: "At least two options are compared before choosing one",
|
|
2826
|
+
metric: "options_compared",
|
|
2827
|
+
threshold: 2,
|
|
2828
|
+
operator: "gte"
|
|
2829
|
+
},
|
|
2830
|
+
{
|
|
2831
|
+
criterionId: "prior-decisions-cited",
|
|
2832
|
+
description: "Decision cites prior beliefs, ADRs, or incidents",
|
|
2833
|
+
metric: "prior_decisions_cited",
|
|
2834
|
+
threshold: 1,
|
|
2835
|
+
operator: "gte"
|
|
2836
|
+
}
|
|
2837
|
+
],
|
|
2838
|
+
severity: "blocking"
|
|
2839
|
+
},
|
|
2840
|
+
{
|
|
2841
|
+
gateId: "verification-covered",
|
|
2842
|
+
name: "Verification Covered",
|
|
2843
|
+
description: "Approval, rollout, and mitigation all require named verification paths",
|
|
2844
|
+
criteria: [
|
|
2845
|
+
{
|
|
2846
|
+
criterionId: "checks-defined",
|
|
2847
|
+
description: "At least one explicit verification path is named",
|
|
2848
|
+
metric: "verification_paths_defined",
|
|
2849
|
+
threshold: 1,
|
|
2850
|
+
operator: "gte"
|
|
2851
|
+
},
|
|
2852
|
+
{
|
|
2853
|
+
criterionId: "owners-named",
|
|
2854
|
+
description: "Owners or on-call responsibility are explicit",
|
|
2855
|
+
metric: "owner_count",
|
|
2856
|
+
threshold: 1,
|
|
2857
|
+
operator: "gte"
|
|
2858
|
+
}
|
|
2859
|
+
],
|
|
2860
|
+
severity: "blocking"
|
|
2861
|
+
}
|
|
2862
|
+
],
|
|
2863
|
+
artifacts: [
|
|
2864
|
+
{
|
|
2865
|
+
artifactId: "memory-brief",
|
|
2866
|
+
name: "Memory Brief",
|
|
2867
|
+
description: "A reusable brief of analogous changes, prior rationale, failed attempts, and contradictions",
|
|
2868
|
+
stage: "recall-history",
|
|
2869
|
+
contentSchema: {
|
|
2870
|
+
type: "object",
|
|
2871
|
+
properties: {
|
|
2872
|
+
analogousChanges: { type: "array", items: { type: "string" } },
|
|
2873
|
+
priorDecisions: { type: "array", items: { type: "string" } },
|
|
2874
|
+
failedAttempts: { type: "array", items: { type: "string" } },
|
|
2875
|
+
contradictions: { type: "array", items: { type: "string" } }
|
|
2876
|
+
},
|
|
2877
|
+
required: ["analogousChanges", "priorDecisions"]
|
|
2878
|
+
},
|
|
2879
|
+
requiredFields: ["analogousChanges", "priorDecisions"]
|
|
2880
|
+
},
|
|
2881
|
+
{
|
|
2882
|
+
artifactId: "migration-plan",
|
|
2883
|
+
name: "Migration Plan",
|
|
2884
|
+
description: "Blast radius, rollback path, rollout checkpoints, and verification plan",
|
|
2885
|
+
stage: "plan-rollout",
|
|
2886
|
+
contentSchema: {
|
|
2887
|
+
type: "object",
|
|
2888
|
+
properties: {
|
|
2889
|
+
blastRadius: { type: "array", items: { type: "string" } },
|
|
2890
|
+
rollbackPlan: { type: "string" },
|
|
2891
|
+
verificationPath: { type: "array", items: { type: "string" } },
|
|
2892
|
+
canarySteps: { type: "array", items: { type: "string" } }
|
|
2893
|
+
},
|
|
2894
|
+
required: ["blastRadius", "rollbackPlan", "verificationPath"]
|
|
2895
|
+
},
|
|
2896
|
+
requiredFields: ["blastRadius", "rollbackPlan", "verificationPath"]
|
|
2897
|
+
},
|
|
2898
|
+
{
|
|
2899
|
+
artifactId: "verification-checklist",
|
|
2900
|
+
name: "Verification Checklist",
|
|
2901
|
+
description: "Named checks, owners, and pass/fail criteria for rollout or approval",
|
|
2902
|
+
stage: "verify-rollout",
|
|
2903
|
+
contentSchema: {
|
|
2904
|
+
type: "object",
|
|
2905
|
+
properties: {
|
|
2906
|
+
checks: { type: "array", items: { type: "string" } },
|
|
2907
|
+
owners: { type: "array", items: { type: "string" } },
|
|
2908
|
+
passCriteria: { type: "array", items: { type: "string" } }
|
|
2909
|
+
},
|
|
2910
|
+
required: ["checks", "owners"]
|
|
2911
|
+
},
|
|
2912
|
+
requiredFields: ["checks", "owners"]
|
|
2913
|
+
},
|
|
2914
|
+
{
|
|
2915
|
+
artifactId: "review-context",
|
|
2916
|
+
name: "Review Context",
|
|
2917
|
+
description: "Prior rationale, related diffs, incidents, and failure history relevant to a review",
|
|
2918
|
+
stage: "recall-review-context",
|
|
2919
|
+
contentSchema: {
|
|
2920
|
+
type: "object",
|
|
2921
|
+
properties: {
|
|
2922
|
+
rationaleLinks: { type: "array", items: { type: "string" } },
|
|
2923
|
+
analogousDiffs: { type: "array", items: { type: "string" } },
|
|
2924
|
+
relatedIncidents: { type: "array", items: { type: "string" } }
|
|
2925
|
+
},
|
|
2926
|
+
required: ["rationaleLinks"]
|
|
2927
|
+
},
|
|
2928
|
+
requiredFields: ["rationaleLinks"]
|
|
2929
|
+
},
|
|
2930
|
+
{
|
|
2931
|
+
artifactId: "review-findings",
|
|
2932
|
+
name: "Review Findings",
|
|
2933
|
+
description: "What could regress, what evidence was checked, and whether the change should be blocked",
|
|
2934
|
+
stage: "inspect-diff",
|
|
2935
|
+
contentSchema: {
|
|
2936
|
+
type: "object",
|
|
2937
|
+
properties: {
|
|
2938
|
+
findings: { type: "array", items: { type: "string" } },
|
|
2939
|
+
regressionsChecked: { type: "array", items: { type: "string" } },
|
|
2940
|
+
blockReason: { type: "string" }
|
|
2941
|
+
},
|
|
2942
|
+
required: ["findings", "regressionsChecked"]
|
|
2943
|
+
},
|
|
2944
|
+
requiredFields: ["findings", "regressionsChecked"]
|
|
2945
|
+
},
|
|
2946
|
+
{
|
|
2947
|
+
artifactId: "incident-brief",
|
|
2948
|
+
name: "Incident Brief",
|
|
2949
|
+
description: "Signals, recent changes, competing hypotheses, and precedent incidents",
|
|
2950
|
+
stage: "collect-signal",
|
|
2951
|
+
contentSchema: {
|
|
2952
|
+
type: "object",
|
|
2953
|
+
properties: {
|
|
2954
|
+
symptoms: { type: "array", items: { type: "string" } },
|
|
2955
|
+
recentChanges: { type: "array", items: { type: "string" } },
|
|
2956
|
+
competingHypotheses: { type: "array", items: { type: "string" } },
|
|
2957
|
+
precedentIncidents: { type: "array", items: { type: "string" } }
|
|
2958
|
+
},
|
|
2959
|
+
required: ["symptoms", "competingHypotheses"]
|
|
2960
|
+
},
|
|
2961
|
+
requiredFields: ["symptoms", "competingHypotheses"]
|
|
2962
|
+
},
|
|
2963
|
+
{
|
|
2964
|
+
artifactId: "contradiction-report",
|
|
2965
|
+
name: "Contradiction Report",
|
|
2966
|
+
description: "Active contradictions, why they matter, and what evidence could collapse them",
|
|
2967
|
+
stage: "surface-contradictions",
|
|
2968
|
+
contentSchema: {
|
|
2969
|
+
type: "object",
|
|
2970
|
+
properties: {
|
|
2971
|
+
contradictions: { type: "array", items: { type: "string" } },
|
|
2972
|
+
likelyRootCauses: { type: "array", items: { type: "string" } },
|
|
2973
|
+
missingEvidence: { type: "array", items: { type: "string" } }
|
|
2974
|
+
},
|
|
2975
|
+
required: ["contradictions", "likelyRootCauses"]
|
|
2976
|
+
},
|
|
2977
|
+
requiredFields: ["contradictions", "likelyRootCauses"]
|
|
2978
|
+
},
|
|
2979
|
+
{
|
|
2980
|
+
artifactId: "mitigation-plan",
|
|
2981
|
+
name: "Mitigation Plan",
|
|
2982
|
+
description: "Chosen mitigation, rollback path, and verification ownership for an incident",
|
|
2983
|
+
stage: "plan-mitigation",
|
|
2984
|
+
contentSchema: {
|
|
2985
|
+
type: "object",
|
|
2986
|
+
properties: {
|
|
2987
|
+
mitigationSteps: { type: "array", items: { type: "string" } },
|
|
2988
|
+
rollbackPlan: { type: "string" },
|
|
2989
|
+
owners: { type: "array", items: { type: "string" } }
|
|
2990
|
+
},
|
|
2991
|
+
required: ["mitigationSteps", "owners"]
|
|
2992
|
+
},
|
|
2993
|
+
requiredFields: ["mitigationSteps", "owners"]
|
|
2994
|
+
},
|
|
2995
|
+
{
|
|
2996
|
+
artifactId: "decision-brief",
|
|
2997
|
+
name: "Decision Brief",
|
|
2998
|
+
description: "Options, cited precedent, trade-offs, and objections for an architecture decision",
|
|
2999
|
+
stage: "compare-options",
|
|
3000
|
+
contentSchema: {
|
|
3001
|
+
type: "object",
|
|
3002
|
+
properties: {
|
|
3003
|
+
options: { type: "array", items: { type: "string" } },
|
|
3004
|
+
citedPrecedent: { type: "array", items: { type: "string" } },
|
|
3005
|
+
objections: { type: "array", items: { type: "string" } }
|
|
3006
|
+
},
|
|
3007
|
+
required: ["options", "citedPrecedent"]
|
|
3008
|
+
},
|
|
3009
|
+
requiredFields: ["options", "citedPrecedent"]
|
|
3010
|
+
},
|
|
3011
|
+
{
|
|
3012
|
+
artifactId: "decision-record",
|
|
3013
|
+
name: "Decision Record",
|
|
3014
|
+
description: "Chosen path, why it won, what it supersedes, and what follow-up remains open",
|
|
3015
|
+
stage: "record-decision",
|
|
3016
|
+
contentSchema: {
|
|
3017
|
+
type: "object",
|
|
3018
|
+
properties: {
|
|
3019
|
+
decision: { type: "string" },
|
|
3020
|
+
rationale: { type: "array", items: { type: "string" } },
|
|
3021
|
+
supersedes: { type: "array", items: { type: "string" } },
|
|
3022
|
+
followUps: { type: "array", items: { type: "string" } }
|
|
3023
|
+
},
|
|
3024
|
+
required: ["decision", "rationale"]
|
|
3025
|
+
},
|
|
3026
|
+
requiredFields: ["decision", "rationale"]
|
|
3027
|
+
}
|
|
3028
|
+
],
|
|
3029
|
+
roles: [
|
|
3030
|
+
{
|
|
3031
|
+
roleId: "context-compiler",
|
|
3032
|
+
name: "Context Compiler",
|
|
3033
|
+
description: "Compiles prior rationale, analogs, and failure memory into reusable first-hour context",
|
|
3034
|
+
perspective: "History-first, evidence-weighted context assembly",
|
|
3035
|
+
optimizesFor: "recall quality and anti-repetition coverage",
|
|
3036
|
+
mayBlock: false
|
|
3037
|
+
},
|
|
3038
|
+
{
|
|
3039
|
+
roleId: "migration-owner",
|
|
3040
|
+
name: "Migration Owner",
|
|
3041
|
+
description: "Scopes rollout blast radius, rollback, sequencing, and compatibility risk",
|
|
3042
|
+
perspective: "Operational caution with explicit rollback discipline",
|
|
3043
|
+
optimizesFor: "safe rollout planning",
|
|
3044
|
+
mayBlock: false
|
|
3045
|
+
},
|
|
3046
|
+
{
|
|
3047
|
+
roleId: "reviewer",
|
|
3048
|
+
name: "Reviewer",
|
|
3049
|
+
description: "Evaluates risky changes against prior regressions, evidence, and missing checks",
|
|
3050
|
+
perspective: "Evidence-backed change approval with regression awareness",
|
|
3051
|
+
optimizesFor: "defect prevention and clear approval rationale",
|
|
3052
|
+
mayBlock: true
|
|
3053
|
+
},
|
|
3054
|
+
{
|
|
3055
|
+
roleId: "incident-commander",
|
|
3056
|
+
name: "Incident Commander",
|
|
3057
|
+
description: "Maintains multiple plausible explanations while driving mitigation decisions",
|
|
3058
|
+
perspective: "Fast, reversible action without collapsing uncertainty too early",
|
|
3059
|
+
optimizesFor: "time-to-mitigation with preserved reasoning integrity",
|
|
3060
|
+
mayBlock: false
|
|
3061
|
+
},
|
|
3062
|
+
{
|
|
3063
|
+
roleId: "architect",
|
|
3064
|
+
name: "Architect",
|
|
3065
|
+
description: "Turns competing options into explicit decisions with cited precedent and follow-up risk",
|
|
3066
|
+
perspective: "Trade-off clarity and long-term maintainability",
|
|
3067
|
+
optimizesFor: "decision quality and rationale reuse",
|
|
3068
|
+
mayBlock: false
|
|
3069
|
+
},
|
|
3070
|
+
{
|
|
3071
|
+
roleId: "critic",
|
|
3072
|
+
name: "Critic",
|
|
3073
|
+
description: "Finds weak assumptions, missing rollback paths, and untested contradictions",
|
|
3074
|
+
perspective: "Skeptical, adversarial, and detail-oriented",
|
|
3075
|
+
optimizesFor: "early detection of brittle plans",
|
|
3076
|
+
mayBlock: true
|
|
3077
|
+
}
|
|
3078
|
+
],
|
|
3079
|
+
inquiryShaping: {
|
|
3080
|
+
questionTemplates: [
|
|
3081
|
+
{
|
|
3082
|
+
templateId: "engineering-rationale-recall",
|
|
3083
|
+
questionType: "comparison",
|
|
3084
|
+
priority: "high",
|
|
3085
|
+
template: "Which prior migration, incident, review, or architecture decision most resembles {{objective}}, and what rationale or failure should we reuse before changing anything?",
|
|
3086
|
+
whenObjectiveIncludes: [
|
|
3087
|
+
"migration",
|
|
3088
|
+
"review",
|
|
3089
|
+
"pull request",
|
|
3090
|
+
"incident",
|
|
3091
|
+
"architecture",
|
|
3092
|
+
"decision",
|
|
3093
|
+
"rollback",
|
|
3094
|
+
"refactor"
|
|
3095
|
+
]
|
|
3096
|
+
},
|
|
3097
|
+
{
|
|
3098
|
+
templateId: "engineering-rollback-falsifier",
|
|
3099
|
+
questionType: "falsification",
|
|
3100
|
+
priority: "critical",
|
|
3101
|
+
template: "What rollback, compatibility, or blast-radius assumption would fail first if {{hypothesis}} is wrong?",
|
|
3102
|
+
whenObjectiveIncludes: ["migration", "deploy", "rollout", "backfill"]
|
|
3103
|
+
},
|
|
3104
|
+
{
|
|
3105
|
+
templateId: "engineering-review-regression",
|
|
3106
|
+
questionType: "counterfactual",
|
|
3107
|
+
priority: "high",
|
|
3108
|
+
template: "Which prior regression, incident, or failed attempt should a reviewer inspect before approving {{objective}}?",
|
|
3109
|
+
whenObjectiveIncludes: ["review", "pull request", "diff", "merge"]
|
|
3110
|
+
},
|
|
3111
|
+
{
|
|
3112
|
+
templateId: "engineering-incident-contradiction",
|
|
3113
|
+
questionType: "mechanism",
|
|
3114
|
+
priority: "high",
|
|
3115
|
+
template: "Which competing hypothesis or contradiction must be surfaced before treating {{objective}} as the root cause?",
|
|
3116
|
+
whenObjectiveIncludes: [
|
|
3117
|
+
"incident",
|
|
3118
|
+
"outage",
|
|
3119
|
+
"error",
|
|
3120
|
+
"latency",
|
|
3121
|
+
"regression"
|
|
3122
|
+
]
|
|
3123
|
+
},
|
|
3124
|
+
{
|
|
3125
|
+
templateId: "engineering-architecture-precedent",
|
|
3126
|
+
questionType: "validation",
|
|
3127
|
+
priority: "high",
|
|
3128
|
+
template: "Which earlier architecture decision would {{objective}} narrow, supersede, or reaffirm, and what evidence justified it then?",
|
|
3129
|
+
whenObjectiveIncludes: [
|
|
3130
|
+
"architecture",
|
|
3131
|
+
"decision",
|
|
3132
|
+
"interface",
|
|
3133
|
+
"contract",
|
|
3134
|
+
"api",
|
|
3135
|
+
"design"
|
|
3136
|
+
]
|
|
3137
|
+
}
|
|
3138
|
+
],
|
|
3139
|
+
taskTemplates: [
|
|
3140
|
+
{
|
|
3141
|
+
templateId: "engineering-memory-brief",
|
|
3142
|
+
title: "Compile prior rationale, analogous changes, and failed attempts for {{objective}}",
|
|
3143
|
+
description: "Create a first-hour memory brief so the workflow starts with precedent instead of rediscovery.",
|
|
3144
|
+
taskType: "analysis",
|
|
3145
|
+
priority: "urgent",
|
|
3146
|
+
whenObjectiveIncludes: [
|
|
3147
|
+
"migration",
|
|
3148
|
+
"review",
|
|
3149
|
+
"incident",
|
|
3150
|
+
"architecture",
|
|
3151
|
+
"decision",
|
|
3152
|
+
"rollback"
|
|
3153
|
+
]
|
|
3154
|
+
},
|
|
3155
|
+
{
|
|
3156
|
+
templateId: "engineering-rollback-check",
|
|
3157
|
+
title: "Define blast radius, rollback path, and verification checkpoints for {{objective}}",
|
|
3158
|
+
description: "Turn risky engineering work into a reversible plan before implementation or approval.",
|
|
3159
|
+
taskType: "analysis",
|
|
3160
|
+
priority: "high",
|
|
3161
|
+
whenObjectiveIncludes: ["migration", "deploy", "rollout", "backfill"]
|
|
3162
|
+
},
|
|
3163
|
+
{
|
|
3164
|
+
templateId: "engineering-review-brief",
|
|
3165
|
+
title: "Draft a review brief linking prior rationale, regressions, and missing checks for {{objective}}",
|
|
3166
|
+
description: "Use prior incidents and earlier review context to focus approval on what can actually break.",
|
|
3167
|
+
taskType: "review",
|
|
3168
|
+
priority: "high",
|
|
3169
|
+
whenObjectiveIncludes: ["review", "pull request", "diff", "merge"]
|
|
3170
|
+
},
|
|
3171
|
+
{
|
|
3172
|
+
templateId: "engineering-contradiction-sweep",
|
|
3173
|
+
title: "Surface competing hypotheses and active contradictions for {{objective}}",
|
|
3174
|
+
description: "Keep incident triage or regression analysis from collapsing into a single untested explanation.",
|
|
3175
|
+
taskType: "analysis",
|
|
3176
|
+
priority: "high",
|
|
3177
|
+
whenObjectiveIncludes: [
|
|
3178
|
+
"incident",
|
|
3179
|
+
"outage",
|
|
3180
|
+
"error",
|
|
3181
|
+
"latency",
|
|
3182
|
+
"regression"
|
|
3183
|
+
]
|
|
3184
|
+
},
|
|
3185
|
+
{
|
|
3186
|
+
templateId: "engineering-decision-record",
|
|
3187
|
+
title: "Capture cited precedent, rejected options, and follow-up risks for {{objective}}",
|
|
3188
|
+
description: "Turn architecture decisions into explicit rationale that future work can recall instead of re-litigating.",
|
|
3189
|
+
taskType: "analysis",
|
|
3190
|
+
priority: "medium",
|
|
3191
|
+
whenObjectiveIncludes: [
|
|
3192
|
+
"architecture",
|
|
3193
|
+
"decision",
|
|
3194
|
+
"interface",
|
|
3195
|
+
"contract",
|
|
3196
|
+
"design",
|
|
3197
|
+
"refactor"
|
|
3198
|
+
]
|
|
3199
|
+
}
|
|
3200
|
+
],
|
|
3201
|
+
frameworkHints: [
|
|
3202
|
+
{
|
|
3203
|
+
frameworkName: "Timeline Replay",
|
|
3204
|
+
whenObjectiveIncludes: [
|
|
3205
|
+
"migration",
|
|
3206
|
+
"deploy",
|
|
3207
|
+
"rollout",
|
|
3208
|
+
"incident",
|
|
3209
|
+
"rollback"
|
|
3210
|
+
],
|
|
3211
|
+
boost: 0.28,
|
|
3212
|
+
reason: "Migration and incident work benefits from replaying prior changes, causes, and rollback timing."
|
|
3213
|
+
},
|
|
3214
|
+
{
|
|
3215
|
+
frameworkName: "Contradiction Sweep",
|
|
3216
|
+
whenObjectiveIncludes: ["incident", "outage", "error", "regression"],
|
|
3217
|
+
boost: 0.3,
|
|
3218
|
+
reason: "Incidents need competing hypotheses surfaced explicitly before confidence collapses too early."
|
|
3219
|
+
},
|
|
3220
|
+
{
|
|
3221
|
+
frameworkName: "ADR Delta Review",
|
|
3222
|
+
whenObjectiveIncludes: [
|
|
3223
|
+
"architecture",
|
|
3224
|
+
"decision",
|
|
3225
|
+
"interface",
|
|
3226
|
+
"contract",
|
|
3227
|
+
"design"
|
|
3228
|
+
],
|
|
3229
|
+
boost: 0.26,
|
|
3230
|
+
reason: "Architecture work should compare against earlier decisions and explain the delta, not just the new plan."
|
|
3231
|
+
},
|
|
3232
|
+
{
|
|
3233
|
+
frameworkName: "Pre-Merge Regression Audit",
|
|
3234
|
+
whenObjectiveIncludes: ["review", "pull request", "diff", "merge"],
|
|
3235
|
+
boost: 0.24,
|
|
3236
|
+
reason: "Risky reviews are faster and better when they start from prior regressions, rationale, and missing checks."
|
|
3237
|
+
}
|
|
3238
|
+
]
|
|
3239
|
+
},
|
|
3240
|
+
operatingSystem: {
|
|
3241
|
+
prompts: [
|
|
3242
|
+
{
|
|
3243
|
+
promptId: "claude-quick-reference",
|
|
3244
|
+
description: "Claude Code quick-reference and Lucern operating loop",
|
|
3245
|
+
source: "file",
|
|
3246
|
+
ref: "CLAUDE.md",
|
|
3247
|
+
channel: "bootstrap",
|
|
3248
|
+
required: true,
|
|
3249
|
+
runtimeTargets: ["claude-code", "hybrid"]
|
|
3250
|
+
},
|
|
3251
|
+
{
|
|
3252
|
+
promptId: "build-command",
|
|
3253
|
+
description: "Main-session worktree execution protocol",
|
|
3254
|
+
source: "file",
|
|
3255
|
+
ref: ".claude/commands/build.md",
|
|
3256
|
+
channel: "workflow",
|
|
3257
|
+
required: true,
|
|
3258
|
+
runtimeTargets: ["claude-code", "codex", "hybrid"]
|
|
3259
|
+
},
|
|
3260
|
+
{
|
|
3261
|
+
promptId: "architect-command",
|
|
3262
|
+
description: "Product-architecture framing command",
|
|
3263
|
+
source: "file",
|
|
3264
|
+
ref: ".claude/commands/architect.md",
|
|
3265
|
+
channel: "analysis",
|
|
3266
|
+
required: true,
|
|
3267
|
+
runtimeTargets: ["claude-code", "codex", "hybrid"]
|
|
3268
|
+
},
|
|
3269
|
+
{
|
|
3270
|
+
promptId: "pipeline-command",
|
|
3271
|
+
description: "Pipeline sequencing and queue-management command",
|
|
3272
|
+
source: "file",
|
|
3273
|
+
ref: ".claude/commands/pipeline.md",
|
|
3274
|
+
channel: "analysis",
|
|
3275
|
+
required: true,
|
|
3276
|
+
runtimeTargets: ["claude-code", "codex", "hybrid"]
|
|
3277
|
+
},
|
|
3278
|
+
{
|
|
3279
|
+
promptId: "pr-command",
|
|
3280
|
+
description: "PR gating and merge-close workflow command",
|
|
3281
|
+
source: "file",
|
|
3282
|
+
ref: ".claude/commands/pr.md",
|
|
3283
|
+
channel: "review",
|
|
3284
|
+
required: true,
|
|
3285
|
+
runtimeTargets: ["claude-code", "codex", "hybrid"]
|
|
3286
|
+
},
|
|
3287
|
+
{
|
|
3288
|
+
promptId: "lucern-generate-questions",
|
|
3289
|
+
description: "Langfuse prompt for pack-shaped question generation",
|
|
3290
|
+
source: "langfuse",
|
|
3291
|
+
ref: "lucern/generate-questions",
|
|
3292
|
+
channel: "analysis",
|
|
3293
|
+
required: true,
|
|
3294
|
+
runtimeTargets: ["claude-code", "codex", "hybrid", "portable"]
|
|
3295
|
+
},
|
|
3296
|
+
{
|
|
3297
|
+
promptId: "lucern-contradiction-analysis",
|
|
3298
|
+
description: "Langfuse prompt for contradiction-heavy debugging and incidents",
|
|
3299
|
+
source: "langfuse",
|
|
3300
|
+
ref: "lucern/contradiction-analysis",
|
|
3301
|
+
channel: "review",
|
|
3302
|
+
required: true,
|
|
3303
|
+
runtimeTargets: ["claude-code", "codex", "hybrid", "portable"]
|
|
3304
|
+
}
|
|
3305
|
+
],
|
|
3306
|
+
tools: [
|
|
3307
|
+
{
|
|
3308
|
+
toolId: "start-investigation",
|
|
3309
|
+
description: "Canonical graph bootstrap before coding or review",
|
|
3310
|
+
kind: "mcp",
|
|
3311
|
+
entrypoint: "compile_context",
|
|
3312
|
+
required: true,
|
|
3313
|
+
runtimeTargets: ["claude-code", "codex", "hybrid", "portable"]
|
|
3314
|
+
},
|
|
3315
|
+
{
|
|
3316
|
+
toolId: "record-scope-learning",
|
|
3317
|
+
description: "Commit-level ledger writeback with touched paths",
|
|
3318
|
+
kind: "mcp",
|
|
3319
|
+
entrypoint: "record_scope_learning",
|
|
3320
|
+
required: true,
|
|
3321
|
+
runtimeTargets: ["claude-code", "codex", "hybrid", "portable"]
|
|
3322
|
+
},
|
|
3323
|
+
{
|
|
3324
|
+
toolId: "record-attempt",
|
|
3325
|
+
description: "Anti-repetition failure logging during implementation",
|
|
3326
|
+
kind: "mcp",
|
|
3327
|
+
entrypoint: "record_attempt",
|
|
3328
|
+
required: true,
|
|
3329
|
+
runtimeTargets: ["claude-code", "codex", "hybrid", "portable"]
|
|
3330
|
+
},
|
|
3331
|
+
{
|
|
3332
|
+
toolId: "pipeline-snapshot",
|
|
3333
|
+
description: "Execution-band and track-aware pipeline summary",
|
|
3334
|
+
kind: "mcp",
|
|
3335
|
+
entrypoint: "pipeline_snapshot",
|
|
3336
|
+
required: true,
|
|
3337
|
+
runtimeTargets: ["claude-code", "codex", "hybrid", "portable"]
|
|
3338
|
+
},
|
|
3339
|
+
{
|
|
3340
|
+
toolId: "session-init",
|
|
3341
|
+
description: "SessionStart hook bootstrap for Lucern context",
|
|
3342
|
+
kind: "hook",
|
|
3343
|
+
entrypoint: "npx tsx apps/mcp-server/src/cli.ts session-init",
|
|
3344
|
+
required: true,
|
|
3345
|
+
runtimeTargets: ["claude-code", "hybrid"]
|
|
3346
|
+
},
|
|
3347
|
+
{
|
|
3348
|
+
toolId: "tool-log",
|
|
3349
|
+
description: "Post-tool ledger logger and edit-counter reset hook",
|
|
3350
|
+
kind: "hook",
|
|
3351
|
+
entrypoint: "npx tsx apps/mcp-server/src/cli.ts tool-log",
|
|
3352
|
+
required: true,
|
|
3353
|
+
runtimeTargets: ["claude-code", "hybrid"]
|
|
3354
|
+
},
|
|
3355
|
+
{
|
|
3356
|
+
toolId: "build-bash-gate",
|
|
3357
|
+
description: "Commit and PR gate enforcing ledger plus knowledge writes",
|
|
3358
|
+
kind: "hook",
|
|
3359
|
+
entrypoint: "npx tsx apps/mcp-server/src/cli.ts build-bash-gate",
|
|
3360
|
+
required: true,
|
|
3361
|
+
runtimeTargets: ["claude-code", "hybrid"]
|
|
3362
|
+
},
|
|
3363
|
+
{
|
|
3364
|
+
toolId: "lucern-cli-init",
|
|
3365
|
+
description: "One-step MCP setup for new repositories",
|
|
3366
|
+
kind: "cli",
|
|
3367
|
+
entrypoint: "npx tsx apps/mcp-server/src/cli.ts init",
|
|
3368
|
+
required: true,
|
|
3369
|
+
runtimeTargets: ["claude-code", "codex", "hybrid"]
|
|
3370
|
+
},
|
|
3371
|
+
{
|
|
3372
|
+
toolId: "kit-install",
|
|
3373
|
+
description: "Manifest-driven installer for the turnkey Lucern engineering solution pack",
|
|
3374
|
+
kind: "cli",
|
|
3375
|
+
entrypoint: "npx tsx apps/mcp-server/src/cli.ts kit install developer-engineering",
|
|
3376
|
+
required: true,
|
|
3377
|
+
runtimeTargets: ["claude-code", "codex", "hybrid"]
|
|
3378
|
+
}
|
|
3379
|
+
],
|
|
3380
|
+
setupAssets: [
|
|
3381
|
+
{
|
|
3382
|
+
assetId: "claude-instructions",
|
|
3383
|
+
kind: "instruction",
|
|
3384
|
+
description: "Primary Claude Code quick-reference and Lucern protocol",
|
|
3385
|
+
path: "CLAUDE.md",
|
|
3386
|
+
required: true,
|
|
3387
|
+
runtimeTargets: ["claude-code", "hybrid"]
|
|
3388
|
+
},
|
|
3389
|
+
{
|
|
3390
|
+
assetId: "codex-bridge",
|
|
3391
|
+
kind: "instruction",
|
|
3392
|
+
description: "Codex bridge instructions for Lucern-native development",
|
|
3393
|
+
path: "AGENTS.md",
|
|
3394
|
+
required: true,
|
|
3395
|
+
runtimeTargets: ["codex", "hybrid"]
|
|
3396
|
+
},
|
|
3397
|
+
{
|
|
3398
|
+
assetId: "mcp-config",
|
|
3399
|
+
kind: "manifest",
|
|
3400
|
+
description: "MCP server registry including lucern-graph",
|
|
3401
|
+
path: ".mcp.json",
|
|
3402
|
+
required: true,
|
|
3403
|
+
runtimeTargets: ["claude-code", "codex", "hybrid"]
|
|
3404
|
+
},
|
|
3405
|
+
{
|
|
3406
|
+
assetId: "kit-manifest",
|
|
3407
|
+
kind: "manifest",
|
|
3408
|
+
description: "Serialized engineering kit blueprint capturing prompts, tools, ontology, and topic scaffolding",
|
|
3409
|
+
path: ".lucern/kits/developer-engineering.json",
|
|
3410
|
+
required: true,
|
|
3411
|
+
runtimeTargets: ["claude-code", "codex", "hybrid"]
|
|
3412
|
+
},
|
|
3413
|
+
{
|
|
3414
|
+
assetId: "lucern-launcher",
|
|
3415
|
+
kind: "script",
|
|
3416
|
+
description: "Launch script used by MCP clients to start lucern-graph",
|
|
3417
|
+
path: "scripts/lucern_start",
|
|
3418
|
+
required: true,
|
|
3419
|
+
runtimeTargets: ["claude-code", "codex", "hybrid"]
|
|
3420
|
+
},
|
|
3421
|
+
{
|
|
3422
|
+
assetId: "lucern-shell-wrapper",
|
|
3423
|
+
kind: "script",
|
|
3424
|
+
description: "Shell wrapper for invoking Lucern CLI commands with credential resolution",
|
|
3425
|
+
path: "scripts/lucern",
|
|
3426
|
+
required: true,
|
|
3427
|
+
runtimeTargets: ["claude-code", "codex", "hybrid"]
|
|
3428
|
+
},
|
|
3429
|
+
{
|
|
3430
|
+
assetId: "lucern-cli-script",
|
|
3431
|
+
kind: "script",
|
|
3432
|
+
description: "CLI entrypoint for hook commands, init, sync, and kit installation",
|
|
3433
|
+
path: "apps/mcp-server/src/cli.ts",
|
|
3434
|
+
required: true,
|
|
3435
|
+
runtimeTargets: ["claude-code", "codex", "hybrid"]
|
|
3436
|
+
},
|
|
3437
|
+
{
|
|
3438
|
+
assetId: "claude-settings",
|
|
3439
|
+
kind: "settings",
|
|
3440
|
+
description: "Claude hook wiring and enforcement defaults",
|
|
3441
|
+
path: ".claude/settings.json",
|
|
3442
|
+
required: true,
|
|
3443
|
+
runtimeTargets: ["claude-code", "hybrid"]
|
|
3444
|
+
},
|
|
3445
|
+
{
|
|
3446
|
+
assetId: "permission-gate-hook",
|
|
3447
|
+
kind: "hook",
|
|
3448
|
+
description: "Rule-based permission gate for risky tool usage",
|
|
3449
|
+
path: ".claude/hooks/permission-gate.sh",
|
|
3450
|
+
required: true,
|
|
3451
|
+
runtimeTargets: ["claude-code", "hybrid"]
|
|
3452
|
+
},
|
|
3453
|
+
{
|
|
3454
|
+
assetId: "inbox-check-hook",
|
|
3455
|
+
kind: "hook",
|
|
3456
|
+
description: "Session-start inbox and PR queue surfacing",
|
|
3457
|
+
path: ".claude/hooks/inbox-check.sh",
|
|
3458
|
+
required: true,
|
|
3459
|
+
runtimeTargets: ["claude-code", "hybrid"]
|
|
3460
|
+
},
|
|
3461
|
+
{
|
|
3462
|
+
assetId: "prompt-router-hook",
|
|
3463
|
+
kind: "hook",
|
|
3464
|
+
description: "Prompt router for /build validation and inbox context",
|
|
3465
|
+
path: ".claude/hooks/prompt-router.sh",
|
|
3466
|
+
required: true,
|
|
3467
|
+
runtimeTargets: ["claude-code", "hybrid"]
|
|
3468
|
+
},
|
|
3469
|
+
{
|
|
3470
|
+
assetId: "writeback-gate-hook",
|
|
3471
|
+
kind: "hook",
|
|
3472
|
+
description: "Session-close writeback quality gate",
|
|
3473
|
+
path: ".claude/hooks/writeback-gate.sh",
|
|
3474
|
+
required: true,
|
|
3475
|
+
runtimeTargets: ["claude-code", "hybrid"]
|
|
3476
|
+
},
|
|
3477
|
+
{
|
|
3478
|
+
assetId: "build-command-doc",
|
|
3479
|
+
kind: "template",
|
|
3480
|
+
description: "Inline /build command contract",
|
|
3481
|
+
path: ".claude/commands/build.md",
|
|
3482
|
+
required: true,
|
|
3483
|
+
runtimeTargets: ["claude-code", "codex", "hybrid"]
|
|
3484
|
+
},
|
|
3485
|
+
{
|
|
3486
|
+
assetId: "architect-command-doc",
|
|
3487
|
+
kind: "template",
|
|
3488
|
+
description: "Inline /architect command contract",
|
|
3489
|
+
path: ".claude/commands/architect.md",
|
|
3490
|
+
required: true,
|
|
3491
|
+
runtimeTargets: ["claude-code", "codex", "hybrid"]
|
|
3492
|
+
},
|
|
3493
|
+
{
|
|
3494
|
+
assetId: "pipeline-command-doc",
|
|
3495
|
+
kind: "template",
|
|
3496
|
+
description: "Inline /pipeline command contract",
|
|
3497
|
+
path: ".claude/commands/pipeline.md",
|
|
3498
|
+
required: true,
|
|
3499
|
+
runtimeTargets: ["claude-code", "codex", "hybrid"]
|
|
3500
|
+
},
|
|
3501
|
+
{
|
|
3502
|
+
assetId: "pr-command-doc",
|
|
3503
|
+
kind: "template",
|
|
3504
|
+
description: "Inline /pr command contract",
|
|
3505
|
+
path: ".claude/commands/pr.md",
|
|
3506
|
+
required: true,
|
|
3507
|
+
runtimeTargets: ["claude-code", "codex", "hybrid"]
|
|
3508
|
+
},
|
|
3509
|
+
{
|
|
3510
|
+
assetId: "claude-agent-catalog",
|
|
3511
|
+
kind: "agent",
|
|
3512
|
+
description: "Curated agent catalog for architecture, pipeline, QA, and PR review",
|
|
3513
|
+
path: ".claude/agents",
|
|
3514
|
+
required: true,
|
|
3515
|
+
runtimeTargets: ["claude-code", "hybrid"]
|
|
3516
|
+
},
|
|
3517
|
+
{
|
|
3518
|
+
assetId: "claude-skill-catalog",
|
|
3519
|
+
kind: "skill",
|
|
3520
|
+
description: "Skill catalog containing build, pipeline, product-architect, and Lucern workflows",
|
|
3521
|
+
path: ".claude/skills",
|
|
3522
|
+
required: true,
|
|
3523
|
+
runtimeTargets: ["claude-code", "hybrid"]
|
|
3524
|
+
},
|
|
3525
|
+
{
|
|
3526
|
+
assetId: "skills-sync-script",
|
|
3527
|
+
kind: "script",
|
|
3528
|
+
description: "Bridge script for syncing Claude and Codex skill mirrors",
|
|
3529
|
+
path: "scripts/sync_codex_claude_skills.sh",
|
|
3530
|
+
required: true,
|
|
3531
|
+
runtimeTargets: ["codex", "hybrid"]
|
|
3532
|
+
},
|
|
3533
|
+
{
|
|
3534
|
+
assetId: "hooks-doc",
|
|
3535
|
+
kind: "template",
|
|
3536
|
+
description: "Hook architecture and writeback enforcement reference",
|
|
3537
|
+
path: "docs/operations/hooks.md",
|
|
3538
|
+
required: true,
|
|
3539
|
+
runtimeTargets: ["claude-code", "codex", "hybrid"]
|
|
3540
|
+
},
|
|
3541
|
+
{
|
|
3542
|
+
assetId: "setup-ui",
|
|
3543
|
+
kind: "ui",
|
|
3544
|
+
description: "Portal setup surface showing quickstart and bootstrap steps",
|
|
3545
|
+
path: "_template/dev/page.tsx",
|
|
3546
|
+
required: false,
|
|
3547
|
+
runtimeTargets: ["portable", "claude-code", "codex", "hybrid"]
|
|
3548
|
+
}
|
|
3549
|
+
],
|
|
3550
|
+
topicTemplates: [
|
|
3551
|
+
{
|
|
3552
|
+
slug: "migration-precedent",
|
|
3553
|
+
name: "Migration Precedent",
|
|
3554
|
+
description: "Analogous schema and rollout changes worth recalling before execution",
|
|
3555
|
+
parentSlug: "migrations",
|
|
3556
|
+
ontologyId: "software-entities"
|
|
3557
|
+
},
|
|
3558
|
+
{
|
|
3559
|
+
slug: "rollback-playbooks",
|
|
3560
|
+
name: "Rollback Playbooks",
|
|
3561
|
+
description: "Named rollback strategies and canary escape hatches for risky changes",
|
|
3562
|
+
parentSlug: "migrations",
|
|
3563
|
+
ontologyId: "software-entities"
|
|
3564
|
+
},
|
|
3565
|
+
{
|
|
3566
|
+
slug: "review-briefs",
|
|
3567
|
+
name: "Review Briefs",
|
|
3568
|
+
description: "Diff-scoped risk briefs grounded in prior regressions and rationale",
|
|
3569
|
+
parentSlug: "reviews",
|
|
3570
|
+
ontologyId: "software-entities"
|
|
3571
|
+
},
|
|
3572
|
+
{
|
|
3573
|
+
slug: "regression-history",
|
|
3574
|
+
name: "Regression History",
|
|
3575
|
+
description: "Past regressions and approval misses that should influence current reviews",
|
|
3576
|
+
parentSlug: "reviews",
|
|
3577
|
+
ontologyId: "software-entities"
|
|
3578
|
+
},
|
|
3579
|
+
{
|
|
3580
|
+
slug: "active-incidents",
|
|
3581
|
+
name: "Active Incidents",
|
|
3582
|
+
description: "Current incidents with competing hypotheses, mitigations, and contradictions",
|
|
3583
|
+
parentSlug: "incidents",
|
|
3584
|
+
ontologyId: "software-entities"
|
|
3585
|
+
},
|
|
3586
|
+
{
|
|
3587
|
+
slug: "incident-postmortems",
|
|
3588
|
+
name: "Incident Postmortems",
|
|
3589
|
+
description: "Resolved incidents with preserved rationale and follow-up learnings",
|
|
3590
|
+
parentSlug: "incidents",
|
|
3591
|
+
ontologyId: "software-entities"
|
|
3592
|
+
},
|
|
3593
|
+
{
|
|
3594
|
+
slug: "adrs",
|
|
3595
|
+
name: "Architecture Decision Records",
|
|
3596
|
+
description: "Citable architecture records with precedent, objections, and supersessions",
|
|
3597
|
+
parentSlug: "architecture",
|
|
3598
|
+
ontologyId: "software-entities"
|
|
3599
|
+
},
|
|
3600
|
+
{
|
|
3601
|
+
slug: "interface-contracts",
|
|
3602
|
+
name: "Interface Contracts",
|
|
3603
|
+
description: "APIs, boundaries, and contract deltas that architecture work depends on",
|
|
3604
|
+
parentSlug: "architecture",
|
|
3605
|
+
ontologyId: "software-entities"
|
|
3606
|
+
},
|
|
3607
|
+
{
|
|
3608
|
+
slug: "failed-attempts",
|
|
3609
|
+
name: "Failed Attempts",
|
|
3610
|
+
description: "Anti-repetition log for engineering decisions and implementation dead ends",
|
|
3611
|
+
parentSlug: "decision-memory",
|
|
3612
|
+
ontologyId: "software-entities"
|
|
3613
|
+
},
|
|
3614
|
+
{
|
|
3615
|
+
slug: "rationale-recall",
|
|
3616
|
+
name: "Rationale Recall",
|
|
3617
|
+
description: "Recalled rationale snippets and analogs worth citing before new work",
|
|
3618
|
+
parentSlug: "decision-memory",
|
|
3619
|
+
ontologyId: "software-entities"
|
|
3620
|
+
}
|
|
3621
|
+
],
|
|
3622
|
+
installProfiles: [
|
|
3623
|
+
{
|
|
3624
|
+
profileId: "claude-code",
|
|
3625
|
+
name: "Claude Code Engineering Kit",
|
|
3626
|
+
description: "Installs Claude-native hooks, commands, agent catalog, and first-hour engineering prompts on top of Lucern.",
|
|
3627
|
+
runtimeTarget: "claude-code",
|
|
3628
|
+
promptIds: [
|
|
3629
|
+
"claude-quick-reference",
|
|
3630
|
+
"build-command",
|
|
3631
|
+
"architect-command",
|
|
3632
|
+
"pipeline-command",
|
|
3633
|
+
"pr-command",
|
|
3634
|
+
"lucern-generate-questions",
|
|
3635
|
+
"lucern-contradiction-analysis"
|
|
3636
|
+
],
|
|
3637
|
+
toolIds: [
|
|
3638
|
+
"start-investigation",
|
|
3639
|
+
"record-scope-learning",
|
|
3640
|
+
"record-attempt",
|
|
3641
|
+
"pipeline-snapshot",
|
|
3642
|
+
"session-init",
|
|
3643
|
+
"tool-log",
|
|
3644
|
+
"build-bash-gate",
|
|
3645
|
+
"lucern-cli-init",
|
|
3646
|
+
"kit-install"
|
|
3647
|
+
],
|
|
3648
|
+
assetIds: [
|
|
3649
|
+
"claude-instructions",
|
|
3650
|
+
"mcp-config",
|
|
3651
|
+
"kit-manifest",
|
|
3652
|
+
"lucern-launcher",
|
|
3653
|
+
"lucern-shell-wrapper",
|
|
3654
|
+
"lucern-cli-script",
|
|
3655
|
+
"claude-settings",
|
|
3656
|
+
"permission-gate-hook",
|
|
3657
|
+
"inbox-check-hook",
|
|
3658
|
+
"prompt-router-hook",
|
|
3659
|
+
"writeback-gate-hook",
|
|
3660
|
+
"build-command-doc",
|
|
3661
|
+
"architect-command-doc",
|
|
3662
|
+
"pipeline-command-doc",
|
|
3663
|
+
"pr-command-doc",
|
|
3664
|
+
"claude-agent-catalog",
|
|
3665
|
+
"claude-skill-catalog",
|
|
3666
|
+
"hooks-doc",
|
|
3667
|
+
"setup-ui"
|
|
3668
|
+
],
|
|
3669
|
+
defaultTopicSlugs: [
|
|
3670
|
+
"migrations",
|
|
3671
|
+
"reviews",
|
|
3672
|
+
"incidents",
|
|
3673
|
+
"architecture",
|
|
3674
|
+
"decision-memory"
|
|
3675
|
+
]
|
|
3676
|
+
},
|
|
3677
|
+
{
|
|
3678
|
+
profileId: "codex",
|
|
3679
|
+
name: "Codex Engineering Kit",
|
|
3680
|
+
description: "Installs the Codex bridge, Lucern MCP wiring, and the same pack-level workflows without Claude-specific hooks.",
|
|
3681
|
+
runtimeTarget: "codex",
|
|
3682
|
+
promptIds: [
|
|
3683
|
+
"build-command",
|
|
3684
|
+
"architect-command",
|
|
3685
|
+
"pipeline-command",
|
|
3686
|
+
"pr-command",
|
|
3687
|
+
"lucern-generate-questions",
|
|
3688
|
+
"lucern-contradiction-analysis"
|
|
3689
|
+
],
|
|
3690
|
+
toolIds: [
|
|
3691
|
+
"start-investigation",
|
|
3692
|
+
"record-scope-learning",
|
|
3693
|
+
"record-attempt",
|
|
3694
|
+
"pipeline-snapshot",
|
|
3695
|
+
"lucern-cli-init",
|
|
3696
|
+
"kit-install"
|
|
3697
|
+
],
|
|
3698
|
+
assetIds: [
|
|
3699
|
+
"codex-bridge",
|
|
3700
|
+
"mcp-config",
|
|
3701
|
+
"kit-manifest",
|
|
3702
|
+
"lucern-launcher",
|
|
3703
|
+
"lucern-shell-wrapper",
|
|
3704
|
+
"lucern-cli-script",
|
|
3705
|
+
"build-command-doc",
|
|
3706
|
+
"architect-command-doc",
|
|
3707
|
+
"pipeline-command-doc",
|
|
3708
|
+
"pr-command-doc",
|
|
3709
|
+
"claude-skill-catalog",
|
|
3710
|
+
"skills-sync-script",
|
|
3711
|
+
"hooks-doc",
|
|
3712
|
+
"setup-ui"
|
|
3713
|
+
],
|
|
3714
|
+
defaultTopicSlugs: [
|
|
3715
|
+
"migrations",
|
|
3716
|
+
"reviews",
|
|
3717
|
+
"incidents",
|
|
3718
|
+
"architecture",
|
|
3719
|
+
"decision-memory"
|
|
3720
|
+
]
|
|
3721
|
+
},
|
|
3722
|
+
{
|
|
3723
|
+
profileId: "hybrid",
|
|
3724
|
+
name: "Hybrid Engineering Kit",
|
|
3725
|
+
description: "Installs both Claude and Codex entry surfaces against one Lucern-native engineering operating system.",
|
|
3726
|
+
runtimeTarget: "hybrid",
|
|
3727
|
+
promptIds: [
|
|
3728
|
+
"claude-quick-reference",
|
|
3729
|
+
"build-command",
|
|
3730
|
+
"architect-command",
|
|
3731
|
+
"pipeline-command",
|
|
3732
|
+
"pr-command",
|
|
3733
|
+
"lucern-generate-questions",
|
|
3734
|
+
"lucern-contradiction-analysis"
|
|
3735
|
+
],
|
|
3736
|
+
toolIds: [
|
|
3737
|
+
"start-investigation",
|
|
3738
|
+
"record-scope-learning",
|
|
3739
|
+
"record-attempt",
|
|
3740
|
+
"pipeline-snapshot",
|
|
3741
|
+
"session-init",
|
|
3742
|
+
"tool-log",
|
|
3743
|
+
"build-bash-gate",
|
|
3744
|
+
"lucern-cli-init",
|
|
3745
|
+
"kit-install"
|
|
3746
|
+
],
|
|
3747
|
+
assetIds: [
|
|
3748
|
+
"claude-instructions",
|
|
3749
|
+
"codex-bridge",
|
|
3750
|
+
"mcp-config",
|
|
3751
|
+
"kit-manifest",
|
|
3752
|
+
"lucern-launcher",
|
|
3753
|
+
"lucern-shell-wrapper",
|
|
3754
|
+
"lucern-cli-script",
|
|
3755
|
+
"claude-settings",
|
|
3756
|
+
"permission-gate-hook",
|
|
3757
|
+
"inbox-check-hook",
|
|
3758
|
+
"prompt-router-hook",
|
|
3759
|
+
"writeback-gate-hook",
|
|
3760
|
+
"build-command-doc",
|
|
3761
|
+
"architect-command-doc",
|
|
3762
|
+
"pipeline-command-doc",
|
|
3763
|
+
"pr-command-doc",
|
|
3764
|
+
"claude-agent-catalog",
|
|
3765
|
+
"claude-skill-catalog",
|
|
3766
|
+
"skills-sync-script",
|
|
3767
|
+
"hooks-doc",
|
|
3768
|
+
"setup-ui"
|
|
3769
|
+
],
|
|
3770
|
+
defaultTopicSlugs: [
|
|
3771
|
+
"migrations",
|
|
3772
|
+
"reviews",
|
|
3773
|
+
"incidents",
|
|
3774
|
+
"architecture",
|
|
3775
|
+
"decision-memory"
|
|
3776
|
+
]
|
|
3777
|
+
}
|
|
3778
|
+
]
|
|
3779
|
+
},
|
|
3780
|
+
appPackKeys: [
|
|
3781
|
+
"chat-v1",
|
|
3782
|
+
"documents-v1",
|
|
3783
|
+
"epistemic-algorithms-v1",
|
|
3784
|
+
"graph-visualization-v1",
|
|
3785
|
+
"task-management-v1"
|
|
3786
|
+
],
|
|
3787
|
+
methodologyPackId: "developer"
|
|
3788
|
+
});
|
|
3789
|
+
|
|
3790
|
+
// src/domain-pack/packs/index.ts
|
|
3791
|
+
var DOMAIN_PACKS = {
|
|
3792
|
+
"developer-reasoning": DEVELOPER_REASONING_PACK,
|
|
3793
|
+
"engineering-accelerator": ENGINEERING_ACCELERATOR_PACK
|
|
3794
|
+
};
|
|
3795
|
+
var shapingContributionRegistry = createShapingContributionRegistry(
|
|
3796
|
+
Object.values(DOMAIN_PACKS)
|
|
3797
|
+
);
|
|
3798
|
+
function getDomainPack(packId) {
|
|
3799
|
+
return DOMAIN_PACKS[packId] ?? null;
|
|
3800
|
+
}
|
|
3801
|
+
function listDomainPacks() {
|
|
3802
|
+
return Object.keys(DOMAIN_PACKS);
|
|
3803
|
+
}
|
|
3804
|
+
function getShapingContribution(packId) {
|
|
3805
|
+
return shapingContributionRegistry.get(packId);
|
|
3806
|
+
}
|
|
3807
|
+
function listShapingContributions() {
|
|
3808
|
+
return shapingContributionRegistry.list();
|
|
3809
|
+
}
|
|
3810
|
+
|
|
3811
|
+
export { DEVELOPER_REASONING_PACK, ENGINEERING_ACCELERATOR_PACK, SOFTWARE_ENTITIES_V1, buildShapingContribution, createDomainPackAuthoringTools, createShapingContributionRegistry, defineDomainPack, defineDomainPackAuthoringManifest, getDomainPack, getShapingContribution, listDomainPacks, listShapingContributions, parseDomainPackAuthoringManifest, previewDomainPackAuthoringManifest, previewDomainPackAuthoringManifestSource, publishDomainPackAuthoringManifest, publishDomainPackAuthoringManifestSource, serializeDomainPackAuthoringManifest, validateDomainPack, validateDomainPackAuthoringManifest, validateDomainPackAuthoringManifestSource, validateShapingContribution };
|
|
3812
|
+
//# sourceMappingURL=domain-pack.js.map
|
|
3813
|
+
//# sourceMappingURL=domain-pack.js.map
|