@lucern/pack-host 0.3.0-alpha.9 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/dist/domain-pack/authoring.core.d.ts +161 -0
  2. package/dist/domain-pack/authoring.core.js +411 -0
  3. package/dist/domain-pack/authoring.core.js.map +1 -0
  4. package/dist/domain-pack/authoring.d.ts +12 -170
  5. package/dist/domain-pack/authoring.js +1155 -1098
  6. package/dist/domain-pack/authoring.js.map +1 -1
  7. package/dist/domain-pack/authoring.validation.d.ts +28 -0
  8. package/dist/domain-pack/authoring.validation.js +1944 -0
  9. package/dist/domain-pack/authoring.validation.js.map +1 -0
  10. package/dist/domain-pack/index.d.ts +2 -1
  11. package/dist/domain-pack/index.js +1979 -1917
  12. package/dist/domain-pack/index.js.map +1 -1
  13. package/dist/domain-pack/packs/engineering-accelerator-tail.d.ts +256 -0
  14. package/dist/domain-pack/packs/engineering-accelerator-tail.js +716 -0
  15. package/dist/domain-pack/packs/engineering-accelerator-tail.js.map +1 -0
  16. package/dist/domain-pack/packs/engineering-accelerator.js +790 -785
  17. package/dist/domain-pack/packs/engineering-accelerator.js.map +1 -1
  18. package/dist/domain-pack/packs/index.js +790 -785
  19. package/dist/domain-pack/packs/index.js.map +1 -1
  20. package/dist/domain-pack.d.ts +2 -1
  21. package/dist/domain-pack.js +1979 -1917
  22. package/dist/domain-pack.js.map +1 -1
  23. package/dist/index.d.ts +3 -1
  24. package/dist/index.js +1843 -1661
  25. package/dist/index.js.map +1 -1
  26. package/dist/manifests/chat-v1.js +17 -6
  27. package/dist/manifests/chat-v1.js.map +1 -1
  28. package/dist/manifests/deals-v1.js +10 -7
  29. package/dist/manifests/deals-v1.js.map +1 -1
  30. package/dist/manifests/decisions-v1.js +11 -4
  31. package/dist/manifests/decisions-v1.js.map +1 -1
  32. package/dist/manifests/documents-v1.js +12 -12
  33. package/dist/manifests/documents-v1.js.map +1 -1
  34. package/dist/manifests/epistemic-algorithms-v1.js +11 -6
  35. package/dist/manifests/epistemic-algorithms-v1.js.map +1 -1
  36. package/dist/manifests/graph-visualization-v1.js +9 -5
  37. package/dist/manifests/graph-visualization-v1.js.map +1 -1
  38. package/dist/manifests/index.d.ts +1 -0
  39. package/dist/manifests/index.js +230 -110
  40. package/dist/manifests/index.js.map +1 -1
  41. package/dist/manifests/news-v1.js +12 -13
  42. package/dist/manifests/news-v1.js.map +1 -1
  43. package/dist/manifests/philosophy-mode-v1.js +10 -12
  44. package/dist/manifests/philosophy-mode-v1.js.map +1 -1
  45. package/dist/manifests/sprints-v1.d.ts +10 -0
  46. package/dist/manifests/sprints-v1.js +106 -0
  47. package/dist/manifests/sprints-v1.js.map +1 -0
  48. package/dist/manifests/task-management-v1.js +18 -6
  49. package/dist/manifests/task-management-v1.js.map +1 -1
  50. package/dist/manifests/team-analysis-v1.js +12 -9
  51. package/dist/manifests/team-analysis-v1.js.map +1 -1
  52. package/dist/manifests/themes-v1.js +12 -16
  53. package/dist/manifests/themes-v1.js.map +1 -1
  54. package/dist/manifests/user-profiles-v1.js +9 -13
  55. package/dist/manifests/user-profiles-v1.js.map +1 -1
  56. package/dist/manifests.d.ts +1 -0
  57. package/dist/manifests.js +230 -110
  58. package/dist/manifests.js.map +1 -1
  59. package/dist/proof-attestation.json +1 -1
  60. package/dist/registry.js +229 -109
  61. package/dist/registry.js.map +1 -1
  62. package/package.json +2 -1
@@ -60,1122 +60,1186 @@ function defineDomainPack(input) {
60
60
  };
61
61
  }
62
62
 
63
- // src/domain-pack/validation.ts
64
- function issue(code, message, path, severity = "error") {
65
- return { code, severity, message, path };
63
+ // src/domain-pack/authoring.core.ts
64
+ var DOMAIN_PACK_MANIFEST_KIND = "lucern-domain-pack-manifest";
65
+ var CURRENT_MANIFEST_VERSION = "1.0.0";
66
+ function isPlainObject(value) {
67
+ return typeof value === "object" && value !== null && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype;
66
68
  }
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) {
69
+ function dedupeStrings2(values) {
82
70
  if (!values) {
83
- return [];
71
+ return void 0;
84
72
  }
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
- });
73
+ return Array.from(
74
+ new Set(values.map((value) => value.trim()).filter((value) => value.length))
75
+ );
97
76
  }
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;
77
+ function normalizeRuntimeTargets2(values) {
78
+ return values ? dedupeStrings2(values) : void 0;
112
79
  }
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
- );
80
+ function normalizeFrameworks(frameworks) {
81
+ if (!frameworks) {
82
+ return void 0;
124
83
  }
125
- if (!prompt.ref?.trim()) {
126
- issues.push(
127
- issue("MISSING_PROMPT_REF", "prompt binding requires ref", `${path}.ref`)
128
- );
84
+ return frameworks.map((framework) => ({
85
+ ...framework,
86
+ frameworkId: framework.frameworkId.trim(),
87
+ version: framework.version.trim(),
88
+ versionConstraint: framework.versionConstraint?.trim(),
89
+ runtimeTargets: normalizeRuntimeTargets2(framework.runtimeTargets)
90
+ }));
91
+ }
92
+ function normalizeSchemaExtensions(extensions) {
93
+ if (!extensions) {
94
+ return void 0;
129
95
  }
130
- issues.push(
131
- ...validateRuntimeTargets(prompt.runtimeTargets, `${path}.runtimeTargets`)
132
- );
133
- return issues;
96
+ return extensions.map((extension) => ({
97
+ ...extension,
98
+ extensionId: extension.extensionId.trim(),
99
+ target: extension.target,
100
+ description: extension.description.trim(),
101
+ version: extension.version.trim(),
102
+ extends: extension.extends?.trim()
103
+ }));
134
104
  }
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
- );
105
+ function normalizeOntologyExtensions(extensions) {
106
+ if (!extensions) {
107
+ return void 0;
142
108
  }
143
- if (!tool.entrypoint?.trim()) {
144
- issues.push(
145
- issue(
146
- "MISSING_TOOL_ENTRYPOINT",
147
- "tool binding requires entrypoint",
148
- `${path}.entrypoint`
149
- )
150
- );
109
+ return extensions.map((extension) => ({
110
+ ...extension,
111
+ extensionId: extension.extensionId.trim(),
112
+ ontologyId: extension.ontologyId.trim(),
113
+ baseVersionConstraint: extension.baseVersionConstraint.trim(),
114
+ entityTypes: extension.entityTypes?.map((entityType) => ({
115
+ ...entityType,
116
+ value: entityType.value.trim(),
117
+ label: entityType.label.trim(),
118
+ description: entityType.description?.trim(),
119
+ subtypes: dedupeStrings2(entityType.subtypes)
120
+ })),
121
+ edgeTypes: extension.edgeTypes?.map((edgeType) => ({
122
+ ...edgeType,
123
+ value: edgeType.value.trim(),
124
+ label: edgeType.label.trim(),
125
+ description: edgeType.description?.trim(),
126
+ sourceTypes: dedupeStrings2(edgeType.sourceTypes),
127
+ targetTypes: dedupeStrings2(edgeType.targetTypes)
128
+ }))
129
+ }));
130
+ }
131
+ function normalizeLineage(lineage) {
132
+ if (!lineage) {
133
+ return { mode: "root" };
151
134
  }
152
- issues.push(
153
- ...validateRuntimeTargets(tool.runtimeTargets, `${path}.runtimeTargets`)
154
- );
155
- return issues;
135
+ return {
136
+ mode: lineage.mode,
137
+ parentPackId: lineage.parentPackId?.trim(),
138
+ parentVersion: lineage.parentVersion?.trim(),
139
+ parentManifestDigest: lineage.parentManifestDigest?.trim(),
140
+ supersedesPackId: lineage.supersedesPackId?.trim(),
141
+ notes: lineage.notes?.trim()
142
+ };
156
143
  }
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
- );
144
+ function normalizeMetadata(metadata) {
145
+ if (!metadata) {
146
+ return void 0;
168
147
  }
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
- );
148
+ return {
149
+ description: metadata.description?.trim(),
150
+ owner: metadata.owner?.trim(),
151
+ tags: dedupeStrings2(metadata.tags)
152
+ };
153
+ }
154
+ function toDomainPack(pack) {
155
+ return defineDomainPack(pack);
156
+ }
157
+ function defineDomainPackAuthoringManifest(input) {
158
+ return {
159
+ kind: input.kind ?? DOMAIN_PACK_MANIFEST_KIND,
160
+ manifestVersion: input.manifestVersion?.trim() || CURRENT_MANIFEST_VERSION,
161
+ pack: toDomainPack(input.pack),
162
+ frameworks: normalizeFrameworks(input.frameworks),
163
+ schemaExtensions: normalizeSchemaExtensions(input.schemaExtensions),
164
+ ontologyExtensions: normalizeOntologyExtensions(input.ontologyExtensions),
165
+ lineage: normalizeLineage(input.lineage),
166
+ metadata: normalizeMetadata(input.metadata)
167
+ };
168
+ }
169
+ function countManifestArtifacts(manifest) {
170
+ if (!manifest) {
171
+ return {
172
+ topicRoots: 0,
173
+ workflows: 0,
174
+ gates: 0,
175
+ artifacts: 0,
176
+ roles: 0,
177
+ prompts: 0,
178
+ tools: 0,
179
+ setupAssets: 0,
180
+ installProfiles: 0,
181
+ frameworks: 0,
182
+ schemaExtensions: 0,
183
+ ontologyExtensions: 0
184
+ };
177
185
  }
178
- issues.push(
179
- ...validateRuntimeTargets(asset.runtimeTargets, `${path}.runtimeTargets`)
180
- );
181
- return issues;
186
+ return {
187
+ topicRoots: manifest.pack.topicRoots.length,
188
+ workflows: manifest.pack.workflows.length,
189
+ gates: manifest.pack.gates.length,
190
+ artifacts: manifest.pack.artifacts.length,
191
+ roles: manifest.pack.roles.length,
192
+ prompts: manifest.pack.operatingSystem?.prompts?.length ?? 0,
193
+ tools: manifest.pack.operatingSystem?.tools?.length ?? 0,
194
+ setupAssets: manifest.pack.operatingSystem?.setupAssets?.length ?? 0,
195
+ installProfiles: manifest.pack.operatingSystem?.installProfiles?.length ?? 0,
196
+ frameworks: manifest.frameworks?.length ?? 0,
197
+ schemaExtensions: manifest.schemaExtensions?.length ?? 0,
198
+ ontologyExtensions: manifest.ontologyExtensions?.length ?? 0
199
+ };
182
200
  }
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
- );
201
+ function sortJsonValue(value) {
202
+ if (Array.isArray(value)) {
203
+ return value.map(sortJsonValue);
194
204
  }
195
- if (!template.template?.trim()) {
196
- issues.push(
197
- issue(
198
- "MISSING_SHAPING_TEMPLATE",
199
- "question template requires template text",
200
- `${path}.template`
201
- )
205
+ if (isPlainObject(value)) {
206
+ return Object.fromEntries(
207
+ Object.entries(value).filter(([, entryValue]) => entryValue !== void 0).sort(([left], [right]) => left.localeCompare(right)).map(([key, entryValue]) => [key, sortJsonValue(entryValue)])
202
208
  );
203
209
  }
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
- );
210
+ return value;
211
+ }
212
+ function toYamlScalar(value) {
213
+ if (value === null) {
214
+ return "null";
212
215
  }
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
- );
216
+ if (typeof value === "boolean" || typeof value === "number") {
217
+ return String(value);
233
218
  }
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
- );
219
+ return JSON.stringify(String(value));
220
+ }
221
+ function renderYaml(value, indent = 0) {
222
+ const prefix = " ".repeat(indent);
223
+ if (Array.isArray(value)) {
224
+ if (value.length === 0) {
225
+ return [`${prefix}[]`];
226
+ }
227
+ return value.flatMap((entry) => {
228
+ if (Array.isArray(entry) || isPlainObject(entry)) {
229
+ return [`${prefix}-`, ...renderYaml(entry, indent + 2)];
230
+ }
231
+ return [`${prefix}- ${toYamlScalar(entry)}`];
232
+ });
242
233
  }
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
- );
234
+ if (isPlainObject(value)) {
235
+ const entries = Object.entries(value);
236
+ if (entries.length === 0) {
237
+ return [`${prefix}{}`];
266
238
  }
239
+ return entries.flatMap(([key, entryValue]) => {
240
+ if (entryValue === void 0) {
241
+ return [];
242
+ }
243
+ if (Array.isArray(entryValue)) {
244
+ if (entryValue.length === 0) {
245
+ return [`${prefix}${key}: []`];
246
+ }
247
+ return [`${prefix}${key}:`, ...renderYaml(entryValue, indent + 2)];
248
+ }
249
+ if (isPlainObject(entryValue)) {
250
+ if (Object.keys(entryValue).length === 0) {
251
+ return [`${prefix}${key}: {}`];
252
+ }
253
+ return [`${prefix}${key}:`, ...renderYaml(entryValue, indent + 2)];
254
+ }
255
+ return [`${prefix}${key}: ${toYamlScalar(entryValue)}`];
256
+ });
267
257
  }
