onto-mcp 0.4.12 → 0.4.13
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 +1 -1
- package/.onto/authority/supported-models.yaml +137 -0
- package/.onto/domains/accounting-kr/competency_qs.md +153 -153
- package/.onto/processes/reconstruct/obligation-coverage-ledger.yaml +842 -0
- package/.onto/processes/reconstruct/obligation-coverage-recorded.yaml +225 -0
- package/.onto/processes/reconstruct/ontology-seeding-and-maturation-design.md +93 -54
- package/.onto/processes/reconstruct/reconstruct-contract-registry.yaml +169 -8
- package/.onto/processes/reconstruct/reconstruct-execution-ux-contract.md +72 -1
- package/.onto/processes/reconstruct/source-profiles/spreadsheet.md +35 -0
- package/.onto/processes/review/productized-live-path.md +9 -5
- package/.onto/processes/review/prompt-execution-runner-contract.md +32 -8
- package/.onto/processes/review/review-target-profile-contract.md +47 -4
- package/.onto/processes/shared/pipeline-execution-ledger-contract.md +11 -0
- package/.onto/processes/shared/target-material-kind-contract.md +1 -1
- package/README.md +64 -1
- package/dist/cli.js +11 -1
- package/dist/core-api/reconstruct-api.js +575 -24
- package/dist/core-api/review-api.js +70 -5
- package/dist/core-api/review-progress.js +7 -0
- package/dist/core-api/runtime-observation.js +7 -0
- package/dist/core-runtime/artifact-io.js +75 -3
- package/dist/core-runtime/cli/claude-code-review-unit-executor.js +19 -8
- package/dist/core-runtime/cli/materialize-review-prompt-packets.js +68 -14
- package/dist/core-runtime/cli/prepare-review-session.js +34 -1
- package/dist/core-runtime/cli/render-review-final-output.js +2 -1
- package/dist/core-runtime/cli/run-review-prompt-execution.js +758 -48
- package/dist/core-runtime/cli/run-seats.js +18 -0
- package/dist/core-runtime/cli/runtime-submit-context.js +10 -2
- package/dist/core-runtime/cli/unit-resubmit.js +269 -0
- package/dist/core-runtime/cli/worker-structured-output.js +80 -2
- package/dist/core-runtime/discovery/host-detection.js +71 -22
- package/dist/core-runtime/discovery/review-cert-assemble.js +208 -0
- package/dist/core-runtime/discovery/review-cert-record.js +442 -0
- package/dist/core-runtime/discovery/review-execution-units.js +22 -0
- package/dist/core-runtime/discovery/seat-inventory.js +167 -0
- package/dist/core-runtime/discovery/settings-chain.js +311 -52
- package/dist/core-runtime/discovery/supported-models.js +282 -29
- package/dist/core-runtime/discovery/synthesize-cert-assemble.js +197 -0
- package/dist/core-runtime/discovery/synthesize-cert-capsule.js +399 -0
- package/dist/core-runtime/discovery/synthesize-cert-judge.js +340 -0
- package/dist/core-runtime/discovery/synthesize-cert-loop.js +234 -0
- package/dist/core-runtime/discovery/synthesize-cert-mutation.js +117 -0
- package/dist/core-runtime/discovery/synthesize-cert-packet.js +182 -0
- package/dist/core-runtime/discovery/synthesize-cert-record.js +831 -0
- package/dist/core-runtime/discovery/synthesize-cert-sampler.js +336 -0
- package/dist/core-runtime/effort-calibration-ingest.js +135 -0
- package/dist/core-runtime/llm/dispatch-breaker.js +412 -0
- package/dist/core-runtime/llm/dispatch-fallback-adapter-capabilities.js +33 -0
- package/dist/core-runtime/llm/llm-caller.js +188 -47
- package/dist/core-runtime/llm/mock-llm-realization.js +35 -4
- package/dist/core-runtime/llm/model-switcher.js +1 -1
- package/dist/core-runtime/llm/openai-responses-incomplete-error.js +46 -0
- package/dist/core-runtime/llm/sealed-dispatch-capability.js +359 -0
- package/dist/core-runtime/llm/structured-dispatch-error.js +15 -0
- package/dist/core-runtime/onboard/claude-profile-scan.js +65 -0
- package/dist/core-runtime/onboard/cli-host.js +5 -2
- package/dist/core-runtime/onboard/configure-provider.js +33 -1
- package/dist/core-runtime/onboard/host-target.js +28 -3
- package/dist/core-runtime/onboard/register.js +54 -12
- package/dist/core-runtime/pipeline-execution-ledger.js +10 -0
- package/dist/core-runtime/reconstruct/artifact-types.js +35 -0
- package/dist/core-runtime/reconstruct/claim-projection-validation.js +17 -0
- package/dist/core-runtime/reconstruct/competency-projection-contract.js +63 -0
- package/dist/core-runtime/reconstruct/comprehension-artifact.js +321 -0
- package/dist/core-runtime/reconstruct/comprehension-reduce.js +367 -0
- package/dist/core-runtime/reconstruct/comprehension-semantic-map.js +771 -0
- package/dist/core-runtime/reconstruct/contract-registry.js +20 -0
- package/dist/core-runtime/reconstruct/dispatch-fallback-artifacts.js +640 -0
- package/dist/core-runtime/reconstruct/execution-telemetry.js +83 -9
- package/dist/core-runtime/reconstruct/final-output-sections.js +89 -0
- package/dist/core-runtime/reconstruct/governing-snapshot.js +36 -1
- package/dist/core-runtime/reconstruct/leaf-reader.js +305 -0
- package/dist/core-runtime/reconstruct/llm-dispatch-failure.js +270 -0
- package/dist/core-runtime/reconstruct/llm-touch-fingerprint.js +94 -0
- package/dist/core-runtime/reconstruct/material-admission-validation.js +18 -0
- package/dist/core-runtime/reconstruct/material-profile-validation.js +14 -0
- package/dist/core-runtime/reconstruct/materialize-preparation.js +304 -18
- package/dist/core-runtime/reconstruct/maturation-validation.js +1231 -53
- package/dist/core-runtime/reconstruct/mock-llm-realization.js +107 -3
- package/dist/core-runtime/reconstruct/obligation-assertion.js +18 -0
- package/dist/core-runtime/reconstruct/ontology-seed-validation.js +27 -0
- package/dist/core-runtime/reconstruct/output-budget.js +6 -0
- package/dist/core-runtime/reconstruct/pipeline-execution-ledger.js +87 -3
- package/dist/core-runtime/reconstruct/post-seed-validation.js +118 -5
- package/dist/core-runtime/reconstruct/purpose-authority-validation.js +117 -2
- package/dist/core-runtime/reconstruct/record.js +42 -0
- package/dist/core-runtime/reconstruct/registry-verification-validation.js +16 -0
- package/dist/core-runtime/reconstruct/run-control-validation.js +1011 -34
- package/dist/core-runtime/reconstruct/run.js +5198 -536
- package/dist/core-runtime/reconstruct/seed-authoring-readiness-validation.js +54 -3
- package/dist/core-runtime/reconstruct/semantic-quality-gate.js +105 -2
- package/dist/core-runtime/reconstruct/source-observation-delta-validation.js +41 -0
- package/dist/core-runtime/reconstruct/source-observations.js +166 -0
- package/dist/core-runtime/reconstruct/source-safety-validation.js +71 -183
- package/dist/core-runtime/reconstruct/source-scout-pack-validation.js +37 -1
- package/dist/core-runtime/reconstruct/terminal-validation.js +132 -2
- package/dist/core-runtime/review/continuation-plan.js +12 -5
- package/dist/core-runtime/review/issue-artifact-runtime.js +4 -1
- package/dist/core-runtime/review/materializers.js +100 -11
- package/dist/core-runtime/review/nesting-batch.js +6 -2
- package/dist/core-runtime/review/obligation-shardability.js +138 -0
- package/dist/core-runtime/review/pipeline-execution-ledger.js +42 -2
- package/dist/core-runtime/review/review-artifact-utils.js +217 -5
- package/dist/core-runtime/review/review-execution-steps.js +32 -8
- package/dist/core-runtime/review/review-progress-contract.js +8 -0
- package/dist/core-runtime/review/review-prompt-budget.js +97 -0
- package/dist/core-runtime/review/semantic-quality-gate.js +33 -7
- package/dist/core-runtime/review/spreadsheet-review-disposition.js +94 -0
- package/dist/core-runtime/route-identity.js +182 -0
- package/dist/core-runtime/spreadsheet-header-escalation.js +204 -0
- package/dist/core-runtime/spreadsheet-structure-observer.js +2689 -0
- package/dist/core-runtime/target-material-kind.js +58 -0
- package/dist/mcp/server.js +12 -5
- package/dist/tui/app.js +167 -0
- package/dist/tui/data/event-follower.js +116 -0
- package/dist/tui/data/node-detail.js +42 -0
- package/dist/tui/data/projection-poll.js +26 -0
- package/dist/tui/data/session-discovery.js +65 -0
- package/dist/tui/index.js +108 -0
- package/dist/tui/screens/log.js +25 -0
- package/dist/tui/screens/node-detail.js +17 -0
- package/dist/tui/screens/session-selector.js +26 -0
- package/dist/tui/screens/workflow-tree.js +90 -0
- package/dist/tui/view-model/reconstruct-adapter.js +162 -0
- package/dist/tui/view-model/review-adapter.js +270 -0
- package/dist/tui/view-model/tree-view-model.js +19 -0
- package/package.json +18 -3
- package/settings.example.json +77 -16
|
@@ -3,25 +3,206 @@ import fs from "node:fs/promises";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { parse as parseYaml } from "yaml";
|
|
5
5
|
import { RECONSTRUCT_STAGE_IDS, } from "../core-runtime/reconstruct/artifact-types.js";
|
|
6
|
-
import { materializeReconstructPreparationArtifacts, } from "../core-runtime/reconstruct/materialize-preparation.js";
|
|
6
|
+
import { deriveDocumentExcerptProjectionBudget, DOCUMENT_EXCERPT_PROJECTION_FLOOR, materializeReconstructPreparationArtifacts, } from "../core-runtime/reconstruct/materialize-preparation.js";
|
|
7
7
|
import { writeTargetMaterialProfileValidationArtifact, } from "../core-runtime/reconstruct/material-profile-validation.js";
|
|
8
|
-
import { assembleReconstructRecord, } from "../core-runtime/reconstruct/record.js";
|
|
8
|
+
import { assembleReconstructRecord, reconstructTerminalStatus, } from "../core-runtime/reconstruct/record.js";
|
|
9
|
+
export { reconstructTerminalStatus, } from "../core-runtime/reconstruct/record.js";
|
|
9
10
|
import { createDirectCallReconstructConfirmationProvider, createDirectCallReconstructDirectiveAuthor, runReconstruct, } from "../core-runtime/reconstruct/run.js";
|
|
11
|
+
import { RECONSTRUCT_SEMANTIC_AUTHOR_MAX_BASE_OUTPUT_TOKENS, } from "../core-runtime/reconstruct/output-budget.js";
|
|
10
12
|
// Explicit reconstruct mock realization switch point (INV-MOCK-1 boundary;
|
|
11
13
|
// allowlisted in scripts/check-import-boundary.ts). Active only when
|
|
12
14
|
// ONTO_LLM_MOCK=1; mock runs record mock actor ids in the run manifest.
|
|
13
15
|
import { RECONSTRUCT_MOCK_AUTHOR_ID, RECONSTRUCT_MOCK_CONFIRMATION_PROVIDER_ID, callReconstructMockLlm, isReconstructMockLlmRealizationEnabled, } from "../core-runtime/reconstruct/mock-llm-realization.js";
|
|
14
|
-
import { assertSettingsModelsSupported, resolveSettingsChain, resolveReconstructActorLlmSettings, } from "../core-runtime/discovery/settings-chain.js";
|
|
16
|
+
import { assertSettingsModelsSupported, completeDispatchBreakerSettings, isReconstructSemanticMapAuthoringEnabled, resolveOptionalReconstructActorLlmSettings, resolveSettingsChain, resolveReconstructActorLlmSettings, resolveReconstructSemanticAuthorLlmRuntimeSettings, } from "../core-runtime/discovery/settings-chain.js";
|
|
17
|
+
import { assertDispatchFallbackSessionAdmission } from "../core-runtime/reconstruct/dispatch-fallback-artifacts.js";
|
|
18
|
+
import { normalizeLlmModelSwitcher, } from "../core-runtime/llm/model-switcher.js";
|
|
15
19
|
import { resolveOntoHome, } from "../core-runtime/discovery/onto-home.js";
|
|
16
|
-
import { isSupportedModelRoute, loadSupportedModelRegistry, } from "../core-runtime/discovery/supported-models.js";
|
|
17
|
-
import { resolveLlmProviderConfig, } from "../core-runtime/llm/llm-caller.js";
|
|
20
|
+
import { isSupportedModelRoute, loadSupportedModelRegistry, supportedModelMaxOutputTokens, } from "../core-runtime/discovery/supported-models.js";
|
|
21
|
+
import { applyOpenAIResponsesOutputHeadroom, resolveLlmProviderConfig, } from "../core-runtime/llm/llm-caller.js";
|
|
22
|
+
import { createSealedDispatchCapability, SemanticMapDispatchAccounting, } from "../core-runtime/llm/sealed-dispatch-capability.js";
|
|
23
|
+
import { createReconstructExecutionTelemetryCollector } from "../core-runtime/reconstruct/execution-telemetry.js";
|
|
18
24
|
import { writeOntologySeedValidationArtifact, writeCandidateDispositionValidationArtifact, } from "../core-runtime/reconstruct/ontology-seed-validation.js";
|
|
19
25
|
import { writeSourceObservationDirectiveValidationArtifact, } from "../core-runtime/reconstruct/directive-validation.js";
|
|
20
26
|
import { loadReconstructSourceProfiles, } from "../core-runtime/reconstruct/source-profiles.js";
|
|
21
27
|
import { assertReconstructDomainId, } from "../core-runtime/reconstruct/domain-id.js";
|
|
22
|
-
import { buildReconstructPipelineExecutionLedger, } from "../core-runtime/reconstruct/pipeline-execution-ledger.js";
|
|
28
|
+
import { buildReconstructPipelineExecutionLedger, reconstructStageIdForArtifactRef, reconstructStageOwner, } from "../core-runtime/reconstruct/pipeline-execution-ledger.js";
|
|
29
|
+
import { reconcileReconstructLlmDispatchFailures, } from "../core-runtime/reconstruct/run-control-validation.js";
|
|
30
|
+
import { isReconstructLlmDispatchFailureRef, projectReconstructLlmDispatchFailureSummary, readReconstructLlmDispatchFailureArtifactWithHash, readReconstructLlmDispatchFailureError, } from "../core-runtime/reconstruct/llm-dispatch-failure.js";
|
|
23
31
|
import { spawnRuntimeWatcherPane, } from "../core-runtime/cli/spawn-watcher.js";
|
|
32
|
+
import { assertPathInsideRoot } from "../core-runtime/path-boundary.js";
|
|
24
33
|
import { appendRuntimeStatusEventSync, runWithRuntimeObservationContext, } from "../core-runtime/observability/runtime-stream-observation.js";
|
|
34
|
+
function failedReconstructProgress(failure, completedStageRefs) {
|
|
35
|
+
return {
|
|
36
|
+
executionProfile: null,
|
|
37
|
+
currentStageId: failure.unit_id,
|
|
38
|
+
stageCount: RECONSTRUCT_STAGE_IDS.length,
|
|
39
|
+
liveness: {
|
|
40
|
+
state: "halted_or_partial",
|
|
41
|
+
recommendedPollIntervalMs: null,
|
|
42
|
+
},
|
|
43
|
+
countSummary: {
|
|
44
|
+
sourceObservationCount: null,
|
|
45
|
+
selectedObservationCount: null,
|
|
46
|
+
semanticClaimCount: null,
|
|
47
|
+
confirmedClaimCount: null,
|
|
48
|
+
partialClaimCount: null,
|
|
49
|
+
deferredClaimCount: null,
|
|
50
|
+
competencyQuestionCount: null,
|
|
51
|
+
assessmentCount: null,
|
|
52
|
+
failureCount: null,
|
|
53
|
+
revisionProposalCount: null,
|
|
54
|
+
unresolvedCount: null,
|
|
55
|
+
passRate: null,
|
|
56
|
+
},
|
|
57
|
+
answerabilitySummary: null,
|
|
58
|
+
stages: RECONSTRUCT_STAGE_IDS.map((stageId) => ({
|
|
59
|
+
stageId,
|
|
60
|
+
state: stageId === failure.unit_id
|
|
61
|
+
? "halted"
|
|
62
|
+
: completedStageRefs.has(stageId)
|
|
63
|
+
? "completed"
|
|
64
|
+
: "pending",
|
|
65
|
+
owner: stageId === failure.unit_id
|
|
66
|
+
? reconstructStageOwner(stageId)
|
|
67
|
+
: null,
|
|
68
|
+
artifactRefs: stageId === failure.unit_id
|
|
69
|
+
? [failure.failure_artifact_ref]
|
|
70
|
+
: [...(completedStageRefs.get(stageId) ?? [])],
|
|
71
|
+
reason: stageId === failure.unit_id ? failure.failure_code : null,
|
|
72
|
+
authorityImpact: stageId === failure.unit_id
|
|
73
|
+
? "The provider output ceiling stopped the owning actor before a canonical stage artifact was accepted."
|
|
74
|
+
: null,
|
|
75
|
+
})),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
async function isRegularRefInsideSession(sessionRoot, artifactRef) {
|
|
79
|
+
const relative = path.relative(sessionRoot, path.resolve(artifactRef));
|
|
80
|
+
if (relative.startsWith("..") || path.isAbsolute(relative))
|
|
81
|
+
return false;
|
|
82
|
+
try {
|
|
83
|
+
const stat = await fs.lstat(artifactRef);
|
|
84
|
+
if (!stat.isFile() || stat.isSymbolicLink())
|
|
85
|
+
return false;
|
|
86
|
+
const [realSessionRoot, realArtifactRef] = await Promise.all([
|
|
87
|
+
fs.realpath(sessionRoot),
|
|
88
|
+
fs.realpath(artifactRef),
|
|
89
|
+
]);
|
|
90
|
+
const realRelative = path.relative(realSessionRoot, realArtifactRef);
|
|
91
|
+
return !realRelative.startsWith("..") && !path.isAbsolute(realRelative);
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
async function collectFailedStatusArtifactEvidence(args) {
|
|
98
|
+
const reusable = new Set();
|
|
99
|
+
const completedStageRefs = new Map();
|
|
100
|
+
const addStageRef = (stageId, ref) => {
|
|
101
|
+
const refs = completedStageRefs.get(stageId) ?? [];
|
|
102
|
+
if (!refs.includes(ref))
|
|
103
|
+
refs.push(ref);
|
|
104
|
+
completedStageRefs.set(stageId, refs);
|
|
105
|
+
};
|
|
106
|
+
for (const transaction of args.runControl.write_transactions) {
|
|
107
|
+
if (transaction.owner_attempt_id !== args.ownerAttemptId ||
|
|
108
|
+
transaction.transaction_status !== "committed" ||
|
|
109
|
+
!transaction.committed_hash ||
|
|
110
|
+
isReconstructLlmDispatchFailureRef(args.sessionRoot, transaction.artifact_ref) ||
|
|
111
|
+
!(await isRegularRefInsideSession(args.sessionRoot, transaction.artifact_ref))) {
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
const bytes = await fs.readFile(transaction.artifact_ref);
|
|
115
|
+
const observedHash = crypto.createHash("sha256").update(bytes).digest("hex");
|
|
116
|
+
if (observedHash !== transaction.committed_hash)
|
|
117
|
+
continue;
|
|
118
|
+
reusable.add(transaction.artifact_ref);
|
|
119
|
+
const stageId = reconstructStageIdForArtifactRef(transaction.artifact_ref);
|
|
120
|
+
if (stageId)
|
|
121
|
+
addStageRef(stageId, transaction.artifact_ref);
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
reusableArtifactRefs: [...reusable].sort(),
|
|
125
|
+
completedStageRefs,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
async function trustedFailedSessionStatus(args) {
|
|
129
|
+
if (!args.reconciliation)
|
|
130
|
+
return null;
|
|
131
|
+
const runControl = args.reconciliation.runControl;
|
|
132
|
+
const validation = args.reconciliation.validation ??
|
|
133
|
+
await readYamlArtifactIfPresent(args.runControlValidationRef);
|
|
134
|
+
const latestAttempt = runControl.attempt_rows.at(-1) ?? null;
|
|
135
|
+
if (latestAttempt?.attempt_status !== "failed")
|
|
136
|
+
return null;
|
|
137
|
+
const failureTransactions = runControl.write_transactions.filter((row) => row.owner_attempt_id === latestAttempt.attempt_id &&
|
|
138
|
+
row.transaction_status === "committed" &&
|
|
139
|
+
isReconstructLlmDispatchFailureRef(args.sessionRoot, row.artifact_ref));
|
|
140
|
+
const failureTransaction = failureTransactions.length === 1
|
|
141
|
+
? failureTransactions[0]
|
|
142
|
+
: null;
|
|
143
|
+
if (!validation ||
|
|
144
|
+
validation.validation_status !== "valid" ||
|
|
145
|
+
validation.current_attempt_id !== latestAttempt.attempt_id ||
|
|
146
|
+
!failureTransaction) {
|
|
147
|
+
throw new Error(`reconstruct session has no trusted failed terminal: ${args.sessionRoot}`);
|
|
148
|
+
}
|
|
149
|
+
const failureRead = await readReconstructLlmDispatchFailureArtifactWithHash({
|
|
150
|
+
sessionRoot: args.sessionRoot,
|
|
151
|
+
artifactRef: failureTransaction.artifact_ref,
|
|
152
|
+
});
|
|
153
|
+
if (failureTransaction.prepared_content_hash !==
|
|
154
|
+
failureTransaction.committed_hash ||
|
|
155
|
+
failureRead.sha256 !== failureTransaction.committed_hash ||
|
|
156
|
+
failureRead.artifact.session_id !== runControl.session_id ||
|
|
157
|
+
failureRead.artifact.owner_attempt_id !== latestAttempt.attempt_id) {
|
|
158
|
+
throw new Error(`trusted failed terminal changed after validation: ${failureTransaction.artifact_ref}`);
|
|
159
|
+
}
|
|
160
|
+
const failure = projectReconstructLlmDispatchFailureSummary(failureRead.artifact, failureTransaction.artifact_ref);
|
|
161
|
+
const artifactEvidence = await collectFailedStatusArtifactEvidence({
|
|
162
|
+
sessionRoot: args.sessionRoot,
|
|
163
|
+
runControl,
|
|
164
|
+
ownerAttemptId: latestAttempt.attempt_id,
|
|
165
|
+
});
|
|
166
|
+
artifactEvidence.completedStageRefs.set("run_control", [args.runControlRef]);
|
|
167
|
+
artifactEvidence.completedStageRefs.set("run_control_validation", [
|
|
168
|
+
args.runControlValidationRef,
|
|
169
|
+
]);
|
|
170
|
+
return {
|
|
171
|
+
sessionId: runControl.session_id,
|
|
172
|
+
sessionRoot: args.sessionRoot,
|
|
173
|
+
status: "failed",
|
|
174
|
+
artifactRefs: {
|
|
175
|
+
reconstruct_run_control: args.runControlRef,
|
|
176
|
+
reconstruct_run_control_validation: args.runControlValidationRef,
|
|
177
|
+
},
|
|
178
|
+
claimProjection: null,
|
|
179
|
+
claimProjectionValidation: null,
|
|
180
|
+
progress: failedReconstructProgress(failure, artifactEvidence.completedStageRefs),
|
|
181
|
+
reconstructRecord: null,
|
|
182
|
+
runControlRef: args.runControlRef,
|
|
183
|
+
runControlValidationRef: args.runControlValidationRef,
|
|
184
|
+
failure,
|
|
185
|
+
reusableArtifactRefs: artifactEvidence.reusableArtifactRefs,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
export async function recoverReconstructFailedRunStatus(args) {
|
|
189
|
+
const typedFailure = readReconstructLlmDispatchFailureError(args.error);
|
|
190
|
+
if (!typedFailure)
|
|
191
|
+
return null;
|
|
192
|
+
const runControlRef = path.join(args.sessionRoot, "reconstruct-run-control.yaml");
|
|
193
|
+
const runControlValidationRef = path.join(args.sessionRoot, "reconstruct-run-control-validation.yaml");
|
|
194
|
+
const reconciliation = await reconcileReconstructLlmDispatchFailures({
|
|
195
|
+
sessionRoot: args.sessionRoot,
|
|
196
|
+
runControlPath: runControlRef,
|
|
197
|
+
validationOutputPath: runControlValidationRef,
|
|
198
|
+
});
|
|
199
|
+
return trustedFailedSessionStatus({
|
|
200
|
+
sessionRoot: args.sessionRoot,
|
|
201
|
+
reconciliation,
|
|
202
|
+
runControlRef,
|
|
203
|
+
runControlValidationRef,
|
|
204
|
+
});
|
|
205
|
+
}
|
|
25
206
|
async function directoryExists(directoryPath) {
|
|
26
207
|
try {
|
|
27
208
|
const stat = await fs.stat(directoryPath);
|
|
@@ -61,7 +242,11 @@ export function resolveJudgeLlmConfig(args) {
|
|
|
61
242
|
// INV-MODEL-1 is keyed by MODEL provider (e.g. openai/gpt-5.5), not the
|
|
62
243
|
// runtime adapter provider (OpenAI OAuth normalizes to codex). Check the
|
|
63
244
|
// model provider so a supported judge model is not spuriously degraded.
|
|
64
|
-
const supported = isSupportedModelRoute(args.judgeModelProvider, candidate.model_id, args.registry
|
|
245
|
+
const supported = isSupportedModelRoute(args.judgeModelProvider, candidate.model_id, args.registry,
|
|
246
|
+
// Judge adoption is a NAMED non-settings dispatch (design §2.3): a
|
|
247
|
+
// role-restricted entry (e.g. synthesize-only) must not be adoptable
|
|
248
|
+
// as the answer-support judge.
|
|
249
|
+
{ kind: "request_judge" });
|
|
65
250
|
// Credential safety: the candidate resolves on the author's provider, so its
|
|
66
251
|
// runtime provider must match the author's (guarantees api_key_env/adapter
|
|
67
252
|
// never cross providers). Uses the runtime provider, not the model provider.
|
|
@@ -85,7 +270,74 @@ export function resolveJudgeLlmConfig(args) {
|
|
|
85
270
|
judge.reasoning_effort = authorEffort;
|
|
86
271
|
else
|
|
87
272
|
delete judge.reasoning_effort;
|
|
88
|
-
|
|
273
|
+
const judgeLlmConfig = args.outputHeadroom
|
|
274
|
+
? applyOpenAIResponsesOutputHeadroom({
|
|
275
|
+
config: judge,
|
|
276
|
+
selection: args.outputHeadroom.selection,
|
|
277
|
+
headroomTokens: args.outputHeadroom.headroomTokens,
|
|
278
|
+
maxBaseOutputTokens: RECONSTRUCT_SEMANTIC_AUTHOR_MAX_BASE_OUTPUT_TOKENS,
|
|
279
|
+
modelMaxOutputTokens: supportedModelMaxOutputTokens(args.registry, args.judgeModelProvider ?? "", judge.model_id ?? ""),
|
|
280
|
+
})
|
|
281
|
+
: judge;
|
|
282
|
+
return { judgeLlmConfig, note };
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Mock-safe IDENTITY projection of the optional synthesize seat (design §5.4):
|
|
286
|
+
* carries only the dispatch-identity axes the reuse fold and census read
|
|
287
|
+
* (provider/model/effort/base_url) — deliberately NOT resolveLlmProviderConfig,
|
|
288
|
+
* which validates provider/auth combinations and resolves credentials that a
|
|
289
|
+
* mock run must not require. The identity is deterministic per seat edit, so
|
|
290
|
+
* P3's fold-rotation assertions hold under mock without any live material.
|
|
291
|
+
* (No execution_adapter under mock — the canonical fold serializes it as
|
|
292
|
+
* "default"; live runs fold the real adapter.)
|
|
293
|
+
*/
|
|
294
|
+
export function synthesizeSeatIdentityProjection(selection) {
|
|
295
|
+
return {
|
|
296
|
+
...(selection.provider !== undefined
|
|
297
|
+
? { provider: selection.provider }
|
|
298
|
+
: {}),
|
|
299
|
+
...(selection.model !== undefined ? { model_id: selection.model } : {}),
|
|
300
|
+
...(selection.effort !== undefined
|
|
301
|
+
? { reasoning_effort: selection.effort }
|
|
302
|
+
: {}),
|
|
303
|
+
...(selection.base_url !== undefined
|
|
304
|
+
? { base_url: selection.base_url }
|
|
305
|
+
: {}),
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* The ONE deterministic seam from post-chain settings to the factory's
|
|
310
|
+
* semantic-map wiring (design §5.4/§5.5): opt-in read, single seat read
|
|
311
|
+
* (resolveOptionalReconstructActorLlmSettings), live provider completion vs
|
|
312
|
+
* mock identity projection, and the dormant-seat honesty note. Coverage is
|
|
313
|
+
* two-layered: unit tests exercise this function over resolved settings, and
|
|
314
|
+
* the seam→factory CONSUMPTION edge is bound by the mock E2Es — the dormant
|
|
315
|
+
* branch via the N11 note, the active branch via the P3 census
|
|
316
|
+
* synthesize_model_identity assertion (dropping either factory spread at the
|
|
317
|
+
* runReconstruct call site fails P3).
|
|
318
|
+
*/
|
|
319
|
+
export function resolveSemanticMapSynthesizeWiring(args) {
|
|
320
|
+
const enabled = isReconstructSemanticMapAuthoringEnabled(args.settings);
|
|
321
|
+
const seat = resolveOptionalReconstructActorLlmSettings(args.settings, "semantic_map_synthesize");
|
|
322
|
+
if (seat === undefined)
|
|
323
|
+
return { enableSemanticMapAuthoring: enabled };
|
|
324
|
+
if (!enabled) {
|
|
325
|
+
return {
|
|
326
|
+
enableSemanticMapAuthoring: false,
|
|
327
|
+
dormantSeatNote: "semantic_map_synthesize seat is configured but reconstruct.execution.semantic_map_authoring is off — the seat is dormant (no synthesize dispatch, not gate-validated) until the opt-in is enabled",
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
return {
|
|
331
|
+
enableSemanticMapAuthoring: true,
|
|
332
|
+
semanticMapSynthesizeLlmConfig: args.mockRealizationEnabled
|
|
333
|
+
? synthesizeSeatIdentityProjection(seat)
|
|
334
|
+
: resolveLlmProviderConfig({
|
|
335
|
+
config: { llm: seat },
|
|
336
|
+
...(args.llmEffortOverride
|
|
337
|
+
? { cliOverrides: args.llmEffortOverride }
|
|
338
|
+
: {}),
|
|
339
|
+
}),
|
|
340
|
+
};
|
|
89
341
|
}
|
|
90
342
|
function dateStamp() {
|
|
91
343
|
return new Date().toISOString().slice(0, 10).replace(/-/g, "");
|
|
@@ -170,15 +422,20 @@ function deriveReconstructProgress(args) {
|
|
|
170
422
|
});
|
|
171
423
|
const lastReachedStage = [...stages].reverse().find((stage) => stage.state !== "pending") ??
|
|
172
424
|
stages[0];
|
|
425
|
+
// Terminality (completed / graceful-blocked / graceful-limited) is judged once, via the single
|
|
426
|
+
// projection (design §16.7). A graceful terminal is terminal for polling (stop) but not
|
|
427
|
+
// "completed" — its liveness state stays "halted_or_partial" while the poll interval goes null.
|
|
428
|
+
const terminalStatus = reconstructTerminalStatus(args.record);
|
|
429
|
+
const isCompleted = terminalStatus === "completed";
|
|
430
|
+
const isGracefulTerminal = terminalStatus === "blocked" || terminalStatus === "limited";
|
|
431
|
+
const isTerminal = isCompleted || isGracefulTerminal;
|
|
173
432
|
return {
|
|
174
433
|
executionProfile: args.runManifest?.execution_profile ?? null,
|
|
175
434
|
currentStageId: lastReachedStage.stageId,
|
|
176
435
|
stageCount: RECONSTRUCT_STAGE_IDS.length,
|
|
177
436
|
liveness: {
|
|
178
|
-
state:
|
|
179
|
-
|
|
180
|
-
: "halted_or_partial",
|
|
181
|
-
recommendedPollIntervalMs: args.record.record_stage === "completed" ? null : 1000,
|
|
437
|
+
state: isCompleted ? "completed" : "halted_or_partial",
|
|
438
|
+
recommendedPollIntervalMs: isTerminal ? null : 1000,
|
|
182
439
|
},
|
|
183
440
|
countSummary: {
|
|
184
441
|
sourceObservationCount: args.metrics?.source_observation_count ?? null,
|
|
@@ -223,6 +480,23 @@ function recordArtifactRefsFromPreparation(refs) {
|
|
|
223
480
|
source_observations: refs.source_observations,
|
|
224
481
|
};
|
|
225
482
|
}
|
|
483
|
+
export async function tryCreateEligiblePrimarySealedDispatchCapability(args) {
|
|
484
|
+
const selection = normalizeLlmModelSwitcher(args.llm);
|
|
485
|
+
if (!selection ||
|
|
486
|
+
selection.auth !== "api_key" ||
|
|
487
|
+
selection.execution_route !== "direct_model_call" ||
|
|
488
|
+
(selection.execution_adapter !== "openai_sdk" &&
|
|
489
|
+
selection.execution_adapter !== "anthropic_sdk") ||
|
|
490
|
+
selection.base_url !== undefined) {
|
|
491
|
+
return undefined;
|
|
492
|
+
}
|
|
493
|
+
try {
|
|
494
|
+
return await createSealedDispatchCapability(args);
|
|
495
|
+
}
|
|
496
|
+
catch {
|
|
497
|
+
return undefined;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
226
500
|
export function createOntoReconstructCoreApi(options = {}) {
|
|
227
501
|
const ontoHome = resolveOntoHome(options.ontoHome);
|
|
228
502
|
return {
|
|
@@ -239,6 +513,11 @@ export function createOntoReconstructCoreApi(options = {}) {
|
|
|
239
513
|
const sessionRoot = request.sessionRoot
|
|
240
514
|
? resolveFromBase(projectRoot, request.sessionRoot)
|
|
241
515
|
: createDefaultSessionRoot(projectRoot);
|
|
516
|
+
await assertPathInsideRoot({
|
|
517
|
+
root: projectRoot,
|
|
518
|
+
candidate: sessionRoot,
|
|
519
|
+
label: "reconstruct sessionRoot",
|
|
520
|
+
});
|
|
242
521
|
const profilesRoot = await resolveProfilesRoot({
|
|
243
522
|
projectRoot,
|
|
244
523
|
...(request.profilesRoot
|
|
@@ -285,6 +564,11 @@ export function createOntoReconstructCoreApi(options = {}) {
|
|
|
285
564
|
const sessionRoot = request.sessionRoot
|
|
286
565
|
? resolveFromBase(projectRoot, request.sessionRoot)
|
|
287
566
|
: createDefaultSessionRoot(projectRoot);
|
|
567
|
+
await assertPathInsideRoot({
|
|
568
|
+
root: projectRoot,
|
|
569
|
+
candidate: sessionRoot,
|
|
570
|
+
label: "reconstruct sessionRoot",
|
|
571
|
+
});
|
|
288
572
|
const profilesRoot = await resolveProfilesRoot({
|
|
289
573
|
projectRoot,
|
|
290
574
|
...(request.profilesRoot
|
|
@@ -294,6 +578,10 @@ export function createOntoReconstructCoreApi(options = {}) {
|
|
|
294
578
|
});
|
|
295
579
|
const targetRefs = request.targetRefs.map((targetRef) => resolveFromBase(projectRoot, targetRef));
|
|
296
580
|
const settings = await resolveSettingsChain(ontoHome ?? projectRoot, projectRoot);
|
|
581
|
+
await assertDispatchFallbackSessionAdmission({
|
|
582
|
+
sessionRoot,
|
|
583
|
+
enabled: settings.reconstruct?.execution?.dispatch_fallback?.enabled === true,
|
|
584
|
+
});
|
|
297
585
|
const semanticAuthorRealization = request.semanticAuthorRealization ?? "direct_call";
|
|
298
586
|
const confirmationProviderRealization = request.confirmationProviderRealization ?? "direct_call";
|
|
299
587
|
if (request.domain) {
|
|
@@ -313,14 +601,20 @@ export function createOntoReconstructCoreApi(options = {}) {
|
|
|
313
601
|
const llmEffortOverride = request.llmEffort
|
|
314
602
|
? { reasoning_effort: request.llmEffort }
|
|
315
603
|
: undefined;
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
604
|
+
// The semantic_author actor settings (non-mock). The MODEL provider here
|
|
605
|
+
// (e.g. "openai") is the supported-models registry key, DISTINCT from the
|
|
606
|
+
// resolved RUNTIME provider (openai OAuth resolves to "codex"). The document
|
|
607
|
+
// projection-budget lookup keys on the model provider so the default
|
|
608
|
+
// gpt-5.5 OAuth seat resolves (see deriveDocumentExcerptProjectionBudget).
|
|
609
|
+
const semanticAuthorActorLlm = mockRealizationEnabled
|
|
610
|
+
? null
|
|
611
|
+
: resolveReconstructActorLlmSettings(settings, "semantic_author");
|
|
612
|
+
let semanticAuthorLlmConfig = semanticAuthorActorLlm
|
|
613
|
+
? resolveLlmProviderConfig({
|
|
614
|
+
config: { llm: semanticAuthorActorLlm },
|
|
322
615
|
...(llmEffortOverride ? { cliOverrides: llmEffortOverride } : {}),
|
|
323
|
-
})
|
|
616
|
+
})
|
|
617
|
+
: {};
|
|
324
618
|
const confirmationProviderLlmConfig = mockRealizationEnabled
|
|
325
619
|
? {}
|
|
326
620
|
: resolveLlmProviderConfig({
|
|
@@ -329,6 +623,150 @@ export function createOntoReconstructCoreApi(options = {}) {
|
|
|
329
623
|
},
|
|
330
624
|
...(llmEffortOverride ? { cliOverrides: llmEffortOverride } : {}),
|
|
331
625
|
});
|
|
626
|
+
// The supported-models registry (non-mock only): loaded once and shared by
|
|
627
|
+
// the judge-override support check and the document projection-budget
|
|
628
|
+
// lookup. Mock realization makes no real provider calls, so it stays
|
|
629
|
+
// decoupled from the install authority file (C6).
|
|
630
|
+
const supportedModelRegistry = mockRealizationEnabled
|
|
631
|
+
? null
|
|
632
|
+
: loadSupportedModelRegistry();
|
|
633
|
+
const semanticAuthorLlmRuntime = mockRealizationEnabled
|
|
634
|
+
? undefined
|
|
635
|
+
: resolveReconstructSemanticAuthorLlmRuntimeSettings(settings);
|
|
636
|
+
if (semanticAuthorLlmRuntime && semanticAuthorActorLlm) {
|
|
637
|
+
const selection = normalizeLlmModelSwitcher(semanticAuthorActorLlm);
|
|
638
|
+
if (!selection) {
|
|
639
|
+
throw new Error("semantic_author output headroom requires a resolved LLM selection.");
|
|
640
|
+
}
|
|
641
|
+
semanticAuthorLlmConfig = applyOpenAIResponsesOutputHeadroom({
|
|
642
|
+
config: semanticAuthorLlmConfig,
|
|
643
|
+
selection,
|
|
644
|
+
headroomTokens: semanticAuthorLlmRuntime.openai_responses_output_headroom_tokens,
|
|
645
|
+
maxBaseOutputTokens: RECONSTRUCT_SEMANTIC_AUTHOR_MAX_BASE_OUTPUT_TOKENS,
|
|
646
|
+
modelMaxOutputTokens: supportedModelMaxOutputTokens(supportedModelRegistry, selection.model_provider, semanticAuthorLlmConfig.model_id ?? selection.model_id ?? ""),
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
// Semantic-map authoring opt-in + optional synthesize seat (INV-MODEL-1
|
|
650
|
+
// role-aware design §5.4/§5.5): ONE deterministic seam owns the wiring
|
|
651
|
+
// (resolveSemanticMapSynthesizeWiring) — live completes the seat into a
|
|
652
|
+
// provider config (own auth/adapter, cross-provider; the request
|
|
653
|
+
// llmEffort pin applies as cliOverrides, so pin > seat effort), mock
|
|
654
|
+
// takes an identity-only projection (no auth material required).
|
|
655
|
+
const semanticMapWiring = resolveSemanticMapSynthesizeWiring({
|
|
656
|
+
settings,
|
|
657
|
+
mockRealizationEnabled,
|
|
658
|
+
llmEffortOverride,
|
|
659
|
+
});
|
|
660
|
+
// Single seed-stage document projection budget (chars), derived once from
|
|
661
|
+
// the semantic author's MODEL window.
|
|
662
|
+
const documentExcerptProjectionBudget = supportedModelRegistry
|
|
663
|
+
? deriveDocumentExcerptProjectionBudget({
|
|
664
|
+
...(semanticAuthorActorLlm?.provider
|
|
665
|
+
? { provider: semanticAuthorActorLlm.provider }
|
|
666
|
+
: {}),
|
|
667
|
+
...(semanticAuthorLlmConfig.model_id
|
|
668
|
+
? { modelId: semanticAuthorLlmConfig.model_id }
|
|
669
|
+
: {}),
|
|
670
|
+
}, supportedModelRegistry)
|
|
671
|
+
: DOCUMENT_EXCERPT_PROJECTION_FLOOR;
|
|
672
|
+
const dispatchFallbackSettings = settings.reconstruct?.execution?.dispatch_fallback;
|
|
673
|
+
const dispatchBreakerSettings = completeDispatchBreakerSettings(settings.reconstruct?.execution?.dispatch_breaker);
|
|
674
|
+
if (semanticAuthorLlmRuntime &&
|
|
675
|
+
dispatchFallbackSettings?.enabled === true) {
|
|
676
|
+
throw new Error("reconstruct output headroom cannot be combined with dispatch_fallback until the sealed semantic-map route preserves the same output-budget and typed-incomplete contract.");
|
|
677
|
+
}
|
|
678
|
+
let dispatchFallbackRuntime;
|
|
679
|
+
let dispatchFallbackTelemetry;
|
|
680
|
+
if (dispatchFallbackSettings?.enabled === true) {
|
|
681
|
+
if (!dispatchBreakerSettings.enabled) {
|
|
682
|
+
throw new Error("reconstruct dispatch_fallback requires reconstruct.execution.dispatch_breaker.enabled=true.");
|
|
683
|
+
}
|
|
684
|
+
if (mockRealizationEnabled) {
|
|
685
|
+
throw new Error("reconstruct dispatch_fallback requires the live sealed SDK path; mock realization is not product evidence.");
|
|
686
|
+
}
|
|
687
|
+
if (!semanticMapWiring.enableSemanticMapAuthoring) {
|
|
688
|
+
throw new Error("reconstruct dispatch_fallback requires reconstruct.execution.semantic_map_authoring=true.");
|
|
689
|
+
}
|
|
690
|
+
const effectiveEffort = request.llmEffort;
|
|
691
|
+
const primarySynthesizeLlm = {
|
|
692
|
+
...(resolveOptionalReconstructActorLlmSettings(settings, "semantic_map_synthesize") ?? resolveReconstructActorLlmSettings(settings, "semantic_author")),
|
|
693
|
+
...(effectiveEffort ? { effort: effectiveEffort } : {}),
|
|
694
|
+
};
|
|
695
|
+
const primaryVerifyLlm = {
|
|
696
|
+
...resolveReconstructActorLlmSettings(settings, "semantic_author"),
|
|
697
|
+
...(effectiveEffort ? { effort: effectiveEffort } : {}),
|
|
698
|
+
};
|
|
699
|
+
const fallbackLlm = {
|
|
700
|
+
...dispatchFallbackSettings.llm,
|
|
701
|
+
...(effectiveEffort ? { effort: effectiveEffort } : {}),
|
|
702
|
+
};
|
|
703
|
+
const [primarySynthesize, primaryVerify, fallbackSynthesize, fallbackVerify] = await Promise.all([
|
|
704
|
+
tryCreateEligiblePrimarySealedDispatchCapability({
|
|
705
|
+
llm: primarySynthesizeLlm,
|
|
706
|
+
operation: "semantic_map_synthesize",
|
|
707
|
+
}),
|
|
708
|
+
tryCreateEligiblePrimarySealedDispatchCapability({
|
|
709
|
+
llm: primaryVerifyLlm,
|
|
710
|
+
operation: "semantic_map_verify",
|
|
711
|
+
}),
|
|
712
|
+
createSealedDispatchCapability({
|
|
713
|
+
llm: fallbackLlm,
|
|
714
|
+
operation: "semantic_map_synthesize",
|
|
715
|
+
}),
|
|
716
|
+
createSealedDispatchCapability({
|
|
717
|
+
llm: fallbackLlm,
|
|
718
|
+
operation: "semantic_map_verify",
|
|
719
|
+
}),
|
|
720
|
+
]);
|
|
721
|
+
const eligiblePrimaryCapabilities = [
|
|
722
|
+
primarySynthesize,
|
|
723
|
+
primaryVerify,
|
|
724
|
+
].filter((capability) => capability !== undefined);
|
|
725
|
+
if (eligiblePrimaryCapabilities.length === 0) {
|
|
726
|
+
throw new Error("reconstruct dispatch_fallback requires at least one eligible sealed primary semantic-map operation.");
|
|
727
|
+
}
|
|
728
|
+
const eligiblePrimaryProviders = new Set(eligiblePrimaryCapabilities.map((capability) => capability.public_descriptor.model_provider));
|
|
729
|
+
if ([...eligiblePrimaryProviders].every((provider) => provider === fallbackSynthesize.public_descriptor.model_provider) ||
|
|
730
|
+
fallbackSynthesize.public_descriptor.model_provider !==
|
|
731
|
+
fallbackVerify.public_descriptor.model_provider) {
|
|
732
|
+
throw new Error("reconstruct dispatch_fallback requires one alternate provider for the complete fallback pair.");
|
|
733
|
+
}
|
|
734
|
+
const accounting = new SemanticMapDispatchAccounting();
|
|
735
|
+
dispatchFallbackTelemetry =
|
|
736
|
+
createReconstructExecutionTelemetryCollector({
|
|
737
|
+
nullMixedRouteProjection: true,
|
|
738
|
+
});
|
|
739
|
+
const fallbackLlmConfig = resolveLlmProviderConfig({
|
|
740
|
+
config: { llm: fallbackLlm },
|
|
741
|
+
});
|
|
742
|
+
const fallbackDirectiveAuthor = createDirectCallReconstructDirectiveAuthor({
|
|
743
|
+
llmConfig: fallbackLlmConfig,
|
|
744
|
+
semanticMapSynthesizeLlmConfig: fallbackLlmConfig,
|
|
745
|
+
enableSemanticMapAuthoring: true,
|
|
746
|
+
semanticMapDispatchCapabilities: {
|
|
747
|
+
synthesize: fallbackSynthesize,
|
|
748
|
+
verify: fallbackVerify,
|
|
749
|
+
accounting,
|
|
750
|
+
executionSource: "fallback",
|
|
751
|
+
allowParseRepair: false,
|
|
752
|
+
maxTransportAttempts: 1,
|
|
753
|
+
},
|
|
754
|
+
documentExcerptProjectionBudget,
|
|
755
|
+
executionTelemetry: dispatchFallbackTelemetry,
|
|
756
|
+
});
|
|
757
|
+
dispatchFallbackRuntime = {
|
|
758
|
+
accounting,
|
|
759
|
+
primary: {
|
|
760
|
+
...(primarySynthesize ? { synthesize: primarySynthesize } : {}),
|
|
761
|
+
...(primaryVerify ? { verify: primaryVerify } : {}),
|
|
762
|
+
},
|
|
763
|
+
fallback: {
|
|
764
|
+
synthesize: fallbackSynthesize,
|
|
765
|
+
verify: fallbackVerify,
|
|
766
|
+
directiveAuthor: fallbackDirectiveAuthor,
|
|
767
|
+
},
|
|
768
|
+
};
|
|
769
|
+
}
|
|
332
770
|
// Opt-in per-stage JUDGE config (semantic-independence lever). Default =
|
|
333
771
|
// inherit the semantic-author config (judgeLlmConfig undefined → no change,
|
|
334
772
|
// zero regression). A judgeModel override resolves ON THE AUTHOR'S PROVIDER
|
|
@@ -347,7 +785,7 @@ export function createOntoReconstructCoreApi(options = {}) {
|
|
|
347
785
|
const judgeAuthorActorLlm = !mockRealizationEnabled && request.judgeModel
|
|
348
786
|
? resolveReconstructActorLlmSettings(settings, "semantic_author")
|
|
349
787
|
: null;
|
|
350
|
-
const
|
|
788
|
+
const judgeModelCandidateBase = judgeAuthorActorLlm
|
|
351
789
|
? resolveLlmProviderConfig({
|
|
352
790
|
config: { llm: judgeAuthorActorLlm },
|
|
353
791
|
cliOverrides: { model: request.judgeModel },
|
|
@@ -360,13 +798,24 @@ export function createOntoReconstructCoreApi(options = {}) {
|
|
|
360
798
|
...(request.judgeLlmEffort
|
|
361
799
|
? { judgeLlmEffort: request.judgeLlmEffort }
|
|
362
800
|
: {}),
|
|
363
|
-
judgeModelCandidate,
|
|
801
|
+
judgeModelCandidate: judgeModelCandidateBase,
|
|
364
802
|
// Registry key is the MODEL provider (e.g. openai), not the runtime
|
|
365
803
|
// adapter (openai OAuth → codex). The judge uses the author's provider.
|
|
366
804
|
...(judgeAuthorActorLlm?.provider
|
|
367
805
|
? { judgeModelProvider: judgeAuthorActorLlm.provider }
|
|
368
806
|
: {}),
|
|
369
|
-
|
|
807
|
+
...(judgeAuthorActorLlm && semanticAuthorLlmRuntime
|
|
808
|
+
? {
|
|
809
|
+
outputHeadroom: {
|
|
810
|
+
selection: normalizeLlmModelSwitcher(judgeAuthorActorLlm),
|
|
811
|
+
headroomTokens: semanticAuthorLlmRuntime
|
|
812
|
+
.openai_responses_output_headroom_tokens,
|
|
813
|
+
},
|
|
814
|
+
}
|
|
815
|
+
: {}),
|
|
816
|
+
// Non-null in this branch: both this and supportedModelRegistry gate on
|
|
817
|
+
// the same mockRealizationEnabled check.
|
|
818
|
+
registry: supportedModelRegistry,
|
|
370
819
|
});
|
|
371
820
|
const judgeLlmConfig = judgeResolution.judgeLlmConfig;
|
|
372
821
|
if (!mockRealizationEnabled)
|
|
@@ -374,6 +823,40 @@ export function createOntoReconstructCoreApi(options = {}) {
|
|
|
374
823
|
const directiveAuthor = createDirectCallReconstructDirectiveAuthor({
|
|
375
824
|
llmConfig: semanticAuthorLlmConfig,
|
|
376
825
|
...(judgeLlmConfig ? { judgeLlmConfig } : {}),
|
|
826
|
+
// Production opt-in + per-role synthesize override (design §5.5/§5.2)
|
|
827
|
+
// from the single wiring seam. Opt-in absent/false = pair not
|
|
828
|
+
// attached, stage skips — byte-parity with today. A dormant seat
|
|
829
|
+
// (configured, opt-in off) is surfaced via the honest note below.
|
|
830
|
+
...(semanticMapWiring.enableSemanticMapAuthoring
|
|
831
|
+
? { enableSemanticMapAuthoring: true }
|
|
832
|
+
: {}),
|
|
833
|
+
...(semanticMapWiring.semanticMapSynthesizeLlmConfig
|
|
834
|
+
? {
|
|
835
|
+
semanticMapSynthesizeLlmConfig: semanticMapWiring.semanticMapSynthesizeLlmConfig,
|
|
836
|
+
}
|
|
837
|
+
: {}),
|
|
838
|
+
documentExcerptProjectionBudget,
|
|
839
|
+
...(dispatchFallbackRuntime
|
|
840
|
+
? {
|
|
841
|
+
semanticMapDispatchCapabilities: {
|
|
842
|
+
...(dispatchFallbackRuntime.primary.synthesize
|
|
843
|
+
? {
|
|
844
|
+
synthesize: dispatchFallbackRuntime.primary.synthesize,
|
|
845
|
+
}
|
|
846
|
+
: {}),
|
|
847
|
+
...(dispatchFallbackRuntime.primary.verify
|
|
848
|
+
? { verify: dispatchFallbackRuntime.primary.verify }
|
|
849
|
+
: {}),
|
|
850
|
+
accounting: dispatchFallbackRuntime.accounting,
|
|
851
|
+
executionSource: "primary",
|
|
852
|
+
allowParseRepair: true,
|
|
853
|
+
maxTransportAttempts: 3,
|
|
854
|
+
},
|
|
855
|
+
}
|
|
856
|
+
: {}),
|
|
857
|
+
...(dispatchFallbackTelemetry
|
|
858
|
+
? { executionTelemetry: dispatchFallbackTelemetry }
|
|
859
|
+
: {}),
|
|
377
860
|
...(mockRealizationEnabled
|
|
378
861
|
? {
|
|
379
862
|
llmCall: callReconstructMockLlm,
|
|
@@ -414,6 +897,22 @@ export function createOntoReconstructCoreApi(options = {}) {
|
|
|
414
897
|
stageId: "answer_support_judgment",
|
|
415
898
|
});
|
|
416
899
|
}
|
|
900
|
+
if (semanticMapWiring.dormantSeatNote) {
|
|
901
|
+
// Honest accounting (design §5.4, N11 / judge-note precedent): the
|
|
902
|
+
// operator configured a synthesize seat but the semantic-map authoring
|
|
903
|
+
// opt-in is off, so the seat is DORMANT — no synthesize dispatch will
|
|
904
|
+
// use it and the gate deliberately excludes it (U6). Emitted BEFORE the
|
|
905
|
+
// run so the inert config is never a silent no-op. This emission binds
|
|
906
|
+
// the seam's DORMANT branch to the live path (N11); the ACTIVE branch
|
|
907
|
+
// is bound by the P3 census-identity assertion on the factory spreads.
|
|
908
|
+
appendRuntimeStatusEventSync({
|
|
909
|
+
pipeline: "reconstruct",
|
|
910
|
+
sessionRoot,
|
|
911
|
+
sourceLabel: "onto_reconstruct",
|
|
912
|
+
message: semanticMapWiring.dormantSeatNote,
|
|
913
|
+
stageId: "start",
|
|
914
|
+
});
|
|
915
|
+
}
|
|
417
916
|
const watcherResult = spawnRuntimeWatcherPane(projectRoot, sessionRoot, ontoHome);
|
|
418
917
|
appendRuntimeStatusEventSync({
|
|
419
918
|
pipeline: "reconstruct",
|
|
@@ -444,6 +943,17 @@ export function createOntoReconstructCoreApi(options = {}) {
|
|
|
444
943
|
confirmationProviderRealization,
|
|
445
944
|
directiveAuthor,
|
|
446
945
|
confirmationProvider,
|
|
946
|
+
// 설계 B: settings가 유일 권위(INV-CFG-1) — 기본 OFF, 완성값은
|
|
947
|
+
// settings chain이 채운다.
|
|
948
|
+
dispatchBreaker: dispatchBreakerSettings,
|
|
949
|
+
...(settings.reconstruct?.execution?.dispatch_fallback
|
|
950
|
+
? {
|
|
951
|
+
dispatchFallback: settings.reconstruct.execution.dispatch_fallback,
|
|
952
|
+
}
|
|
953
|
+
: {}),
|
|
954
|
+
...(dispatchFallbackRuntime
|
|
955
|
+
? { dispatchFallbackRuntime }
|
|
956
|
+
: {}),
|
|
447
957
|
filesystemAllowedRoots: request.filesystemAllowedRoots?.map((root) => resolveFromBase(projectRoot, root)) ??
|
|
448
958
|
[projectRoot],
|
|
449
959
|
}));
|
|
@@ -464,6 +974,12 @@ export function createOntoReconstructCoreApi(options = {}) {
|
|
|
464
974
|
message: `reconstruct session failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
465
975
|
stageId: "complete",
|
|
466
976
|
});
|
|
977
|
+
const failedStatus = await recoverReconstructFailedRunStatus({
|
|
978
|
+
sessionRoot,
|
|
979
|
+
error,
|
|
980
|
+
});
|
|
981
|
+
if (failedStatus)
|
|
982
|
+
return failedStatus;
|
|
467
983
|
throw error;
|
|
468
984
|
}
|
|
469
985
|
},
|
|
@@ -510,7 +1026,33 @@ export function createOntoReconstructCoreApi(options = {}) {
|
|
|
510
1026
|
},
|
|
511
1027
|
async getRunStatus(sessionRoot) {
|
|
512
1028
|
const resolvedSessionRoot = path.resolve(sessionRoot);
|
|
513
|
-
const
|
|
1029
|
+
const runControlRef = path.join(resolvedSessionRoot, "reconstruct-run-control.yaml");
|
|
1030
|
+
const runControlValidationRef = path.join(resolvedSessionRoot, "reconstruct-run-control-validation.yaml");
|
|
1031
|
+
const reconciliation = await reconcileReconstructLlmDispatchFailures({
|
|
1032
|
+
sessionRoot: resolvedSessionRoot,
|
|
1033
|
+
runControlPath: runControlRef,
|
|
1034
|
+
validationOutputPath: runControlValidationRef,
|
|
1035
|
+
});
|
|
1036
|
+
const blockedPartialWrite = reconciliation
|
|
1037
|
+
? [...reconciliation.runControl.resume_rows].reverse().find((row) => row.resume_decision === "blocked_partial_write")
|
|
1038
|
+
: undefined;
|
|
1039
|
+
if (blockedPartialWrite) {
|
|
1040
|
+
throw new Error(`reconstruct session is blocked by a partial failure write: ${blockedPartialWrite.stale_artifact_refs.join(",") || "unknown ref"}`);
|
|
1041
|
+
}
|
|
1042
|
+
const failedStatus = await trustedFailedSessionStatus({
|
|
1043
|
+
sessionRoot: resolvedSessionRoot,
|
|
1044
|
+
reconciliation,
|
|
1045
|
+
runControlRef,
|
|
1046
|
+
runControlValidationRef,
|
|
1047
|
+
});
|
|
1048
|
+
if (failedStatus)
|
|
1049
|
+
return failedStatus;
|
|
1050
|
+
const reconstructRecord = await readYamlArtifactIfPresent(path.join(resolvedSessionRoot, "reconstruct-record.yaml"));
|
|
1051
|
+
if (!reconstructRecord) {
|
|
1052
|
+
throw new Error(reconciliation
|
|
1053
|
+
? `reconstruct session has no readable terminal record or trusted failed terminal: ${resolvedSessionRoot}`
|
|
1054
|
+
: `reconstruct session has neither a record nor run-control: ${resolvedSessionRoot}`);
|
|
1055
|
+
}
|
|
514
1056
|
const reconstructRunManifest = await readYamlArtifactIfPresent(reconstructRecord.artifact_refs.reconstruct_run_manifest);
|
|
515
1057
|
const reconstructMetrics = await readYamlArtifactIfPresent(reconstructRecord.artifact_refs.reconstruct_metrics);
|
|
516
1058
|
const claimProjection = await readYamlArtifactIfPresent(reconstructRecord.artifact_refs.claim_projection);
|
|
@@ -526,7 +1068,7 @@ export function createOntoReconstructCoreApi(options = {}) {
|
|
|
526
1068
|
return {
|
|
527
1069
|
sessionId: path.basename(resolvedSessionRoot),
|
|
528
1070
|
sessionRoot: resolvedSessionRoot,
|
|
529
|
-
status: reconstructRecord
|
|
1071
|
+
status: reconstructTerminalStatus(reconstructRecord),
|
|
530
1072
|
artifactRefs: reconstructRecord.artifact_refs,
|
|
531
1073
|
claimProjection,
|
|
532
1074
|
claimProjectionValidation,
|
|
@@ -541,6 +1083,15 @@ export function createOntoReconstructCoreApi(options = {}) {
|
|
|
541
1083
|
},
|
|
542
1084
|
async getRunResult(sessionRoot) {
|
|
543
1085
|
const status = await this.getRunStatus(sessionRoot);
|
|
1086
|
+
if (status.status === "failed") {
|
|
1087
|
+
return {
|
|
1088
|
+
...status,
|
|
1089
|
+
finalOutputPath: null,
|
|
1090
|
+
finalOutputText: null,
|
|
1091
|
+
reconstructRunManifestPath: null,
|
|
1092
|
+
reconstructRunManifest: null,
|
|
1093
|
+
};
|
|
1094
|
+
}
|
|
544
1095
|
const finalOutputPath = status.reconstructRecord.artifact_refs.final_output;
|
|
545
1096
|
const reconstructRunManifestPath = status.reconstructRecord.artifact_refs.reconstruct_run_manifest;
|
|
546
1097
|
return {
|