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
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
export const PIPELINE_EXECUTION_LEDGER_SCHEMA_VERSION = "1";
|
|
4
|
+
export async function fileSha256IfPresent(filePath) {
|
|
5
|
+
if (!filePath)
|
|
6
|
+
return null;
|
|
7
|
+
try {
|
|
8
|
+
const content = await fs.readFile(filePath);
|
|
9
|
+
return createHash("sha256").update(content).digest("hex");
|
|
10
|
+
}
|
|
11
|
+
catch (error) {
|
|
12
|
+
const code = error.code;
|
|
13
|
+
if (code === "ENOENT" || code === "ENOTDIR")
|
|
14
|
+
return null;
|
|
15
|
+
throw error;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export async function fileExists(filePath) {
|
|
19
|
+
if (!filePath)
|
|
20
|
+
return false;
|
|
21
|
+
try {
|
|
22
|
+
await fs.access(filePath);
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
export async function buildOutputHashes(outputRefs) {
|
|
30
|
+
const entries = await Promise.all(outputRefs.map(async (outputRef) => [
|
|
31
|
+
outputRef,
|
|
32
|
+
await fileSha256IfPresent(outputRef),
|
|
33
|
+
]));
|
|
34
|
+
return Object.fromEntries(entries);
|
|
35
|
+
}
|
|
36
|
+
export function hasAllRequiredOutputHashes(unit) {
|
|
37
|
+
return unit.outputRefs.every((outputRef) => unit.outputHashes[outputRef] !== null);
|
|
38
|
+
}
|
|
39
|
+
export function isTrustedLedgerUnit(unit) {
|
|
40
|
+
return (unit.status === "completed" &&
|
|
41
|
+
unit.trustStatus === "trusted" &&
|
|
42
|
+
hasAllRequiredOutputHashes(unit));
|
|
43
|
+
}
|
|
44
|
+
export function firstUntrustedRequiredUnit(ledger) {
|
|
45
|
+
return ledger.units.find((unit) => !isTrustedLedgerUnit(unit)) ?? null;
|
|
46
|
+
}
|
|
47
|
+
export function normalizeLedgerRefs(refs) {
|
|
48
|
+
return [...new Set(refs.filter((ref) => typeof ref === "string" && ref.length > 0))]
|
|
49
|
+
.sort();
|
|
50
|
+
}
|
|
51
|
+
export function buildLedgerTrust(args) {
|
|
52
|
+
if (!args.upstreamTrusted) {
|
|
53
|
+
return {
|
|
54
|
+
trustStatus: "blocked_by_upstream",
|
|
55
|
+
trustReason: "A required upstream unit is not trusted.",
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
if (args.status === "completed") {
|
|
59
|
+
const missingOutputRefs = args.outputRefs.filter((outputRef) => args.outputHashes[outputRef] === null);
|
|
60
|
+
if (missingOutputRefs.length > 0) {
|
|
61
|
+
return {
|
|
62
|
+
trustStatus: "untrusted",
|
|
63
|
+
trustReason: `Completed unit is missing required output refs: ${missingOutputRefs.join(", ")}.`,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
trustStatus: "trusted",
|
|
68
|
+
trustReason: "Unit completed and required output refs are present.",
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
if (args.status === "failed") {
|
|
72
|
+
return {
|
|
73
|
+
trustStatus: "untrusted",
|
|
74
|
+
trustReason: args.lastFailureMessage?.trim() ||
|
|
75
|
+
"Unit failed before producing a trusted output.",
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
if (args.status === "skipped") {
|
|
79
|
+
return {
|
|
80
|
+
trustStatus: "untrusted",
|
|
81
|
+
trustReason: "Unit was skipped and did not produce a trusted output.",
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
if (args.status === "missing") {
|
|
85
|
+
return {
|
|
86
|
+
trustStatus: "untrusted",
|
|
87
|
+
trustReason: "Required unit output is missing.",
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
if (args.status === "not_reached") {
|
|
91
|
+
return {
|
|
92
|
+
trustStatus: "blocked_by_upstream",
|
|
93
|
+
trustReason: "Unit was not reached because upstream execution did not complete.",
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
trustStatus: "untrusted",
|
|
98
|
+
trustReason: "Unit is planned but has not completed.",
|
|
99
|
+
};
|
|
100
|
+
}
|
|
@@ -1 +1,33 @@
|
|
|
1
|
-
export
|
|
1
|
+
export const RECONSTRUCT_STAGE_IDS = [
|
|
2
|
+
"invocation_binding",
|
|
3
|
+
"target_material_profile",
|
|
4
|
+
"source_inventory",
|
|
5
|
+
"initial_source_frontier",
|
|
6
|
+
"source_observation",
|
|
7
|
+
"observation_directive",
|
|
8
|
+
"observation_directive_validation",
|
|
9
|
+
"lens_judgment",
|
|
10
|
+
"exploration_synthesis",
|
|
11
|
+
"source_frontier",
|
|
12
|
+
"source_frontier_validation",
|
|
13
|
+
"domain_context_selection",
|
|
14
|
+
"domain_context_selection_validation",
|
|
15
|
+
"seed_candidate",
|
|
16
|
+
"seed_candidate_validation",
|
|
17
|
+
"claim_realization",
|
|
18
|
+
"claim_realization_validation",
|
|
19
|
+
"seed_confirmation",
|
|
20
|
+
"seed_confirmation_validation",
|
|
21
|
+
"competency_questions",
|
|
22
|
+
"competency_questions_validation",
|
|
23
|
+
"competency_question_assessment",
|
|
24
|
+
"competency_question_assessment_validation",
|
|
25
|
+
"failure_classification",
|
|
26
|
+
"failure_classification_validation",
|
|
27
|
+
"revision_proposal",
|
|
28
|
+
"revision_proposal_validation",
|
|
29
|
+
"metrics",
|
|
30
|
+
"stop_decision",
|
|
31
|
+
"final_output",
|
|
32
|
+
"record_assembly",
|
|
33
|
+
];
|
|
@@ -2,7 +2,7 @@ import crypto from "node:crypto";
|
|
|
2
2
|
import fs from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { stringify as stringifyYaml } from "yaml";
|
|
5
|
-
import {
|
|
5
|
+
import { aggregateTargetMaterialDetections, detectTargetMaterialRefs, } from "../target-material-kind.js";
|
|
6
6
|
import { validateSourceObservationBoundary, } from "./source-observations.js";
|
|
7
7
|
import { loadReconstructSourceProfiles, } from "./source-profiles.js";
|
|
8
8
|
const CONCRETE_TARGET_MATERIAL_KINDS = new Set([
|
|
@@ -38,8 +38,8 @@ function supportForMaterial(args) {
|
|
|
38
38
|
}
|
|
39
39
|
if (args.targetMaterialKind === "mixed") {
|
|
40
40
|
return {
|
|
41
|
-
support_status: "
|
|
42
|
-
unsupported_reason: "mixed target material kind
|
|
41
|
+
support_status: "partial_composite",
|
|
42
|
+
unsupported_reason: "mixed target material kind is observed through per-ref source profiles; unsupported members are skipped with authority impact",
|
|
43
43
|
};
|
|
44
44
|
}
|
|
45
45
|
if (args.selectedProfiles.length === 0) {
|
|
@@ -91,15 +91,20 @@ function selectedProfileRefs(profiles, candidates) {
|
|
|
91
91
|
async function textStats(ref) {
|
|
92
92
|
try {
|
|
93
93
|
const text = await fs.readFile(ref, "utf8");
|
|
94
|
+
const excerptLimit = 6000;
|
|
94
95
|
return {
|
|
95
96
|
line_count: text.length === 0 ? 0 : text.split(/\r?\n/).length,
|
|
96
97
|
char_count: text.length,
|
|
98
|
+
content_excerpt: text.slice(0, excerptLimit),
|
|
99
|
+
excerpt_truncated: text.length > excerptLimit,
|
|
97
100
|
};
|
|
98
101
|
}
|
|
99
102
|
catch {
|
|
100
103
|
return {
|
|
101
104
|
line_count: null,
|
|
102
105
|
char_count: null,
|
|
106
|
+
content_excerpt: null,
|
|
107
|
+
excerpt_truncated: false,
|
|
103
108
|
};
|
|
104
109
|
}
|
|
105
110
|
}
|
|
@@ -113,6 +118,8 @@ async function buildObservation(detection) {
|
|
|
113
118
|
const stats = stat.isFile() ? await textStats(detection.ref) : {
|
|
114
119
|
line_count: null,
|
|
115
120
|
char_count: null,
|
|
121
|
+
content_excerpt: null,
|
|
122
|
+
excerpt_truncated: false,
|
|
116
123
|
};
|
|
117
124
|
const observation = {
|
|
118
125
|
observation_id: stableObservationId({
|
|
@@ -132,6 +139,8 @@ async function buildObservation(detection) {
|
|
|
132
139
|
size_bytes: stat.isFile() ? stat.size : null,
|
|
133
140
|
line_count: stats.line_count,
|
|
134
141
|
char_count: stats.char_count,
|
|
142
|
+
content_excerpt: stats.content_excerpt,
|
|
143
|
+
excerpt_truncated: stats.excerpt_truncated,
|
|
135
144
|
},
|
|
136
145
|
};
|
|
137
146
|
const validation = validateSourceObservationBoundary(observation);
|
|
@@ -140,6 +149,40 @@ async function buildObservation(detection) {
|
|
|
140
149
|
}
|
|
141
150
|
return observation;
|
|
142
151
|
}
|
|
152
|
+
function stableFrontierRefId(unit) {
|
|
153
|
+
const digest = crypto
|
|
154
|
+
.createHash("sha256")
|
|
155
|
+
.update(`${unit.target_material_kind}\n${path.resolve(unit.ref)}\n${unit.inventory_unit}`)
|
|
156
|
+
.digest("hex")
|
|
157
|
+
.slice(0, 16);
|
|
158
|
+
return `frontier_initial_${digest}`;
|
|
159
|
+
}
|
|
160
|
+
function buildInitialSourceFrontier(args) {
|
|
161
|
+
return {
|
|
162
|
+
schema_version: "1",
|
|
163
|
+
session_id: args.sessionId,
|
|
164
|
+
created_at: isoNow(),
|
|
165
|
+
frontier_id: "initial",
|
|
166
|
+
source_refs: args.inventory.inventory_units
|
|
167
|
+
.filter((unit) => unit.scan_status === "planned")
|
|
168
|
+
.map((unit) => ({
|
|
169
|
+
frontier_ref_id: stableFrontierRefId(unit),
|
|
170
|
+
source_ref: unit.ref,
|
|
171
|
+
target_material_kind: unit.target_material_kind,
|
|
172
|
+
inventory_unit: unit.inventory_unit,
|
|
173
|
+
profile_ref: unit.profile_ref,
|
|
174
|
+
rationale: "Initial source frontier derived from runtime material inventory and selected source profile.",
|
|
175
|
+
})),
|
|
176
|
+
skipped_refs: args.inventory.inventory_units
|
|
177
|
+
.filter((unit) => unit.scan_status === "skipped")
|
|
178
|
+
.map((unit) => ({
|
|
179
|
+
source_ref: unit.ref,
|
|
180
|
+
target_material_kind: unit.target_material_kind,
|
|
181
|
+
reason: unit.skip_reason ?? "skipped",
|
|
182
|
+
authority_impact: "Semantic artifacts cannot use this ref as trusted evidence until a supported material profile and observation exist.",
|
|
183
|
+
})),
|
|
184
|
+
};
|
|
185
|
+
}
|
|
143
186
|
function buildInventoryUnits(args) {
|
|
144
187
|
return args.detections.map((detection) => {
|
|
145
188
|
const profileRef = profileRefForKind(args.profiles, detection.kind);
|
|
@@ -169,7 +212,8 @@ export async function materializeReconstructPreparationArtifacts(params) {
|
|
|
169
212
|
const sessionId = path.basename(sessionRoot);
|
|
170
213
|
const targetRefs = params.targetRefs.map((ref) => path.resolve(ref));
|
|
171
214
|
const profiles = await loadReconstructSourceProfiles(params.profilesRoot);
|
|
172
|
-
const
|
|
215
|
+
const perRefDetections = await detectTargetMaterialRefs(targetRefs);
|
|
216
|
+
const detection = aggregateTargetMaterialDetections(perRefDetections);
|
|
173
217
|
const selectedProfiles = selectedProfileRefs(profiles, detection.target_material_kind === "mixed"
|
|
174
218
|
? detection.target_material_kind_candidates
|
|
175
219
|
: [detection.target_material_kind]);
|
|
@@ -207,6 +251,10 @@ export async function materializeReconstructPreparationArtifacts(params) {
|
|
|
207
251
|
source: "binding",
|
|
208
252
|
},
|
|
209
253
|
};
|
|
254
|
+
const initialSourceFrontier = buildInitialSourceFrontier({
|
|
255
|
+
sessionId,
|
|
256
|
+
inventory,
|
|
257
|
+
});
|
|
210
258
|
const observations = [];
|
|
211
259
|
const skippedRefs = [];
|
|
212
260
|
for (const unit of inventory.inventory_units) {
|
|
@@ -240,11 +288,13 @@ export async function materializeReconstructPreparationArtifacts(params) {
|
|
|
240
288
|
const refs = {
|
|
241
289
|
target_material_profile: path.join(sessionRoot, "target-material-profile.yaml"),
|
|
242
290
|
source_inventory: path.join(sessionRoot, "source-inventory.yaml"),
|
|
291
|
+
initial_source_frontier: path.join(sessionRoot, "initial-source-frontier.yaml"),
|
|
243
292
|
source_observations: path.join(sessionRoot, "source-observations.yaml"),
|
|
244
293
|
};
|
|
245
294
|
await Promise.all([
|
|
246
295
|
writeYamlDocument(refs.target_material_profile, targetMaterialProfile),
|
|
247
296
|
writeYamlDocument(refs.source_inventory, inventory),
|
|
297
|
+
writeYamlDocument(refs.initial_source_frontier, initialSourceFrontier),
|
|
248
298
|
writeYamlDocument(refs.source_observations, sourceObservations),
|
|
249
299
|
]);
|
|
250
300
|
return refs;
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { PIPELINE_EXECUTION_LEDGER_SCHEMA_VERSION, buildLedgerTrust, buildOutputHashes, isTrustedLedgerUnit, normalizeLedgerRefs, } from "../pipeline-execution-ledger.js";
|
|
3
|
+
const RECONSTRUCT_LEDGER_STAGE_SPECS = [
|
|
4
|
+
{
|
|
5
|
+
unitId: "target_material_profile",
|
|
6
|
+
unitKind: "material_profile",
|
|
7
|
+
owner: "runtime",
|
|
8
|
+
artifactKey: "target_material_profile",
|
|
9
|
+
upstreamUnitIds: [],
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
unitId: "source_inventory",
|
|
13
|
+
unitKind: "source_inventory",
|
|
14
|
+
owner: "runtime",
|
|
15
|
+
artifactKey: "source_inventory",
|
|
16
|
+
upstreamUnitIds: ["target_material_profile"],
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
unitId: "initial_source_frontier",
|
|
20
|
+
unitKind: "source_frontier_initial",
|
|
21
|
+
owner: "runtime",
|
|
22
|
+
artifactKey: "initial_source_frontier",
|
|
23
|
+
upstreamUnitIds: ["source_inventory"],
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
unitId: "source_observation",
|
|
27
|
+
unitKind: "source_observation",
|
|
28
|
+
owner: "runtime",
|
|
29
|
+
artifactKey: "source_observations",
|
|
30
|
+
upstreamUnitIds: ["initial_source_frontier"],
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
unitId: "observation_directive",
|
|
34
|
+
unitKind: "semantic_directive",
|
|
35
|
+
owner: "host_llm",
|
|
36
|
+
artifactKey: "source_observation_directive",
|
|
37
|
+
upstreamUnitIds: ["source_observation"],
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
unitId: "observation_directive_validation",
|
|
41
|
+
unitKind: "runtime_validation",
|
|
42
|
+
owner: "runtime",
|
|
43
|
+
artifactKey: "source_observation_directive_validation",
|
|
44
|
+
upstreamUnitIds: ["observation_directive"],
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
unitId: "domain_context_selection",
|
|
48
|
+
unitKind: "semantic_context_selection",
|
|
49
|
+
owner: "host_llm",
|
|
50
|
+
artifactKey: "domain_context_selection",
|
|
51
|
+
upstreamUnitIds: ["observation_directive_validation"],
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
unitId: "domain_context_selection_validation",
|
|
55
|
+
unitKind: "runtime_validation",
|
|
56
|
+
owner: "runtime",
|
|
57
|
+
artifactKey: "domain_context_selection_validation",
|
|
58
|
+
upstreamUnitIds: ["domain_context_selection"],
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
unitId: "lens_judgment",
|
|
62
|
+
unitKind: "semantic_lens_judgment",
|
|
63
|
+
owner: "host_llm",
|
|
64
|
+
artifactKey: "lens_judgment_index",
|
|
65
|
+
upstreamUnitIds: ["observation_directive_validation"],
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
unitId: "exploration_synthesis",
|
|
69
|
+
unitKind: "semantic_exploration_synthesis",
|
|
70
|
+
owner: "host_llm",
|
|
71
|
+
artifactKey: "exploration_synthesis",
|
|
72
|
+
upstreamUnitIds: ["lens_judgment"],
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
unitId: "source_frontier",
|
|
76
|
+
unitKind: "semantic_source_frontier",
|
|
77
|
+
owner: "host_llm",
|
|
78
|
+
artifactKey: "source_frontier",
|
|
79
|
+
upstreamUnitIds: ["exploration_synthesis"],
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
unitId: "source_frontier_validation",
|
|
83
|
+
unitKind: "runtime_validation",
|
|
84
|
+
owner: "runtime",
|
|
85
|
+
artifactKey: "source_frontier_validation",
|
|
86
|
+
upstreamUnitIds: ["source_frontier"],
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
unitId: "seed_candidate",
|
|
90
|
+
unitKind: "semantic_seed",
|
|
91
|
+
owner: "host_llm",
|
|
92
|
+
artifactKey: "seed_candidate",
|
|
93
|
+
upstreamUnitIds: ["source_frontier_validation"],
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
unitId: "seed_candidate_validation",
|
|
97
|
+
unitKind: "runtime_validation",
|
|
98
|
+
owner: "runtime",
|
|
99
|
+
artifactKey: "seed_candidate_validation",
|
|
100
|
+
upstreamUnitIds: ["seed_candidate"],
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
unitId: "claim_realization",
|
|
104
|
+
unitKind: "semantic_map",
|
|
105
|
+
owner: "host_llm",
|
|
106
|
+
artifactKey: "claim_realization_map",
|
|
107
|
+
upstreamUnitIds: ["seed_candidate_validation"],
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
unitId: "claim_realization_validation",
|
|
111
|
+
unitKind: "runtime_validation",
|
|
112
|
+
owner: "runtime",
|
|
113
|
+
artifactKey: "claim_realization_map_validation",
|
|
114
|
+
upstreamUnitIds: ["claim_realization"],
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
unitId: "seed_confirmation",
|
|
118
|
+
unitKind: "confirmation",
|
|
119
|
+
owner: "user_or_host_mediated",
|
|
120
|
+
artifactKey: "seed_confirmation",
|
|
121
|
+
upstreamUnitIds: ["seed_candidate_validation", "claim_realization_validation"],
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
unitId: "seed_confirmation_validation",
|
|
125
|
+
unitKind: "runtime_validation",
|
|
126
|
+
owner: "runtime",
|
|
127
|
+
artifactKey: "seed_confirmation_validation",
|
|
128
|
+
upstreamUnitIds: ["seed_confirmation"],
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
unitId: "competency_questions",
|
|
132
|
+
unitKind: "semantic_questions",
|
|
133
|
+
owner: "host_llm",
|
|
134
|
+
artifactKey: "competency_questions",
|
|
135
|
+
upstreamUnitIds: ["seed_confirmation_validation"],
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
unitId: "competency_questions_validation",
|
|
139
|
+
unitKind: "runtime_validation",
|
|
140
|
+
owner: "runtime",
|
|
141
|
+
artifactKey: "competency_questions_validation",
|
|
142
|
+
upstreamUnitIds: ["competency_questions"],
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
unitId: "competency_question_assessment",
|
|
146
|
+
unitKind: "semantic_assessment",
|
|
147
|
+
owner: "host_llm",
|
|
148
|
+
artifactKey: "competency_question_assessment",
|
|
149
|
+
upstreamUnitIds: ["competency_questions_validation"],
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
unitId: "competency_question_assessment_validation",
|
|
153
|
+
unitKind: "runtime_validation",
|
|
154
|
+
owner: "runtime",
|
|
155
|
+
artifactKey: "competency_question_assessment_validation",
|
|
156
|
+
upstreamUnitIds: ["competency_question_assessment"],
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
unitId: "failure_classification",
|
|
160
|
+
unitKind: "semantic_failure_classification",
|
|
161
|
+
owner: "host_llm",
|
|
162
|
+
artifactKey: "failure_classification",
|
|
163
|
+
upstreamUnitIds: ["competency_question_assessment_validation"],
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
unitId: "failure_classification_validation",
|
|
167
|
+
unitKind: "runtime_validation",
|
|
168
|
+
owner: "runtime",
|
|
169
|
+
artifactKey: "failure_classification_validation",
|
|
170
|
+
upstreamUnitIds: ["failure_classification"],
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
unitId: "revision_proposal",
|
|
174
|
+
unitKind: "semantic_revision",
|
|
175
|
+
owner: "host_llm",
|
|
176
|
+
artifactKey: "revision_proposal",
|
|
177
|
+
upstreamUnitIds: ["failure_classification_validation"],
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
unitId: "revision_proposal_validation",
|
|
181
|
+
unitKind: "runtime_validation",
|
|
182
|
+
owner: "runtime",
|
|
183
|
+
artifactKey: "revision_proposal_validation",
|
|
184
|
+
upstreamUnitIds: ["revision_proposal"],
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
unitId: "metrics",
|
|
188
|
+
unitKind: "runtime_metrics",
|
|
189
|
+
owner: "runtime",
|
|
190
|
+
artifactKey: "reconstruct_metrics",
|
|
191
|
+
upstreamUnitIds: ["revision_proposal_validation"],
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
unitId: "stop_decision",
|
|
195
|
+
unitKind: "semantic_decision",
|
|
196
|
+
owner: "host_llm",
|
|
197
|
+
artifactKey: "stop_decision",
|
|
198
|
+
upstreamUnitIds: ["metrics"],
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
unitId: "final_output",
|
|
202
|
+
unitKind: "final_output",
|
|
203
|
+
owner: "host_llm",
|
|
204
|
+
artifactKey: "final_output",
|
|
205
|
+
upstreamUnitIds: ["stop_decision"],
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
unitId: "record_assembly",
|
|
209
|
+
unitKind: "record_assembly",
|
|
210
|
+
owner: "runtime",
|
|
211
|
+
artifactKey: "reconstruct_record",
|
|
212
|
+
upstreamUnitIds: ["final_output"],
|
|
213
|
+
},
|
|
214
|
+
];
|
|
215
|
+
const VALIDATION_GATE_BY_AUTHORED_UNIT = new Map([
|
|
216
|
+
["observation_directive", "observation_directive_validation"],
|
|
217
|
+
["source_frontier", "source_frontier_validation"],
|
|
218
|
+
["seed_candidate", "seed_candidate_validation"],
|
|
219
|
+
["claim_realization", "claim_realization_validation"],
|
|
220
|
+
["seed_confirmation", "seed_confirmation_validation"],
|
|
221
|
+
["competency_questions", "competency_questions_validation"],
|
|
222
|
+
["competency_question_assessment", "competency_question_assessment_validation"],
|
|
223
|
+
["failure_classification", "failure_classification_validation"],
|
|
224
|
+
["revision_proposal", "revision_proposal_validation"],
|
|
225
|
+
]);
|
|
226
|
+
function artifactRefForKey(args) {
|
|
227
|
+
if (args.key === "reconstruct_record")
|
|
228
|
+
return args.reconstructRecordRef ?? null;
|
|
229
|
+
return args.record.artifact_refs[args.key] ?? null;
|
|
230
|
+
}
|
|
231
|
+
function downstreamMap() {
|
|
232
|
+
const map = new Map();
|
|
233
|
+
for (const spec of RECONSTRUCT_LEDGER_STAGE_SPECS)
|
|
234
|
+
map.set(spec.unitId, []);
|
|
235
|
+
for (const spec of RECONSTRUCT_LEDGER_STAGE_SPECS) {
|
|
236
|
+
for (const upstreamUnitId of spec.upstreamUnitIds) {
|
|
237
|
+
map.set(upstreamUnitId, [...(map.get(upstreamUnitId) ?? []), spec.unitId]);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return map;
|
|
241
|
+
}
|
|
242
|
+
function manifestStatus(manifest, unitId) {
|
|
243
|
+
const status = manifest?.steps.find((step) => step.step_id === unitId)?.status;
|
|
244
|
+
if (status === "completed" || status === "failed" || status === "skipped") {
|
|
245
|
+
return status;
|
|
246
|
+
}
|
|
247
|
+
return null;
|
|
248
|
+
}
|
|
249
|
+
function trustForReconstructUnit(args) {
|
|
250
|
+
const validationGateUnitId = VALIDATION_GATE_BY_AUTHORED_UNIT.get(args.spec.unitId);
|
|
251
|
+
if (validationGateUnitId) {
|
|
252
|
+
const validationOutputPresent = args.artifactRefsByUnitId.get(validationGateUnitId)?.some((ref) => ref.length > 0) ?? false;
|
|
253
|
+
if (!validationOutputPresent) {
|
|
254
|
+
return {
|
|
255
|
+
trustStatus: "untrusted",
|
|
256
|
+
trustReason: "LLM or user-authored artifact exists only as a candidate until its runtime validation gate completes.",
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return buildLedgerTrust({
|
|
261
|
+
status: args.status,
|
|
262
|
+
outputRefs: args.outputRefs,
|
|
263
|
+
outputHashes: args.outputHashes,
|
|
264
|
+
upstreamTrusted: args.upstreamTrusted,
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
export async function buildReconstructPipelineExecutionLedger(params) {
|
|
268
|
+
const downstreamUnitIds = downstreamMap();
|
|
269
|
+
const manifestStepByUnitId = new Map((params.reconstructRunManifest?.steps ?? []).map((step) => [step.step_id, step]));
|
|
270
|
+
const artifactRefsByUnitId = new Map(RECONSTRUCT_LEDGER_STAGE_SPECS.map((spec) => [
|
|
271
|
+
spec.unitId,
|
|
272
|
+
normalizeLedgerRefs([
|
|
273
|
+
artifactRefForKey({
|
|
274
|
+
key: spec.artifactKey,
|
|
275
|
+
record: params.reconstructRecord,
|
|
276
|
+
reconstructRecordRef: params.reconstructRecordRef ?? null,
|
|
277
|
+
}),
|
|
278
|
+
]),
|
|
279
|
+
]));
|
|
280
|
+
const trustedUnitIds = new Set();
|
|
281
|
+
const units = [];
|
|
282
|
+
for (const spec of RECONSTRUCT_LEDGER_STAGE_SPECS) {
|
|
283
|
+
const outputRefs = artifactRefsByUnitId.get(spec.unitId) ?? [];
|
|
284
|
+
const outputHashes = await buildOutputHashes(outputRefs);
|
|
285
|
+
const outputPresent = outputRefs.length > 0 &&
|
|
286
|
+
outputRefs.every((outputRef) => outputHashes[outputRef] !== null);
|
|
287
|
+
const upstreamTrusted = spec.upstreamUnitIds.every((unitId) => {
|
|
288
|
+
if (spec.unitKind === "runtime_validation") {
|
|
289
|
+
return (artifactRefsByUnitId.get(unitId) ?? []).length > 0;
|
|
290
|
+
}
|
|
291
|
+
return trustedUnitIds.has(unitId);
|
|
292
|
+
});
|
|
293
|
+
const status = manifestStatus(params.reconstructRunManifest, spec.unitId) ??
|
|
294
|
+
(outputPresent
|
|
295
|
+
? "completed"
|
|
296
|
+
: upstreamTrusted
|
|
297
|
+
? "missing"
|
|
298
|
+
: "not_reached");
|
|
299
|
+
const trust = trustForReconstructUnit({
|
|
300
|
+
spec,
|
|
301
|
+
status,
|
|
302
|
+
outputRefs,
|
|
303
|
+
outputHashes,
|
|
304
|
+
upstreamTrusted,
|
|
305
|
+
artifactRefsByUnitId,
|
|
306
|
+
});
|
|
307
|
+
const manifestStep = manifestStepByUnitId.get(spec.unitId);
|
|
308
|
+
const entry = {
|
|
309
|
+
unitId: spec.unitId,
|
|
310
|
+
unitKind: spec.unitKind,
|
|
311
|
+
owner: spec.owner,
|
|
312
|
+
producedArtifactRefs: outputRefs,
|
|
313
|
+
consumedArtifactRefs: normalizeLedgerRefs([
|
|
314
|
+
...spec.upstreamUnitIds.flatMap((unitId) => artifactRefsByUnitId.get(unitId) ?? []),
|
|
315
|
+
]),
|
|
316
|
+
outputRefs,
|
|
317
|
+
outputHashes,
|
|
318
|
+
status,
|
|
319
|
+
trustStatus: trust.trustStatus,
|
|
320
|
+
trustReason: trust.trustReason,
|
|
321
|
+
attemptCount: manifestStep ? 1 : 0,
|
|
322
|
+
lastFailureMessage: null,
|
|
323
|
+
upstreamUnitIds: spec.upstreamUnitIds,
|
|
324
|
+
downstreamUnitIds: downstreamUnitIds.get(spec.unitId) ?? [],
|
|
325
|
+
};
|
|
326
|
+
units.push(entry);
|
|
327
|
+
if (isTrustedLedgerUnit(entry))
|
|
328
|
+
trustedUnitIds.add(entry.unitId);
|
|
329
|
+
}
|
|
330
|
+
return {
|
|
331
|
+
schemaVersion: PIPELINE_EXECUTION_LEDGER_SCHEMA_VERSION,
|
|
332
|
+
pipeline: "reconstruct",
|
|
333
|
+
sessionId: params.reconstructRecord.session_id || path.basename(params.sessionRoot),
|
|
334
|
+
sourceRefs: normalizeLedgerRefs([
|
|
335
|
+
params.reconstructRecordRef,
|
|
336
|
+
params.reconstructRunManifestRef,
|
|
337
|
+
...Object.values(params.reconstructRecord.artifact_refs),
|
|
338
|
+
...Object.values(params.reconstructRunManifest?.artifact_refs ?? {}),
|
|
339
|
+
]),
|
|
340
|
+
units,
|
|
341
|
+
};
|
|
342
|
+
}
|