268
- return issues;
258
+ return [`${prefix}${toYamlScalar(value)}`];
269
259
  }
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
- );
260
+ function countIndent(line) {
261
+ return line.length - line.trimStart().length;
262
+ }
263
+ function parseYamlScalar(raw) {
264
+ const value = raw.trim();
265
+ if (value === "null") {
266
+ return null;
281
267
  }
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
- );
268
+ if (value === "true") {
269
+ return true;
290
270
  }
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
- }
271
+ if (value === "false") {
272
+ return false;
315
273
  }
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
- );
274
+ if (/^-?\d+(?:\.\d+)?$/.test(value)) {
275
+ return Number(value);
337
276
  }
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
- );
277
+ if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
278
+ if (value.startsWith("'")) {
279
+ return value.slice(1, -1).replace(/''/g, "'");
280
+ }
281
+ return JSON.parse(value);
346
282
  }
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
- );
283
+ if (value === "[]") {
284
+ return [];
355
285
  }
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
- );
286
+ if (value === "{}") {
287
+ return {};
364
288
  }
365
- return issues;
289
+ return value;
366
290
  }
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
- );
291
+ function splitYamlKeyValue(trimmed) {
292
+ const separatorIndex = trimmed.indexOf(":");
293
+ if (separatorIndex === -1) {
294
+ throw new Error(`Invalid YAML mapping entry: ${trimmed}`);
378
295
  }
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
- );
296
+ const key = trimmed.slice(0, separatorIndex).trim();
297
+ const value = trimmed.slice(separatorIndex + 1).trim();
298
+ return { key, value: value.length ? value : null };
299
+ }
300
+ function parseYamlDocument(text) {
301
+ const rawLines = text.replace(/\r\n/g, "\n").split("\n").map((line) => line.replace(/\t/g, " "));
302
+ const lines = rawLines.filter((line) => {
303
+ const trimmed = line.trim();
304
+ return trimmed.length > 0 && trimmed !== "---" && trimmed !== "...";
305
+ });
306
+ let index = 0;
307
+ function parseBlock(indent) {
308
+ if (index >= lines.length) {
309
+ return {};
310
+ }
311
+ const currentLine = lines[index];
312
+ const currentIndent = countIndent(currentLine);
313
+ if (currentIndent < indent) {
314
+ return {};
315
+ }
316
+ if (currentLine.trimStart().startsWith("-")) {
317
+ return parseArray(indent);
318
+ }
319
+ return parseObject(indent);
387
320
  }
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
- );
321
+ function parseArray(indent) {
322
+ const items = [];
323
+ while (index < lines.length) {
324
+ const line = lines[index];
325
+ const currentIndent = countIndent(line);
326
+ if (currentIndent < indent) {
327
+ break;
328
+ }
329
+ if (currentIndent !== indent) {
330
+ throw new Error(`Invalid YAML indentation near: ${line.trim()}`);
331
+ }
332
+ const trimmed = line.trimStart();
333
+ if (!trimmed.startsWith("-")) {
334
+ break;
335
+ }
336
+ const rest = trimmed.slice(1).trimStart();
337
+ index += 1;
338
+ if (!rest.length) {
339
+ items.push(parseBlock(indent + 2));
340
+ continue;
341
+ }
342
+ items.push(parseYamlScalar(rest));
415
343
  }
344
+ return items;
416
345
  }
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
- );
346
+ function parseObject(indent) {
347
+ const objectValue = {};
348
+ while (index < lines.length) {
349
+ const line = lines[index];
350
+ const currentIndent = countIndent(line);
351
+ if (currentIndent < indent) {
352
+ break;
353
+ }
354
+ if (currentIndent !== indent) {
355
+ throw new Error(`Invalid YAML indentation near: ${line.trim()}`);
356
+ }
357
+ const trimmed = line.trim();
358
+ if (trimmed.startsWith("-")) {
359
+ break;
360
+ }
361
+ const { key, value } = splitYamlKeyValue(trimmed);
362
+ index += 1;
363
+ objectValue[key] = value === null ? parseBlock(indent + 2) : parseYamlScalar(value);
426
364
  }
365
+ return objectValue;
427
366
  }
428
- for (const [assetIndex, assetId] of profile.assetIds.entries()) {
429
- if (!knownAssetIds.has(assetId)) {
430
- issues.push(
367
+ return parseBlock(0);
368
+ }
369
+ function detectDomainPackManifestFormat(source, explicitFormat) {
370
+ if (explicitFormat) {
371
+ return explicitFormat;
372
+ }
373
+ const trimmed = source.trim();
374
+ if (trimmed.startsWith("{")) {
375
+ return "json";
376
+ }
377
+ return "yaml";
378
+ }
379
+ function serializeDomainPackAuthoringManifest(manifest, format = "json") {
380
+ const canonicalValue = sortJsonValue(manifest);
381
+ if (format === "json") {
382
+ return `${JSON.stringify(canonicalValue, null, 2)}
383
+ `;
384
+ }
385
+ return `${renderYaml(canonicalValue).join("\n")}
386
+ `;
387
+ }
388
+ function parseDomainPackAuthoringManifest(source, format) {
389
+ const detectedFormat = detectDomainPackManifestFormat(source, format);
390
+ const parsed = detectedFormat === "json" ? JSON.parse(source) : parseYamlDocument(source);
391
+ if (!isPlainObject(parsed)) {
392
+ throw new Error("Domain pack manifest must parse to an object.");
393
+ }
394
+ if (!("pack" in parsed)) {
395
+ throw new Error("Domain pack manifest requires a top-level pack object.");
396
+ }
397
+ return defineDomainPackAuthoringManifest({
398
+ kind: parsed.kind,
399
+ manifestVersion: parsed.manifestVersion,
400
+ pack: parsed.pack,
401
+ frameworks: parsed.frameworks,
402
+ schemaExtensions: parsed.schemaExtensions,
403
+ ontologyExtensions: parsed.ontologyExtensions,
404
+ lineage: parsed.lineage,
405
+ metadata: parsed.metadata
406
+ });
407
+ }
408
+
409
+ // src/domain-pack/validation.ts
410
+ function issue(code, message, path, severity = "error") {
411
+ return { code, severity, message, path };
412
+ }
413
+ var KEBAB_CASE = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
414
+ 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-]+)*))?$/;
415
+ var SHAPING_QUESTION_TYPES = /* @__PURE__ */ new Set([
416
+ "validation",
417
+ "falsification",
418
+ "assumption_probe",
419
+ "counterfactual",
420
+ "scope",
421
+ "comparison",
422
+ "mechanism",
423
+ "general"
424
+ ]);
425
+ var RUNTIME_TARGETS = /* @__PURE__ */ new Set(["claude-code", "codex", "hybrid", "portable"]);
426
+ var ONTOLOGY_PROVISION_MODES = /* @__PURE__ */ new Set(["bind", "seed", "extend"]);
427
+ function validateStringArray(values, path, label) {
428
+ if (!values) {
429
+ return [];
430
+ }
431
+ return values.flatMap((value, index) => {
432
+ if (!value?.trim()) {
433
+ return [
431
434
  issue(
432
- "UNKNOWN_SETUP_ASSET_REF",
433
- `install profile references unknown setup asset "${assetId}"`,
434
- `${path}.assetIds[${assetIndex}]`
435
+ "INVALID_SHAPING_CONDITION",
436
+ `${label} must not contain empty strings`,
437
+ `${path}[${index}]`
435
438
  )
436
- );
439
+ ];
437
440
  }
438
- }
439
- for (const [topicIndex, topicSlug] of profile.defaultTopicSlugs.entries()) {
440
- if (!knownTopicSlugs.has(topicSlug)) {
441
+ return [];
442
+ });
443
+ }
444
+ function validateRuntimeTargets(values, path) {
445
+ const issues = validateStringArray(values, path, "runtimeTargets");
446
+ for (const [index, value] of (values || []).entries()) {
447
+ if (!RUNTIME_TARGETS.has(value)) {
441
448
  issues.push(
442
449
  issue(
443
- "UNKNOWN_TOPIC_REF",
444
- `install profile references unknown topic "${topicSlug}"`,
445
- `${path}.defaultTopicSlugs[${topicIndex}]`
450
+ "INVALID_RUNTIME_TARGET",
451
+ `Unsupported runtime target "${value}"`,
452
+ `${path}[${index}]`
446
453
  )
447
454
  );
448
455
  }
449
456
  }
450
457
  return issues;
451
458
  }
452
- function checkDuplicateIds(items, idField, path) {
459
+ function validatePromptBinding(prompt, index) {
460
+ const path = `operatingSystem.prompts[${index}]`;
453
461
  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);
462
+ if (!prompt.promptId?.trim()) {
463
+ issues.push(
464
+ issue(
465
+ "MISSING_PROMPT_ID",
466
+ "prompt binding requires promptId",
467
+ `${path}.promptId`
468
+ )
469
+ );
470
+ }
471
+ if (!prompt.ref?.trim()) {
472
+ issues.push(
473
+ issue("MISSING_PROMPT_REF", "prompt binding requires ref", `${path}.ref`)
474
+ );
467
475
  }
476
+ issues.push(
477
+ ...validateRuntimeTargets(prompt.runtimeTargets, `${path}.runtimeTargets`)
478
+ );
468
479
  return issues;
469
480
  }
