onto-mcp 0.3.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.onto/authority/core-lexicon.yaml +12 -0
- package/.onto/domains/software-engineering/competency_qs.md +192 -63
- package/.onto/domains/software-engineering/concepts.md +67 -5
- package/.onto/domains/software-engineering/conciseness_rules.md +22 -2
- package/.onto/domains/software-engineering/dependency_rules.md +78 -8
- package/.onto/domains/software-engineering/domain_scope.md +181 -150
- package/.onto/domains/software-engineering/extension_cases.md +318 -542
- package/.onto/domains/software-engineering/logic_rules.md +75 -3
- package/.onto/domains/software-engineering/problem_framing_profile.md +29 -2
- package/.onto/domains/software-engineering/prompt_interface.md +122 -0
- package/.onto/domains/software-engineering/structure_spec.md +53 -4
- package/.onto/principles/llm-native-development-guideline.md +20 -0
- package/.onto/principles/productization-charter.md +6 -0
- package/.onto/processes/evolve/material-kind-adapter-contract.md +6 -0
- package/.onto/processes/reconstruct/reconstruct-boundary-contract.md +468 -81
- package/.onto/processes/reconstruct/reconstruct-execution-ux-contract.md +177 -0
- package/.onto/processes/reconstruct/source-profile-contract.md +39 -6
- package/.onto/processes/reconstruct/top-level-concept-discovery-contract.md +387 -0
- package/.onto/processes/review/binding-contract.md +8 -0
- package/.onto/processes/review/lens-registry.md +16 -0
- package/.onto/processes/review/pre-dispatch-contracts.md +34 -13
- package/.onto/processes/review/productized-live-path.md +3 -1
- package/.onto/processes/shared/pipeline-execution-ledger-contract.md +185 -0
- package/.onto/processes/shared/target-material-kind-contract.md +24 -2
- package/.onto/roles/axiology.md +7 -2
- package/AGENTS.md +4 -2
- package/README.md +52 -29
- package/dist/core-api/reconstruct-api.js +92 -5
- package/dist/core-api/review-api.js +1744 -371
- package/dist/core-runtime/cli/mock-review-unit-executor.js +17 -0
- package/dist/core-runtime/cli/render-review-final-output.js +9 -0
- package/dist/core-runtime/cli/review-invoke.js +387 -55
- package/dist/core-runtime/cli/run-review-prompt-execution.js +361 -90
- package/dist/core-runtime/path-boundary.js +58 -0
- package/dist/core-runtime/pipeline-execution-ledger.js +100 -0
- package/dist/core-runtime/reconstruct/artifact-types.js +33 -1
- package/dist/core-runtime/reconstruct/materialize-preparation.js +54 -4
- package/dist/core-runtime/reconstruct/pipeline-execution-ledger.js +342 -0
- package/dist/core-runtime/reconstruct/post-seed-validation.js +630 -0
- package/dist/core-runtime/reconstruct/record.js +105 -1
- package/dist/core-runtime/reconstruct/run.js +1594 -38
- package/dist/core-runtime/reconstruct/seed-candidate-validation.js +29 -0
- package/dist/core-runtime/review/continuation-plan.js +160 -0
- package/dist/core-runtime/review/execution-plan-boundary.js +123 -0
- package/dist/core-runtime/review/materializers.js +8 -3
- package/dist/core-runtime/review/pipeline-execution-ledger.js +250 -0
- package/dist/core-runtime/review/review-artifact-utils.js +15 -2
- package/dist/core-runtime/review/review-invocation-runner.js +604 -0
- package/dist/core-runtime/target-material-kind.js +43 -5
- package/dist/mcp/server.js +289 -59
- package/dist/mcp/tool-schemas.js +28 -2
- package/package.json +4 -2
- package/.onto/domains/llm-native-development/competency_qs.md +0 -430
- package/.onto/domains/llm-native-development/concepts.md +0 -242
- package/.onto/domains/llm-native-development/conciseness_rules.md +0 -163
- package/.onto/domains/llm-native-development/dependency_rules.md +0 -216
- package/.onto/domains/llm-native-development/domain_scope.md +0 -197
- package/.onto/domains/llm-native-development/extension_cases.md +0 -474
- package/.onto/domains/llm-native-development/logic_rules.md +0 -123
- package/.onto/domains/llm-native-development/prompt_interface.md +0 -49
- package/.onto/domains/llm-native-development/structure_spec.md +0 -245
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
|
|
4
|
+
import { callLlm } from "../llm/llm-caller.js";
|
|
5
|
+
import { loadCoreLensRegistry } from "../discovery/lens-registry.js";
|
|
4
6
|
import { writeSourceObservationDirectiveValidationArtifact } from "./directive-validation.js";
|
|
5
7
|
import { materializeReconstructPreparationArtifacts } from "./materialize-preparation.js";
|
|
8
|
+
import { validateFinalOutputProvenance, writeClaimRealizationMapValidationArtifact, writeCompetencyQuestionAssessmentValidationArtifact, writeCompetencyQuestionsValidationArtifact, writeFailureClassificationValidationArtifact, writeRevisionProposalValidationArtifact, writeSeedConfirmationValidationArtifact, } from "./post-seed-validation.js";
|
|
6
9
|
import { assembleReconstructRecord } from "./record.js";
|
|
7
10
|
import { writeSeedCandidateValidationArtifact } from "./seed-candidate-validation.js";
|
|
8
11
|
function isoNow() {
|
|
@@ -26,6 +29,74 @@ function allClaims(seedCandidate) {
|
|
|
26
29
|
...seedCandidate.rules,
|
|
27
30
|
];
|
|
28
31
|
}
|
|
32
|
+
function compactStatement(statement) {
|
|
33
|
+
const limit = 240;
|
|
34
|
+
return statement.length <= limit ? statement : `${statement.slice(0, limit - 3)}...`;
|
|
35
|
+
}
|
|
36
|
+
function sourceBasename(sourceRef) {
|
|
37
|
+
return path.basename(sourceRef) || sourceRef;
|
|
38
|
+
}
|
|
39
|
+
function summarizeSeedClaimsForConfirmation(seedCandidate) {
|
|
40
|
+
const groups = [
|
|
41
|
+
["purpose", [seedCandidate.purpose]],
|
|
42
|
+
["non_goal", seedCandidate.non_goals],
|
|
43
|
+
["entity", seedCandidate.entities],
|
|
44
|
+
["relation", seedCandidate.relations],
|
|
45
|
+
["action", seedCandidate.actions],
|
|
46
|
+
["property", seedCandidate.properties],
|
|
47
|
+
["rule", seedCandidate.rules],
|
|
48
|
+
];
|
|
49
|
+
return groups.flatMap(([claimKind, claims]) => claims.map((claim) => ({
|
|
50
|
+
claim_id: claim.claim_id,
|
|
51
|
+
claim_kind: claimKind,
|
|
52
|
+
name: claim.name,
|
|
53
|
+
statement: compactStatement(claim.statement),
|
|
54
|
+
evidence_observation_ids: [
|
|
55
|
+
...new Set(claim.evidence_refs.map((ref) => ref.observation_id)),
|
|
56
|
+
],
|
|
57
|
+
evidence_source_basenames: [
|
|
58
|
+
...new Set(claim.evidence_refs.map((ref) => sourceBasename(ref.source_ref))),
|
|
59
|
+
],
|
|
60
|
+
})));
|
|
61
|
+
}
|
|
62
|
+
function countBy(values, selected) {
|
|
63
|
+
const counts = Object.fromEntries(values.map((value) => [value, 0]));
|
|
64
|
+
for (const value of selected) {
|
|
65
|
+
counts[value] += 1;
|
|
66
|
+
}
|
|
67
|
+
return counts;
|
|
68
|
+
}
|
|
69
|
+
const CLAIM_REALIZATION_STANCES = [
|
|
70
|
+
"observed_runtime_behavior",
|
|
71
|
+
"declared_design_intent",
|
|
72
|
+
"schema_or_contract_presence",
|
|
73
|
+
"test_or_fixture_only",
|
|
74
|
+
"deferred_or_non_goal",
|
|
75
|
+
"unknown",
|
|
76
|
+
];
|
|
77
|
+
const ANSWER_STATUSES = [
|
|
78
|
+
"answered",
|
|
79
|
+
"partially_answered",
|
|
80
|
+
"not_answered",
|
|
81
|
+
"needs_evidence",
|
|
82
|
+
"out_of_scope",
|
|
83
|
+
];
|
|
84
|
+
const FAILURE_KINDS = [
|
|
85
|
+
"unsupported_claim",
|
|
86
|
+
"unanswered_question",
|
|
87
|
+
"contradicted_evidence",
|
|
88
|
+
"insufficient_evidence",
|
|
89
|
+
"deferred_scope",
|
|
90
|
+
"out_of_scope",
|
|
91
|
+
];
|
|
92
|
+
const REVISION_ACTIONS = [
|
|
93
|
+
"reuse",
|
|
94
|
+
"extend",
|
|
95
|
+
"rename",
|
|
96
|
+
"split",
|
|
97
|
+
"reject",
|
|
98
|
+
"defer",
|
|
99
|
+
];
|
|
29
100
|
function evidenceRefFromObservation(observation) {
|
|
30
101
|
return {
|
|
31
102
|
observation_id: observation.observation_id,
|
|
@@ -46,18 +117,34 @@ function calculateMetrics(args) {
|
|
|
46
117
|
source_observation_directive: args.sourceObservationDirectiveValidation.validation_status,
|
|
47
118
|
seed_candidate: args.seedCandidateValidation.validation_status,
|
|
48
119
|
seed_confirmation: args.seedConfirmation.confirmation_status,
|
|
120
|
+
claim_realization: args.claimRealizationMapValidation.validation_status,
|
|
121
|
+
seed_confirmation_validation: args.seedConfirmationValidation.validation_status,
|
|
122
|
+
competency_questions: args.competencyQuestionsValidation.validation_status,
|
|
123
|
+
competency_question_assessment: args.competencyQuestionAssessmentValidation.validation_status,
|
|
124
|
+
failure_classification: args.failureClassificationValidation.validation_status,
|
|
125
|
+
revision_proposal: args.revisionProposalValidation.validation_status,
|
|
49
126
|
};
|
|
50
|
-
const rejectedClaimCount = args.
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
127
|
+
const rejectedClaimCount = args.seedConfirmationValidation.rejected_claim_ids.length;
|
|
128
|
+
const partialClaimCount = args.seedConfirmationValidation.partial_claim_ids.length;
|
|
129
|
+
const deferredClaimCount = args.seedConfirmationValidation.deferred_claim_ids.length;
|
|
130
|
+
const invalidGateCount = [
|
|
131
|
+
validationStatus.source_observation_directive,
|
|
132
|
+
validationStatus.seed_candidate,
|
|
133
|
+
validationStatus.claim_realization,
|
|
134
|
+
validationStatus.seed_confirmation_validation,
|
|
135
|
+
validationStatus.competency_questions,
|
|
136
|
+
validationStatus.competency_question_assessment,
|
|
137
|
+
validationStatus.failure_classification,
|
|
138
|
+
validationStatus.revision_proposal,
|
|
139
|
+
].filter((status) => status !== "valid").length;
|
|
56
140
|
const unresolvedQuestionCount = rejectedClaimCount +
|
|
141
|
+
partialClaimCount +
|
|
142
|
+
args.failureClassificationValidation.material_failure_count +
|
|
57
143
|
args.competencyQuestions.open_questions.length +
|
|
58
|
-
|
|
144
|
+
invalidGateCount;
|
|
59
145
|
const competencyQuestionCount = args.competencyQuestions.questions.length;
|
|
60
146
|
const passedQuestions = Math.max(0, competencyQuestionCount - unresolvedQuestionCount);
|
|
147
|
+
const answerStatusCounts = args.competencyQuestionAssessmentValidation.answer_status_counts;
|
|
61
148
|
return {
|
|
62
149
|
schema_version: "1",
|
|
63
150
|
session_id: args.sessionId,
|
|
@@ -66,10 +153,26 @@ function calculateMetrics(args) {
|
|
|
66
153
|
selected_observation_count: args.sourceObservationDirectiveValidation.selected_observation_count,
|
|
67
154
|
semantic_claim_count: args.seedCandidateValidation.semantic_claim_count,
|
|
68
155
|
evidence_ref_count: args.seedCandidateValidation.evidence_ref_count,
|
|
69
|
-
confirmed_claim_count: args.
|
|
156
|
+
confirmed_claim_count: args.seedConfirmationValidation.accepted_claim_ids.length,
|
|
70
157
|
rejected_claim_count: rejectedClaimCount,
|
|
158
|
+
partial_claim_count: partialClaimCount,
|
|
159
|
+
deferred_claim_count: deferredClaimCount,
|
|
71
160
|
competency_question_count: competencyQuestionCount,
|
|
161
|
+
competency_question_assessment_count: args.competencyQuestionAssessmentValidation.assessment_count,
|
|
72
162
|
unresolved_question_count: unresolvedQuestionCount,
|
|
163
|
+
deferred_count: deferredClaimCount +
|
|
164
|
+
answerStatusCounts.out_of_scope +
|
|
165
|
+
args.failureClassificationValidation.failure_kind_counts.deferred_scope,
|
|
166
|
+
claim_realization_stance_counts: args.claimRealizationMapValidation.stance_counts,
|
|
167
|
+
confirmation_state_counts: {
|
|
168
|
+
accepted: args.seedConfirmationValidation.accepted_claim_ids.length,
|
|
169
|
+
rejected: rejectedClaimCount,
|
|
170
|
+
partial: partialClaimCount,
|
|
171
|
+
deferred: deferredClaimCount,
|
|
172
|
+
},
|
|
173
|
+
competency_question_answer_status_counts: answerStatusCounts,
|
|
174
|
+
failure_kind_counts: args.failureClassificationValidation.failure_kind_counts,
|
|
175
|
+
revision_proposal_action_counts: args.revisionProposalValidation.action_counts,
|
|
73
176
|
pass_rate: competencyQuestionCount === 0
|
|
74
177
|
? 0
|
|
75
178
|
: Number((passedQuestions / competencyQuestionCount).toFixed(4)),
|
|
@@ -80,16 +183,30 @@ function artifactRefsWithDefaults(args) {
|
|
|
80
183
|
return {
|
|
81
184
|
target_material_profile: args.refs.target_material_profile ?? null,
|
|
82
185
|
source_inventory: args.refs.source_inventory ?? null,
|
|
186
|
+
initial_source_frontier: args.refs.initial_source_frontier ?? null,
|
|
83
187
|
source_observations: args.refs.source_observations ?? null,
|
|
84
188
|
source_observation_directive: args.refs.source_observation_directive ?? null,
|
|
85
189
|
source_observation_directive_validation: args.refs.source_observation_directive_validation ?? null,
|
|
190
|
+
lens_judgment_index: args.refs.lens_judgment_index ?? null,
|
|
191
|
+
exploration_synthesis: args.refs.exploration_synthesis ?? null,
|
|
192
|
+
source_frontier: args.refs.source_frontier ?? null,
|
|
193
|
+
source_frontier_validation: args.refs.source_frontier_validation ?? null,
|
|
86
194
|
domain_context_selection: args.refs.domain_context_selection ?? null,
|
|
195
|
+
domain_context_selection_validation: args.refs.domain_context_selection_validation ?? null,
|
|
87
196
|
seed_candidate: args.refs.seed_candidate ?? null,
|
|
88
197
|
seed_candidate_validation: args.refs.seed_candidate_validation ?? null,
|
|
198
|
+
claim_realization_map: args.refs.claim_realization_map ?? null,
|
|
199
|
+
claim_realization_map_validation: args.refs.claim_realization_map_validation ?? null,
|
|
89
200
|
seed_confirmation: args.refs.seed_confirmation ?? null,
|
|
201
|
+
seed_confirmation_validation: args.refs.seed_confirmation_validation ?? null,
|
|
90
202
|
competency_questions: args.refs.competency_questions ?? null,
|
|
203
|
+
competency_questions_validation: args.refs.competency_questions_validation ?? null,
|
|
204
|
+
competency_question_assessment: args.refs.competency_question_assessment ?? null,
|
|
205
|
+
competency_question_assessment_validation: args.refs.competency_question_assessment_validation ?? null,
|
|
91
206
|
failure_classification: args.refs.failure_classification ?? null,
|
|
207
|
+
failure_classification_validation: args.refs.failure_classification_validation ?? null,
|
|
92
208
|
revision_proposal: args.refs.revision_proposal ?? null,
|
|
209
|
+
revision_proposal_validation: args.refs.revision_proposal_validation ?? null,
|
|
93
210
|
reconstruct_metrics: args.refs.reconstruct_metrics ?? null,
|
|
94
211
|
stop_decision: args.refs.stop_decision ?? null,
|
|
95
212
|
final_output: args.refs.final_output ?? null,
|
|
@@ -105,6 +222,17 @@ function completedStep(stepId, owner, performedBy, artifactRefs) {
|
|
|
105
222
|
artifact_refs: artifactRefs,
|
|
106
223
|
};
|
|
107
224
|
}
|
|
225
|
+
function skippedStep(stepId, owner, performedBy, reason, authorityImpact) {
|
|
226
|
+
return {
|
|
227
|
+
step_id: stepId,
|
|
228
|
+
owner,
|
|
229
|
+
performed_by: performedBy,
|
|
230
|
+
status: "skipped",
|
|
231
|
+
artifact_refs: [],
|
|
232
|
+
reason,
|
|
233
|
+
authority_impact: authorityImpact,
|
|
234
|
+
};
|
|
235
|
+
}
|
|
108
236
|
function runtimePerformer() {
|
|
109
237
|
return {
|
|
110
238
|
authority: "runtime",
|
|
@@ -115,14 +243,14 @@ function runtimePerformer() {
|
|
|
115
243
|
function directiveAuthorPerformer(directiveAuthor) {
|
|
116
244
|
return {
|
|
117
245
|
authority: "host_llm",
|
|
118
|
-
realization: "mock",
|
|
246
|
+
realization: directiveAuthor.owner === "mock" ? "mock" : "direct_call",
|
|
119
247
|
actor_id: directiveAuthor.authorId,
|
|
120
248
|
};
|
|
121
249
|
}
|
|
122
250
|
function confirmationProviderPerformer(confirmationProvider) {
|
|
123
251
|
return {
|
|
124
252
|
authority: "host_or_user",
|
|
125
|
-
realization: "mock",
|
|
253
|
+
realization: confirmationProvider.owner === "mock" ? "mock" : "direct_call",
|
|
126
254
|
actor_id: confirmationProvider.providerId,
|
|
127
255
|
};
|
|
128
256
|
}
|
|
@@ -136,11 +264,19 @@ function createRunManifest(args) {
|
|
|
136
264
|
target_refs: args.targetRefs,
|
|
137
265
|
intent: args.intent,
|
|
138
266
|
execution_profile: {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
267
|
+
profile_kind: args.semanticAuthorRealization === "mock"
|
|
268
|
+
? "mock_semantic_slice"
|
|
269
|
+
: "full_integral_exploration",
|
|
270
|
+
runner: args.semanticAuthorRealization === "mock"
|
|
271
|
+
? "material-aware-happy-path"
|
|
272
|
+
: "integral-exploration-direct-call",
|
|
273
|
+
semantic_author_realization: args.semanticAuthorRealization,
|
|
274
|
+
confirmation_provider_realization: args.confirmationProviderRealization,
|
|
142
275
|
directive_author_id: args.directiveAuthor.authorId,
|
|
143
276
|
confirmation_provider_id: args.confirmationProvider.providerId,
|
|
277
|
+
allowed_completion_claim: args.semanticAuthorRealization === "mock"
|
|
278
|
+
? "Runtime exercised the post-Seed artifact flow with mock authorship; live semantic reconstruction is not claimed."
|
|
279
|
+
: "Runtime completed the live integral reconstruct path for the produced and explicitly skipped artifacts.",
|
|
144
280
|
},
|
|
145
281
|
artifact_refs: {
|
|
146
282
|
...args.artifactRefs,
|
|
@@ -150,13 +286,28 @@ function createRunManifest(args) {
|
|
|
150
286
|
implemented_artifacts: [
|
|
151
287
|
"target_material_profile",
|
|
152
288
|
"source_inventory",
|
|
289
|
+
"initial_source_frontier",
|
|
153
290
|
"source_observations",
|
|
154
291
|
"source_observation_directive",
|
|
155
292
|
"source_observation_directive_validation",
|
|
293
|
+
"lens_judgment_index",
|
|
294
|
+
"exploration_synthesis",
|
|
295
|
+
"source_frontier",
|
|
296
|
+
"source_frontier_validation",
|
|
156
297
|
"seed_candidate",
|
|
157
298
|
"seed_candidate_validation",
|
|
299
|
+
"claim_realization_map",
|
|
300
|
+
"claim_realization_map_validation",
|
|
158
301
|
"seed_confirmation",
|
|
302
|
+
"seed_confirmation_validation",
|
|
159
303
|
"competency_questions",
|
|
304
|
+
"competency_questions_validation",
|
|
305
|
+
"competency_question_assessment",
|
|
306
|
+
"competency_question_assessment_validation",
|
|
307
|
+
"failure_classification",
|
|
308
|
+
"failure_classification_validation",
|
|
309
|
+
"revision_proposal",
|
|
310
|
+
"revision_proposal_validation",
|
|
160
311
|
"reconstruct_metrics",
|
|
161
312
|
"stop_decision",
|
|
162
313
|
"final_output",
|
|
@@ -165,36 +316,76 @@ function createRunManifest(args) {
|
|
|
165
316
|
],
|
|
166
317
|
deferred_artifacts: [
|
|
167
318
|
"domain_context_selection",
|
|
168
|
-
"
|
|
169
|
-
"revision_proposal",
|
|
319
|
+
"domain_context_selection_validation",
|
|
170
320
|
],
|
|
171
|
-
deferred_reason: "The current runner
|
|
321
|
+
deferred_reason: "The current runner does not yet select domain context; downstream authority is narrowed to source-grounded reconstruction without selected domain-document alignment.",
|
|
172
322
|
},
|
|
173
323
|
steps: [
|
|
174
|
-
completedStep("
|
|
324
|
+
completedStep("invocation_binding", "runtime", runtimePerformer(), []),
|
|
325
|
+
completedStep("target_material_profile", "runtime", runtimePerformer(), [
|
|
175
326
|
args.artifactRefs.target_material_profile,
|
|
176
327
|
].filter((ref) => ref !== null)),
|
|
177
328
|
completedStep("source_inventory", "runtime", runtimePerformer(), [
|
|
178
329
|
args.artifactRefs.source_inventory,
|
|
179
330
|
].filter((ref) => ref !== null)),
|
|
331
|
+
completedStep("initial_source_frontier", "runtime", runtimePerformer(), [
|
|
332
|
+
args.artifactRefs.initial_source_frontier,
|
|
333
|
+
].filter((ref) => ref !== null)),
|
|
180
334
|
completedStep("source_observation", "runtime", runtimePerformer(), [
|
|
181
335
|
args.artifactRefs.source_observations,
|
|
182
336
|
].filter((ref) => ref !== null)),
|
|
183
|
-
completedStep("
|
|
337
|
+
completedStep("observation_directive", "host_llm", directiveAuthorPerformer(args.directiveAuthor), [args.artifactRefs.source_observation_directive]
|
|
184
338
|
.filter((ref) => ref !== null)),
|
|
185
|
-
completedStep("
|
|
339
|
+
completedStep("observation_directive_validation", "runtime", runtimePerformer(), [
|
|
186
340
|
args.artifactRefs.source_observation_directive_validation,
|
|
187
341
|
].filter((ref) => ref !== null)),
|
|
342
|
+
completedStep("lens_judgment", "host_llm", directiveAuthorPerformer(args.directiveAuthor), [args.artifactRefs.lens_judgment_index]
|
|
343
|
+
.filter((ref) => ref !== null)),
|
|
344
|
+
completedStep("exploration_synthesis", "host_llm", directiveAuthorPerformer(args.directiveAuthor), [args.artifactRefs.exploration_synthesis]
|
|
345
|
+
.filter((ref) => ref !== null)),
|
|
346
|
+
completedStep("source_frontier", "host_llm", directiveAuthorPerformer(args.directiveAuthor), [args.artifactRefs.source_frontier]
|
|
347
|
+
.filter((ref) => ref !== null)),
|
|
348
|
+
completedStep("source_frontier_validation", "runtime", runtimePerformer(), [
|
|
349
|
+
args.artifactRefs.source_frontier_validation,
|
|
350
|
+
].filter((ref) => ref !== null)),
|
|
351
|
+
skippedStep("domain_context_selection", "host_llm", directiveAuthorPerformer(args.directiveAuthor), "domain context selection is not implemented in this direct-call runner.", "Final output cannot claim selected domain-document alignment."),
|
|
352
|
+
skippedStep("domain_context_selection_validation", "runtime", runtimePerformer(), "domain context selection was skipped.", "Runtime cannot validate domain snapshot identity for this run."),
|
|
188
353
|
completedStep("seed_candidate", "host_llm", directiveAuthorPerformer(args.directiveAuthor), [args.artifactRefs.seed_candidate]
|
|
189
354
|
.filter((ref) => ref !== null)),
|
|
190
355
|
completedStep("seed_candidate_validation", "runtime", runtimePerformer(), [
|
|
191
356
|
args.artifactRefs.seed_candidate_validation,
|
|
192
357
|
].filter((ref) => ref !== null)),
|
|
358
|
+
completedStep("claim_realization", "host_llm", directiveAuthorPerformer(args.directiveAuthor), [args.artifactRefs.claim_realization_map]
|
|
359
|
+
.filter((ref) => ref !== null)),
|
|
360
|
+
completedStep("claim_realization_validation", "runtime", runtimePerformer(), [
|
|
361
|
+
args.artifactRefs.claim_realization_map_validation,
|
|
362
|
+
].filter((ref) => ref !== null)),
|
|
193
363
|
completedStep("seed_confirmation", "host_or_user", confirmationProviderPerformer(args.confirmationProvider), [args.artifactRefs.seed_confirmation]
|
|
194
364
|
.filter((ref) => ref !== null)),
|
|
365
|
+
completedStep("seed_confirmation_validation", "runtime", runtimePerformer(), [
|
|
366
|
+
args.artifactRefs.seed_confirmation_validation,
|
|
367
|
+
].filter((ref) => ref !== null)),
|
|
195
368
|
completedStep("competency_questions", "host_llm", directiveAuthorPerformer(args.directiveAuthor), [args.artifactRefs.competency_questions]
|
|
196
369
|
.filter((ref) => ref !== null)),
|
|
197
|
-
completedStep("
|
|
370
|
+
completedStep("competency_questions_validation", "runtime", runtimePerformer(), [
|
|
371
|
+
args.artifactRefs.competency_questions_validation,
|
|
372
|
+
].filter((ref) => ref !== null)),
|
|
373
|
+
completedStep("competency_question_assessment", "host_llm", directiveAuthorPerformer(args.directiveAuthor), [args.artifactRefs.competency_question_assessment]
|
|
374
|
+
.filter((ref) => ref !== null)),
|
|
375
|
+
completedStep("competency_question_assessment_validation", "runtime", runtimePerformer(), [
|
|
376
|
+
args.artifactRefs.competency_question_assessment_validation,
|
|
377
|
+
].filter((ref) => ref !== null)),
|
|
378
|
+
completedStep("failure_classification", "host_llm", directiveAuthorPerformer(args.directiveAuthor), [args.artifactRefs.failure_classification]
|
|
379
|
+
.filter((ref) => ref !== null)),
|
|
380
|
+
completedStep("failure_classification_validation", "runtime", runtimePerformer(), [
|
|
381
|
+
args.artifactRefs.failure_classification_validation,
|
|
382
|
+
].filter((ref) => ref !== null)),
|
|
383
|
+
completedStep("revision_proposal", "host_llm", directiveAuthorPerformer(args.directiveAuthor), [args.artifactRefs.revision_proposal]
|
|
384
|
+
.filter((ref) => ref !== null)),
|
|
385
|
+
completedStep("revision_proposal_validation", "runtime", runtimePerformer(), [
|
|
386
|
+
args.artifactRefs.revision_proposal_validation,
|
|
387
|
+
].filter((ref) => ref !== null)),
|
|
388
|
+
completedStep("metrics", "runtime", runtimePerformer(), [
|
|
198
389
|
args.artifactRefs.reconstruct_metrics,
|
|
199
390
|
].filter((ref) => ref !== null)),
|
|
200
391
|
completedStep("stop_decision", "host_llm", directiveAuthorPerformer(args.directiveAuthor), [args.artifactRefs.stop_decision]
|
|
@@ -211,6 +402,766 @@ function createRunManifest(args) {
|
|
|
211
402
|
},
|
|
212
403
|
};
|
|
213
404
|
}
|
|
405
|
+
function stripJsonFences(text) {
|
|
406
|
+
const trimmed = text.trim();
|
|
407
|
+
const fenced = /^```(?:json)?\s*([\s\S]*?)\s*```$/i.exec(trimmed);
|
|
408
|
+
return fenced?.[1]?.trim() ?? trimmed;
|
|
409
|
+
}
|
|
410
|
+
function parseLlmJsonObject(text, artifactName) {
|
|
411
|
+
const stripped = stripJsonFences(text);
|
|
412
|
+
const start = stripped.indexOf("{");
|
|
413
|
+
const end = stripped.lastIndexOf("}");
|
|
414
|
+
if (start < 0 || end < start) {
|
|
415
|
+
throw new Error(`${artifactName} author returned no JSON object.`);
|
|
416
|
+
}
|
|
417
|
+
try {
|
|
418
|
+
const parsed = JSON.parse(stripped.slice(start, end + 1));
|
|
419
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
420
|
+
throw new Error("top-level value is not an object");
|
|
421
|
+
}
|
|
422
|
+
return parsed;
|
|
423
|
+
}
|
|
424
|
+
catch (error) {
|
|
425
|
+
throw new Error(`${artifactName} author returned invalid JSON: ${error instanceof Error ? error.message : String(error)}`);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
function records(value, fieldName) {
|
|
429
|
+
if (!Array.isArray(value)) {
|
|
430
|
+
throw new Error(`${fieldName} must be an array.`);
|
|
431
|
+
}
|
|
432
|
+
return value.map((item, index) => {
|
|
433
|
+
if (item === null || typeof item !== "object" || Array.isArray(item)) {
|
|
434
|
+
throw new Error(`${fieldName}[${index}] must be an object.`);
|
|
435
|
+
}
|
|
436
|
+
return item;
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
function stringValue(value, fieldName) {
|
|
440
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
441
|
+
throw new Error(`${fieldName} must be a non-empty string.`);
|
|
442
|
+
}
|
|
443
|
+
return value.trim();
|
|
444
|
+
}
|
|
445
|
+
function optionalString(value) {
|
|
446
|
+
return typeof value === "string" && value.trim().length > 0
|
|
447
|
+
? value.trim()
|
|
448
|
+
: null;
|
|
449
|
+
}
|
|
450
|
+
function stringArray(value, fieldName) {
|
|
451
|
+
if (value === undefined)
|
|
452
|
+
return [];
|
|
453
|
+
if (!Array.isArray(value))
|
|
454
|
+
throw new Error(`${fieldName} must be an array.`);
|
|
455
|
+
return value.map((item, index) => stringValue(item, `${fieldName}[${index}]`));
|
|
456
|
+
}
|
|
457
|
+
function evidenceRefByObservationId(sourceObservations) {
|
|
458
|
+
return new Map(sourceObservations.observations.map((observation) => [
|
|
459
|
+
observation.observation_id,
|
|
460
|
+
evidenceRefFromObservation(observation),
|
|
461
|
+
]));
|
|
462
|
+
}
|
|
463
|
+
function evidenceRefsFromIds(args) {
|
|
464
|
+
const byId = evidenceRefByObservationId(args.sourceObservations);
|
|
465
|
+
const refs = args.observationIds.map((observationId) => {
|
|
466
|
+
const ref = byId.get(observationId);
|
|
467
|
+
if (!ref) {
|
|
468
|
+
throw new Error(`${args.fieldName} references unknown observation id: ${observationId}`);
|
|
469
|
+
}
|
|
470
|
+
return ref;
|
|
471
|
+
});
|
|
472
|
+
if (refs.length === 0) {
|
|
473
|
+
throw new Error(`${args.fieldName} must reference at least one observation id.`);
|
|
474
|
+
}
|
|
475
|
+
return refs;
|
|
476
|
+
}
|
|
477
|
+
function claimFromLlm(args) {
|
|
478
|
+
const claimId = optionalString(args.raw.claim_id) ?? args.fallbackId;
|
|
479
|
+
return {
|
|
480
|
+
claim_id: claimId,
|
|
481
|
+
name: stringValue(args.raw.name, `${args.fieldName}.name`),
|
|
482
|
+
statement: stringValue(args.raw.statement, `${args.fieldName}.statement`),
|
|
483
|
+
evidence_refs: evidenceRefsFromIds({
|
|
484
|
+
observationIds: stringArray(args.raw.evidence_observation_ids, `${args.fieldName}.evidence_observation_ids`),
|
|
485
|
+
sourceObservations: args.sourceObservations,
|
|
486
|
+
fieldName: `${args.fieldName}.evidence_observation_ids`,
|
|
487
|
+
}),
|
|
488
|
+
};
|
|
489
|
+
}
|
|
490
|
+
function claimsFromLlm(args) {
|
|
491
|
+
return records(args.value ?? [], args.prefix).map((raw, index) => claimFromLlm({
|
|
492
|
+
raw,
|
|
493
|
+
fallbackId: `${args.prefix}-${index + 1}`,
|
|
494
|
+
sourceObservations: args.sourceObservations,
|
|
495
|
+
fieldName: `${args.prefix}[${index}]`,
|
|
496
|
+
}));
|
|
497
|
+
}
|
|
498
|
+
function observationPromptPayload(sourceObservations) {
|
|
499
|
+
return sourceObservations.observations.map((observation) => ({
|
|
500
|
+
observation_id: observation.observation_id,
|
|
501
|
+
target_material_kind: observation.target_material_kind,
|
|
502
|
+
source_ref: observation.source_ref,
|
|
503
|
+
location: observation.location,
|
|
504
|
+
summary: observation.summary,
|
|
505
|
+
structural_data: observation.structural_data,
|
|
506
|
+
}));
|
|
507
|
+
}
|
|
508
|
+
function lensJudgmentPromptPayload(lensJudgments) {
|
|
509
|
+
return lensJudgments.map((judgment) => ({
|
|
510
|
+
lens_id: judgment.lens_id,
|
|
511
|
+
candidate_labels: judgment.candidate_labels.map((label) => ({
|
|
512
|
+
label_id: label.label_id,
|
|
513
|
+
label: label.label,
|
|
514
|
+
evidence_observation_ids: label.evidence_refs.map((ref) => ref.observation_id),
|
|
515
|
+
rationale: label.rationale,
|
|
516
|
+
})),
|
|
517
|
+
semantic_gaps: judgment.semantic_gaps.map((gap) => ({
|
|
518
|
+
gap_id: gap.gap_id,
|
|
519
|
+
description: gap.description,
|
|
520
|
+
evidence_observation_ids: gap.evidence_refs.map((ref) => ref.observation_id),
|
|
521
|
+
requested_source_refs: gap.requested_source_refs,
|
|
522
|
+
materiality_rationale: gap.materiality_rationale,
|
|
523
|
+
})),
|
|
524
|
+
no_next_frontier_rationale: judgment.no_next_frontier_rationale,
|
|
525
|
+
}));
|
|
526
|
+
}
|
|
527
|
+
async function callJsonAuthor(args) {
|
|
528
|
+
const result = await args.llmCall(args.systemPrompt, JSON.stringify(args.userPayload, null, 2), { ...args.llmConfig, max_tokens: args.maxTokens });
|
|
529
|
+
return parseLlmJsonObject(result.text, args.artifactName);
|
|
530
|
+
}
|
|
531
|
+
export function createDirectCallReconstructDirectiveAuthor(args = {}) {
|
|
532
|
+
const authorId = "direct-call-reconstruct-directive-author";
|
|
533
|
+
const llmConfig = args.llmConfig ?? {};
|
|
534
|
+
const llmCall = args.llmCall ?? callLlm;
|
|
535
|
+
const baseSystem = [
|
|
536
|
+
"You are authoring reconstruct semantic artifacts.",
|
|
537
|
+
"Return only valid JSON. Do not wrap in Markdown.",
|
|
538
|
+
"Use only provided observation ids as evidence. Do not invent source refs, ids, files, or facts.",
|
|
539
|
+
"Runtime will validate ids and refs. If evidence is insufficient, mark gaps or open questions instead of guessing.",
|
|
540
|
+
].join("\n");
|
|
541
|
+
return {
|
|
542
|
+
authorId,
|
|
543
|
+
owner: "host_llm",
|
|
544
|
+
async writeSourceObservationDirective(input) {
|
|
545
|
+
requireFirstObservation(input.sourceObservations);
|
|
546
|
+
const raw = await callJsonAuthor({
|
|
547
|
+
llmCall,
|
|
548
|
+
llmConfig,
|
|
549
|
+
artifactName: "SourceObservationDirective",
|
|
550
|
+
maxTokens: 2400,
|
|
551
|
+
systemPrompt: [
|
|
552
|
+
baseSystem,
|
|
553
|
+
"Select observations that should become evidence candidates for the declared reconstruct purpose.",
|
|
554
|
+
"JSON shape: {\"selected_observations\":[{\"observation_id\":\"...\",\"selection_rationale\":\"...\"}],\"open_questions\":[\"...\"]}",
|
|
555
|
+
].join("\n"),
|
|
556
|
+
userPayload: {
|
|
557
|
+
intent: input.intent,
|
|
558
|
+
target_material_profile: input.targetMaterialProfile,
|
|
559
|
+
source_observations: observationPromptPayload(input.sourceObservations),
|
|
560
|
+
},
|
|
561
|
+
});
|
|
562
|
+
const byId = new Map(input.sourceObservations.observations.map((observation) => [
|
|
563
|
+
observation.observation_id,
|
|
564
|
+
observation,
|
|
565
|
+
]));
|
|
566
|
+
const selected = records(raw.selected_observations, "selected_observations").map((selection, index) => {
|
|
567
|
+
const observationId = stringValue(selection.observation_id, `selected_observations[${index}].observation_id`);
|
|
568
|
+
const observation = byId.get(observationId);
|
|
569
|
+
if (!observation) {
|
|
570
|
+
throw new Error(`SourceObservationDirective selected unknown observation id: ${observationId}`);
|
|
571
|
+
}
|
|
572
|
+
return {
|
|
573
|
+
...evidenceRefFromObservation(observation),
|
|
574
|
+
selection_rationale: stringValue(selection.selection_rationale, `selected_observations[${index}].selection_rationale`),
|
|
575
|
+
};
|
|
576
|
+
});
|
|
577
|
+
return {
|
|
578
|
+
schema_version: "1",
|
|
579
|
+
session_id: input.sessionId,
|
|
580
|
+
created_at: isoNow(),
|
|
581
|
+
selected_observations: selected,
|
|
582
|
+
open_questions: stringArray(raw.open_questions, "open_questions"),
|
|
583
|
+
};
|
|
584
|
+
},
|
|
585
|
+
async writeLensJudgment(input) {
|
|
586
|
+
const raw = await callJsonAuthor({
|
|
587
|
+
llmCall,
|
|
588
|
+
llmConfig,
|
|
589
|
+
artifactName: `ReconstructLensJudgment:${input.lensId}`,
|
|
590
|
+
maxTokens: 3200,
|
|
591
|
+
systemPrompt: [
|
|
592
|
+
baseSystem,
|
|
593
|
+
`You are the ${input.lensId} reconstruct lens. Apply this perspective:`,
|
|
594
|
+
input.lensPrompt,
|
|
595
|
+
"JSON shape: {\"candidate_labels\":[{\"label_id\":\"...\",\"label\":\"...\",\"evidence_observation_ids\":[\"...\"],\"rationale\":\"...\"}],\"semantic_gaps\":[{\"gap_id\":\"...\",\"description\":\"...\",\"evidence_observation_ids\":[\"...\"],\"requested_source_refs\":[\"...\"],\"materiality_rationale\":\"...\"}],\"no_next_frontier_rationale\":\"... or null\"}",
|
|
596
|
+
].join("\n"),
|
|
597
|
+
userPayload: {
|
|
598
|
+
intent: input.intent,
|
|
599
|
+
round_id: input.roundId,
|
|
600
|
+
source_observation_directive_ref: input.sourceObservationDirectiveRef,
|
|
601
|
+
selected_observations: input.sourceObservationDirective.selected_observations,
|
|
602
|
+
source_observations: observationPromptPayload(input.sourceObservations),
|
|
603
|
+
},
|
|
604
|
+
});
|
|
605
|
+
return {
|
|
606
|
+
schema_version: "1",
|
|
607
|
+
session_id: input.sessionId,
|
|
608
|
+
round_id: input.roundId,
|
|
609
|
+
lens_id: input.lensId,
|
|
610
|
+
created_at: isoNow(),
|
|
611
|
+
source_observation_directive_ref: input.sourceObservationDirectiveRef,
|
|
612
|
+
candidate_labels: records(raw.candidate_labels ?? [], "candidate_labels")
|
|
613
|
+
.map((label, index) => ({
|
|
614
|
+
label_id: optionalString(label.label_id) ?? `${input.lensId}-label-${index + 1}`,
|
|
615
|
+
label: stringValue(label.label, `candidate_labels[${index}].label`),
|
|
616
|
+
evidence_refs: evidenceRefsFromIds({
|
|
617
|
+
observationIds: stringArray(label.evidence_observation_ids, `candidate_labels[${index}].evidence_observation_ids`),
|
|
618
|
+
sourceObservations: input.sourceObservations,
|
|
619
|
+
fieldName: `candidate_labels[${index}].evidence_observation_ids`,
|
|
620
|
+
}),
|
|
621
|
+
rationale: stringValue(label.rationale, `candidate_labels[${index}].rationale`),
|
|
622
|
+
})),
|
|
623
|
+
semantic_gaps: records(raw.semantic_gaps ?? [], "semantic_gaps")
|
|
624
|
+
.map((gap, index) => ({
|
|
625
|
+
gap_id: optionalString(gap.gap_id) ?? `${input.lensId}-gap-${index + 1}`,
|
|
626
|
+
description: stringValue(gap.description, `semantic_gaps[${index}].description`),
|
|
627
|
+
evidence_refs: evidenceRefsFromIds({
|
|
628
|
+
observationIds: stringArray(gap.evidence_observation_ids, `semantic_gaps[${index}].evidence_observation_ids`),
|
|
629
|
+
sourceObservations: input.sourceObservations,
|
|
630
|
+
fieldName: `semantic_gaps[${index}].evidence_observation_ids`,
|
|
631
|
+
}),
|
|
632
|
+
requested_source_refs: stringArray(gap.requested_source_refs, `semantic_gaps[${index}].requested_source_refs`),
|
|
633
|
+
materiality_rationale: stringValue(gap.materiality_rationale, `semantic_gaps[${index}].materiality_rationale`),
|
|
634
|
+
})),
|
|
635
|
+
no_next_frontier_rationale: optionalString(raw.no_next_frontier_rationale),
|
|
636
|
+
directive_author: {
|
|
637
|
+
owner: "host_llm",
|
|
638
|
+
author_id: authorId,
|
|
639
|
+
},
|
|
640
|
+
};
|
|
641
|
+
},
|
|
642
|
+
async writeExplorationSynthesis(input) {
|
|
643
|
+
const raw = await callJsonAuthor({
|
|
644
|
+
llmCall,
|
|
645
|
+
llmConfig,
|
|
646
|
+
artifactName: "ExplorationSynthesis",
|
|
647
|
+
maxTokens: 3200,
|
|
648
|
+
systemPrompt: [
|
|
649
|
+
baseSystem,
|
|
650
|
+
"Integrate reconstruct lens judgments. Preserve disagreements and gaps. Request new source refs only when they are concrete and unjudged.",
|
|
651
|
+
"JSON shape: {\"accepted_gaps\":[{\"gap_id\":\"...\",\"lens_id\":\"...\",\"description\":\"...\",\"evidence_observation_ids\":[\"...\"]}],\"requested_source_refs\":[{\"source_ref\":\"...\",\"rationale\":\"...\",\"priority\":\"high|medium|low\"}],\"no_next_frontier_rationale\":\"... or null\"}",
|
|
652
|
+
].join("\n"),
|
|
653
|
+
userPayload: {
|
|
654
|
+
intent: input.intent,
|
|
655
|
+
round_id: input.roundId,
|
|
656
|
+
lens_judgment_index_ref: input.lensJudgmentIndexRef,
|
|
657
|
+
lens_judgments: lensJudgmentPromptPayload(input.lensJudgments),
|
|
658
|
+
},
|
|
659
|
+
});
|
|
660
|
+
const sourceObservations = {
|
|
661
|
+
schema_version: "1",
|
|
662
|
+
session_id: input.sessionId,
|
|
663
|
+
created_at: isoNow(),
|
|
664
|
+
observations: input.lensJudgments.flatMap((judgment) => [
|
|
665
|
+
...judgment.candidate_labels.flatMap((label) => label.evidence_refs),
|
|
666
|
+
...judgment.semantic_gaps.flatMap((gap) => gap.evidence_refs),
|
|
667
|
+
].map((ref) => ({
|
|
668
|
+
observation_id: ref.observation_id,
|
|
669
|
+
target_material_kind: ref.target_material_kind,
|
|
670
|
+
adapter_id: "evidence-ref-projection",
|
|
671
|
+
source_ref: ref.source_ref,
|
|
672
|
+
location: ref.location,
|
|
673
|
+
summary: "Projected from lens judgment evidence refs.",
|
|
674
|
+
structural_data: {},
|
|
675
|
+
}))),
|
|
676
|
+
skipped_refs: [],
|
|
677
|
+
validation_results: [],
|
|
678
|
+
};
|
|
679
|
+
return {
|
|
680
|
+
schema_version: "1",
|
|
681
|
+
session_id: input.sessionId,
|
|
682
|
+
round_id: input.roundId,
|
|
683
|
+
created_at: isoNow(),
|
|
684
|
+
lens_judgment_index_ref: input.lensJudgmentIndexRef,
|
|
685
|
+
accepted_gaps: records(raw.accepted_gaps ?? [], "accepted_gaps")
|
|
686
|
+
.map((gap, index) => ({
|
|
687
|
+
gap_id: stringValue(gap.gap_id, `accepted_gaps[${index}].gap_id`),
|
|
688
|
+
lens_id: stringValue(gap.lens_id, `accepted_gaps[${index}].lens_id`),
|
|
689
|
+
description: stringValue(gap.description, `accepted_gaps[${index}].description`),
|
|
690
|
+
evidence_refs: evidenceRefsFromIds({
|
|
691
|
+
observationIds: stringArray(gap.evidence_observation_ids, `accepted_gaps[${index}].evidence_observation_ids`),
|
|
692
|
+
sourceObservations,
|
|
693
|
+
fieldName: `accepted_gaps[${index}].evidence_observation_ids`,
|
|
694
|
+
}),
|
|
695
|
+
})),
|
|
696
|
+
requested_source_refs: records(raw.requested_source_refs ?? [], "requested_source_refs").map((request, index) => {
|
|
697
|
+
const priorityValue = stringValue(request.priority, `requested_source_refs[${index}].priority`);
|
|
698
|
+
if (priorityValue !== "high" && priorityValue !== "medium" && priorityValue !== "low") {
|
|
699
|
+
throw new Error(`requested_source_refs[${index}].priority is invalid.`);
|
|
700
|
+
}
|
|
701
|
+
const priority = priorityValue;
|
|
702
|
+
return {
|
|
703
|
+
source_ref: stringValue(request.source_ref, `requested_source_refs[${index}].source_ref`),
|
|
704
|
+
rationale: stringValue(request.rationale, `requested_source_refs[${index}].rationale`),
|
|
705
|
+
priority,
|
|
706
|
+
};
|
|
707
|
+
}),
|
|
708
|
+
no_next_frontier_rationale: optionalString(raw.no_next_frontier_rationale),
|
|
709
|
+
directive_author: {
|
|
710
|
+
owner: "host_llm",
|
|
711
|
+
author_id: authorId,
|
|
712
|
+
},
|
|
713
|
+
};
|
|
714
|
+
},
|
|
715
|
+
async writeSourceFrontier(input) {
|
|
716
|
+
const raw = await callJsonAuthor({
|
|
717
|
+
llmCall,
|
|
718
|
+
llmConfig,
|
|
719
|
+
artifactName: "SourceFrontier",
|
|
720
|
+
maxTokens: 2000,
|
|
721
|
+
systemPrompt: [
|
|
722
|
+
baseSystem,
|
|
723
|
+
"Convert exploration synthesis into a concrete source frontier. If no new source should be read, return an empty frontier_refs array and a no_next_frontier_rationale.",
|
|
724
|
+
"JSON shape: {\"frontier_refs\":[{\"source_ref\":\"...\",\"rationale\":\"...\",\"priority\":\"high|medium|low\"}],\"no_next_frontier_rationale\":\"... or null\"}",
|
|
725
|
+
].join("\n"),
|
|
726
|
+
userPayload: {
|
|
727
|
+
intent: input.intent,
|
|
728
|
+
round_id: input.roundId,
|
|
729
|
+
exploration_synthesis_ref: input.explorationSynthesisRef,
|
|
730
|
+
exploration_synthesis: input.explorationSynthesis,
|
|
731
|
+
},
|
|
732
|
+
});
|
|
733
|
+
const frontierRefs = records(raw.frontier_refs ?? [], "frontier_refs")
|
|
734
|
+
.map((frontier, index) => {
|
|
735
|
+
const priorityValue = stringValue(frontier.priority, `frontier_refs[${index}].priority`);
|
|
736
|
+
if (priorityValue !== "high" && priorityValue !== "medium" && priorityValue !== "low") {
|
|
737
|
+
throw new Error(`frontier_refs[${index}].priority is invalid.`);
|
|
738
|
+
}
|
|
739
|
+
const priority = priorityValue;
|
|
740
|
+
const sourceRef = stringValue(frontier.source_ref, `frontier_refs[${index}].source_ref`);
|
|
741
|
+
return {
|
|
742
|
+
frontier_ref_id: `frontier_${index + 1}`,
|
|
743
|
+
source_ref: sourceRef,
|
|
744
|
+
rationale: stringValue(frontier.rationale, `frontier_refs[${index}].rationale`),
|
|
745
|
+
priority,
|
|
746
|
+
};
|
|
747
|
+
});
|
|
748
|
+
return {
|
|
749
|
+
schema_version: "1",
|
|
750
|
+
session_id: input.sessionId,
|
|
751
|
+
round_id: input.roundId,
|
|
752
|
+
created_at: isoNow(),
|
|
753
|
+
exploration_synthesis_ref: input.explorationSynthesisRef,
|
|
754
|
+
frontier_refs: frontierRefs,
|
|
755
|
+
no_next_frontier_rationale: optionalString(raw.no_next_frontier_rationale),
|
|
756
|
+
directive_author: {
|
|
757
|
+
owner: "host_llm",
|
|
758
|
+
author_id: authorId,
|
|
759
|
+
},
|
|
760
|
+
};
|
|
761
|
+
},
|
|
762
|
+
async writeSeedCandidate(input) {
|
|
763
|
+
const raw = await callJsonAuthor({
|
|
764
|
+
llmCall,
|
|
765
|
+
llmConfig,
|
|
766
|
+
artifactName: "SeedCandidate",
|
|
767
|
+
maxTokens: 4200,
|
|
768
|
+
systemPrompt: [
|
|
769
|
+
baseSystem,
|
|
770
|
+
"Author an ontology Seed candidate for the declared purpose. Claims must be evidence-backed by observation ids. Cover purpose, non-goals, entities, relations, actions, properties, rules, and open questions.",
|
|
771
|
+
"Each claim must include claim_id for artifact linkage and name for user-facing meaning. name must be a concise meaningful label such as RawIngestEvent, Usage Mart, or Dashboard Overview, not Entity 1 or a numbered placeholder.",
|
|
772
|
+
"Each claim shape: {\"claim_id\":\"...\",\"name\":\"...\",\"statement\":\"...\",\"evidence_observation_ids\":[\"...\"]}",
|
|
773
|
+
"JSON shape: {\"purpose\":claim,\"non_goals\":[claim],\"entities\":[claim],\"relations\":[claim],\"actions\":[claim],\"properties\":[claim],\"rules\":[claim],\"open_questions\":[\"...\"]}",
|
|
774
|
+
].join("\n"),
|
|
775
|
+
userPayload: {
|
|
776
|
+
intent: input.intent,
|
|
777
|
+
selected_observations: input.sourceObservationDirective.selected_observations,
|
|
778
|
+
source_observations: observationPromptPayload(input.sourceObservations),
|
|
779
|
+
lens_judgment_index: input.lensJudgmentIndex,
|
|
780
|
+
exploration_synthesis: input.explorationSynthesis,
|
|
781
|
+
source_frontier_validation: input.sourceFrontierValidation,
|
|
782
|
+
},
|
|
783
|
+
});
|
|
784
|
+
const purposeRaw = raw.purpose && typeof raw.purpose === "object" && !Array.isArray(raw.purpose)
|
|
785
|
+
? raw.purpose
|
|
786
|
+
: null;
|
|
787
|
+
if (!purposeRaw)
|
|
788
|
+
throw new Error("SeedCandidate.purpose must be an object.");
|
|
789
|
+
return {
|
|
790
|
+
schema_version: "1",
|
|
791
|
+
session_id: input.sessionId,
|
|
792
|
+
created_at: isoNow(),
|
|
793
|
+
purpose: claimFromLlm({
|
|
794
|
+
raw: purposeRaw,
|
|
795
|
+
fallbackId: "purpose-1",
|
|
796
|
+
sourceObservations: input.sourceObservations,
|
|
797
|
+
fieldName: "purpose",
|
|
798
|
+
}),
|
|
799
|
+
non_goals: claimsFromLlm({
|
|
800
|
+
value: raw.non_goals,
|
|
801
|
+
prefix: "non-goal",
|
|
802
|
+
sourceObservations: input.sourceObservations,
|
|
803
|
+
}),
|
|
804
|
+
entities: claimsFromLlm({
|
|
805
|
+
value: raw.entities,
|
|
806
|
+
prefix: "entity",
|
|
807
|
+
sourceObservations: input.sourceObservations,
|
|
808
|
+
}),
|
|
809
|
+
relations: claimsFromLlm({
|
|
810
|
+
value: raw.relations,
|
|
811
|
+
prefix: "relation",
|
|
812
|
+
sourceObservations: input.sourceObservations,
|
|
813
|
+
}),
|
|
814
|
+
actions: claimsFromLlm({
|
|
815
|
+
value: raw.actions,
|
|
816
|
+
prefix: "action",
|
|
817
|
+
sourceObservations: input.sourceObservations,
|
|
818
|
+
}),
|
|
819
|
+
properties: claimsFromLlm({
|
|
820
|
+
value: raw.properties,
|
|
821
|
+
prefix: "property",
|
|
822
|
+
sourceObservations: input.sourceObservations,
|
|
823
|
+
}),
|
|
824
|
+
rules: claimsFromLlm({
|
|
825
|
+
value: raw.rules,
|
|
826
|
+
prefix: "rule",
|
|
827
|
+
sourceObservations: input.sourceObservations,
|
|
828
|
+
}),
|
|
829
|
+
open_questions: stringArray(raw.open_questions, "open_questions"),
|
|
830
|
+
};
|
|
831
|
+
},
|
|
832
|
+
async writeClaimRealizationMap(input) {
|
|
833
|
+
const raw = await callJsonAuthor({
|
|
834
|
+
llmCall,
|
|
835
|
+
llmConfig,
|
|
836
|
+
artifactName: "ClaimRealizationMap",
|
|
837
|
+
maxTokens: 3000,
|
|
838
|
+
systemPrompt: [
|
|
839
|
+
baseSystem,
|
|
840
|
+
`Classify every Seed claim with one stance from: ${CLAIM_REALIZATION_STANCES.join(", ")}.`,
|
|
841
|
+
"JSON shape: {\"claim_realizations\":[{\"claim_id\":\"...\",\"stance\":\"...\",\"rationale\":\"...\"}]}",
|
|
842
|
+
].join("\n"),
|
|
843
|
+
userPayload: {
|
|
844
|
+
seed_candidate_ref: input.seedCandidateRef,
|
|
845
|
+
seed_candidate: input.seedCandidate,
|
|
846
|
+
source_observations: observationPromptPayload(input.sourceObservations),
|
|
847
|
+
},
|
|
848
|
+
});
|
|
849
|
+
const claimById = new Map(allClaims(input.seedCandidate).map((claim) => [
|
|
850
|
+
claim.claim_id,
|
|
851
|
+
claim,
|
|
852
|
+
]));
|
|
853
|
+
const realizations = records(raw.claim_realizations, "claim_realizations").map((realization, index) => {
|
|
854
|
+
const claimId = stringValue(realization.claim_id, `claim_realizations[${index}].claim_id`);
|
|
855
|
+
const claim = claimById.get(claimId);
|
|
856
|
+
if (!claim)
|
|
857
|
+
throw new Error(`ClaimRealizationMap references unknown claim id: ${claimId}`);
|
|
858
|
+
const stance = stringValue(realization.stance, `claim_realizations[${index}].stance`);
|
|
859
|
+
if (!CLAIM_REALIZATION_STANCES.includes(stance)) {
|
|
860
|
+
throw new Error(`ClaimRealizationMap stance is invalid for ${claimId}: ${stance}`);
|
|
861
|
+
}
|
|
862
|
+
return {
|
|
863
|
+
claim_id: claimId,
|
|
864
|
+
stance,
|
|
865
|
+
evidence_refs: claim.evidence_refs,
|
|
866
|
+
rationale: stringValue(realization.rationale, `claim_realizations[${index}].rationale`),
|
|
867
|
+
};
|
|
868
|
+
});
|
|
869
|
+
return {
|
|
870
|
+
schema_version: "1",
|
|
871
|
+
session_id: input.sessionId,
|
|
872
|
+
created_at: isoNow(),
|
|
873
|
+
seed_candidate_ref: input.seedCandidateRef,
|
|
874
|
+
claim_realizations: realizations,
|
|
875
|
+
directive_author: {
|
|
876
|
+
owner: "host_llm",
|
|
877
|
+
author_id: authorId,
|
|
878
|
+
},
|
|
879
|
+
};
|
|
880
|
+
},
|
|
881
|
+
async writeCompetencyQuestions(input) {
|
|
882
|
+
const raw = await callJsonAuthor({
|
|
883
|
+
llmCall,
|
|
884
|
+
llmConfig,
|
|
885
|
+
artifactName: "CompetencyQuestions",
|
|
886
|
+
maxTokens: 3200,
|
|
887
|
+
systemPrompt: [
|
|
888
|
+
baseSystem,
|
|
889
|
+
"Write competency questions that test accepted or CQ-eligible Seed claims for the declared purpose.",
|
|
890
|
+
"Every cq_eligible_claim_id must appear in at least one linked_claim_ids array. Group related claims when useful, but do not leave an eligible claim untested.",
|
|
891
|
+
"JSON shape: {\"questions\":[{\"question_id\":\"...\",\"question\":\"...\",\"linked_claim_ids\":[\"...\"],\"evidence_observation_ids\":[\"...\"]}],\"open_questions\":[\"...\"]}",
|
|
892
|
+
].join("\n"),
|
|
893
|
+
userPayload: {
|
|
894
|
+
seed_candidate: input.seedCandidate,
|
|
895
|
+
seed_confirmation: input.seedConfirmation,
|
|
896
|
+
seed_confirmation_validation: input.seedConfirmationValidation,
|
|
897
|
+
claim_realization_map: input.claimRealizationMap,
|
|
898
|
+
},
|
|
899
|
+
});
|
|
900
|
+
const eligibleClaimIds = new Set(input.seedConfirmationValidation.cq_eligible_claim_ids);
|
|
901
|
+
return {
|
|
902
|
+
schema_version: "1",
|
|
903
|
+
session_id: input.sessionId,
|
|
904
|
+
created_at: isoNow(),
|
|
905
|
+
seed_confirmation_ref: input.seedConfirmationRef,
|
|
906
|
+
questions: records(raw.questions, "questions").map((question, index) => {
|
|
907
|
+
const linkedClaimIds = stringArray(question.linked_claim_ids, `questions[${index}].linked_claim_ids`);
|
|
908
|
+
for (const claimId of linkedClaimIds) {
|
|
909
|
+
if (!eligibleClaimIds.has(claimId)) {
|
|
910
|
+
throw new Error(`CompetencyQuestions linked non-eligible claim id: ${claimId}`);
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
return {
|
|
914
|
+
question_id: optionalString(question.question_id) ?? `cq-${index + 1}`,
|
|
915
|
+
question: stringValue(question.question, `questions[${index}].question`),
|
|
916
|
+
linked_claim_ids: linkedClaimIds,
|
|
917
|
+
evidence_refs: evidenceRefsFromIds({
|
|
918
|
+
observationIds: stringArray(question.evidence_observation_ids, `questions[${index}].evidence_observation_ids`),
|
|
919
|
+
sourceObservations: {
|
|
920
|
+
schema_version: "1",
|
|
921
|
+
session_id: input.sessionId,
|
|
922
|
+
created_at: isoNow(),
|
|
923
|
+
observations: allClaims(input.seedCandidate).flatMap((claim) => claim.evidence_refs.map((ref) => ({
|
|
924
|
+
observation_id: ref.observation_id,
|
|
925
|
+
target_material_kind: ref.target_material_kind,
|
|
926
|
+
adapter_id: "seed-evidence-ref-projection",
|
|
927
|
+
source_ref: ref.source_ref,
|
|
928
|
+
location: ref.location,
|
|
929
|
+
summary: "Projected from Seed evidence refs.",
|
|
930
|
+
structural_data: {},
|
|
931
|
+
}))),
|
|
932
|
+
skipped_refs: [],
|
|
933
|
+
validation_results: [],
|
|
934
|
+
},
|
|
935
|
+
fieldName: `questions[${index}].evidence_observation_ids`,
|
|
936
|
+
}),
|
|
937
|
+
};
|
|
938
|
+
}),
|
|
939
|
+
open_questions: stringArray(raw.open_questions, "open_questions"),
|
|
940
|
+
directive_author: {
|
|
941
|
+
owner: "host_llm",
|
|
942
|
+
author_id: authorId,
|
|
943
|
+
},
|
|
944
|
+
};
|
|
945
|
+
},
|
|
946
|
+
async writeCompetencyQuestionAssessment(input) {
|
|
947
|
+
const raw = await callJsonAuthor({
|
|
948
|
+
llmCall,
|
|
949
|
+
llmConfig,
|
|
950
|
+
artifactName: "CompetencyQuestionAssessment",
|
|
951
|
+
maxTokens: 3200,
|
|
952
|
+
systemPrompt: [
|
|
953
|
+
baseSystem,
|
|
954
|
+
`Assess every competency question exactly once. answer_status must be one of: ${ANSWER_STATUSES.join(", ")}.`,
|
|
955
|
+
"JSON shape: {\"assessments\":[{\"question_id\":\"...\",\"answer_status\":\"...\",\"rationale\":\"...\"}]}",
|
|
956
|
+
].join("\n"),
|
|
957
|
+
userPayload: {
|
|
958
|
+
competency_questions_ref: input.competencyQuestionsRef,
|
|
959
|
+
competency_questions: input.competencyQuestions,
|
|
960
|
+
competency_questions_validation: input.competencyQuestionsValidation,
|
|
961
|
+
claim_realization_map: input.claimRealizationMap,
|
|
962
|
+
},
|
|
963
|
+
});
|
|
964
|
+
const questionById = new Map(input.competencyQuestions.questions.map((question) => [
|
|
965
|
+
question.question_id,
|
|
966
|
+
question,
|
|
967
|
+
]));
|
|
968
|
+
return {
|
|
969
|
+
schema_version: "1",
|
|
970
|
+
session_id: input.sessionId,
|
|
971
|
+
created_at: isoNow(),
|
|
972
|
+
competency_questions_ref: input.competencyQuestionsRef,
|
|
973
|
+
competency_questions_validation_ref: input.competencyQuestionsValidationRef,
|
|
974
|
+
assessments: records(raw.assessments, "assessments").map((assessment, index) => {
|
|
975
|
+
const questionId = stringValue(assessment.question_id, `assessments[${index}].question_id`);
|
|
976
|
+
const question = questionById.get(questionId);
|
|
977
|
+
if (!question) {
|
|
978
|
+
throw new Error(`CompetencyQuestionAssessment references unknown question id: ${questionId}`);
|
|
979
|
+
}
|
|
980
|
+
const answerStatus = stringValue(assessment.answer_status, `assessments[${index}].answer_status`);
|
|
981
|
+
if (!ANSWER_STATUSES.includes(answerStatus)) {
|
|
982
|
+
throw new Error(`CompetencyQuestionAssessment answer_status is invalid: ${answerStatus}`);
|
|
983
|
+
}
|
|
984
|
+
return {
|
|
985
|
+
question_id: questionId,
|
|
986
|
+
answer_status: answerStatus,
|
|
987
|
+
linked_claim_ids: question.linked_claim_ids,
|
|
988
|
+
evidence_refs: question.evidence_refs,
|
|
989
|
+
rationale: stringValue(assessment.rationale, `assessments[${index}].rationale`),
|
|
990
|
+
};
|
|
991
|
+
}),
|
|
992
|
+
directive_author: {
|
|
993
|
+
owner: "host_llm",
|
|
994
|
+
author_id: authorId,
|
|
995
|
+
},
|
|
996
|
+
};
|
|
997
|
+
},
|
|
998
|
+
async writeFailureClassification(input) {
|
|
999
|
+
const raw = await callJsonAuthor({
|
|
1000
|
+
llmCall,
|
|
1001
|
+
llmConfig,
|
|
1002
|
+
artifactName: "FailureClassification",
|
|
1003
|
+
maxTokens: 2600,
|
|
1004
|
+
systemPrompt: [
|
|
1005
|
+
baseSystem,
|
|
1006
|
+
`Classify unsafe or incomplete assessments. failure_kind must be one of: ${FAILURE_KINDS.join(", ")}. recommended_action must be revise_seed, collect_evidence, defer, reject_claim, or ask_user.`,
|
|
1007
|
+
"JSON shape: {\"failures\":[{\"failure_id\":\"...\",\"failure_kind\":\"...\",\"materiality\":\"material|non_material\",\"question_id\":\"... or null\",\"claim_id\":\"... or null\",\"rationale\":\"...\",\"recommended_action\":\"...\"}]}",
|
|
1008
|
+
].join("\n"),
|
|
1009
|
+
userPayload: {
|
|
1010
|
+
competency_question_assessment_ref: input.competencyQuestionAssessmentRef,
|
|
1011
|
+
competency_question_assessment: input.competencyQuestionAssessment,
|
|
1012
|
+
competency_question_assessment_validation: input.competencyQuestionAssessmentValidation,
|
|
1013
|
+
seed_confirmation_validation: input.seedConfirmationValidation,
|
|
1014
|
+
},
|
|
1015
|
+
});
|
|
1016
|
+
return {
|
|
1017
|
+
schema_version: "1",
|
|
1018
|
+
session_id: input.sessionId,
|
|
1019
|
+
created_at: isoNow(),
|
|
1020
|
+
competency_question_assessment_ref: input.competencyQuestionAssessmentRef,
|
|
1021
|
+
seed_confirmation_validation_ref: input.seedConfirmationValidation.seed_confirmation_ref,
|
|
1022
|
+
failures: records(raw.failures ?? [], "failures").map((failure, index) => {
|
|
1023
|
+
const failureKind = stringValue(failure.failure_kind, `failures[${index}].failure_kind`);
|
|
1024
|
+
if (!FAILURE_KINDS.includes(failureKind)) {
|
|
1025
|
+
throw new Error(`FailureClassification failure_kind is invalid: ${failureKind}`);
|
|
1026
|
+
}
|
|
1027
|
+
const materiality = stringValue(failure.materiality, `failures[${index}].materiality`);
|
|
1028
|
+
if (materiality !== "material" && materiality !== "non_material") {
|
|
1029
|
+
throw new Error(`FailureClassification materiality is invalid: ${materiality}`);
|
|
1030
|
+
}
|
|
1031
|
+
const recommendedAction = stringValue(failure.recommended_action, `failures[${index}].recommended_action`);
|
|
1032
|
+
if (!["revise_seed", "collect_evidence", "defer", "reject_claim", "ask_user"].includes(recommendedAction)) {
|
|
1033
|
+
throw new Error(`FailureClassification recommended_action is invalid: ${recommendedAction}`);
|
|
1034
|
+
}
|
|
1035
|
+
return {
|
|
1036
|
+
failure_id: optionalString(failure.failure_id) ?? `failure-${index + 1}`,
|
|
1037
|
+
failure_kind: failureKind,
|
|
1038
|
+
materiality,
|
|
1039
|
+
question_id: optionalString(failure.question_id),
|
|
1040
|
+
claim_id: optionalString(failure.claim_id),
|
|
1041
|
+
rationale: stringValue(failure.rationale, `failures[${index}].rationale`),
|
|
1042
|
+
recommended_action: recommendedAction,
|
|
1043
|
+
};
|
|
1044
|
+
}),
|
|
1045
|
+
directive_author: {
|
|
1046
|
+
owner: "host_llm",
|
|
1047
|
+
author_id: authorId,
|
|
1048
|
+
},
|
|
1049
|
+
};
|
|
1050
|
+
},
|
|
1051
|
+
async writeRevisionProposal(input) {
|
|
1052
|
+
const raw = await callJsonAuthor({
|
|
1053
|
+
llmCall,
|
|
1054
|
+
llmConfig,
|
|
1055
|
+
artifactName: "RevisionProposal",
|
|
1056
|
+
maxTokens: 2600,
|
|
1057
|
+
systemPrompt: [
|
|
1058
|
+
baseSystem,
|
|
1059
|
+
`Propose bounded ontology actions for failures. action must be one of: ${REVISION_ACTIONS.join(", ")}.`,
|
|
1060
|
+
"JSON shape: {\"proposals\":[{\"proposal_id\":\"...\",\"target_type\":\"claim|question|failure|seed|domain_context\",\"target_id\":\"...\",\"action\":\"...\",\"rationale\":\"...\",\"expected_effect\":\"...\"}]}",
|
|
1061
|
+
].join("\n"),
|
|
1062
|
+
userPayload: {
|
|
1063
|
+
failure_classification_ref: input.failureClassificationRef,
|
|
1064
|
+
failure_classification: input.failureClassification,
|
|
1065
|
+
failure_classification_validation: input.failureClassificationValidation,
|
|
1066
|
+
},
|
|
1067
|
+
});
|
|
1068
|
+
return {
|
|
1069
|
+
schema_version: "1",
|
|
1070
|
+
session_id: input.sessionId,
|
|
1071
|
+
created_at: isoNow(),
|
|
1072
|
+
failure_classification_ref: input.failureClassificationRef,
|
|
1073
|
+
proposals: records(raw.proposals ?? [], "proposals").map((proposal, index) => {
|
|
1074
|
+
const action = stringValue(proposal.action, `proposals[${index}].action`);
|
|
1075
|
+
if (!REVISION_ACTIONS.includes(action)) {
|
|
1076
|
+
throw new Error(`RevisionProposal action is invalid: ${action}`);
|
|
1077
|
+
}
|
|
1078
|
+
const targetType = stringValue(proposal.target_type, `proposals[${index}].target_type`);
|
|
1079
|
+
if (!["claim", "question", "failure", "seed", "domain_context"].includes(targetType)) {
|
|
1080
|
+
throw new Error(`RevisionProposal target_type is invalid: ${targetType}`);
|
|
1081
|
+
}
|
|
1082
|
+
return {
|
|
1083
|
+
proposal_id: optionalString(proposal.proposal_id) ?? `proposal-${index + 1}`,
|
|
1084
|
+
target_type: targetType,
|
|
1085
|
+
target_id: stringValue(proposal.target_id, `proposals[${index}].target_id`),
|
|
1086
|
+
action,
|
|
1087
|
+
rationale: stringValue(proposal.rationale, `proposals[${index}].rationale`),
|
|
1088
|
+
expected_effect: stringValue(proposal.expected_effect, `proposals[${index}].expected_effect`),
|
|
1089
|
+
};
|
|
1090
|
+
}),
|
|
1091
|
+
directive_author: {
|
|
1092
|
+
owner: "host_llm",
|
|
1093
|
+
author_id: authorId,
|
|
1094
|
+
},
|
|
1095
|
+
};
|
|
1096
|
+
},
|
|
1097
|
+
async writeStopDecision(input) {
|
|
1098
|
+
const raw = await callJsonAuthor({
|
|
1099
|
+
llmCall,
|
|
1100
|
+
llmConfig,
|
|
1101
|
+
artifactName: "StopDecision",
|
|
1102
|
+
maxTokens: 1600,
|
|
1103
|
+
systemPrompt: [
|
|
1104
|
+
baseSystem,
|
|
1105
|
+
"Decide whether the current reconstructed result is decision-ready for the declared purpose. This is a presentation decision, not user control.",
|
|
1106
|
+
"JSON shape: {\"decision\":\"stop|continue|ask_user\",\"rationale\":\"...\",\"next_actions\":[\"...\"]}",
|
|
1107
|
+
].join("\n"),
|
|
1108
|
+
userPayload: {
|
|
1109
|
+
intent: input.intent,
|
|
1110
|
+
metrics: input.metrics,
|
|
1111
|
+
failure_classification: input.failureClassification,
|
|
1112
|
+
revision_proposal: input.revisionProposal,
|
|
1113
|
+
},
|
|
1114
|
+
});
|
|
1115
|
+
const decision = stringValue(raw.decision, "decision");
|
|
1116
|
+
if (decision !== "stop" && decision !== "continue" && decision !== "ask_user") {
|
|
1117
|
+
throw new Error(`StopDecision decision is invalid: ${decision}`);
|
|
1118
|
+
}
|
|
1119
|
+
return {
|
|
1120
|
+
schema_version: "1",
|
|
1121
|
+
session_id: input.sessionId,
|
|
1122
|
+
created_at: isoNow(),
|
|
1123
|
+
decision,
|
|
1124
|
+
declared_purpose: input.intent,
|
|
1125
|
+
metrics_ref: input.metricsRef,
|
|
1126
|
+
rationale: stringValue(raw.rationale, "rationale"),
|
|
1127
|
+
next_actions: stringArray(raw.next_actions, "next_actions"),
|
|
1128
|
+
directive_author: {
|
|
1129
|
+
owner: "host_llm",
|
|
1130
|
+
author_id: authorId,
|
|
1131
|
+
},
|
|
1132
|
+
};
|
|
1133
|
+
},
|
|
1134
|
+
async writeFinalOutput(input) {
|
|
1135
|
+
const result = await llmCall([
|
|
1136
|
+
"You are writing the final reconstruct result for the user.",
|
|
1137
|
+
"Write concise Markdown. Ground every important statement in artifact refs or ids.",
|
|
1138
|
+
"Use claim.name as the user-facing label. Include claim_id only where artifact truth or traceability needs it.",
|
|
1139
|
+
"Include execution profile, completion scope, skipped/deferred stages, confirmed Seed content, CQ assessment, material failures, revision proposals, and artifact truth.",
|
|
1140
|
+
"Do not claim full domain-context alignment when domain context selection was skipped.",
|
|
1141
|
+
].join("\n"), JSON.stringify({
|
|
1142
|
+
session_id: input.sessionId,
|
|
1143
|
+
intent: input.intent,
|
|
1144
|
+
target_material_profile: input.targetMaterialProfile,
|
|
1145
|
+
seed_candidate: input.seedCandidate,
|
|
1146
|
+
claim_realization_map: input.claimRealizationMap,
|
|
1147
|
+
seed_confirmation: input.seedConfirmation,
|
|
1148
|
+
seed_confirmation_validation: input.seedConfirmationValidation,
|
|
1149
|
+
competency_questions: input.competencyQuestions,
|
|
1150
|
+
competency_question_assessment: input.competencyQuestionAssessment,
|
|
1151
|
+
failure_classification: input.failureClassification,
|
|
1152
|
+
revision_proposal: input.revisionProposal,
|
|
1153
|
+
metrics: input.metrics,
|
|
1154
|
+
stop_decision: input.stopDecision,
|
|
1155
|
+
artifact_refs: input.artifactRefs,
|
|
1156
|
+
reconstruct_record_path: input.reconstructRecordPath,
|
|
1157
|
+
reconstruct_run_manifest_path: input.reconstructRunManifestPath,
|
|
1158
|
+
execution_profile: input.reconstructRunManifest.execution_profile,
|
|
1159
|
+
skipped_steps: input.reconstructRunManifest.steps.filter((step) => step.status === "skipped"),
|
|
1160
|
+
}, null, 2), { ...llmConfig, max_tokens: 4200 });
|
|
1161
|
+
return result.text;
|
|
1162
|
+
},
|
|
1163
|
+
};
|
|
1164
|
+
}
|
|
214
1165
|
export function createMockReconstructDirectiveAuthor() {
|
|
215
1166
|
const authorId = "mock-reconstruct-directive-author";
|
|
216
1167
|
return {
|
|
@@ -236,6 +1187,63 @@ export function createMockReconstructDirectiveAuthor() {
|
|
|
236
1187
|
],
|
|
237
1188
|
};
|
|
238
1189
|
},
|
|
1190
|
+
async writeLensJudgment(input) {
|
|
1191
|
+
const observation = requireFirstObservation(input.sourceObservations);
|
|
1192
|
+
return {
|
|
1193
|
+
schema_version: "1",
|
|
1194
|
+
session_id: input.sessionId,
|
|
1195
|
+
round_id: input.roundId,
|
|
1196
|
+
lens_id: input.lensId,
|
|
1197
|
+
created_at: isoNow(),
|
|
1198
|
+
source_observation_directive_ref: input.sourceObservationDirectiveRef,
|
|
1199
|
+
candidate_labels: [
|
|
1200
|
+
{
|
|
1201
|
+
label_id: `${input.lensId}-label-1`,
|
|
1202
|
+
label: `${input.lensId} candidate label for observed material`,
|
|
1203
|
+
evidence_refs: [evidenceRefFromObservation(observation)],
|
|
1204
|
+
rationale: "Mock lens judgment preserves the stage shape for tests.",
|
|
1205
|
+
},
|
|
1206
|
+
],
|
|
1207
|
+
semantic_gaps: [],
|
|
1208
|
+
no_next_frontier_rationale: "Mock lens does not request additional source frontier refs.",
|
|
1209
|
+
directive_author: {
|
|
1210
|
+
owner: "mock",
|
|
1211
|
+
author_id: authorId,
|
|
1212
|
+
},
|
|
1213
|
+
};
|
|
1214
|
+
},
|
|
1215
|
+
async writeExplorationSynthesis(input) {
|
|
1216
|
+
return {
|
|
1217
|
+
schema_version: "1",
|
|
1218
|
+
session_id: input.sessionId,
|
|
1219
|
+
round_id: input.roundId,
|
|
1220
|
+
created_at: isoNow(),
|
|
1221
|
+
lens_judgment_index_ref: input.lensJudgmentIndexRef,
|
|
1222
|
+
accepted_gaps: [],
|
|
1223
|
+
requested_source_refs: [],
|
|
1224
|
+
no_next_frontier_rationale: "Mock synthesis accepts no next frontier for the bounded test slice.",
|
|
1225
|
+
directive_author: {
|
|
1226
|
+
owner: "mock",
|
|
1227
|
+
author_id: authorId,
|
|
1228
|
+
},
|
|
1229
|
+
};
|
|
1230
|
+
},
|
|
1231
|
+
async writeSourceFrontier(input) {
|
|
1232
|
+
return {
|
|
1233
|
+
schema_version: "1",
|
|
1234
|
+
session_id: input.sessionId,
|
|
1235
|
+
round_id: input.roundId,
|
|
1236
|
+
created_at: isoNow(),
|
|
1237
|
+
exploration_synthesis_ref: input.explorationSynthesisRef,
|
|
1238
|
+
frontier_refs: [],
|
|
1239
|
+
no_next_frontier_rationale: input.explorationSynthesis.no_next_frontier_rationale ??
|
|
1240
|
+
"Mock frontier declares no next source refs.",
|
|
1241
|
+
directive_author: {
|
|
1242
|
+
owner: "mock",
|
|
1243
|
+
author_id: authorId,
|
|
1244
|
+
},
|
|
1245
|
+
};
|
|
1246
|
+
},
|
|
239
1247
|
async writeSeedCandidate(input) {
|
|
240
1248
|
const selections = input.sourceObservationDirective.selected_observations;
|
|
241
1249
|
if (selections.length === 0) {
|
|
@@ -248,21 +1256,65 @@ export function createMockReconstructDirectiveAuthor() {
|
|
|
248
1256
|
location: selection.location,
|
|
249
1257
|
}));
|
|
250
1258
|
const materialKinds = new Set(selections.map((selection) => selection.target_material_kind));
|
|
1259
|
+
const firstEvidence = evidenceRefs[0];
|
|
251
1260
|
return {
|
|
252
1261
|
schema_version: "1",
|
|
253
1262
|
session_id: input.sessionId,
|
|
254
1263
|
created_at: isoNow(),
|
|
255
1264
|
purpose: {
|
|
256
1265
|
claim_id: "purpose-1",
|
|
1266
|
+
name: "Bounded Ontology Seed Purpose",
|
|
257
1267
|
statement: `Reconstruct a bounded ontology Seed for the declared purpose: ${input.intent}`,
|
|
258
1268
|
evidence_refs: evidenceRefs,
|
|
259
1269
|
},
|
|
260
|
-
non_goals: [
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
1270
|
+
non_goals: [
|
|
1271
|
+
{
|
|
1272
|
+
claim_id: "non-goal-1",
|
|
1273
|
+
name: "Runtime Authorship Boundary",
|
|
1274
|
+
statement: "The runtime does not author ontology meaning; semantic expansion remains host-owned.",
|
|
1275
|
+
evidence_refs: [firstEvidence],
|
|
1276
|
+
},
|
|
1277
|
+
],
|
|
1278
|
+
entities: [
|
|
1279
|
+
{
|
|
1280
|
+
claim_id: "entity-1",
|
|
1281
|
+
name: "Observed Source Evidence Set",
|
|
1282
|
+
statement: `The target material exposes ${selections.length} observed source unit(s) as ontology Seed evidence.`,
|
|
1283
|
+
evidence_refs: evidenceRefs,
|
|
1284
|
+
},
|
|
1285
|
+
],
|
|
1286
|
+
relations: [
|
|
1287
|
+
{
|
|
1288
|
+
claim_id: "relation-1",
|
|
1289
|
+
name: "Observation Evidence Boundary",
|
|
1290
|
+
statement: "Selected source observations provide the evidence boundary for every Seed claim.",
|
|
1291
|
+
evidence_refs: evidenceRefs,
|
|
1292
|
+
},
|
|
1293
|
+
],
|
|
1294
|
+
actions: [
|
|
1295
|
+
{
|
|
1296
|
+
claim_id: "action-1",
|
|
1297
|
+
name: "Competency Question Assessment",
|
|
1298
|
+
statement: "The reconstruct process can ask competency questions against confirmed Seed claims.",
|
|
1299
|
+
evidence_refs: [firstEvidence],
|
|
1300
|
+
},
|
|
1301
|
+
],
|
|
1302
|
+
properties: [
|
|
1303
|
+
{
|
|
1304
|
+
claim_id: "property-1",
|
|
1305
|
+
name: "Target Material Kind",
|
|
1306
|
+
statement: `The target material kind is ${selections[0]?.target_material_kind ?? "unknown"} for at least one selected evidence unit.`,
|
|
1307
|
+
evidence_refs: [firstEvidence],
|
|
1308
|
+
},
|
|
1309
|
+
],
|
|
1310
|
+
rules: [
|
|
1311
|
+
{
|
|
1312
|
+
claim_id: "rule-1",
|
|
1313
|
+
name: "Artifact Truth Rule",
|
|
1314
|
+
statement: "Any final output must cite artifact truth rather than becoming a second ontology authority.",
|
|
1315
|
+
evidence_refs: [firstEvidence],
|
|
1316
|
+
},
|
|
1317
|
+
],
|
|
266
1318
|
open_questions: [
|
|
267
1319
|
...(input.sourceObservationDirectiveValidation.validation_status === "valid"
|
|
268
1320
|
? []
|
|
@@ -275,8 +1327,32 @@ export function createMockReconstructDirectiveAuthor() {
|
|
|
275
1327
|
],
|
|
276
1328
|
};
|
|
277
1329
|
},
|
|
1330
|
+
async writeClaimRealizationMap(input) {
|
|
1331
|
+
const claims = allClaims(input.seedCandidate);
|
|
1332
|
+
return {
|
|
1333
|
+
schema_version: "1",
|
|
1334
|
+
session_id: input.sessionId,
|
|
1335
|
+
created_at: isoNow(),
|
|
1336
|
+
seed_candidate_ref: input.seedCandidateRef,
|
|
1337
|
+
claim_realizations: claims.map((claim, index) => {
|
|
1338
|
+
const stance = CLAIM_REALIZATION_STANCES[index % CLAIM_REALIZATION_STANCES.length] ?? "unknown";
|
|
1339
|
+
return {
|
|
1340
|
+
claim_id: claim.claim_id,
|
|
1341
|
+
stance,
|
|
1342
|
+
evidence_refs: claim.evidence_refs,
|
|
1343
|
+
rationale: stance === "observed_runtime_behavior"
|
|
1344
|
+
? "Mock author treats this claim as directly supported by runtime observations."
|
|
1345
|
+
: `Mock author records ${stance} so downstream gates exercise non-happy-path evidence states.`,
|
|
1346
|
+
};
|
|
1347
|
+
}),
|
|
1348
|
+
directive_author: {
|
|
1349
|
+
owner: "mock",
|
|
1350
|
+
author_id: authorId,
|
|
1351
|
+
},
|
|
1352
|
+
};
|
|
1353
|
+
},
|
|
278
1354
|
async writeCompetencyQuestions(input) {
|
|
279
|
-
const confirmedClaims = new Set(input.
|
|
1355
|
+
const confirmedClaims = new Set(input.seedConfirmationValidation.cq_eligible_claim_ids);
|
|
280
1356
|
const questions = allClaims(input.seedCandidate)
|
|
281
1357
|
.filter((claim) => confirmedClaims.has(claim.claim_id))
|
|
282
1358
|
.map((claim, index) => ({
|
|
@@ -301,10 +1377,104 @@ export function createMockReconstructDirectiveAuthor() {
|
|
|
301
1377
|
},
|
|
302
1378
|
};
|
|
303
1379
|
},
|
|
1380
|
+
async writeCompetencyQuestionAssessment(input) {
|
|
1381
|
+
const realizationByClaim = new Map(input.claimRealizationMap.claim_realizations.map((realization) => [
|
|
1382
|
+
realization.claim_id,
|
|
1383
|
+
realization,
|
|
1384
|
+
]));
|
|
1385
|
+
return {
|
|
1386
|
+
schema_version: "1",
|
|
1387
|
+
session_id: input.sessionId,
|
|
1388
|
+
created_at: isoNow(),
|
|
1389
|
+
competency_questions_ref: input.competencyQuestionsRef,
|
|
1390
|
+
competency_questions_validation_ref: input.competencyQuestionsValidationRef,
|
|
1391
|
+
assessments: input.competencyQuestions.questions.map((question) => {
|
|
1392
|
+
const firstClaimId = question.linked_claim_ids[0] ?? null;
|
|
1393
|
+
const stance = firstClaimId
|
|
1394
|
+
? realizationByClaim.get(firstClaimId)?.stance ?? "unknown"
|
|
1395
|
+
: "unknown";
|
|
1396
|
+
const answerStatus = stance === "observed_runtime_behavior" ||
|
|
1397
|
+
stance === "schema_or_contract_presence"
|
|
1398
|
+
? "answered"
|
|
1399
|
+
: stance === "declared_design_intent"
|
|
1400
|
+
? "partially_answered"
|
|
1401
|
+
: stance === "deferred_or_non_goal"
|
|
1402
|
+
? "out_of_scope"
|
|
1403
|
+
: "needs_evidence";
|
|
1404
|
+
return {
|
|
1405
|
+
question_id: question.question_id,
|
|
1406
|
+
answer_status: answerStatus,
|
|
1407
|
+
linked_claim_ids: question.linked_claim_ids,
|
|
1408
|
+
evidence_refs: question.evidence_refs,
|
|
1409
|
+
rationale: `Mock assessment maps claim realization stance ${stance} to answer status ${answerStatus}.`,
|
|
1410
|
+
};
|
|
1411
|
+
}),
|
|
1412
|
+
directive_author: {
|
|
1413
|
+
owner: "mock",
|
|
1414
|
+
author_id: authorId,
|
|
1415
|
+
},
|
|
1416
|
+
};
|
|
1417
|
+
},
|
|
1418
|
+
async writeFailureClassification(input) {
|
|
1419
|
+
const failures = input.competencyQuestionAssessment.assessments
|
|
1420
|
+
.filter((assessment) => assessment.answer_status !== "answered")
|
|
1421
|
+
.map((assessment, index) => {
|
|
1422
|
+
const failureKind = assessment.answer_status === "out_of_scope"
|
|
1423
|
+
? "deferred_scope"
|
|
1424
|
+
: assessment.answer_status === "partially_answered"
|
|
1425
|
+
? "insufficient_evidence"
|
|
1426
|
+
: "unanswered_question";
|
|
1427
|
+
return {
|
|
1428
|
+
failure_id: `failure-${index + 1}`,
|
|
1429
|
+
failure_kind: failureKind,
|
|
1430
|
+
materiality: "material",
|
|
1431
|
+
question_id: assessment.question_id,
|
|
1432
|
+
claim_id: assessment.linked_claim_ids[0] ?? null,
|
|
1433
|
+
rationale: `Question ${assessment.question_id} is ${assessment.answer_status}, so the Seed is not fully safe to trust for that question.`,
|
|
1434
|
+
recommended_action: failureKind === "deferred_scope" ? "defer" : "collect_evidence",
|
|
1435
|
+
};
|
|
1436
|
+
});
|
|
1437
|
+
return {
|
|
1438
|
+
schema_version: "1",
|
|
1439
|
+
session_id: input.sessionId,
|
|
1440
|
+
created_at: isoNow(),
|
|
1441
|
+
competency_question_assessment_ref: input.competencyQuestionAssessmentRef,
|
|
1442
|
+
seed_confirmation_validation_ref: input.seedConfirmationValidation.seed_confirmation_ref,
|
|
1443
|
+
failures,
|
|
1444
|
+
directive_author: {
|
|
1445
|
+
owner: "mock",
|
|
1446
|
+
author_id: authorId,
|
|
1447
|
+
},
|
|
1448
|
+
};
|
|
1449
|
+
},
|
|
1450
|
+
async writeRevisionProposal(input) {
|
|
1451
|
+
return {
|
|
1452
|
+
schema_version: "1",
|
|
1453
|
+
session_id: input.sessionId,
|
|
1454
|
+
created_at: isoNow(),
|
|
1455
|
+
failure_classification_ref: input.failureClassificationRef,
|
|
1456
|
+
proposals: input.failureClassification.failures.map((failure, index) => ({
|
|
1457
|
+
proposal_id: `proposal-${index + 1}`,
|
|
1458
|
+
target_type: "failure",
|
|
1459
|
+
target_id: failure.failure_id,
|
|
1460
|
+
action: failure.recommended_action === "defer"
|
|
1461
|
+
? "defer"
|
|
1462
|
+
: failure.recommended_action === "reject_claim"
|
|
1463
|
+
? "reject"
|
|
1464
|
+
: "extend",
|
|
1465
|
+
rationale: `Address ${failure.failure_id} before treating the reconstructed Seed as complete.`,
|
|
1466
|
+
expected_effect: "Improve artifact-backed trust without making runtime author ontology meaning.",
|
|
1467
|
+
})),
|
|
1468
|
+
directive_author: {
|
|
1469
|
+
owner: "mock",
|
|
1470
|
+
author_id: authorId,
|
|
1471
|
+
},
|
|
1472
|
+
};
|
|
1473
|
+
},
|
|
304
1474
|
async writeStopDecision(input) {
|
|
305
1475
|
const shouldStop = input.metrics.validation_status.source_observation_directive === "valid" &&
|
|
306
1476
|
input.metrics.validation_status.seed_candidate === "valid" &&
|
|
307
|
-
input.metrics.validation_status.
|
|
1477
|
+
input.metrics.validation_status.seed_confirmation_validation === "valid" &&
|
|
308
1478
|
input.metrics.unresolved_question_count === 0;
|
|
309
1479
|
return {
|
|
310
1480
|
schema_version: "1",
|
|
@@ -326,10 +1496,20 @@ export function createMockReconstructDirectiveAuthor() {
|
|
|
326
1496
|
};
|
|
327
1497
|
},
|
|
328
1498
|
async writeFinalOutput(input) {
|
|
329
|
-
const confirmedClaims = allClaims(input.seedCandidate).filter((claim) => input.
|
|
1499
|
+
const confirmedClaims = allClaims(input.seedCandidate).filter((claim) => input.seedConfirmationValidation.accepted_claim_ids.includes(claim.claim_id));
|
|
330
1500
|
const claimLines = confirmedClaims.length === 0
|
|
331
1501
|
? ["- No Seed claims were confirmed."]
|
|
332
|
-
: confirmedClaims.map((claim) => `- ${claim.claim_id}: ${claim.statement}`);
|
|
1502
|
+
: confirmedClaims.map((claim) => `- ${claim.name} (${claim.claim_id}): ${claim.statement} (seed-candidate.yaml, seed-confirmation-validation.yaml)`);
|
|
1503
|
+
const realizationLines = input.claimRealizationMap.claim_realizations.map((realization) => `- ${realization.claim_id}: ${realization.stance} (claim-realization-map.yaml)`);
|
|
1504
|
+
const assessmentLines = input.competencyQuestionAssessment.assessments.length === 0
|
|
1505
|
+
? ["- No competency question assessments recorded."]
|
|
1506
|
+
: input.competencyQuestionAssessment.assessments.map((assessment) => `- ${assessment.question_id}: ${assessment.answer_status} for ${assessment.linked_claim_ids.join(", ")} (competency-question-assessment.yaml)`);
|
|
1507
|
+
const failureLines = input.failureClassification.failures.length === 0
|
|
1508
|
+
? ["- No material failures recorded."]
|
|
1509
|
+
: input.failureClassification.failures.map((failure) => `- ${failure.failure_id}: ${failure.failure_kind} on ${failure.question_id ?? failure.claim_id ?? "run"} (${failure.materiality}) (failure-classification.yaml)`);
|
|
1510
|
+
const revisionLines = input.revisionProposal.proposals.length === 0
|
|
1511
|
+
? ["- No revision proposals recorded."]
|
|
1512
|
+
: input.revisionProposal.proposals.map((proposal) => `- ${proposal.proposal_id}: ${proposal.action} ${proposal.target_type} ${proposal.target_id} (revision-proposal.yaml)`);
|
|
333
1513
|
const unresolvedQuestions = [
|
|
334
1514
|
...input.seedCandidate.open_questions,
|
|
335
1515
|
...input.competencyQuestions.open_questions,
|
|
@@ -361,8 +1541,27 @@ export function createMockReconstructDirectiveAuthor() {
|
|
|
361
1541
|
`- Semantic claims: ${input.metrics.semantic_claim_count}`,
|
|
362
1542
|
`- Evidence refs: ${input.metrics.evidence_ref_count}`,
|
|
363
1543
|
`- Competency questions: ${input.metrics.competency_question_count}`,
|
|
1544
|
+
`- Competency question assessments: ${input.metrics.competency_question_assessment_count}`,
|
|
1545
|
+
`- Material failures: ${input.failureClassificationValidation.material_failure_count}`,
|
|
1546
|
+
`- Revision proposals: ${input.revisionProposalValidation.proposal_count}`,
|
|
364
1547
|
`- Pass rate: ${input.metrics.pass_rate}`,
|
|
365
1548
|
"",
|
|
1549
|
+
"## Claim Realization Summary",
|
|
1550
|
+
"",
|
|
1551
|
+
...realizationLines,
|
|
1552
|
+
"",
|
|
1553
|
+
"## Competency Question Assessment",
|
|
1554
|
+
"",
|
|
1555
|
+
...assessmentLines,
|
|
1556
|
+
"",
|
|
1557
|
+
"## Failure Classifications",
|
|
1558
|
+
"",
|
|
1559
|
+
...failureLines,
|
|
1560
|
+
"",
|
|
1561
|
+
"## Revision Proposals",
|
|
1562
|
+
"",
|
|
1563
|
+
...revisionLines,
|
|
1564
|
+
"",
|
|
366
1565
|
"## Unresolved Material Questions",
|
|
367
1566
|
"",
|
|
368
1567
|
...unresolvedLines,
|
|
@@ -377,6 +1576,12 @@ export function createMockReconstructDirectiveAuthor() {
|
|
|
377
1576
|
"",
|
|
378
1577
|
"## Artifact Truth",
|
|
379
1578
|
"",
|
|
1579
|
+
`- Seed candidate: ${input.artifactRefs.seed_candidate}`,
|
|
1580
|
+
`- Claim realization map: ${input.artifactRefs.claim_realization_map}`,
|
|
1581
|
+
`- Seed confirmation validation: ${input.artifactRefs.seed_confirmation_validation}`,
|
|
1582
|
+
`- Competency question assessment: ${input.artifactRefs.competency_question_assessment}`,
|
|
1583
|
+
`- Failure classification: ${input.artifactRefs.failure_classification}`,
|
|
1584
|
+
`- Revision proposal: ${input.artifactRefs.revision_proposal}`,
|
|
380
1585
|
`- Reconstruct record: ${input.reconstructRecordPath}`,
|
|
381
1586
|
`- Reconstruct run manifest: ${input.reconstructRunManifestPath}`,
|
|
382
1587
|
`- Record stage at final output authoring: ${input.record.record_stage}`,
|
|
@@ -387,24 +1592,32 @@ export function createMockReconstructDirectiveAuthor() {
|
|
|
387
1592
|
};
|
|
388
1593
|
}
|
|
389
1594
|
export function createAutoAcceptReconstructConfirmationProvider() {
|
|
390
|
-
const providerId = "mock-
|
|
1595
|
+
const providerId = "mock-mixed-confirmation-provider";
|
|
391
1596
|
return {
|
|
392
1597
|
providerId,
|
|
393
1598
|
owner: "mock",
|
|
394
1599
|
async confirmSeedCandidate(input) {
|
|
395
1600
|
const claims = allClaims(input.seedCandidate);
|
|
396
1601
|
const canAccept = input.seedCandidateValidation.validation_status === "valid";
|
|
1602
|
+
const acceptedClaims = canAccept ? claims.slice(0, 3) : [];
|
|
1603
|
+
const partialClaims = canAccept ? claims.slice(3, 4) : [];
|
|
1604
|
+
const deferredClaims = canAccept ? claims.slice(4, 5) : [];
|
|
1605
|
+
const rejectedClaims = canAccept ? claims.slice(5) : claims;
|
|
397
1606
|
return {
|
|
398
1607
|
schema_version: "1",
|
|
399
1608
|
session_id: input.sessionId,
|
|
400
1609
|
created_at: isoNow(),
|
|
401
1610
|
seed_candidate_ref: input.seedCandidateRef,
|
|
402
1611
|
seed_candidate_validation_ref: input.seedCandidateValidationRef,
|
|
403
|
-
confirmation_status: canAccept ? "
|
|
404
|
-
confirmed_claim_ids:
|
|
405
|
-
rejected_claim_ids:
|
|
1612
|
+
confirmation_status: canAccept ? "partial" : "rejected",
|
|
1613
|
+
confirmed_claim_ids: acceptedClaims.map((claim) => claim.claim_id),
|
|
1614
|
+
rejected_claim_ids: rejectedClaims.map((claim) => claim.claim_id),
|
|
1615
|
+
partial_claim_ids: partialClaims.map((claim) => claim.claim_id),
|
|
1616
|
+
deferred_claim_ids: deferredClaims.map((claim) => claim.claim_id),
|
|
406
1617
|
notes: canAccept
|
|
407
|
-
? [
|
|
1618
|
+
? [
|
|
1619
|
+
"Mock confirmation intentionally emits mixed claim states to exercise downstream reconstruct gates.",
|
|
1620
|
+
]
|
|
408
1621
|
: ["Seed candidate validation failed; confirmation rejected by provider."],
|
|
409
1622
|
confirmation_provider: {
|
|
410
1623
|
owner: "mock",
|
|
@@ -414,18 +1627,151 @@ export function createAutoAcceptReconstructConfirmationProvider() {
|
|
|
414
1627
|
},
|
|
415
1628
|
};
|
|
416
1629
|
}
|
|
1630
|
+
export function createDirectCallReconstructConfirmationProvider(args = {}) {
|
|
1631
|
+
const providerId = "direct-call-reconstruct-confirmation-provider";
|
|
1632
|
+
const llmConfig = args.llmConfig ?? {};
|
|
1633
|
+
const llmCall = args.llmCall ?? callLlm;
|
|
1634
|
+
return {
|
|
1635
|
+
providerId,
|
|
1636
|
+
owner: "host_or_user",
|
|
1637
|
+
async confirmSeedCandidate(input) {
|
|
1638
|
+
const claimSummaries = summarizeSeedClaimsForConfirmation(input.seedCandidate);
|
|
1639
|
+
const result = await llmCall([
|
|
1640
|
+
"You are mediating reconstruct Seed confirmation for a non-interactive host.",
|
|
1641
|
+
"Return only valid JSON. Do not wrap in Markdown.",
|
|
1642
|
+
"Classify every Seed claim summary into confirmed, rejected, partial, or deferred for the declared purpose.",
|
|
1643
|
+
"Use the claim id, claim kind, short statement, validation status, and evidence observation ids. Do not invent new claim ids.",
|
|
1644
|
+
"Do not re-author Seed content. This step only assigns confirmation state.",
|
|
1645
|
+
"JSON shape: {\"confirmation_status\":\"accepted|rejected|partial|deferred\",\"confirmed_claim_ids\":[\"...\"],\"rejected_claim_ids\":[\"...\"],\"partial_claim_ids\":[\"...\"],\"deferred_claim_ids\":[\"...\"],\"notes\":[\"...\"]}",
|
|
1646
|
+
].join("\n"), JSON.stringify({
|
|
1647
|
+
seed_candidate_ref: input.seedCandidateRef,
|
|
1648
|
+
seed_candidate_validation_status: input.seedCandidateValidation.validation_status,
|
|
1649
|
+
seed_candidate_validation_results: input.seedCandidateValidation.validation_results,
|
|
1650
|
+
seed_candidate_validation_violation_count: input.seedCandidateValidation.violations.length,
|
|
1651
|
+
claim_summaries: claimSummaries,
|
|
1652
|
+
}, null, 2), { ...llmConfig, max_tokens: 2400 });
|
|
1653
|
+
const raw = parseLlmJsonObject(result.text, "SeedConfirmation");
|
|
1654
|
+
const confirmationStatus = stringValue(raw.confirmation_status, "confirmation_status");
|
|
1655
|
+
if (!["accepted", "rejected", "partial", "deferred"].includes(confirmationStatus)) {
|
|
1656
|
+
throw new Error(`SeedConfirmation confirmation_status is invalid: ${confirmationStatus}`);
|
|
1657
|
+
}
|
|
1658
|
+
return {
|
|
1659
|
+
schema_version: "1",
|
|
1660
|
+
session_id: input.sessionId,
|
|
1661
|
+
created_at: isoNow(),
|
|
1662
|
+
seed_candidate_ref: input.seedCandidateRef,
|
|
1663
|
+
seed_candidate_validation_ref: input.seedCandidateValidationRef,
|
|
1664
|
+
confirmation_status: confirmationStatus,
|
|
1665
|
+
confirmed_claim_ids: stringArray(raw.confirmed_claim_ids, "confirmed_claim_ids"),
|
|
1666
|
+
rejected_claim_ids: stringArray(raw.rejected_claim_ids, "rejected_claim_ids"),
|
|
1667
|
+
partial_claim_ids: stringArray(raw.partial_claim_ids, "partial_claim_ids"),
|
|
1668
|
+
deferred_claim_ids: stringArray(raw.deferred_claim_ids, "deferred_claim_ids"),
|
|
1669
|
+
notes: stringArray(raw.notes, "notes"),
|
|
1670
|
+
confirmation_provider: {
|
|
1671
|
+
owner: "host_or_user",
|
|
1672
|
+
provider_id: providerId,
|
|
1673
|
+
},
|
|
1674
|
+
};
|
|
1675
|
+
},
|
|
1676
|
+
};
|
|
1677
|
+
}
|
|
1678
|
+
async function readLensPrompt(args) {
|
|
1679
|
+
const ontoRoot = path.resolve(args.profilesRoot, "..", "..", "..");
|
|
1680
|
+
return fs.readFile(path.join(ontoRoot, "roles", `${args.lensId}.md`), "utf8");
|
|
1681
|
+
}
|
|
1682
|
+
function validateSourceFrontier(args) {
|
|
1683
|
+
const inventoryRefs = new Set(args.sourceInventory.inventory_units.map((unit) => path.resolve(unit.ref)));
|
|
1684
|
+
const observedRefs = new Set(args.sourceObservations.observations.map((observation) => path.resolve(observation.source_ref)));
|
|
1685
|
+
const accepted = [];
|
|
1686
|
+
const rejected = [];
|
|
1687
|
+
const seen = new Set();
|
|
1688
|
+
for (const frontier of args.sourceFrontier.frontier_refs) {
|
|
1689
|
+
const resolved = path.resolve(frontier.source_ref);
|
|
1690
|
+
if (seen.has(resolved)) {
|
|
1691
|
+
rejected.push({
|
|
1692
|
+
frontier_ref_id: frontier.frontier_ref_id,
|
|
1693
|
+
source_ref: frontier.source_ref,
|
|
1694
|
+
reason: "duplicate_frontier_ref",
|
|
1695
|
+
});
|
|
1696
|
+
continue;
|
|
1697
|
+
}
|
|
1698
|
+
seen.add(resolved);
|
|
1699
|
+
if (observedRefs.has(resolved)) {
|
|
1700
|
+
rejected.push({
|
|
1701
|
+
frontier_ref_id: frontier.frontier_ref_id,
|
|
1702
|
+
source_ref: frontier.source_ref,
|
|
1703
|
+
reason: "already_observed",
|
|
1704
|
+
});
|
|
1705
|
+
continue;
|
|
1706
|
+
}
|
|
1707
|
+
if (!inventoryRefs.has(resolved)) {
|
|
1708
|
+
rejected.push({
|
|
1709
|
+
frontier_ref_id: frontier.frontier_ref_id,
|
|
1710
|
+
source_ref: frontier.source_ref,
|
|
1711
|
+
reason: "not_in_source_inventory",
|
|
1712
|
+
});
|
|
1713
|
+
continue;
|
|
1714
|
+
}
|
|
1715
|
+
accepted.push(frontier.frontier_ref_id);
|
|
1716
|
+
}
|
|
1717
|
+
const noNextFrontierAccepted = args.sourceFrontier.frontier_refs.length === 0 &&
|
|
1718
|
+
typeof args.sourceFrontier.no_next_frontier_rationale === "string" &&
|
|
1719
|
+
args.sourceFrontier.no_next_frontier_rationale.length > 0;
|
|
1720
|
+
const valid = rejected.length === 0 &&
|
|
1721
|
+
(accepted.length > 0 || noNextFrontierAccepted);
|
|
1722
|
+
return {
|
|
1723
|
+
schema_version: "1",
|
|
1724
|
+
session_id: args.sessionId,
|
|
1725
|
+
round_id: args.roundId,
|
|
1726
|
+
created_at: isoNow(),
|
|
1727
|
+
source_frontier_ref: args.sourceFrontierRef,
|
|
1728
|
+
source_inventory_ref: args.sourceInventoryRef,
|
|
1729
|
+
source_observations_ref: args.sourceObservationsRef,
|
|
1730
|
+
validation_status: valid ? "valid" : "invalid",
|
|
1731
|
+
accepted_frontier_ref_ids: accepted,
|
|
1732
|
+
rejected_frontier_refs: rejected,
|
|
1733
|
+
no_next_frontier_accepted: noNextFrontierAccepted,
|
|
1734
|
+
validation_results: [
|
|
1735
|
+
...(valid ? ["source_frontier_boundary_valid"] : []),
|
|
1736
|
+
...(noNextFrontierAccepted ? ["no_next_frontier_rationale_present"] : []),
|
|
1737
|
+
],
|
|
1738
|
+
};
|
|
1739
|
+
}
|
|
1740
|
+
function appendFinalOutputProvenanceFooter(finalOutputText, requiredFragments) {
|
|
1741
|
+
const missing = requiredFragments.filter((fragment) => !finalOutputText.includes(fragment));
|
|
1742
|
+
if (missing.length === 0)
|
|
1743
|
+
return finalOutputText;
|
|
1744
|
+
return [
|
|
1745
|
+
finalOutputText.trimEnd(),
|
|
1746
|
+
"",
|
|
1747
|
+
"## Runtime Artifact Truth Footer",
|
|
1748
|
+
"",
|
|
1749
|
+
...missing.map((fragment) => `- ${fragment}`),
|
|
1750
|
+
"",
|
|
1751
|
+
].join("\n");
|
|
1752
|
+
}
|
|
417
1753
|
export async function runReconstruct(params) {
|
|
418
1754
|
const projectRoot = path.resolve(params.projectRoot);
|
|
419
1755
|
const sessionRoot = path.resolve(params.sessionRoot);
|
|
420
1756
|
const sessionId = path.basename(sessionRoot);
|
|
421
1757
|
const targetRefs = params.targetRefs.map((targetRef) => path.resolve(targetRef));
|
|
422
1758
|
const { directiveAuthor, confirmationProvider } = params;
|
|
423
|
-
if (params.semanticAuthorRealization !== "mock"
|
|
1759
|
+
if (params.semanticAuthorRealization !== "mock" &&
|
|
1760
|
+
params.semanticAuthorRealization !== "direct_call") {
|
|
424
1761
|
throw new Error(`Unsupported reconstruct semanticAuthorRealization: ${params.semanticAuthorRealization}`);
|
|
425
1762
|
}
|
|
426
|
-
if (params.confirmationProviderRealization !== "mock"
|
|
1763
|
+
if (params.confirmationProviderRealization !== "mock" &&
|
|
1764
|
+
params.confirmationProviderRealization !== "direct_call") {
|
|
427
1765
|
throw new Error(`Unsupported reconstruct confirmationProviderRealization: ${params.confirmationProviderRealization}`);
|
|
428
1766
|
}
|
|
1767
|
+
if (params.semanticAuthorRealization === "direct_call" &&
|
|
1768
|
+
directiveAuthor.owner !== "host_llm") {
|
|
1769
|
+
throw new Error("direct_call semantic author realization requires a host_llm directive author.");
|
|
1770
|
+
}
|
|
1771
|
+
if (params.confirmationProviderRealization === "direct_call" &&
|
|
1772
|
+
confirmationProvider.owner !== "host_or_user") {
|
|
1773
|
+
throw new Error("direct_call confirmation provider realization requires a host_or_user provider.");
|
|
1774
|
+
}
|
|
429
1775
|
const preparationRefs = await materializeReconstructPreparationArtifacts({
|
|
430
1776
|
sessionRoot,
|
|
431
1777
|
targetRefs,
|
|
@@ -435,6 +1781,7 @@ export async function runReconstruct(params) {
|
|
|
435
1781
|
});
|
|
436
1782
|
const targetMaterialProfile = await readYamlDocument(preparationRefs.target_material_profile);
|
|
437
1783
|
const sourceObservations = await readYamlDocument(preparationRefs.source_observations);
|
|
1784
|
+
const sourceInventory = await readYamlDocument(preparationRefs.source_inventory);
|
|
438
1785
|
const sourceObservationDirectivePath = path.join(sessionRoot, "source-observation-directive.yaml");
|
|
439
1786
|
const sourceObservationDirective = await directiveAuthor.writeSourceObservationDirective({
|
|
440
1787
|
sessionId,
|
|
@@ -449,6 +1796,78 @@ export async function runReconstruct(params) {
|
|
|
449
1796
|
sourceObservationsPath: preparationRefs.source_observations,
|
|
450
1797
|
outputPath: sourceObservationDirectiveValidationPath,
|
|
451
1798
|
});
|
|
1799
|
+
const roundId = "round-1";
|
|
1800
|
+
const roundRoot = path.join(sessionRoot, "rounds", roundId);
|
|
1801
|
+
const roundObservationDirectivePath = path.join(roundRoot, "source-observation-directive.yaml");
|
|
1802
|
+
const roundObservationDirectiveValidationPath = path.join(roundRoot, "source-observation-directive-validation.yaml");
|
|
1803
|
+
await writeYamlDocument(roundObservationDirectivePath, sourceObservationDirective);
|
|
1804
|
+
await writeYamlDocument(roundObservationDirectiveValidationPath, sourceObservationDirectiveValidation);
|
|
1805
|
+
const lensJudgmentRoot = path.join(roundRoot, "lens-judgments");
|
|
1806
|
+
const lensIds = loadCoreLensRegistry().full_review_lens_ids;
|
|
1807
|
+
const lensJudgments = [];
|
|
1808
|
+
const lensJudgmentRefs = [];
|
|
1809
|
+
for (const lensId of lensIds) {
|
|
1810
|
+
const lensPrompt = await readLensPrompt({
|
|
1811
|
+
profilesRoot: path.resolve(params.profilesRoot),
|
|
1812
|
+
lensId,
|
|
1813
|
+
});
|
|
1814
|
+
const lensJudgment = await directiveAuthor.writeLensJudgment({
|
|
1815
|
+
sessionId,
|
|
1816
|
+
intent: params.intent,
|
|
1817
|
+
roundId,
|
|
1818
|
+
lensId,
|
|
1819
|
+
lensPrompt,
|
|
1820
|
+
sourceObservations,
|
|
1821
|
+
sourceObservationDirective,
|
|
1822
|
+
sourceObservationDirectiveRef: roundObservationDirectivePath,
|
|
1823
|
+
});
|
|
1824
|
+
const lensJudgmentPath = path.join(lensJudgmentRoot, `${lensId}.yaml`);
|
|
1825
|
+
await writeYamlDocument(lensJudgmentPath, lensJudgment);
|
|
1826
|
+
lensJudgments.push(lensJudgment);
|
|
1827
|
+
lensJudgmentRefs.push({
|
|
1828
|
+
lens_id: lensId,
|
|
1829
|
+
artifact_ref: lensJudgmentPath,
|
|
1830
|
+
});
|
|
1831
|
+
}
|
|
1832
|
+
const lensJudgmentIndexPath = path.join(roundRoot, "lens-judgment-index.yaml");
|
|
1833
|
+
const lensJudgmentIndex = {
|
|
1834
|
+
schema_version: "1",
|
|
1835
|
+
session_id: sessionId,
|
|
1836
|
+
round_id: roundId,
|
|
1837
|
+
created_at: isoNow(),
|
|
1838
|
+
lens_judgment_refs: lensJudgmentRefs,
|
|
1839
|
+
};
|
|
1840
|
+
await writeYamlDocument(lensJudgmentIndexPath, lensJudgmentIndex);
|
|
1841
|
+
const explorationSynthesisPath = path.join(roundRoot, "exploration-synthesis.yaml");
|
|
1842
|
+
const explorationSynthesis = await directiveAuthor.writeExplorationSynthesis({
|
|
1843
|
+
sessionId,
|
|
1844
|
+
intent: params.intent,
|
|
1845
|
+
roundId,
|
|
1846
|
+
lensJudgments,
|
|
1847
|
+
lensJudgmentIndexRef: lensJudgmentIndexPath,
|
|
1848
|
+
});
|
|
1849
|
+
await writeYamlDocument(explorationSynthesisPath, explorationSynthesis);
|
|
1850
|
+
const sourceFrontierPath = path.join(roundRoot, "source-frontier.yaml");
|
|
1851
|
+
const sourceFrontier = await directiveAuthor.writeSourceFrontier({
|
|
1852
|
+
sessionId,
|
|
1853
|
+
intent: params.intent,
|
|
1854
|
+
roundId,
|
|
1855
|
+
explorationSynthesis,
|
|
1856
|
+
explorationSynthesisRef: explorationSynthesisPath,
|
|
1857
|
+
});
|
|
1858
|
+
await writeYamlDocument(sourceFrontierPath, sourceFrontier);
|
|
1859
|
+
const sourceFrontierValidationPath = path.join(roundRoot, "source-frontier-validation.yaml");
|
|
1860
|
+
const sourceFrontierValidation = validateSourceFrontier({
|
|
1861
|
+
sessionId,
|
|
1862
|
+
roundId,
|
|
1863
|
+
sourceFrontier,
|
|
1864
|
+
sourceFrontierRef: sourceFrontierPath,
|
|
1865
|
+
sourceInventory,
|
|
1866
|
+
sourceInventoryRef: preparationRefs.source_inventory,
|
|
1867
|
+
sourceObservations,
|
|
1868
|
+
sourceObservationsRef: preparationRefs.source_observations,
|
|
1869
|
+
});
|
|
1870
|
+
await writeYamlDocument(sourceFrontierValidationPath, sourceFrontierValidation);
|
|
452
1871
|
const seedCandidatePath = path.join(sessionRoot, "seed-candidate.yaml");
|
|
453
1872
|
const seedCandidate = await directiveAuthor.writeSeedCandidate({
|
|
454
1873
|
sessionId,
|
|
@@ -456,6 +1875,9 @@ export async function runReconstruct(params) {
|
|
|
456
1875
|
sourceObservations,
|
|
457
1876
|
sourceObservationDirective,
|
|
458
1877
|
sourceObservationDirectiveValidation,
|
|
1878
|
+
lensJudgmentIndex,
|
|
1879
|
+
explorationSynthesis,
|
|
1880
|
+
sourceFrontierValidation,
|
|
459
1881
|
});
|
|
460
1882
|
await writeYamlDocument(seedCandidatePath, seedCandidate);
|
|
461
1883
|
const seedCandidateValidationPath = path.join(sessionRoot, "seed-candidate-validation.yaml");
|
|
@@ -466,6 +1888,21 @@ export async function runReconstruct(params) {
|
|
|
466
1888
|
sourceObservationDirectivePath,
|
|
467
1889
|
sourceObservationDirectiveValidationPath,
|
|
468
1890
|
});
|
|
1891
|
+
const claimRealizationMapPath = path.join(sessionRoot, "claim-realization-map.yaml");
|
|
1892
|
+
const claimRealizationMap = await directiveAuthor.writeClaimRealizationMap({
|
|
1893
|
+
sessionId,
|
|
1894
|
+
seedCandidate,
|
|
1895
|
+
seedCandidateRef: seedCandidatePath,
|
|
1896
|
+
sourceObservations,
|
|
1897
|
+
});
|
|
1898
|
+
await writeYamlDocument(claimRealizationMapPath, claimRealizationMap);
|
|
1899
|
+
const claimRealizationMapValidationPath = path.join(sessionRoot, "claim-realization-map-validation.yaml");
|
|
1900
|
+
const claimRealizationMapValidation = await writeClaimRealizationMapValidationArtifact({
|
|
1901
|
+
claimRealizationMapPath,
|
|
1902
|
+
seedCandidatePath,
|
|
1903
|
+
sourceObservationsPath: preparationRefs.source_observations,
|
|
1904
|
+
outputPath: claimRealizationMapValidationPath,
|
|
1905
|
+
});
|
|
469
1906
|
const seedConfirmationPath = path.join(sessionRoot, "seed-confirmation.yaml");
|
|
470
1907
|
const seedConfirmation = await confirmationProvider.confirmSeedCandidate({
|
|
471
1908
|
sessionId,
|
|
@@ -475,22 +1912,91 @@ export async function runReconstruct(params) {
|
|
|
475
1912
|
seedCandidateValidationRef: seedCandidateValidationPath,
|
|
476
1913
|
});
|
|
477
1914
|
await writeYamlDocument(seedConfirmationPath, seedConfirmation);
|
|
1915
|
+
const seedConfirmationValidationPath = path.join(sessionRoot, "seed-confirmation-validation.yaml");
|
|
1916
|
+
const seedConfirmationValidation = await writeSeedConfirmationValidationArtifact({
|
|
1917
|
+
seedConfirmationPath,
|
|
1918
|
+
seedCandidatePath,
|
|
1919
|
+
seedCandidateValidationPath,
|
|
1920
|
+
outputPath: seedConfirmationValidationPath,
|
|
1921
|
+
});
|
|
478
1922
|
const competencyQuestionsPath = path.join(sessionRoot, "competency-questions.yaml");
|
|
479
1923
|
const competencyQuestions = await directiveAuthor.writeCompetencyQuestions({
|
|
480
1924
|
sessionId,
|
|
481
1925
|
seedCandidate,
|
|
482
1926
|
seedConfirmation,
|
|
483
1927
|
seedConfirmationRef: seedConfirmationPath,
|
|
1928
|
+
seedConfirmationValidation,
|
|
1929
|
+
seedConfirmationValidationRef: seedConfirmationValidationPath,
|
|
1930
|
+
claimRealizationMap,
|
|
484
1931
|
});
|
|
485
1932
|
await writeYamlDocument(competencyQuestionsPath, competencyQuestions);
|
|
1933
|
+
const competencyQuestionsValidationPath = path.join(sessionRoot, "competency-questions-validation.yaml");
|
|
1934
|
+
const competencyQuestionsValidation = await writeCompetencyQuestionsValidationArtifact({
|
|
1935
|
+
competencyQuestionsPath,
|
|
1936
|
+
seedConfirmationValidationPath,
|
|
1937
|
+
sourceObservationsPath: preparationRefs.source_observations,
|
|
1938
|
+
outputPath: competencyQuestionsValidationPath,
|
|
1939
|
+
});
|
|
1940
|
+
const competencyQuestionAssessmentPath = path.join(sessionRoot, "competency-question-assessment.yaml");
|
|
1941
|
+
const competencyQuestionAssessment = await directiveAuthor.writeCompetencyQuestionAssessment({
|
|
1942
|
+
sessionId,
|
|
1943
|
+
competencyQuestions,
|
|
1944
|
+
competencyQuestionsRef: competencyQuestionsPath,
|
|
1945
|
+
competencyQuestionsValidation,
|
|
1946
|
+
competencyQuestionsValidationRef: competencyQuestionsValidationPath,
|
|
1947
|
+
claimRealizationMap,
|
|
1948
|
+
});
|
|
1949
|
+
await writeYamlDocument(competencyQuestionAssessmentPath, competencyQuestionAssessment);
|
|
1950
|
+
const competencyQuestionAssessmentValidationPath = path.join(sessionRoot, "competency-question-assessment-validation.yaml");
|
|
1951
|
+
const competencyQuestionAssessmentValidation = await writeCompetencyQuestionAssessmentValidationArtifact({
|
|
1952
|
+
competencyQuestionAssessmentPath,
|
|
1953
|
+
competencyQuestionsPath,
|
|
1954
|
+
outputPath: competencyQuestionAssessmentValidationPath,
|
|
1955
|
+
});
|
|
1956
|
+
const failureClassificationPath = path.join(sessionRoot, "failure-classification.yaml");
|
|
1957
|
+
const failureClassification = await directiveAuthor.writeFailureClassification({
|
|
1958
|
+
sessionId,
|
|
1959
|
+
competencyQuestionAssessment,
|
|
1960
|
+
competencyQuestionAssessmentRef: competencyQuestionAssessmentPath,
|
|
1961
|
+
competencyQuestionAssessmentValidation,
|
|
1962
|
+
seedConfirmationValidation,
|
|
1963
|
+
});
|
|
1964
|
+
await writeYamlDocument(failureClassificationPath, failureClassification);
|
|
1965
|
+
const failureClassificationValidationPath = path.join(sessionRoot, "failure-classification-validation.yaml");
|
|
1966
|
+
const failureClassificationValidation = await writeFailureClassificationValidationArtifact({
|
|
1967
|
+
failureClassificationPath,
|
|
1968
|
+
competencyQuestionAssessmentPath,
|
|
1969
|
+
seedConfirmationValidationPath,
|
|
1970
|
+
outputPath: failureClassificationValidationPath,
|
|
1971
|
+
});
|
|
1972
|
+
const revisionProposalPath = path.join(sessionRoot, "revision-proposal.yaml");
|
|
1973
|
+
const revisionProposal = await directiveAuthor.writeRevisionProposal({
|
|
1974
|
+
sessionId,
|
|
1975
|
+
failureClassification,
|
|
1976
|
+
failureClassificationRef: failureClassificationPath,
|
|
1977
|
+
failureClassificationValidation,
|
|
1978
|
+
});
|
|
1979
|
+
await writeYamlDocument(revisionProposalPath, revisionProposal);
|
|
1980
|
+
const revisionProposalValidationPath = path.join(sessionRoot, "revision-proposal-validation.yaml");
|
|
1981
|
+
const revisionProposalValidation = await writeRevisionProposalValidationArtifact({
|
|
1982
|
+
revisionProposalPath,
|
|
1983
|
+
failureClassificationPath,
|
|
1984
|
+
outputPath: revisionProposalValidationPath,
|
|
1985
|
+
});
|
|
486
1986
|
const metricsPath = path.join(sessionRoot, "reconstruct-metrics.yaml");
|
|
487
1987
|
const metrics = calculateMetrics({
|
|
488
1988
|
sessionId,
|
|
489
1989
|
sourceObservations,
|
|
490
1990
|
sourceObservationDirectiveValidation,
|
|
491
1991
|
seedCandidateValidation,
|
|
1992
|
+
claimRealizationMapValidation,
|
|
492
1993
|
seedConfirmation,
|
|
1994
|
+
seedConfirmationValidation,
|
|
493
1995
|
competencyQuestions,
|
|
1996
|
+
competencyQuestionsValidation,
|
|
1997
|
+
competencyQuestionAssessmentValidation,
|
|
1998
|
+
failureClassificationValidation,
|
|
1999
|
+
revisionProposalValidation,
|
|
494
2000
|
});
|
|
495
2001
|
await writeYamlDocument(metricsPath, metrics);
|
|
496
2002
|
const stopDecisionPath = path.join(sessionRoot, "stop-decision.yaml");
|
|
@@ -499,6 +2005,8 @@ export async function runReconstruct(params) {
|
|
|
499
2005
|
intent: params.intent,
|
|
500
2006
|
metrics,
|
|
501
2007
|
metricsRef: metricsPath,
|
|
2008
|
+
failureClassification,
|
|
2009
|
+
revisionProposal,
|
|
502
2010
|
});
|
|
503
2011
|
await writeYamlDocument(stopDecisionPath, stopDecision);
|
|
504
2012
|
const finalOutputPath = path.join(sessionRoot, "final-output.md");
|
|
@@ -508,13 +2016,28 @@ export async function runReconstruct(params) {
|
|
|
508
2016
|
refs: {
|
|
509
2017
|
target_material_profile: preparationRefs.target_material_profile,
|
|
510
2018
|
source_inventory: preparationRefs.source_inventory,
|
|
2019
|
+
initial_source_frontier: preparationRefs.initial_source_frontier,
|
|
511
2020
|
source_observations: preparationRefs.source_observations,
|
|
512
2021
|
source_observation_directive: sourceObservationDirectivePath,
|
|
513
2022
|
source_observation_directive_validation: sourceObservationDirectiveValidationPath,
|
|
2023
|
+
lens_judgment_index: lensJudgmentIndexPath,
|
|
2024
|
+
exploration_synthesis: explorationSynthesisPath,
|
|
2025
|
+
source_frontier: sourceFrontierPath,
|
|
2026
|
+
source_frontier_validation: sourceFrontierValidationPath,
|
|
514
2027
|
seed_candidate: seedCandidatePath,
|
|
515
2028
|
seed_candidate_validation: seedCandidateValidationPath,
|
|
2029
|
+
claim_realization_map: claimRealizationMapPath,
|
|
2030
|
+
claim_realization_map_validation: claimRealizationMapValidationPath,
|
|
516
2031
|
seed_confirmation: seedConfirmationPath,
|
|
2032
|
+
seed_confirmation_validation: seedConfirmationValidationPath,
|
|
517
2033
|
competency_questions: competencyQuestionsPath,
|
|
2034
|
+
competency_questions_validation: competencyQuestionsValidationPath,
|
|
2035
|
+
competency_question_assessment: competencyQuestionAssessmentPath,
|
|
2036
|
+
competency_question_assessment_validation: competencyQuestionAssessmentValidationPath,
|
|
2037
|
+
failure_classification: failureClassificationPath,
|
|
2038
|
+
failure_classification_validation: failureClassificationValidationPath,
|
|
2039
|
+
revision_proposal: revisionProposalPath,
|
|
2040
|
+
revision_proposal_validation: revisionProposalValidationPath,
|
|
518
2041
|
reconstruct_metrics: metricsPath,
|
|
519
2042
|
stop_decision: stopDecisionPath,
|
|
520
2043
|
final_output: finalOutputPath,
|
|
@@ -525,6 +2048,8 @@ export async function runReconstruct(params) {
|
|
|
525
2048
|
sessionId,
|
|
526
2049
|
targetRefs,
|
|
527
2050
|
intent: params.intent,
|
|
2051
|
+
semanticAuthorRealization: params.semanticAuthorRealization,
|
|
2052
|
+
confirmationProviderRealization: params.confirmationProviderRealization,
|
|
528
2053
|
directiveAuthor,
|
|
529
2054
|
confirmationProvider,
|
|
530
2055
|
artifactRefs,
|
|
@@ -536,13 +2061,23 @@ export async function runReconstruct(params) {
|
|
|
536
2061
|
artifactRefs,
|
|
537
2062
|
outputPath: recordPath,
|
|
538
2063
|
});
|
|
539
|
-
const
|
|
2064
|
+
const authoredFinalOutputText = await directiveAuthor.writeFinalOutput({
|
|
540
2065
|
sessionId,
|
|
541
2066
|
intent: params.intent,
|
|
542
2067
|
targetMaterialProfile,
|
|
543
2068
|
seedCandidate,
|
|
2069
|
+
claimRealizationMap,
|
|
2070
|
+
claimRealizationMapValidation,
|
|
544
2071
|
seedConfirmation,
|
|
2072
|
+
seedConfirmationValidation,
|
|
545
2073
|
competencyQuestions,
|
|
2074
|
+
competencyQuestionsValidation,
|
|
2075
|
+
competencyQuestionAssessment,
|
|
2076
|
+
competencyQuestionAssessmentValidation,
|
|
2077
|
+
failureClassification,
|
|
2078
|
+
failureClassificationValidation,
|
|
2079
|
+
revisionProposal,
|
|
2080
|
+
revisionProposalValidation,
|
|
546
2081
|
metrics,
|
|
547
2082
|
stopDecision,
|
|
548
2083
|
sourceObservations,
|
|
@@ -552,6 +2087,27 @@ export async function runReconstruct(params) {
|
|
|
552
2087
|
reconstructRunManifest,
|
|
553
2088
|
record: interimRecord,
|
|
554
2089
|
});
|
|
2090
|
+
const requiredFinalOutputFragments = [
|
|
2091
|
+
recordPath,
|
|
2092
|
+
manifestPath,
|
|
2093
|
+
seedCandidatePath,
|
|
2094
|
+
claimRealizationMapPath,
|
|
2095
|
+
seedConfirmationValidationPath,
|
|
2096
|
+
competencyQuestionAssessmentPath,
|
|
2097
|
+
failureClassificationPath,
|
|
2098
|
+
revisionProposalPath,
|
|
2099
|
+
...seedConfirmationValidation.accepted_claim_ids,
|
|
2100
|
+
...failureClassification.failures.map((failure) => failure.failure_id),
|
|
2101
|
+
...revisionProposal.proposals.map((proposal) => proposal.proposal_id),
|
|
2102
|
+
];
|
|
2103
|
+
const finalOutputText = appendFinalOutputProvenanceFooter(authoredFinalOutputText, requiredFinalOutputFragments);
|
|
2104
|
+
const finalOutputViolations = validateFinalOutputProvenance({
|
|
2105
|
+
finalOutputText,
|
|
2106
|
+
requiredFragments: requiredFinalOutputFragments,
|
|
2107
|
+
});
|
|
2108
|
+
if (finalOutputViolations.length > 0) {
|
|
2109
|
+
throw new Error(`final-output.md failed provenance validation: ${finalOutputViolations.map((item) => item.message).join("; ")}`);
|
|
2110
|
+
}
|
|
555
2111
|
await fs.writeFile(finalOutputPath, finalOutputText, "utf8");
|
|
556
2112
|
const finalRecord = await assembleReconstructRecord({
|
|
557
2113
|
sessionRoot,
|