470
- function validateDomainPack(pack) {
481
+ function validateToolBinding(tool, index) {
482
+ const path = `operatingSystem.tools[${index}]`;
471
483
  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)) {
484
+ if (!tool.toolId?.trim()) {
485
+ issues.push(
486
+ issue("MISSING_TOOL_ID", "tool binding requires toolId", `${path}.toolId`)
487
+ );
488
+ }
489
+ if (!tool.entrypoint?.trim()) {
475
490
  issues.push(
476
491
  issue(
477
- "INVALID_PACK_ID",
478
- `packId "${pack.packId}" must be kebab-case`,
479
- "packId"
492
+ "MISSING_TOOL_ENTRYPOINT",
493
+ "tool binding requires entrypoint",
494
+ `${path}.entrypoint`
480
495
  )
481
496
  );
482
497
  }
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)) {
498
+ issues.push(
499
+ ...validateRuntimeTargets(tool.runtimeTargets, `${path}.runtimeTargets`)
500
+ );
501
+ return issues;
502
+ }
503
+ function validateSetupAsset(asset, index) {
504
+ const path = `operatingSystem.setupAssets[${index}]`;
505
+ const issues = [];
506
+ if (!asset.assetId?.trim()) {
489
507
  issues.push(
490
508
  issue(
491
- "INVALID_VERSION",
492
- `version "${pack.version}" must be valid semver`,
493
- "version"
509
+ "MISSING_SETUP_ASSET_ID",
510
+ "setup asset requires assetId",
511
+ `${path}.assetId`
494
512
  )
495
513
  );
496
514
  }
497
- if (!pack.ontologyBindings || pack.ontologyBindings.length === 0) {
515
+ if (!asset.path?.trim()) {
498
516
  issues.push(
499
517
  issue(
500
- "MISSING_ONTOLOGY_BINDINGS",
501
- "At least one ontologyBinding is required",
502
- "ontologyBindings"
518
+ "MISSING_SETUP_ASSET_PATH",
519
+ "setup asset requires path",
520
+ `${path}.path`
503
521
  )
504
522
  );
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
523
  }
557
- if (!pack.topicRoots || pack.topicRoots.length === 0) {
524
+ issues.push(
525
+ ...validateRuntimeTargets(asset.runtimeTargets, `${path}.runtimeTargets`)
526
+ );
527
+ return issues;
528
+ }
529
+ function validateQuestionTemplate(template, index) {
530
+ const path = `inquiryShaping.questionTemplates[${index}]`;
531
+ const issues = [];
532
+ if (!template.templateId?.trim()) {
558
533
  issues.push(
559
534
  issue(
560
- "MISSING_TOPIC_ROOTS",
561
- "At least one topicRoot is required",
562
- "topicRoots"
535
+ "MISSING_SHAPING_TEMPLATE_ID",
536
+ "question template requires templateId",
537
+ `${path}.templateId`
563
538
  )
564
539
  );
565
- } else {
540
+ }
541
+ if (!template.template?.trim()) {
566
542
  issues.push(
567
- ...checkDuplicateIds(
568
- pack.topicRoots,
569
- "slug",
570
- "topicRoots"
543
+ issue(
544
+ "MISSING_SHAPING_TEMPLATE",
545
+ "question template requires template text",
546
+ `${path}.template`
571
547
  )
572
548
  );
573
549
  }
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 {
550
+ if (!SHAPING_QUESTION_TYPES.has(template.questionType)) {
670
551
  issues.push(
671
- ...checkDuplicateIds(
672
- pack.roles,
673
- "roleId",
674
- "roles"
552
+ issue(
553
+ "INVALID_SHAPING_QUESTION_TYPE",
554
+ `Unsupported questionType "${template.questionType}"`,
555
+ `${path}.questionType`
675
556
  )
676
557
  );
677
558
  }
678
- const knownGateIds = new Set(pack.gates?.map((g) => g.gateId) ?? []);
679
- const knownArtifactIds = new Set(
680
- pack.artifacts?.map((a) => a.artifactId) ?? []
559
+ issues.push(
560
+ ...validateStringArray(
561
+ template.whenObjectiveIncludes,
562
+ `${path}.whenObjectiveIncludes`,
563
+ "whenObjectiveIncludes"
564
+ )
681
565
  );
682
- const knownRoleIds = new Set(pack.roles?.map((r) => r.roleId) ?? []);
683
- if (pack.gates) {
566
+ return issues;
567
+ }
568
+ function validateTaskTemplate(template, index) {
569
+ const path = `inquiryShaping.taskTemplates[${index}]`;
570
+ const issues = [];
571
+ if (!template.templateId?.trim()) {
684
572
  issues.push(
685
- ...checkDuplicateIds(
686
- pack.gates,
687
- "gateId",
688
- "gates"
573
+ issue(
574
+ "MISSING_TASK_GENERATOR_ID",
575
+ "task template requires templateId",
576
+ `${path}.templateId`
689
577
  )
690
578
  );
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
579
  }
712
- if (pack.artifacts) {
580
+ if (!template.title?.trim()) {
713
581
  issues.push(
714
- ...checkDuplicateIds(
715
- pack.artifacts,
716
- "artifactId",
717
- "artifacts"
582
+ issue(
583
+ "MISSING_TASK_GENERATOR_TITLE",
584
+ "task template requires title",
585
+ `${path}.title`
718
586
  )
719
587
  );
720
588
  }
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
- }
589
+ issues.push(
590
+ ...validateStringArray(
591
+ template.whenObjectiveIncludes,
592
+ `${path}.whenObjectiveIncludes`,
593
+ "whenObjectiveIncludes"
594
+ )
595
+ );
596
+ issues.push(
597
+ ...validateStringArray(
598
+ template.whenQuestionTypes,
599
+ `${path}.whenQuestionTypes`,
600
+ "whenQuestionTypes"
601
+ )
602
+ );
603
+ for (const [questionTypeIndex, questionType] of (template.whenQuestionTypes || []).entries()) {
604
+ if (!SHAPING_QUESTION_TYPES.has(questionType)) {
605
+ issues.push(
606
+ issue(
607
+ "INVALID_TASK_GENERATOR_QUESTION_TYPE",
608
+ `Unsupported whenQuestionTypes value "${questionType}"`,
609
+ `${path}.whenQuestionTypes[${questionTypeIndex}]`
610
+ )
611
+ );
787
612
  }
788
613
  }
789
- if (pack.inquiryShaping) {
790
- if (pack.inquiryShaping.questionTemplates) {
614
+ return issues;
615
+ }
616
+ function validateFrameworkHint(hint, index) {
617
+ const path = `inquiryShaping.frameworkHints[${index}]`;
618
+ const issues = [];
619
+ if (!hint.frameworkName?.trim()) {
620
+ issues.push(
621
+ issue(
622
+ "MISSING_FRAMEWORK_HOOK_NAME",
623
+ "framework hint requires frameworkName",
624
+ `${path}.frameworkName`
625
+ )
626
+ );
627
+ }
628
+ if (hint.boost != null && (!Number.isFinite(hint.boost) || hint.boost < 0)) {
629
+ issues.push(
630
+ issue(
631
+ "INVALID_FRAMEWORK_HOOK_BOOST",
632
+ "framework hint boost must be a non-negative number",
633
+ `${path}.boost`
634
+ )
635
+ );
636
+ }
637
+ issues.push(
638
+ ...validateStringArray(
639
+ hint.whenObjectiveIncludes,
640
+ `${path}.whenObjectiveIncludes`,
641
+ "whenObjectiveIncludes"
642
+ )
643
+ );
644
+ issues.push(
645
+ ...validateStringArray(
646
+ hint.whenQuestionTypes,
647
+ `${path}.whenQuestionTypes`,
648
+ "whenQuestionTypes"
649
+ )
650
+ );
651
+ for (const [questionTypeIndex, questionType] of (hint.whenQuestionTypes || []).entries()) {
652
+ if (!SHAPING_QUESTION_TYPES.has(questionType)) {
791
653
  issues.push(
792
- ...checkDuplicateIds(
793
- pack.inquiryShaping.questionTemplates,
794
- "templateId",
795
- "inquiryShaping.questionTemplates"
654
+ issue(
655
+ "INVALID_FRAMEWORK_HOOK_QUESTION_TYPE",
656
+ `Unsupported whenQuestionTypes value "${questionType}"`,
657
+ `${path}.whenQuestionTypes[${questionTypeIndex}]`
796
658
  )
797
659
  );
798
- pack.inquiryShaping.questionTemplates.forEach((template, index) => {
799
- issues.push(...validateQuestionTemplate(template, index));
800
- });
801
660
  }
802
- if (pack.inquiryShaping.taskTemplates) {
661
+ }
662
+ return issues;
663
+ }
664
+ function validateTopicTemplate(template, index, knownTopicSlugs) {
665
+ const path = `operatingSystem.topicTemplates[${index}]`;
666
+ const issues = [];
667
+ if (!template.slug?.trim()) {
668
+ issues.push(
669
+ issue(
670
+ "MISSING_TOPIC_TEMPLATE_SLUG",
671
+ "topic template requires slug",
672
+ `${path}.slug`
673
+ )
674
+ );
675
+ } else if (!KEBAB_CASE.test(template.slug)) {
676
+ issues.push(
677
+ issue(
678
+ "INVALID_TOPIC_TEMPLATE_SLUG",
679
+ `topic template slug "${template.slug}" must be kebab-case`,
680
+ `${path}.slug`
681
+ )
682
+ );
683
+ }
684
+ if (!template.name?.trim()) {
685
+ issues.push(
686
+ issue(
687
+ "MISSING_TOPIC_TEMPLATE_NAME",
688
+ "topic template requires name",
689
+ `${path}.name`
690
+ )
691
+ );
692
+ }
693
+ if (!template.description?.trim()) {
694
+ issues.push(
695
+ issue(
696
+ "MISSING_TOPIC_TEMPLATE_DESCRIPTION",
697
+ "topic template requires description",
698
+ `${path}.description`
699
+ )
700
+ );
701
+ }
702
+ if (template.parentSlug && !knownTopicSlugs.has(template.parentSlug)) {
703
+ issues.push(
704
+ issue(
705
+ "UNKNOWN_TOPIC_PARENT",
706
+ `topic template references unknown parent "${template.parentSlug}"`,
707
+ `${path}.parentSlug`
708
+ )
709
+ );
710
+ }
711
+ return issues;
712
+ }
713
+ function validateInstallProfile(profile, index, knownPromptIds, knownToolIds, knownAssetIds, knownTopicSlugs) {
714
+ const path = `operatingSystem.installProfiles[${index}]`;
715
+ const issues = [];
716
+ if (!profile.profileId?.trim()) {
717
+ issues.push(
718
+ issue(
719
+ "MISSING_INSTALL_PROFILE_ID",
720
+ "install profile requires profileId",
721
+ `${path}.profileId`
722
+ )
723
+ );
724
+ }
725
+ if (!profile.name?.trim()) {
726
+ issues.push(
727
+ issue(
728
+ "MISSING_INSTALL_PROFILE_NAME",
729
+ "install profile requires name",
730
+ `${path}.name`
731
+ )
732
+ );
733
+ }
734
+ if (!profile.description?.trim()) {
735
+ issues.push(
736
+ issue(
737
+ "MISSING_INSTALL_PROFILE_DESCRIPTION",
738
+ "install profile requires description",
739
+ `${path}.description`
740
+ )
741
+ );
742
+ }
743
+ if (!RUNTIME_TARGETS.has(profile.runtimeTarget)) {
744
+ issues.push(
745
+ issue(
746
+ "INVALID_RUNTIME_TARGET",
747
+ `Unsupported runtime target "${profile.runtimeTarget}"`,
748
+ `${path}.runtimeTarget`
749
+ )
750
+ );
751
+ }
752
+ for (const [promptIndex, promptId] of profile.promptIds.entries()) {
753
+ if (!knownPromptIds.has(promptId)) {
803
754
  issues.push(
804
- ...checkDuplicateIds(
805
- pack.inquiryShaping.taskTemplates,
806
- "templateId",
807
- "inquiryShaping.taskTemplates"
755
+ issue(
756
+ "UNKNOWN_PROMPT_REF",
757
+ `install profile references unknown prompt "${promptId}"`,
758
+ `${path}.promptIds[${promptIndex}]`
808
759
  )
809
760
  );
810
- pack.inquiryShaping.taskTemplates.forEach((template, index) => {
811
- issues.push(...validateTaskTemplate(template, index));
812
- });
813
761
  }
814
- if (pack.inquiryShaping.frameworkHints) {
762
+ }
763
+ for (const [toolIndex, toolId] of profile.toolIds.entries()) {
764
+ if (!knownToolIds.has(toolId)) {
815
765
  issues.push(
816
- ...checkDuplicateIds(
817
- pack.inquiryShaping.frameworkHints.map((hint) => ({
818
- frameworkName: hint.frameworkName
819
- })),
820
- "frameworkName",
821
- "inquiryShaping.frameworkHints"
766
+ issue(
767
+ "UNKNOWN_TOOL_REF",
768
+ `install profile references unknown tool "${toolId}"`,
769
+ `${path}.toolIds[${toolIndex}]`
822
770
  )
823
771
  );
824
- pack.inquiryShaping.frameworkHints.forEach((hint, index) => {
825
- issues.push(...validateFrameworkHint(hint, index));
826
- });
827
772
  }
828
773
  }
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 describeParseFailure(error) {
889
- return error instanceof Error ? error.message : "Manifest parse failed.";
890
- }
891
- function dedupeStrings2(values) {
892
- if (!values) {
893
- return void 0;
894
- }
895
- return Array.from(
896
- new Set(values.map((value) => value.trim()).filter((value) => value.length))
897
- );
898
- }
899
- function normalizeRuntimeTargets2(values) {
900
- return values ? dedupeStrings2(values) : void 0;
901
- }
902
- function normalizeFrameworks(frameworks) {
903
- if (!frameworks) {
904
- return void 0;
905
- }
906
- return frameworks.map((framework) => ({
907
- ...framework,
908
- frameworkId: framework.frameworkId.trim(),
909
- version: framework.version.trim(),
910
- versionConstraint: framework.versionConstraint?.trim(),
911
- runtimeTargets: normalizeRuntimeTargets2(framework.runtimeTargets)
912
- }));
913
- }
914
- function normalizeSchemaExtensions(extensions) {
915
- if (!extensions) {
916
- return void 0;
917
- }
918
- return extensions.map((extension) => ({
919
- ...extension,
920
- extensionId: extension.extensionId.trim(),
921
- target: extension.target,
922
- description: extension.description.trim(),
923
- version: extension.version.trim(),
924
- extends: extension.extends?.trim()
925
- }));
926
- }
927
- function normalizeOntologyExtensions(extensions) {
928
- if (!extensions) {
929
- return void 0;
930
- }
931
- return extensions.map((extension) => ({
932
- ...extension,
933
- extensionId: extension.extensionId.trim(),
934
- ontologyId: extension.ontologyId.trim(),
935
- baseVersionConstraint: extension.baseVersionConstraint.trim(),
936
- entityTypes: extension.entityTypes?.map((entityType) => ({
937
- ...entityType,
938
- value: entityType.value.trim(),
939
- label: entityType.label.trim(),
940
- description: entityType.description?.trim(),
941
- subtypes: dedupeStrings2(entityType.subtypes)
942
- })),
943
- edgeTypes: extension.edgeTypes?.map((edgeType) => ({
944
- ...edgeType,
945
- value: edgeType.value.trim(),
946
- label: edgeType.label.trim(),
947
- description: edgeType.description?.trim(),
948
- sourceTypes: dedupeStrings2(edgeType.sourceTypes),
949
- targetTypes: dedupeStrings2(edgeType.targetTypes)
950
- }))
951
- }));
952
- }
953
- function normalizeLineage(lineage) {
954
- if (!lineage) {
955
- return { mode: "root" };
774
+ for (const [assetIndex, assetId] of profile.assetIds.entries()) {
775
+ if (!knownAssetIds.has(assetId)) {
776
+ issues.push(
777
+ issue(
778
+ "UNKNOWN_SETUP_ASSET_REF",
779
+ `install profile references unknown setup asset "${assetId}"`,
780
+ `${path}.assetIds[${assetIndex}]`
781
+ )
782
+ );
783
+ }
956
784
  }
957
- return {
958
- mode: lineage.mode,
959
- parentPackId: lineage.parentPackId?.trim(),
960
- parentVersion: lineage.parentVersion?.trim(),
961
- parentManifestDigest: lineage.parentManifestDigest?.trim(),
962
- supersedesPackId: lineage.supersedesPackId?.trim(),
963
- notes: lineage.notes?.trim()
964
- };
965
- }
966
- function normalizeMetadata(metadata) {
967
- if (!metadata) {
968
- return void 0;
785
+ for (const [topicIndex, topicSlug] of profile.defaultTopicSlugs.entries()) {
786
+ if (!knownTopicSlugs.has(topicSlug)) {
787
+ issues.push(
788
+ issue(
789
+ "UNKNOWN_TOPIC_REF",
790
+ `install profile references unknown topic "${topicSlug}"`,
791
+ `${path}.defaultTopicSlugs[${topicIndex}]`
792
+ )
793
+ );
794
+ }
969
795
  }
970
- return {
971
- description: metadata.description?.trim(),
972
- owner: metadata.owner?.trim(),
973
- tags: dedupeStrings2(metadata.tags)
974
- };
975
- }
976
- function toDomainPack(pack) {
977
- return defineDomainPack(pack);
978
- }
979
- function defineDomainPackAuthoringManifest(input) {
980
- return {
981
- kind: input.kind ?? DOMAIN_PACK_MANIFEST_KIND,
982
- manifestVersion: input.manifestVersion?.trim() || CURRENT_MANIFEST_VERSION,
983
- pack: toDomainPack(input.pack),
984
- frameworks: normalizeFrameworks(input.frameworks),
985
- schemaExtensions: normalizeSchemaExtensions(input.schemaExtensions),
986
- ontologyExtensions: normalizeOntologyExtensions(input.ontologyExtensions),
987
- lineage: normalizeLineage(input.lineage),
988
- metadata: normalizeMetadata(input.metadata)
989
- };
796
+ return issues;
990
797
  }
991
- function countManifestArtifacts(manifest) {
992
- if (!manifest) {
993
- return emptyCounts();
798
+ function checkDuplicateIds(items, idField, path) {
799
+ const issues = [];
800
+ const seen = /* @__PURE__ */ new Set();
801
+ for (const item of items) {
802
+ const id = item[idField];
803
+ if (seen.has(id)) {
804
+ issues.push(
805
+ issue(
806
+ "DUPLICATE_ID",
807
+ `Duplicate ${idField} "${id}"`,
808
+ `${path}.${idField}`
809
+ )
810
+ );
811
+ }
812
+ seen.add(id);
994
813
  }
995
- return {
996
- topicRoots: manifest.pack.topicRoots.length,
997
- workflows: manifest.pack.workflows.length,
998
- gates: manifest.pack.gates.length,
999
- artifacts: manifest.pack.artifacts.length,
1000
- roles: manifest.pack.roles.length,
1001
- prompts: manifest.pack.operatingSystem?.prompts?.length ?? 0,
1002
- tools: manifest.pack.operatingSystem?.tools?.length ?? 0,
1003
- setupAssets: manifest.pack.operatingSystem?.setupAssets?.length ?? 0,
1004
- installProfiles: manifest.pack.operatingSystem?.installProfiles?.length ?? 0,
1005
- frameworks: manifest.frameworks?.length ?? 0,
1006
- schemaExtensions: manifest.schemaExtensions?.length ?? 0,
1007
- ontologyExtensions: manifest.ontologyExtensions?.length ?? 0
1008
- };
814
+ return issues;
1009
815
  }
1010
- function sortJsonValue(value) {
1011
- if (Array.isArray(value)) {
1012
- return value.map(sortJsonValue);
1013
- }
1014
- if (isPlainObject(value)) {
1015
- return Object.fromEntries(
1016
- Object.entries(value).filter(([, entryValue]) => entryValue !== void 0).sort(([left], [right]) => left.localeCompare(right)).map(([key, entryValue]) => [key, sortJsonValue(entryValue)])
816
+ function validateDomainPack(pack) {
817
+ const issues = [];
818
+ if (!pack.packId || !pack.packId.trim()) {
819
+ issues.push(issue("MISSING_PACK_ID", "packId is required", "packId"));
820
+ } else if (!KEBAB_CASE.test(pack.packId)) {
821
+ issues.push(
822
+ issue(
823
+ "INVALID_PACK_ID",
824
+ `packId "${pack.packId}" must be kebab-case`,
825
+ "packId"
826
+ )
1017
827
  );
1018
828
  }
1019
- return value;
1020
- }
1021
- function toYamlScalar(value) {
1022
- if (value === null) {
1023
- return "null";
829
+ if (!pack.name || !pack.name.trim()) {
830
+ issues.push(issue("MISSING_NAME", "name is required", "name"));
1024
831
  }
1025
- if (typeof value === "boolean" || typeof value === "number") {
1026
- return String(value);
832
+ if (!pack.version || !pack.version.trim()) {
833
+ issues.push(issue("MISSING_VERSION", "version is required", "version"));
834
+ } else if (!SEMVER.test(pack.version)) {
835
+ issues.push(
836
+ issue(
837
+ "INVALID_VERSION",
838
+ `version "${pack.version}" must be valid semver`,
839
+ "version"
840
+ )
841
+ );
1027
842
  }
1028
- return JSON.stringify(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)];
843
+ if (!pack.ontologyBindings || pack.ontologyBindings.length === 0) {
844
+ issues.push(
845
+ issue(
846
+ "MISSING_ONTOLOGY_BINDINGS",
847
+ "At least one ontologyBinding is required",
848
+ "ontologyBindings"
849
+ )
850
+ );
851
+ } else {
852
+ for (const [i, binding] of pack.ontologyBindings.entries()) {
853
+ if (!binding.ontologyId?.trim()) {
854
+ issues.push(
855
+ issue(
856
+ "MISSING_ONTOLOGY_ID",
857
+ `ontologyBinding[${i}].ontologyId is required`,
858
+ `ontologyBindings[${i}].ontologyId`
859
+ )
860
+ );
1039
861
  }
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 [];
862
+ if (!binding.versionConstraint?.trim()) {
863
+ issues.push(
864
+ issue(
865
+ "MISSING_VERSION_CONSTRAINT",
866
+ `ontologyBinding[${i}].versionConstraint is required`,
867
+ `ontologyBindings[${i}].versionConstraint`
868
+ )
869
+ );
1051
870
  }
1052
- if (Array.isArray(entryValue)) {
1053
- if (entryValue.length === 0) {
1054
- return [`${prefix}${key}: []`];
1055
- }
1056
- return [`${prefix}${key}:`, ...renderYaml(entryValue, indent + 2)];
871
+ if (binding.provisionMode && !ONTOLOGY_PROVISION_MODES.has(binding.provisionMode)) {
872
+ issues.push(
873
+ issue(
874
+ "INVALID_ONTOLOGY_PROVISION_MODE",
875
+ `Unsupported provisionMode "${binding.provisionMode}"`,
876
+ `ontologyBindings[${i}].provisionMode`
877
+ )
878
+ );
1057
879
  }
1058
- if (isPlainObject(entryValue)) {
1059
- if (Object.keys(entryValue).length === 0) {
1060
- return [`${prefix}${key}: {}`];
1061
- }
1062
- return [`${prefix}${key}:`, ...renderYaml(entryValue, indent + 2)];
880
+ if (binding.provisionMode && binding.provisionMode !== "bind" && !binding.seedRef?.trim()) {
881
+ issues.push(
882
+ issue(
883
+ "MISSING_ONTOLOGY_SEED_REF",
884
+ `ontologyBinding[${i}] requires seedRef when provisionMode is "${binding.provisionMode}"`,
885
+ `ontologyBindings[${i}].seedRef`
886
+ )
887
+ );
1063
888
  }
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, "'");
889
+ issues.push(
890
+ ...validateStringArray(
891
+ binding.requiredEntityTypes,
892
+ `ontologyBindings[${i}].requiredEntityTypes`,
893
+ "requiredEntityTypes"
894
+ ),
895
+ ...validateStringArray(
896
+ binding.requiredEdgeTypes,
897
+ `ontologyBindings[${i}].requiredEdgeTypes`,
898
+ "requiredEdgeTypes"
899
+ )
900
+ );
1089
901
  }
1090
- return JSON.parse(value);
1091
902
  }
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}`);
903
+ if (!pack.topicRoots || pack.topicRoots.length === 0) {
904
+ issues.push(
905
+ issue(
906
+ "MISSING_TOPIC_ROOTS",
907
+ "At least one topicRoot is required",
908
+ "topicRoots"
909
+ )
910
+ );
911
+ } else {
912
+ issues.push(
913
+ ...checkDuplicateIds(
914
+ pack.topicRoots,
915
+ "slug",
916
+ "topicRoots"
917
+ )
918
+ );
1104
919
  }
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 {};
920
+ if (pack.operatingSystem) {
921
+ const knownRootSlugs = new Set(
922
+ pack.topicRoots?.map((topic) => topic.slug) ?? []
923
+ );
924
+ if (pack.operatingSystem.prompts) {
925
+ issues.push(
926
+ ...checkDuplicateIds(
927
+ pack.operatingSystem.prompts,
928
+ "promptId",
929
+ "operatingSystem.prompts"
930
+ )
931
+ );
932
+ pack.operatingSystem.prompts.forEach((prompt, index) => {
933
+ issues.push(...validatePromptBinding(prompt, index));
934
+ });
1119
935
  }
1120
- const currentLine = lines[index];
1121
- const currentIndent = countIndent(currentLine);
1122
- if (currentIndent < indent) {
1123
- return {};
936
+ if (pack.operatingSystem.tools) {
937
+ issues.push(
938
+ ...checkDuplicateIds(
939
+ pack.operatingSystem.tools,
940
+ "toolId",
941
+ "operatingSystem.tools"
942
+ )
943
+ );
944
+ pack.operatingSystem.tools.forEach((tool, index) => {
945
+ issues.push(...validateToolBinding(tool, index));
946
+ });
1124
947
  }
1125
- if (currentLine.trimStart().startsWith("-")) {
1126
- return parseArray(indent);
948
+ if (pack.operatingSystem.setupAssets) {
949
+ issues.push(
950
+ ...checkDuplicateIds(
951
+ pack.operatingSystem.setupAssets,
952
+ "assetId",
953
+ "operatingSystem.setupAssets"
954
+ )
955
+ );
956
+ pack.operatingSystem.setupAssets.forEach((asset, index) => {
957
+ issues.push(...validateSetupAsset(asset, index));
958
+ });
1127
959
  }
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));
960
+ const templateSlugs = /* @__PURE__ */ new Set();
961
+ if (pack.operatingSystem.topicTemplates) {
962
+ issues.push(
963
+ ...checkDuplicateIds(
964
+ pack.operatingSystem.topicTemplates,
965
+ "slug",
966
+ "operatingSystem.topicTemplates"
967
+ )
968
+ );
969
+ pack.operatingSystem.topicTemplates.forEach((template) => {
970
+ if (template.slug) {
971
+ templateSlugs.add(template.slug);
972
+ }
973
+ });
974
+ const knownTopicSlugs = /* @__PURE__ */ new Set([...knownRootSlugs, ...templateSlugs]);
975
+ pack.operatingSystem.topicTemplates.forEach((template, index) => {
976
+ issues.push(...validateTopicTemplate(template, index, knownTopicSlugs));
977
+ });
978
+ }
979
+ if (pack.operatingSystem.installProfiles) {
980
+ issues.push(
981
+ ...checkDuplicateIds(
982
+ pack.operatingSystem.installProfiles,
983
+ "profileId",
984
+ "operatingSystem.installProfiles"
985
+ )
986
+ );
987
+ const knownPromptIds = new Set(
988
+ pack.operatingSystem.prompts?.map((prompt) => prompt.promptId) ?? []
989
+ );
990
+ const knownToolIds = new Set(
991
+ pack.operatingSystem.tools?.map((tool) => tool.toolId) ?? []
992
+ );
993
+ const knownAssetIds = new Set(
994
+ pack.operatingSystem.setupAssets?.map((asset) => asset.assetId) ?? []
995
+ );
996
+ const knownTopicSlugs = /* @__PURE__ */ new Set([...knownRootSlugs, ...templateSlugs]);
997
+ pack.operatingSystem.installProfiles.forEach((profile, index) => {
998
+ issues.push(
999
+ ...validateInstallProfile(
1000
+ profile,
1001
+ index,
1002
+ knownPromptIds,
1003
+ knownToolIds,
1004
+ knownAssetIds,
1005
+ knownTopicSlugs
1006
+ )
1007
+ );
1008
+ });
1152
1009
  }
1153
- return items;
1154
1010
  }
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);
1011
+ if (!pack.roles || pack.roles.length === 0) {
1012
+ issues.push(
1013
+ issue("MISSING_ROLES", "At least one reasoning role is required", "roles")
1014
+ );
1015
+ } else {
1016
+ issues.push(
1017
+ ...checkDuplicateIds(
1018
+ pack.roles,
1019
+ "roleId",
1020
+ "roles"
1021
+ )
1022
+ );
1023
+ }
1024
+ const knownGateIds = new Set(pack.gates?.map((g) => g.gateId) ?? []);
1025
+ const knownArtifactIds = new Set(
1026
+ pack.artifacts?.map((a) => a.artifactId) ?? []
1027
+ );
1028
+ const knownRoleIds = new Set(pack.roles?.map((r) => r.roleId) ?? []);
1029
+ if (pack.gates) {
1030
+ issues.push(
1031
+ ...checkDuplicateIds(
1032
+ pack.gates,
1033
+ "gateId",
1034
+ "gates"
1035
+ )
1036
+ );
1037
+ for (const [i, gate] of pack.gates.entries()) {
1038
+ if (!gate.criteria || gate.criteria.length === 0) {
1039
+ issues.push(
1040
+ issue(
1041
+ "EMPTY_GATE_CRITERIA",
1042
+ `Gate "${gate.gateId}" has no criteria`,
1043
+ `gates[${i}].criteria`,
1044
+ "warning"
1045
+ )
1046
+ );
1047
+ } else {
1048
+ issues.push(
1049
+ ...checkDuplicateIds(
1050
+ gate.criteria,
1051
+ "criterionId",
1052
+ `gates[${i}].criteria`
1053
+ )
1054
+ );
1055
+ }
1173
1056
  }
1174
- return objectValue;
1175
1057
  }
1176
- return parseBlock(0);
1058
+ if (pack.artifacts) {
1059
+ issues.push(
1060
+ ...checkDuplicateIds(
1061
+ pack.artifacts,
1062
+ "artifactId",
1063
+ "artifacts"
1064
+ )
1065
+ );
1066
+ }
1067
+ if (pack.workflows) {
1068
+ issues.push(
1069
+ ...checkDuplicateIds(
1070
+ pack.workflows,
1071
+ "workflowId",
1072
+ "workflows"
1073
+ )
1074
+ );
1075
+ for (const [wi, workflow] of pack.workflows.entries()) {
1076
+ for (const gateId of workflow.gateCheckpoints) {
1077
+ if (!knownGateIds.has(gateId)) {
1078
+ issues.push(
1079
+ issue(
1080
+ "UNKNOWN_GATE_REF",
1081
+ `Workflow "${workflow.workflowId}" references unknown gate "${gateId}"`,
1082
+ `workflows[${wi}].gateCheckpoints`
1083
+ )
1084
+ );
1085
+ }
1086
+ }
1087
+ for (const artifactId of workflow.requiredArtifacts) {
1088
+ if (!knownArtifactIds.has(artifactId)) {
1089
+ issues.push(
1090
+ issue(
1091
+ "UNKNOWN_ARTIFACT_REF",
1092
+ `Workflow "${workflow.workflowId}" references unknown artifact "${artifactId}"`,
1093
+ `workflows[${wi}].requiredArtifacts`
1094
+ )
1095
+ );
1096
+ }
1097
+ }
1098
+ for (const [si, step] of workflow.steps.entries()) {
1099
+ for (const roleId of step.requiredRoles) {
1100
+ if (!knownRoleIds.has(roleId)) {
1101
+ issues.push(
1102
+ issue(
1103
+ "UNKNOWN_ROLE_REF",
1104
+ `Step "${step.stepId}" references unknown role "${roleId}"`,
1105
+ `workflows[${wi}].steps[${si}].requiredRoles`
1106
+ )
1107
+ );
1108
+ }
1109
+ }
1110
+ if (step.gateId && !knownGateIds.has(step.gateId)) {
1111
+ issues.push(
1112
+ issue(
1113
+ "UNKNOWN_GATE_REF",
1114
+ `Step "${step.stepId}" references unknown gate "${step.gateId}"`,
1115
+ `workflows[${wi}].steps[${si}].gateId`
1116
+ )
1117
+ );
1118
+ }
1119
+ if (step.produces) {
1120
+ for (const artifactId of step.produces) {
1121
+ if (!knownArtifactIds.has(artifactId)) {
1122
+ issues.push(
1123
+ issue(
1124
+ "UNKNOWN_ARTIFACT_REF",
1125
+ `Step "${step.stepId}" references unknown artifact "${artifactId}"`,
1126
+ `workflows[${wi}].steps[${si}].produces`
1127
+ )
1128
+ );
1129
+ }
1130
+ }
1131
+ }
1132
+ }
1133
+ }
1134
+ }
1135
+ if (pack.inquiryShaping) {
1136
+ if (pack.inquiryShaping.questionTemplates) {
1137
+ issues.push(
1138
+ ...checkDuplicateIds(
1139
+ pack.inquiryShaping.questionTemplates,
1140
+ "templateId",
1141
+ "inquiryShaping.questionTemplates"
1142
+ )
1143
+ );
1144
+ pack.inquiryShaping.questionTemplates.forEach((template, index) => {
1145
+ issues.push(...validateQuestionTemplate(template, index));
1146
+ });
1147
+ }
1148
+ if (pack.inquiryShaping.taskTemplates) {
1149
+ issues.push(
1150
+ ...checkDuplicateIds(
1151
+ pack.inquiryShaping.taskTemplates,
1152
+ "templateId",
1153
+ "inquiryShaping.taskTemplates"
1154
+ )
1155
+ );
1156
+ pack.inquiryShaping.taskTemplates.forEach((template, index) => {
1157
+ issues.push(...validateTaskTemplate(template, index));
1158
+ });
1159
+ }
1160
+ if (pack.inquiryShaping.frameworkHints) {
1161
+ issues.push(
1162
+ ...checkDuplicateIds(
1163
+ pack.inquiryShaping.frameworkHints.map((hint) => ({
1164
+ frameworkName: hint.frameworkName
1165
+ })),
1166
+ "frameworkName",
1167
+ "inquiryShaping.frameworkHints"
1168
+ )
1169
+ );
1170
+ pack.inquiryShaping.frameworkHints.forEach((hint, index) => {
1171
+ issues.push(...validateFrameworkHint(hint, index));
1172
+ });
1173
+ }
1174
+ }
1175
+ return {
1176
+ valid: issues.filter((i) => i.severity === "error").length === 0,
1177
+ issues
1178
+ };
1177
1179
  }
1178
- function detectDomainPackManifestFormat(source, explicitFormat) {
1180
+
1181
+ // src/domain-pack/authoring.validation.ts
1182
+ var KEBAB_CASE2 = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
1183
+ 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-]+)*))?$/;
1184
+ var LEGACY_PUBLIC_KEYS = /* @__PURE__ */ new Set([
1185
+ "project",
1186
+ "projects",
1187
+ "projectId",
1188
+ "projectIds",
1189
+ "sprint",
1190
+ "sprints",
1191
+ "sprintId",
1192
+ "sprintIds"
1193
+ ]);
1194
+ var SCHEMA_EXTENSION_TARGETS = /* @__PURE__ */ new Set([
1195
+ "artifact",
1196
+ "workflow",
1197
+ "gate",
1198
+ "prompt",
1199
+ "tool",
1200
+ "install-profile",
1201
+ "topic-template"
1202
+ ]);
1203
+ var ONTOLOGY_CONSTRAINT_SEVERITIES = /* @__PURE__ */ new Set([
1204
+ "error",
1205
+ "warning",
1206
+ "informational"
1207
+ ]);
1208
+ var LINEAGE_MODES = /* @__PURE__ */ new Set(["root", "remix", "fork"]);
1209
+ var AUTHORING_TOOL_NAMES = {
1210
+ validate: "validate_domain_pack_manifest",
1211
+ preview: "preview_domain_pack_manifest",
1212
+ publish: "publish_domain_pack_manifest"
1213
+ };
1214
+ function issue2(code, message, path, source, severity = "error") {
1215
+ return { code, message, path, severity, source };
1216
+ }
1217
+ function emptyCounts() {
1218
+ return {
1219
+ topicRoots: 0,
1220
+ workflows: 0,
1221
+ gates: 0,
1222
+ artifacts: 0,
1223
+ roles: 0,
1224
+ prompts: 0,
1225
+ tools: 0,
1226
+ setupAssets: 0,
1227
+ installProfiles: 0,
1228
+ frameworks: 0,
1229
+ schemaExtensions: 0,
1230
+ ontologyExtensions: 0
1231
+ };
1232
+ }
1233
+ function isPlainObject2(value) {
1234
+ return typeof value === "object" && value !== null && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype;
1235
+ }
1236
+ function describeParseFailure(error) {
1237
+ return error instanceof Error ? error.message : "Manifest parse failed.";
1238
+ }
1239
+ function asToolDefinition(tool) {
1240
+ return tool;
1241
+ }
1242
+ function detectDomainPackManifestFormat2(source, explicitFormat) {
1179
1243
  if (explicitFormat) {
1180
1244
  return explicitFormat;
1181
1245
  }
@@ -1185,35 +1249,6 @@ function detectDomainPackManifestFormat(source, explicitFormat) {
1185
1249
  }
1186
1250
  return "yaml";
1187
1251
  }
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
1252
  function validateFrameworks(frameworks) {
1218
1253
  if (!frameworks) {
1219
1254
  return [];
@@ -1342,7 +1377,7 @@ function validateSchemaExtensions(extensions) {
1342
1377
  )
1343
1378
  );
1344
1379
  }
1345
- if (!isPlainObject(extension.schema)) {
1380
+ if (!isPlainObject2(extension.schema)) {
1346
1381
  issues.push(
1347
1382
  issue2(
1348
1383
  "INVALID_SCHEMA_EXTENSION_SCHEMA",
@@ -1424,85 +1459,89 @@ function validateOntologyExtensions(extensions) {
1424
1459
  );
1425
1460
  }
1426
1461
  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
- );
1462
+ extension.entityTypes?.forEach(
1463
+ (entityType, entityTypeIndex) => {
1464
+ const entityPath = `${path}.entityTypes[${entityTypeIndex}]`;
1465
+ if (!entityType.value || !KEBAB_CASE2.test(entityType.value)) {
1466
+ issues.push(
1467
+ issue2(
1468
+ "INVALID_ONTOLOGY_ENTITY_VALUE",
1469
+ "entity extension value must be kebab-case",
1470
+ `${entityPath}.value`,
1471
+ "ontology-extension"
1472
+ )
1473
+ );
1474
+ } else if (entityTypeValues.has(entityType.value)) {
1475
+ issues.push(
1476
+ issue2(
1477
+ "DUPLICATE_ONTOLOGY_ENTITY_VALUE",
1478
+ `Duplicate entity extension value "${entityType.value}"`,
1479
+ `${entityPath}.value`,
1480
+ "ontology-extension"
1481
+ )
1482
+ );
1483
+ } else {
1484
+ entityTypeValues.add(entityType.value);
1485
+ }
1486
+ if (!entityType.label) {
1487
+ issues.push(
1488
+ issue2(
1489
+ "MISSING_ONTOLOGY_ENTITY_LABEL",
1490
+ "entity extension label is required",
1491
+ `${entityPath}.label`,
1492
+ "ontology-extension"
1493
+ )
1494
+ );
1495
+ }
1459
1496
  }
1460
- });
1497
+ );
1461
1498
  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
- );
1499
+ extension.edgeTypes?.forEach(
1500
+ (edgeType, edgeTypeIndex) => {
1501
+ const edgePath = `${path}.edgeTypes[${edgeTypeIndex}]`;
1502
+ if (!edgeType.value || !KEBAB_CASE2.test(edgeType.value)) {
1503
+ issues.push(
1504
+ issue2(
1505
+ "INVALID_ONTOLOGY_EDGE_VALUE",
1506
+ "edge extension value must be kebab-case",
1507
+ `${edgePath}.value`,
1508
+ "ontology-extension"
1509
+ )
1510
+ );
1511
+ } else if (edgeTypeValues.has(edgeType.value)) {
1512
+ issues.push(
1513
+ issue2(
1514
+ "DUPLICATE_ONTOLOGY_EDGE_VALUE",
1515
+ `Duplicate edge extension value "${edgeType.value}"`,
1516
+ `${edgePath}.value`,
1517
+ "ontology-extension"
1518
+ )
1519
+ );
1520
+ } else {
1521
+ edgeTypeValues.add(edgeType.value);
1522
+ }
1523
+ if (!edgeType.label) {
1524
+ issues.push(
1525
+ issue2(
1526
+ "MISSING_ONTOLOGY_EDGE_LABEL",
1527
+ "edge extension label is required",
1528
+ `${edgePath}.label`,
1529
+ "ontology-extension"
1530
+ )
1531
+ );
1532
+ }
1533
+ if (edgeType.constraintSeverity && !ONTOLOGY_CONSTRAINT_SEVERITIES.has(edgeType.constraintSeverity)) {
1534
+ issues.push(
1535
+ issue2(
1536
+ "INVALID_ONTOLOGY_EDGE_SEVERITY",
1537
+ `Unsupported constraint severity "${edgeType.constraintSeverity}"`,
1538
+ `${edgePath}.constraintSeverity`,
1539
+ "ontology-extension"
1540
+ )
1541
+ );
1542
+ }
1504
1543
  }
1505
- });
1544
+ );
1506
1545
  });
1507
1546
  return issues;
1508
1547
  }
@@ -1621,7 +1660,7 @@ function scanLegacyPublicKeys(value, path = "") {
1621
1660
  });
1622
1661
  return issues;
1623
1662
  }
1624
- if (!isPlainObject(value)) {
1663
+ if (!isPlainObject2(value)) {
1625
1664
  return issues;
1626
1665
  }
1627
1666
  Object.entries(value).forEach(([key, entryValue]) => {
@@ -1720,7 +1759,7 @@ function validateDomainPackAuthoringManifest(manifest) {
1720
1759
  );
1721
1760
  }
1722
1761
  function validateDomainPackAuthoringManifestSource(source, format) {
1723
- const detectedFormat = detectDomainPackManifestFormat(source, format);
1762
+ const detectedFormat = detectDomainPackManifestFormat2(source, format);
1724
1763
  try {
1725
1764
  const manifest = parseDomainPackAuthoringManifest(source, detectedFormat);
1726
1765
  return evaluateDomainPackAuthoringManifest(manifest, detectedFormat);
@@ -1870,26 +1909,44 @@ function createDomainPackAuthoringTools() {
1870
1909
  additionalProperties: false
1871
1910
  };
1872
1911
  return {
1873
- validate: {
1912
+ validate: asToolDefinition({
1874
1913
  name: AUTHORING_TOOL_NAMES.validate,
1875
1914
  description: "Validate a domain pack authoring manifest and return structural, lineage, terminology, and extension issues.",
1876
1915
  inputSchema,
1877
1916
  execute: (args) => validateDomainPackAuthoringManifestSource(args.manifestText, args.format)
1878
- },
1879
- preview: {
1917
+ }),
1918
+ preview: asToolDefinition({
1880
1919
  name: AUTHORING_TOOL_NAMES.preview,
1881
1920
  description: "Preview a domain pack manifest with canonical JSON/YAML renderings, runtime targets, and publication readiness.",
1882
1921
  inputSchema,
1883
1922
  execute: (args) => previewDomainPackAuthoringManifestSource(args.manifestText, args.format)
1884
- },
1885
- publish: {
1923
+ }),
1924
+ publish: asToolDefinition({
1886
1925
  name: AUTHORING_TOOL_NAMES.publish,
1887
1926
  description: "Build a publication-ready domain pack artifact when validation passes, including remix/fork lineage metadata.",
1888
1927
  inputSchema,
1889
1928
  execute: (args) => publishDomainPackAuthoringManifestSource(args.manifestText, args.format)
1890
- }
1929
+ })
1891
1930
  };
1892
1931
  }
1932
+ var domainPackAuthoringValidation = {
1933
+ validateDomainPackAuthoringManifest,
1934
+ validateDomainPackAuthoringManifestSource,
1935
+ previewDomainPackAuthoringManifest,
1936
+ previewDomainPackAuthoringManifestSource,
1937
+ publishDomainPackAuthoringManifest,
1938
+ publishDomainPackAuthoringManifestSource,
1939
+ createDomainPackAuthoringTools
1940
+ };
1941
+
1942
+ // src/domain-pack/authoring.ts
1943
+ var validateDomainPackAuthoringManifest2 = domainPackAuthoringValidation.validateDomainPackAuthoringManifest;
1944
+ var validateDomainPackAuthoringManifestSource2 = domainPackAuthoringValidation.validateDomainPackAuthoringManifestSource;
1945
+ var previewDomainPackAuthoringManifest2 = domainPackAuthoringValidation.previewDomainPackAuthoringManifest;
1946
+ var previewDomainPackAuthoringManifestSource2 = domainPackAuthoringValidation.previewDomainPackAuthoringManifestSource;
1947
+ var publishDomainPackAuthoringManifest2 = domainPackAuthoringValidation.publishDomainPackAuthoringManifest;
1948
+ var publishDomainPackAuthoringManifestSource2 = domainPackAuthoringValidation.publishDomainPackAuthoringManifestSource;
1949
+ var createDomainPackAuthoringTools2 = domainPackAuthoringValidation.createDomainPackAuthoringTools;
1893
1950
 
1894
1951
  // src/domain-pack/ontology/software-entities-v1.ts
1895
1952
  var SOFTWARE_ENTITIES_V1 = {
@@ -2504,609 +2561,39 @@ var DEVELOPER_REASONING_PACK = defineDomainPack({
2504
2561
  methodologyPackId: "developer"
2505
2562
  });
2506
2563
 
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"]
2564
+ // src/domain-pack/packs/engineering-accelerator-tail.ts
2565
+ var ENGINEERING_ACCELERATOR_TAIL = {
2566
+ inquiryShaping: {
2567
+ questionTemplates: [
2568
+ {
2569
+ templateId: "engineering-rationale-recall",
2570
+ questionType: "comparison",
2571
+ priority: "high",
2572
+ template: "Which prior migration, incident, review, or architecture decision most resembles {{objective}}, and what rationale or failure should we reuse before changing anything?",
2573
+ whenObjectiveIncludes: [
2574
+ "migration",
2575
+ "review",
2576
+ "pull request",
2577
+ "incident",
2578
+ "architecture",
2579
+ "decision",
2580
+ "rollback",
2581
+ "refactor"
2582
+ ]
2895
2583
  },
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"]
2584
+ {
2585
+ templateId: "engineering-rollback-falsifier",
2586
+ questionType: "falsification",
2587
+ priority: "critical",
2588
+ template: "What rollback, compatibility, or blast-radius assumption would fail first if {{hypothesis}} is wrong?",
2589
+ whenObjectiveIncludes: ["migration", "deploy", "rollout", "backfill"]
2911
2590
  },
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"]
2591
+ {
2592
+ templateId: "engineering-review-regression",
2593
+ questionType: "counterfactual",
2594
+ priority: "high",
2595
+ template: "Which prior regression, incident, or failed attempt should a reviewer inspect before approving {{objective}}?",
2596
+ whenObjectiveIncludes: ["review", "pull request", "diff", "merge"]
3110
2597
  },
3111
2598
  {
3112
2599
  templateId: "engineering-incident-contradiction",
@@ -3562,229 +3049,804 @@ var ENGINEERING_ACCELERATOR_PACK = defineDomainPack({
3562
3049
  parentSlug: "migrations",
3563
3050
  ontologyId: "software-entities"
3564
3051
  },
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"
3052
+ {
3053
+ slug: "review-briefs",
3054
+ name: "Review Briefs",
3055
+ description: "Diff-scoped risk briefs grounded in prior regressions and rationale",
3056
+ parentSlug: "reviews",
3057
+ ontologyId: "software-entities"
3058
+ },
3059
+ {
3060
+ slug: "regression-history",
3061
+ name: "Regression History",
3062
+ description: "Past regressions and approval misses that should influence current reviews",
3063
+ parentSlug: "reviews",
3064
+ ontologyId: "software-entities"
3065
+ },
3066
+ {
3067
+ slug: "active-incidents",
3068
+ name: "Active Incidents",
3069
+ description: "Current incidents with competing hypotheses, mitigations, and contradictions",
3070
+ parentSlug: "incidents",
3071
+ ontologyId: "software-entities"
3072
+ },
3073
+ {
3074
+ slug: "incident-postmortems",
3075
+ name: "Incident Postmortems",
3076
+ description: "Resolved incidents with preserved rationale and follow-up learnings",
3077
+ parentSlug: "incidents",
3078
+ ontologyId: "software-entities"
3079
+ },
3080
+ {
3081
+ slug: "adrs",
3082
+ name: "Architecture Decision Records",
3083
+ description: "Citable architecture records with precedent, objections, and supersessions",
3084
+ parentSlug: "architecture",
3085
+ ontologyId: "software-entities"
3086
+ },
3087
+ {
3088
+ slug: "interface-contracts",
3089
+ name: "Interface Contracts",
3090
+ description: "APIs, boundaries, and contract deltas that architecture work depends on",
3091
+ parentSlug: "architecture",
3092
+ ontologyId: "software-entities"
3093
+ },
3094
+ {
3095
+ slug: "failed-attempts",
3096
+ name: "Failed Attempts",
3097
+ description: "Anti-repetition log for engineering decisions and implementation dead ends",
3098
+ parentSlug: "decision-memory",
3099
+ ontologyId: "software-entities"
3100
+ },
3101
+ {
3102
+ slug: "rationale-recall",
3103
+ name: "Rationale Recall",
3104
+ description: "Recalled rationale snippets and analogs worth citing before new work",
3105
+ parentSlug: "decision-memory",
3106
+ ontologyId: "software-entities"
3107
+ }
3108
+ ],
3109
+ installProfiles: [
3110
+ {
3111
+ profileId: "claude-code",
3112
+ name: "Claude Code Engineering Kit",
3113
+ description: "Installs Claude-native hooks, commands, agent catalog, and first-hour engineering prompts on top of Lucern.",
3114
+ runtimeTarget: "claude-code",
3115
+ promptIds: [
3116
+ "claude-quick-reference",
3117
+ "build-command",
3118
+ "architect-command",
3119
+ "pipeline-command",
3120
+ "pr-command",
3121
+ "lucern-generate-questions",
3122
+ "lucern-contradiction-analysis"
3123
+ ],
3124
+ toolIds: [
3125
+ "start-investigation",
3126
+ "record-scope-learning",
3127
+ "record-attempt",
3128
+ "pipeline-snapshot",
3129
+ "session-init",
3130
+ "tool-log",
3131
+ "build-bash-gate",
3132
+ "lucern-cli-init",
3133
+ "kit-install"
3134
+ ],
3135
+ assetIds: [
3136
+ "claude-instructions",
3137
+ "mcp-config",
3138
+ "kit-manifest",
3139
+ "lucern-launcher",
3140
+ "lucern-shell-wrapper",
3141
+ "lucern-cli-script",
3142
+ "claude-settings",
3143
+ "permission-gate-hook",
3144
+ "inbox-check-hook",
3145
+ "prompt-router-hook",
3146
+ "writeback-gate-hook",
3147
+ "build-command-doc",
3148
+ "architect-command-doc",
3149
+ "pipeline-command-doc",
3150
+ "pr-command-doc",
3151
+ "claude-agent-catalog",
3152
+ "claude-skill-catalog",
3153
+ "hooks-doc",
3154
+ "setup-ui"
3155
+ ],
3156
+ defaultTopicSlugs: [
3157
+ "migrations",
3158
+ "reviews",
3159
+ "incidents",
3160
+ "architecture",
3161
+ "decision-memory"
3162
+ ]
3163
+ },
3164
+ {
3165
+ profileId: "codex",
3166
+ name: "Codex Engineering Kit",
3167
+ description: "Installs the Codex bridge, Lucern MCP wiring, and the same pack-level workflows without Claude-specific hooks.",
3168
+ runtimeTarget: "codex",
3169
+ promptIds: [
3170
+ "build-command",
3171
+ "architect-command",
3172
+ "pipeline-command",
3173
+ "pr-command",
3174
+ "lucern-generate-questions",
3175
+ "lucern-contradiction-analysis"
3176
+ ],
3177
+ toolIds: [
3178
+ "start-investigation",
3179
+ "record-scope-learning",
3180
+ "record-attempt",
3181
+ "pipeline-snapshot",
3182
+ "lucern-cli-init",
3183
+ "kit-install"
3184
+ ],
3185
+ assetIds: [
3186
+ "codex-bridge",
3187
+ "mcp-config",
3188
+ "kit-manifest",
3189
+ "lucern-launcher",
3190
+ "lucern-shell-wrapper",
3191
+ "lucern-cli-script",
3192
+ "build-command-doc",
3193
+ "architect-command-doc",
3194
+ "pipeline-command-doc",
3195
+ "pr-command-doc",
3196
+ "claude-skill-catalog",
3197
+ "skills-sync-script",
3198
+ "hooks-doc",
3199
+ "setup-ui"
3200
+ ],
3201
+ defaultTopicSlugs: [
3202
+ "migrations",
3203
+ "reviews",
3204
+ "incidents",
3205
+ "architecture",
3206
+ "decision-memory"
3207
+ ]
3208
+ },
3209
+ {
3210
+ profileId: "hybrid",
3211
+ name: "Hybrid Engineering Kit",
3212
+ description: "Installs both Claude and Codex entry surfaces against one Lucern-native engineering operating system.",
3213
+ runtimeTarget: "hybrid",
3214
+ promptIds: [
3215
+ "claude-quick-reference",
3216
+ "build-command",
3217
+ "architect-command",
3218
+ "pipeline-command",
3219
+ "pr-command",
3220
+ "lucern-generate-questions",
3221
+ "lucern-contradiction-analysis"
3222
+ ],
3223
+ toolIds: [
3224
+ "start-investigation",
3225
+ "record-scope-learning",
3226
+ "record-attempt",
3227
+ "pipeline-snapshot",
3228
+ "session-init",
3229
+ "tool-log",
3230
+ "build-bash-gate",
3231
+ "lucern-cli-init",
3232
+ "kit-install"
3233
+ ],
3234
+ assetIds: [
3235
+ "claude-instructions",
3236
+ "codex-bridge",
3237
+ "mcp-config",
3238
+ "kit-manifest",
3239
+ "lucern-launcher",
3240
+ "lucern-shell-wrapper",
3241
+ "lucern-cli-script",
3242
+ "claude-settings",
3243
+ "permission-gate-hook",
3244
+ "inbox-check-hook",
3245
+ "prompt-router-hook",
3246
+ "writeback-gate-hook",
3247
+ "build-command-doc",
3248
+ "architect-command-doc",
3249
+ "pipeline-command-doc",
3250
+ "pr-command-doc",
3251
+ "claude-agent-catalog",
3252
+ "claude-skill-catalog",
3253
+ "skills-sync-script",
3254
+ "hooks-doc",
3255
+ "setup-ui"
3256
+ ],
3257
+ defaultTopicSlugs: [
3258
+ "migrations",
3259
+ "reviews",
3260
+ "incidents",
3261
+ "architecture",
3262
+ "decision-memory"
3263
+ ]
3264
+ }
3265
+ ]
3266
+ },
3267
+ appPackKeys: [
3268
+ "chat-v1",
3269
+ "documents-v1",
3270
+ "epistemic-algorithms-v1",
3271
+ "graph-visualization-v1",
3272
+ "task-management-v1"
3273
+ ],
3274
+ methodologyPackId: "developer"
3275
+ };
3276
+
3277
+ // src/domain-pack/packs/engineering-accelerator.ts
3278
+ var ENGINEERING_ACCELERATOR_PACK = defineDomainPack({
3279
+ packId: "engineering-accelerator",
3280
+ name: "Engineering Accelerator",
3281
+ version: "1.0.0",
3282
+ ontologyBindings: [
3283
+ {
3284
+ ontologyId: "software-entities",
3285
+ versionConstraint: "^1.0.0",
3286
+ required: true,
3287
+ provisionMode: "seed",
3288
+ seedRef: "packages/pack-host/src/domain-pack/ontology/software-entities-v1.ts",
3289
+ requiredEntityTypes: [
3290
+ "repository",
3291
+ "service",
3292
+ "module",
3293
+ "workflow",
3294
+ "incident",
3295
+ "migration",
3296
+ "decision_record",
3297
+ "agent"
3298
+ ],
3299
+ requiredEdgeTypes: [
3300
+ "depends_on",
3301
+ "owns",
3302
+ "calls",
3303
+ "blocks",
3304
+ "reviews",
3305
+ "mitigates",
3306
+ "supersedes"
3307
+ ]
3308
+ }
3309
+ ],
3310
+ topicRoots: [
3311
+ {
3312
+ slug: "migrations",
3313
+ name: "Migrations",
3314
+ description: "Schema, API, and runtime migrations with blast-radius, rollback, and parity memory",
3315
+ ontologyId: "software-entities"
3316
+ },
3317
+ {
3318
+ slug: "reviews",
3319
+ name: "Reviews",
3320
+ description: "Pull-request and change-review workflows grounded in prior rationale and regressions",
3321
+ ontologyId: "software-entities"
3322
+ },
3323
+ {
3324
+ slug: "incidents",
3325
+ name: "Incidents",
3326
+ description: "Incident response driven by competing hypotheses, contradictions, and mitigations",
3327
+ ontologyId: "software-entities"
3328
+ },
3329
+ {
3330
+ slug: "architecture",
3331
+ name: "Architecture",
3332
+ description: "Architecture decisions, interface trade-offs, and precedent-aware rationale recall",
3333
+ ontologyId: "software-entities"
3334
+ },
3335
+ {
3336
+ slug: "decision-memory",
3337
+ name: "Decision Memory",
3338
+ description: "Cross-cutting rationale recall, failed attempts, and analog reuse across engineering work",
3339
+ ontologyId: "software-entities"
3340
+ }
3341
+ ],
3342
+ workflows: [
3343
+ {
3344
+ workflowId: "migration-readiness",
3345
+ name: "Migration Readiness",
3346
+ description: "Recall similar migrations, map blast radius, and define rollback before rollout",
3347
+ steps: [
3348
+ {
3349
+ stepId: "recall-history",
3350
+ name: "Recall History",
3351
+ description: "Compile analogous migrations, prior rationale, failed attempts, and compatibility constraints",
3352
+ requiredRoles: ["context-compiler", "migration-owner"],
3353
+ produces: ["memory-brief"],
3354
+ gateId: "memory-grounded"
3355
+ },
3356
+ {
3357
+ stepId: "plan-rollout",
3358
+ name: "Plan Rollout",
3359
+ description: "Define blast radius, sequencing, rollback, and verification checkpoints",
3360
+ requiredRoles: ["migration-owner", "critic"],
3361
+ produces: ["migration-plan"],
3362
+ gateId: "rollback-ready"
3363
+ },
3364
+ {
3365
+ stepId: "verify-rollout",
3366
+ name: "Verify Rollout",
3367
+ description: "Confirm canary, rollback, and parity checks are explicit before execution",
3368
+ requiredRoles: ["reviewer"],
3369
+ produces: ["verification-checklist"],
3370
+ gateId: "verification-covered"
3371
+ }
3372
+ ],
3373
+ requiredArtifacts: [
3374
+ "memory-brief",
3375
+ "migration-plan",
3376
+ "verification-checklist"
3377
+ ],
3378
+ gateCheckpoints: [
3379
+ "memory-grounded",
3380
+ "rollback-ready",
3381
+ "verification-covered"
3382
+ ]
3383
+ },
3384
+ {
3385
+ workflowId: "pull-request-review",
3386
+ name: "Pull Request Review",
3387
+ description: "Use prior rationale, regressions, and verification history to review risky changes faster",
3388
+ steps: [
3389
+ {
3390
+ stepId: "recall-review-context",
3391
+ name: "Recall Review Context",
3392
+ description: "Load earlier decisions, similar diffs, failed attempts, and relevant incidents",
3393
+ requiredRoles: ["context-compiler", "reviewer"],
3394
+ produces: ["review-context"],
3395
+ gateId: "memory-grounded"
3396
+ },
3397
+ {
3398
+ stepId: "inspect-diff",
3399
+ name: "Inspect Diff",
3400
+ description: "Surface risk areas, stale assumptions, and regressions that should block approval",
3401
+ requiredRoles: ["reviewer", "critic"],
3402
+ produces: ["review-findings"],
3403
+ gateId: "review-risks-surfaced"
3404
+ },
3405
+ {
3406
+ stepId: "verify-changes",
3407
+ name: "Verify Changes",
3408
+ description: "Tie approval to explicit typecheck, test, and integration evidence",
3409
+ requiredRoles: ["reviewer"],
3410
+ produces: ["verification-checklist"],
3411
+ gateId: "verification-covered"
3412
+ }
3413
+ ],
3414
+ requiredArtifacts: [
3415
+ "review-context",
3416
+ "review-findings",
3417
+ "verification-checklist"
3418
+ ],
3419
+ gateCheckpoints: [
3420
+ "memory-grounded",
3421
+ "review-risks-surfaced",
3422
+ "verification-covered"
3423
+ ]
3424
+ },
3425
+ {
3426
+ workflowId: "incident-response",
3427
+ name: "Incident Response",
3428
+ description: "Treat incidents as contradiction-heavy reasoning tasks before committing to a root cause",
3429
+ steps: [
3430
+ {
3431
+ stepId: "collect-signal",
3432
+ name: "Collect Signal",
3433
+ description: "Assemble symptoms, recent changes, precedent incidents, and active hypotheses",
3434
+ requiredRoles: ["context-compiler", "incident-commander"],
3435
+ produces: ["incident-brief"],
3436
+ gateId: "memory-grounded"
3437
+ },
3438
+ {
3439
+ stepId: "surface-contradictions",
3440
+ name: "Surface Contradictions",
3441
+ description: "Make competing explanations explicit before mitigation narrows the search space",
3442
+ requiredRoles: ["incident-commander", "critic"],
3443
+ produces: ["contradiction-report"],
3444
+ gateId: "contradictions-surfaced"
3445
+ },
3446
+ {
3447
+ stepId: "plan-mitigation",
3448
+ name: "Plan Mitigation",
3449
+ description: "Choose mitigations with owners, reversibility, and verification paths",
3450
+ requiredRoles: ["incident-commander", "reviewer"],
3451
+ produces: ["mitigation-plan"],
3452
+ gateId: "verification-covered"
3453
+ }
3454
+ ],
3455
+ requiredArtifacts: [
3456
+ "incident-brief",
3457
+ "contradiction-report",
3458
+ "mitigation-plan"
3459
+ ],
3460
+ gateCheckpoints: [
3461
+ "memory-grounded",
3462
+ "contradictions-surfaced",
3463
+ "verification-covered"
3464
+ ]
3465
+ },
3466
+ {
3467
+ workflowId: "architecture-decision",
3468
+ name: "Architecture Decision",
3469
+ description: "Ground architecture choices in cited precedent, explicit alternatives, and follow-up risk",
3470
+ steps: [
3471
+ {
3472
+ stepId: "recall-precedent",
3473
+ name: "Recall Precedent",
3474
+ description: "Gather analogous decisions, trade-offs, reversals, and evidence already in the graph",
3475
+ requiredRoles: ["context-compiler", "architect"],
3476
+ produces: ["decision-brief"],
3477
+ gateId: "memory-grounded"
3478
+ },
3479
+ {
3480
+ stepId: "compare-options",
3481
+ name: "Compare Options",
3482
+ description: "Contrast viable paths, show what changes, and surface objections early",
3483
+ requiredRoles: ["architect", "critic"],
3484
+ produces: ["decision-brief"],
3485
+ gateId: "decision-rationale-citable"
3486
+ },
3487
+ {
3488
+ stepId: "record-decision",
3489
+ name: "Record Decision",
3490
+ description: "Capture the chosen path, cited rationale, and follow-up risks for later recall",
3491
+ requiredRoles: ["architect"],
3492
+ produces: ["decision-record"]
3493
+ }
3494
+ ],
3495
+ requiredArtifacts: ["decision-brief", "decision-record"],
3496
+ gateCheckpoints: ["memory-grounded", "decision-rationale-citable"]
3497
+ }
3498
+ ],
3499
+ gates: [
3500
+ {
3501
+ gateId: "memory-grounded",
3502
+ name: "Memory Grounded",
3503
+ description: "The workflow is anchored in prior rationale, analogs, and failure memory before action",
3504
+ criteria: [
3505
+ {
3506
+ criterionId: "precedent-cited",
3507
+ description: "At least one prior change, incident, or decision is cited",
3508
+ metric: "precedent_citations",
3509
+ threshold: 1,
3510
+ operator: "gte"
3511
+ },
3512
+ {
3513
+ criterionId: "failure-log-checked",
3514
+ description: "Relevant failed attempts or incident history were checked",
3515
+ metric: "failure_log_checked",
3516
+ threshold: 1,
3517
+ operator: "eq"
3518
+ }
3519
+ ],
3520
+ severity: "blocking"
3521
+ },
3522
+ {
3523
+ gateId: "rollback-ready",
3524
+ name: "Rollback Ready",
3525
+ description: "Risky migrations cannot proceed without explicit rollback and blast-radius coverage",
3526
+ criteria: [
3527
+ {
3528
+ criterionId: "blast-radius-scoped",
3529
+ description: "Blast radius is enumerated for the proposed change",
3530
+ metric: "blast_radius_scoped",
3531
+ threshold: 1,
3532
+ operator: "eq"
3533
+ },
3534
+ {
3535
+ criterionId: "rollback-path-defined",
3536
+ description: "Rollback path is explicit and reversible",
3537
+ metric: "rollback_path_defined",
3538
+ threshold: 1,
3539
+ operator: "eq"
3540
+ }
3541
+ ],
3542
+ severity: "blocking"
3543
+ },
3544
+ {
3545
+ gateId: "review-risks-surfaced",
3546
+ name: "Review Risks Surfaced",
3547
+ description: "Review must explain what could regress and why approval is still justified",
3548
+ criteria: [
3549
+ {
3550
+ criterionId: "risk-areas-documented",
3551
+ description: "Risk areas and likely regressions are called out explicitly",
3552
+ metric: "risk_areas_documented",
3553
+ threshold: 1,
3554
+ operator: "gte"
3555
+ },
3556
+ {
3557
+ criterionId: "prior-regressions-checked",
3558
+ description: "Reviewer checked analogous regressions or incidents",
3559
+ metric: "prior_regressions_checked",
3560
+ threshold: 1,
3561
+ operator: "eq"
3562
+ }
3563
+ ],
3564
+ severity: "blocking"
3565
+ },
3566
+ {
3567
+ gateId: "contradictions-surfaced",
3568
+ name: "Contradictions Surfaced",
3569
+ description: "Incidents should preserve competing hypotheses long enough to avoid false certainty",
3570
+ criteria: [
3571
+ {
3572
+ criterionId: "multiple-hypotheses",
3573
+ description: "At least two plausible hypotheses remain visible",
3574
+ metric: "competing_hypotheses_count",
3575
+ threshold: 2,
3576
+ operator: "gte"
3577
+ },
3578
+ {
3579
+ criterionId: "contradictions-reviewed",
3580
+ description: "Relevant contradictions or tensions were reviewed",
3581
+ metric: "contradictions_reviewed",
3582
+ threshold: 1,
3583
+ operator: "gte"
3584
+ }
3585
+ ],
3586
+ severity: "blocking"
3587
+ },
3588
+ {
3589
+ gateId: "decision-rationale-citable",
3590
+ name: "Decision Rationale Citable",
3591
+ description: "Architecture choices should cite prior rationale and compare viable alternatives",
3592
+ criteria: [
3593
+ {
3594
+ criterionId: "options-compared",
3595
+ description: "At least two options are compared before choosing one",
3596
+ metric: "options_compared",
3597
+ threshold: 2,
3598
+ operator: "gte"
3599
+ },
3600
+ {
3601
+ criterionId: "prior-decisions-cited",
3602
+ description: "Decision cites prior beliefs, ADRs, or incidents",
3603
+ metric: "prior_decisions_cited",
3604
+ threshold: 1,
3605
+ operator: "gte"
3606
+ }
3607
+ ],
3608
+ severity: "blocking"
3609
+ },
3610
+ {
3611
+ gateId: "verification-covered",
3612
+ name: "Verification Covered",
3613
+ description: "Approval, rollout, and mitigation all require named verification paths",
3614
+ criteria: [
3615
+ {
3616
+ criterionId: "checks-defined",
3617
+ description: "At least one explicit verification path is named",
3618
+ metric: "verification_paths_defined",
3619
+ threshold: 1,
3620
+ operator: "gte"
3621
+ },
3622
+ {
3623
+ criterionId: "owners-named",
3624
+ description: "Owners or on-call responsibility are explicit",
3625
+ metric: "owner_count",
3626
+ threshold: 1,
3627
+ operator: "gte"
3628
+ }
3629
+ ],
3630
+ severity: "blocking"
3631
+ }
3632
+ ],
3633
+ artifacts: [
3634
+ {
3635
+ artifactId: "memory-brief",
3636
+ name: "Memory Brief",
3637
+ description: "A reusable brief of analogous changes, prior rationale, failed attempts, and contradictions",
3638
+ stage: "recall-history",
3639
+ contentSchema: {
3640
+ type: "object",
3641
+ properties: {
3642
+ analogousChanges: { type: "array", items: { type: "string" } },
3643
+ priorDecisions: { type: "array", items: { type: "string" } },
3644
+ failedAttempts: { type: "array", items: { type: "string" } },
3645
+ contradictions: { type: "array", items: { type: "string" } }
3646
+ },
3647
+ required: ["analogousChanges", "priorDecisions"]
3648
+ },
3649
+ requiredFields: ["analogousChanges", "priorDecisions"]
3650
+ },
3651
+ {
3652
+ artifactId: "migration-plan",
3653
+ name: "Migration Plan",
3654
+ description: "Blast radius, rollback path, rollout checkpoints, and verification plan",
3655
+ stage: "plan-rollout",
3656
+ contentSchema: {
3657
+ type: "object",
3658
+ properties: {
3659
+ blastRadius: { type: "array", items: { type: "string" } },
3660
+ rollbackPlan: { type: "string" },
3661
+ verificationPath: { type: "array", items: { type: "string" } },
3662
+ canarySteps: { type: "array", items: { type: "string" } }
3663
+ },
3664
+ required: ["blastRadius", "rollbackPlan", "verificationPath"]
3571
3665
  },
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"
3666
+ requiredFields: ["blastRadius", "rollbackPlan", "verificationPath"]
3667
+ },
3668
+ {
3669
+ artifactId: "verification-checklist",
3670
+ name: "Verification Checklist",
3671
+ description: "Named checks, owners, and pass/fail criteria for rollout or approval",
3672
+ stage: "verify-rollout",
3673
+ contentSchema: {
3674
+ type: "object",
3675
+ properties: {
3676
+ checks: { type: "array", items: { type: "string" } },
3677
+ owners: { type: "array", items: { type: "string" } },
3678
+ passCriteria: { type: "array", items: { type: "string" } }
3679
+ },
3680
+ required: ["checks", "owners"]
3578
3681
  },
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"
3682
+ requiredFields: ["checks", "owners"]
3683
+ },
3684
+ {
3685
+ artifactId: "review-context",
3686
+ name: "Review Context",
3687
+ description: "Prior rationale, related diffs, incidents, and failure history relevant to a review",
3688
+ stage: "recall-review-context",
3689
+ contentSchema: {
3690
+ type: "object",
3691
+ properties: {
3692
+ rationaleLinks: { type: "array", items: { type: "string" } },
3693
+ analogousDiffs: { type: "array", items: { type: "string" } },
3694
+ relatedIncidents: { type: "array", items: { type: "string" } }
3695
+ },
3696
+ required: ["rationaleLinks"]
3585
3697
  },
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"
3698
+ requiredFields: ["rationaleLinks"]
3699
+ },
3700
+ {
3701
+ artifactId: "review-findings",
3702
+ name: "Review Findings",
3703
+ description: "What could regress, what evidence was checked, and whether the change should be blocked",
3704
+ stage: "inspect-diff",
3705
+ contentSchema: {
3706
+ type: "object",
3707
+ properties: {
3708
+ findings: { type: "array", items: { type: "string" } },
3709
+ regressionsChecked: { type: "array", items: { type: "string" } },
3710
+ blockReason: { type: "string" }
3711
+ },
3712
+ required: ["findings", "regressionsChecked"]
3592
3713
  },
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"
3714
+ requiredFields: ["findings", "regressionsChecked"]
3715
+ },
3716
+ {
3717
+ artifactId: "incident-brief",
3718
+ name: "Incident Brief",
3719
+ description: "Signals, recent changes, competing hypotheses, and precedent incidents",
3720
+ stage: "collect-signal",
3721
+ contentSchema: {
3722
+ type: "object",
3723
+ properties: {
3724
+ symptoms: { type: "array", items: { type: "string" } },
3725
+ recentChanges: { type: "array", items: { type: "string" } },
3726
+ competingHypotheses: { type: "array", items: { type: "string" } },
3727
+ precedentIncidents: { type: "array", items: { type: "string" } }
3728
+ },
3729
+ required: ["symptoms", "competingHypotheses"]
3599
3730
  },
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"
3731
+ requiredFields: ["symptoms", "competingHypotheses"]
3732
+ },
3733
+ {
3734
+ artifactId: "contradiction-report",
3735
+ name: "Contradiction Report",
3736
+ description: "Active contradictions, why they matter, and what evidence could collapse them",
3737
+ stage: "surface-contradictions",
3738
+ contentSchema: {
3739
+ type: "object",
3740
+ properties: {
3741
+ contradictions: { type: "array", items: { type: "string" } },
3742
+ likelyRootCauses: { type: "array", items: { type: "string" } },
3743
+ missingEvidence: { type: "array", items: { type: "string" } }
3744
+ },
3745
+ required: ["contradictions", "likelyRootCauses"]
3606
3746
  },
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"
3747
+ requiredFields: ["contradictions", "likelyRootCauses"]
3748
+ },
3749
+ {
3750
+ artifactId: "mitigation-plan",
3751
+ name: "Mitigation Plan",
3752
+ description: "Chosen mitigation, rollback path, and verification ownership for an incident",
3753
+ stage: "plan-mitigation",
3754
+ contentSchema: {
3755
+ type: "object",
3756
+ properties: {
3757
+ mitigationSteps: { type: "array", items: { type: "string" } },
3758
+ rollbackPlan: { type: "string" },
3759
+ owners: { type: "array", items: { type: "string" } }
3760
+ },
3761
+ required: ["mitigationSteps", "owners"]
3613
3762
  },
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
- ]
3763
+ requiredFields: ["mitigationSteps", "owners"]
3764
+ },
3765
+ {
3766
+ artifactId: "decision-brief",
3767
+ name: "Decision Brief",
3768
+ description: "Options, cited precedent, trade-offs, and objections for an architecture decision",
3769
+ stage: "compare-options",
3770
+ contentSchema: {
3771
+ type: "object",
3772
+ properties: {
3773
+ options: { type: "array", items: { type: "string" } },
3774
+ citedPrecedent: { type: "array", items: { type: "string" } },
3775
+ objections: { type: "array", items: { type: "string" } }
3776
+ },
3777
+ required: ["options", "citedPrecedent"]
3676
3778
  },
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
- ]
3779
+ requiredFields: ["options", "citedPrecedent"]
3780
+ },
3781
+ {
3782
+ artifactId: "decision-record",
3783
+ name: "Decision Record",
3784
+ description: "Chosen path, why it won, what it supersedes, and what follow-up remains open",
3785
+ stage: "record-decision",
3786
+ contentSchema: {
3787
+ type: "object",
3788
+ properties: {
3789
+ decision: { type: "string" },
3790
+ rationale: { type: "array", items: { type: "string" } },
3791
+ supersedes: { type: "array", items: { type: "string" } },
3792
+ followUps: { type: "array", items: { type: "string" } }
3793
+ },
3794
+ required: ["decision", "rationale"]
3721
3795
  },
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"
3796
+ requiredFields: ["decision", "rationale"]
3797
+ }
3786
3798
  ],
3787
- methodologyPackId: "developer"
3799
+ roles: [
3800
+ {
3801
+ roleId: "context-compiler",
3802
+ name: "Context Compiler",
3803
+ description: "Compiles prior rationale, analogs, and failure memory into reusable first-hour context",
3804
+ perspective: "History-first, evidence-weighted context assembly",
3805
+ optimizesFor: "recall quality and anti-repetition coverage",
3806
+ mayBlock: false
3807
+ },
3808
+ {
3809
+ roleId: "migration-owner",
3810
+ name: "Migration Owner",
3811
+ description: "Scopes rollout blast radius, rollback, sequencing, and compatibility risk",
3812
+ perspective: "Operational caution with explicit rollback discipline",
3813
+ optimizesFor: "safe rollout planning",
3814
+ mayBlock: false
3815
+ },
3816
+ {
3817
+ roleId: "reviewer",
3818
+ name: "Reviewer",
3819
+ description: "Evaluates risky changes against prior regressions, evidence, and missing checks",
3820
+ perspective: "Evidence-backed change approval with regression awareness",
3821
+ optimizesFor: "defect prevention and clear approval rationale",
3822
+ mayBlock: true
3823
+ },
3824
+ {
3825
+ roleId: "incident-commander",
3826
+ name: "Incident Commander",
3827
+ description: "Maintains multiple plausible explanations while driving mitigation decisions",
3828
+ perspective: "Fast, reversible action without collapsing uncertainty too early",
3829
+ optimizesFor: "time-to-mitigation with preserved reasoning integrity",
3830
+ mayBlock: false
3831
+ },
3832
+ {
3833
+ roleId: "architect",
3834
+ name: "Architect",
3835
+ description: "Turns competing options into explicit decisions with cited precedent and follow-up risk",
3836
+ perspective: "Trade-off clarity and long-term maintainability",
3837
+ optimizesFor: "decision quality and rationale reuse",
3838
+ mayBlock: false
3839
+ },
3840
+ {
3841
+ roleId: "critic",
3842
+ name: "Critic",
3843
+ description: "Finds weak assumptions, missing rollback paths, and untested contradictions",
3844
+ perspective: "Skeptical, adversarial, and detail-oriented",
3845
+ optimizesFor: "early detection of brittle plans",
3846
+ mayBlock: true
3847
+ }
3848
+ ],
3849
+ ...ENGINEERING_ACCELERATOR_TAIL
3788
3850
  });
3789
3851
 
3790
3852
  // src/domain-pack/packs/index.ts
@@ -3808,6 +3870,6 @@ var listShapingContributions = shapingContributionRegistry.list.bind(
3808
3870
  shapingContributionRegistry
3809
3871
  );
3810
3872
 
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 };
3873
+ export { DEVELOPER_REASONING_PACK, ENGINEERING_ACCELERATOR_PACK, SOFTWARE_ENTITIES_V1, buildShapingContribution, createDomainPackAuthoringTools2 as createDomainPackAuthoringTools, createShapingContributionRegistry, defineDomainPack, defineDomainPackAuthoringManifest, getDomainPack, getShapingContribution, listDomainPacks, listShapingContributions, parseDomainPackAuthoringManifest, previewDomainPackAuthoringManifest2 as previewDomainPackAuthoringManifest, previewDomainPackAuthoringManifestSource2 as previewDomainPackAuthoringManifestSource, publishDomainPackAuthoringManifest2 as publishDomainPackAuthoringManifest, publishDomainPackAuthoringManifestSource2 as publishDomainPackAuthoringManifestSource, serializeDomainPackAuthoringManifest, validateDomainPack, validateDomainPackAuthoringManifest2 as validateDomainPackAuthoringManifest, validateDomainPackAuthoringManifestSource2 as validateDomainPackAuthoringManifestSource, validateShapingContribution };
3812
3874
  //# sourceMappingURL=index.js.map
3813
3875
  //# sourceMappingURL=index.js.map