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
|
@@ -11,14 +11,17 @@ import { executeReviewPromptExecution, } from "./run-review-prompt-execution.js"
|
|
|
11
11
|
import { startReviewSession } from "./start-review-session.js";
|
|
12
12
|
import { spawnWatcherPane } from "./spawn-watcher.js";
|
|
13
13
|
import { generateReviewSessionId } from "../review/materializers.js";
|
|
14
|
-
import { fileExists, hasOptionFlag, normalizeDomainValue, readMultiOptionValuesFromArgv, readYamlDocument, readSingleOptionValueFromArgv, } from "../review/review-artifact-utils.js";
|
|
14
|
+
import { fileExists, hasOptionFlag, isDeprecatedDomainAlias, normalizeDomainValue, readMultiOptionValuesFromArgv, readYamlDocument, readSingleOptionValueFromArgv, } from "../review/review-artifact-utils.js";
|
|
15
15
|
import { printOntoReleaseChannelNotice } from "../release-channel/release-channel.js";
|
|
16
|
-
import { resolveOntoHome } from "../discovery/onto-home.js";
|
|
16
|
+
import { isOntoRoot, resolveOntoHome } from "../discovery/onto-home.js";
|
|
17
|
+
import { resolveInstallationPath } from "../discovery/installation-paths.js";
|
|
17
18
|
import { resolveSettingsChain } from "../discovery/settings-chain.js";
|
|
18
19
|
import { loadCoreLensRegistry } from "../discovery/lens-registry.js";
|
|
20
|
+
import { isPathInsideRoot, isPathInsideRootRealpathAwareSync, } from "../path-boundary.js";
|
|
19
21
|
import { normalizeLlmModelSwitcher } from "../llm/model-switcher.js";
|
|
20
22
|
import { resolveReviewExecutionProfile, } from "../review/review-execution-profile.js";
|
|
21
23
|
import { buildReviewExecutionRoute } from "../review/review-execution-route.js";
|
|
24
|
+
import { prepareReviewInvocationArgv, runReviewInvocationArgv, } from "../review/review-invocation-runner.js";
|
|
22
25
|
import { readValidatedReviewRecord } from "../review/review-record-validation.js";
|
|
23
26
|
import { readReviewResultClassification } from "../review/review-result-classification.js";
|
|
24
27
|
import { createStructuredFailureRecord, ReviewStructuredFailureError, writeAndThrowStructuredFailureRecord, } from "../review/failure-records.js";
|
|
@@ -124,7 +127,7 @@ function resolveDirectExecutorPath(realization, ontoHome) {
|
|
|
124
127
|
}
|
|
125
128
|
return null;
|
|
126
129
|
}
|
|
127
|
-
function buildExecutorConfigFromRealization(realization, ontoHome) {
|
|
130
|
+
export function buildExecutorConfigFromRealization(realization, ontoHome) {
|
|
128
131
|
if (typeof ontoHome === "string" && ontoHome.length > 0) {
|
|
129
132
|
const direct = resolveDirectExecutorPath(realization, ontoHome);
|
|
130
133
|
if (direct) {
|
|
@@ -139,7 +142,7 @@ function buildExecutorConfigFromRealization(realization, ontoHome) {
|
|
|
139
142
|
}
|
|
140
143
|
throw new Error("ontoHome is required to resolve review executor script paths.");
|
|
141
144
|
}
|
|
142
|
-
function inferExecutorRealization(config) {
|
|
145
|
+
export function inferExecutorRealization(config) {
|
|
143
146
|
const joinedArgs = config.args.join(" ");
|
|
144
147
|
for (const [realization, filename] of Object.entries(EXECUTOR_SCRIPT_FILENAMES)) {
|
|
145
148
|
if (joinedArgs.includes(filename)) {
|
|
@@ -179,10 +182,6 @@ function applyExecutorOverrideToProfile(profile, argv) {
|
|
|
179
182
|
}
|
|
180
183
|
return profile;
|
|
181
184
|
}
|
|
182
|
-
function isInsidePath(root, candidate) {
|
|
183
|
-
const relative = path.relative(path.resolve(root), path.resolve(candidate));
|
|
184
|
-
return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative));
|
|
185
|
-
}
|
|
186
185
|
function displayPathFromProject(projectRoot, candidate) {
|
|
187
186
|
if (!path.isAbsolute(candidate))
|
|
188
187
|
return candidate;
|
|
@@ -217,7 +216,7 @@ function renderReviewStartPreview(args) {
|
|
|
217
216
|
const { projectRoot, sessionRoot, setup, reviewExecutionProfile } = args;
|
|
218
217
|
const inputs = setup.resolvedInvokeInputs;
|
|
219
218
|
const targetPath = path.resolve(inputs.targetPath);
|
|
220
|
-
const boundaryLabel =
|
|
219
|
+
const boundaryLabel = isPathInsideRoot(projectRoot, targetPath)
|
|
221
220
|
? "project"
|
|
222
221
|
: "external";
|
|
223
222
|
const projectSettingsPath = path.join(projectRoot, ".onto", "settings.json");
|
|
@@ -246,6 +245,7 @@ function renderReviewStartPreview(args) {
|
|
|
246
245
|
` selected: ${selectedDomain}`,
|
|
247
246
|
` selection_mode: ${inputs.domainSelectionMode}`,
|
|
248
247
|
` selection_required: ${String(inputs.domainSelectionRequired)}`,
|
|
248
|
+
` selection_reason: ${inputs.domainSelectionReason}`,
|
|
249
249
|
"review_lenses:",
|
|
250
250
|
` review_mode: ${inputs.reviewMode}`,
|
|
251
251
|
` lens_count: ${configuredLensIds.length}`,
|
|
@@ -337,7 +337,7 @@ function renderScreenBoundedLines(text, maxLines = 10) {
|
|
|
337
337
|
}
|
|
338
338
|
return bounded;
|
|
339
339
|
}
|
|
340
|
-
async function readReviewResultExplanationSummary(finalOutputPath) {
|
|
340
|
+
export async function readReviewResultExplanationSummary(finalOutputPath) {
|
|
341
341
|
if (!(await fileExists(finalOutputPath))) {
|
|
342
342
|
const unavailable = "- final output unavailable";
|
|
343
343
|
return {
|
|
@@ -357,7 +357,7 @@ async function readReviewResultExplanationSummary(finalOutputPath) {
|
|
|
357
357
|
screen_lines: renderScreenBoundedLines(finalReviewResult),
|
|
358
358
|
};
|
|
359
359
|
}
|
|
360
|
-
async function readReviewResultClosureSummary(sessionRoot) {
|
|
360
|
+
export async function readReviewResultClosureSummary(sessionRoot) {
|
|
361
361
|
const problemFramingPath = path.join(sessionRoot, "problem-framing.yaml");
|
|
362
362
|
const resultClassification = await readReviewResultClassification(sessionRoot);
|
|
363
363
|
const problemFraming = (await fileExists(problemFramingPath))
|
|
@@ -407,6 +407,7 @@ function renderReviewResultOverview(args) {
|
|
|
407
407
|
` target: ${args.target}`,
|
|
408
408
|
` target_scope_kind: ${args.targetScopeKind}`,
|
|
409
409
|
` domain: ${args.domain.length > 0 ? args.domain : "none"}`,
|
|
410
|
+
` domain_selection_reason: ${args.domainSelectionReason}`,
|
|
410
411
|
"coverage:",
|
|
411
412
|
` lenses: ${args.participatingLensIds.length}/${args.plannedLensIds.length} participating`,
|
|
412
413
|
` degraded_lenses: ${degraded}`,
|
|
@@ -613,7 +614,7 @@ function buildNoHostDetectedError() {
|
|
|
613
614
|
" 4. 테스트 실행은 --executor-realization mock 사용",
|
|
614
615
|
].join("\n"));
|
|
615
616
|
}
|
|
616
|
-
function resolveExecutorConfig(argv, optionPrefix, ontoConfig, ontoHome, reviewExecutionProfile, actor = "lens") {
|
|
617
|
+
export function resolveExecutorConfig(argv, optionPrefix, ontoConfig, ontoHome, reviewExecutionProfile, actor = "lens") {
|
|
617
618
|
const optionPrefixLabel = optionPrefix.length > 0 ? optionPrefix : "";
|
|
618
619
|
const actorLlmRef = reviewExecutionProfile?.[actor].llm;
|
|
619
620
|
const explicitBin = readSingleOptionValueFromArgv(argv, `${optionPrefixLabel}executor-bin`);
|
|
@@ -684,7 +685,7 @@ function assertValidLocalBaseUrl(baseUrl) {
|
|
|
684
685
|
throw new Error(`Invalid local provider base_url: ${baseUrl}`);
|
|
685
686
|
}
|
|
686
687
|
}
|
|
687
|
-
async function ensureProviderRouteReadyForDispatch(args) {
|
|
688
|
+
export async function ensureProviderRouteReadyForDispatch(args) {
|
|
688
689
|
const profile = args.reviewExecutionProfile;
|
|
689
690
|
if (profile.worker_executor === "mock") {
|
|
690
691
|
return;
|
|
@@ -855,26 +856,6 @@ function parseHostFacingPositionals(positionals) {
|
|
|
855
856
|
intentText: [second, ...rest].filter((value) => typeof value === "string").join(" ").trim(),
|
|
856
857
|
};
|
|
857
858
|
}
|
|
858
|
-
function isPathInsideRoot(candidatePath, rootPath) {
|
|
859
|
-
let resolvedCandidate;
|
|
860
|
-
let resolvedRoot;
|
|
861
|
-
try {
|
|
862
|
-
resolvedCandidate = fsSync.realpathSync(candidatePath);
|
|
863
|
-
resolvedRoot = fsSync.realpathSync(rootPath);
|
|
864
|
-
}
|
|
865
|
-
catch {
|
|
866
|
-
resolvedCandidate = path.resolve(candidatePath);
|
|
867
|
-
resolvedRoot = path.resolve(rootPath);
|
|
868
|
-
}
|
|
869
|
-
const relative = path.relative(resolvedRoot, resolvedCandidate);
|
|
870
|
-
if (relative === "") {
|
|
871
|
-
return true;
|
|
872
|
-
}
|
|
873
|
-
if (relative.startsWith("..")) {
|
|
874
|
-
return false;
|
|
875
|
-
}
|
|
876
|
-
return !path.isAbsolute(relative);
|
|
877
|
-
}
|
|
878
859
|
function normalizeFilesystemAllowedRoot(root, defaultProjectRoot) {
|
|
879
860
|
if (path.isAbsolute(root)) {
|
|
880
861
|
return path.resolve(root);
|
|
@@ -894,7 +875,7 @@ function normalizeFilesystemAllowedRoots(filesystemAllowedRoots, defaultProjectR
|
|
|
894
875
|
return deduped;
|
|
895
876
|
}
|
|
896
877
|
function isInsideAnyDeclaredFilesystemRoot(targetPath, allowedRoots) {
|
|
897
|
-
return allowedRoots.some((allowedRoot) =>
|
|
878
|
+
return allowedRoots.some((allowedRoot) => isPathInsideRootRealpathAwareSync(allowedRoot, targetPath));
|
|
898
879
|
}
|
|
899
880
|
function deriveFilesystemBoundaryFromTarget(targetPath, targetScopeKind) {
|
|
900
881
|
return targetScopeKind === "file"
|
|
@@ -960,10 +941,11 @@ function normalizeDomainToken(domainValue) {
|
|
|
960
941
|
if (trimmed.length === 0) {
|
|
961
942
|
return null;
|
|
962
943
|
}
|
|
963
|
-
|
|
944
|
+
const normalized = normalizeDomainValue(trimmed);
|
|
945
|
+
if (normalized === "none") {
|
|
964
946
|
return "@-";
|
|
965
947
|
}
|
|
966
|
-
return
|
|
948
|
+
return `@${normalized}`;
|
|
967
949
|
}
|
|
968
950
|
function collectConfiguredDomainTokens(ontoConfig) {
|
|
969
951
|
const collected = [];
|
|
@@ -996,6 +978,313 @@ function collectConfiguredDomainTokens(ontoConfig) {
|
|
|
996
978
|
pushTokenList(ontoConfig.domains);
|
|
997
979
|
return collected;
|
|
998
980
|
}
|
|
981
|
+
const DOMAIN_INFERENCE_MAX_FILE_BYTES = 64 * 1024;
|
|
982
|
+
const DOMAIN_INFERENCE_MAX_DIRECTORY_ENTRIES = 200;
|
|
983
|
+
const DOMAIN_INFERENCE_MAX_DIRECTORY_DEPTH = 3;
|
|
984
|
+
const DOMAIN_INFERENCE_MIN_SCORE = 18;
|
|
985
|
+
const DOMAIN_INFERENCE_EXCLUDED_NAMES = new Set([
|
|
986
|
+
".git",
|
|
987
|
+
"node_modules",
|
|
988
|
+
".onto/review",
|
|
989
|
+
"dist",
|
|
990
|
+
"build",
|
|
991
|
+
".next",
|
|
992
|
+
"coverage",
|
|
993
|
+
]);
|
|
994
|
+
const DOMAIN_INFERENCE_CODE_EXTENSIONS = new Set([
|
|
995
|
+
".c",
|
|
996
|
+
".cc",
|
|
997
|
+
".cpp",
|
|
998
|
+
".cs",
|
|
999
|
+
".go",
|
|
1000
|
+
".java",
|
|
1001
|
+
".js",
|
|
1002
|
+
".jsx",
|
|
1003
|
+
".kt",
|
|
1004
|
+
".mjs",
|
|
1005
|
+
".py",
|
|
1006
|
+
".rs",
|
|
1007
|
+
".swift",
|
|
1008
|
+
".ts",
|
|
1009
|
+
".tsx",
|
|
1010
|
+
]);
|
|
1011
|
+
const DOMAIN_INFERENCE_STOPWORDS = new Set([
|
|
1012
|
+
"a",
|
|
1013
|
+
"an",
|
|
1014
|
+
"and",
|
|
1015
|
+
"are",
|
|
1016
|
+
"as",
|
|
1017
|
+
"be",
|
|
1018
|
+
"by",
|
|
1019
|
+
"can",
|
|
1020
|
+
"code",
|
|
1021
|
+
"content",
|
|
1022
|
+
"data",
|
|
1023
|
+
"doc",
|
|
1024
|
+
"document",
|
|
1025
|
+
"domain",
|
|
1026
|
+
"file",
|
|
1027
|
+
"for",
|
|
1028
|
+
"from",
|
|
1029
|
+
"has",
|
|
1030
|
+
"in",
|
|
1031
|
+
"is",
|
|
1032
|
+
"it",
|
|
1033
|
+
"of",
|
|
1034
|
+
"on",
|
|
1035
|
+
"or",
|
|
1036
|
+
"review",
|
|
1037
|
+
"rule",
|
|
1038
|
+
"should",
|
|
1039
|
+
"system",
|
|
1040
|
+
"target",
|
|
1041
|
+
"that",
|
|
1042
|
+
"the",
|
|
1043
|
+
"this",
|
|
1044
|
+
"to",
|
|
1045
|
+
"with",
|
|
1046
|
+
]);
|
|
1047
|
+
function addDomainRootCandidates(args) {
|
|
1048
|
+
if (!fsSync.existsSync(args.root))
|
|
1049
|
+
return;
|
|
1050
|
+
let entries;
|
|
1051
|
+
try {
|
|
1052
|
+
entries = fsSync.readdirSync(args.root, { withFileTypes: true });
|
|
1053
|
+
}
|
|
1054
|
+
catch {
|
|
1055
|
+
return;
|
|
1056
|
+
}
|
|
1057
|
+
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
1058
|
+
for (const entry of entries) {
|
|
1059
|
+
if (!entry.isDirectory() || entry.name.startsWith("."))
|
|
1060
|
+
continue;
|
|
1061
|
+
if (isDeprecatedDomainAlias(entry.name))
|
|
1062
|
+
continue;
|
|
1063
|
+
if (args.seenIds.has(entry.name))
|
|
1064
|
+
continue;
|
|
1065
|
+
args.seenIds.add(entry.name);
|
|
1066
|
+
args.candidates.push({
|
|
1067
|
+
id: entry.name,
|
|
1068
|
+
dir: path.join(args.root, entry.name),
|
|
1069
|
+
source: args.source,
|
|
1070
|
+
});
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
function collectAvailableDomainCandidates(projectRoot, ontoHome) {
|
|
1074
|
+
const candidates = [];
|
|
1075
|
+
const seenIds = new Set();
|
|
1076
|
+
const seenRoots = new Set();
|
|
1077
|
+
const addRoot = (root, source) => {
|
|
1078
|
+
const resolvedRoot = path.resolve(root);
|
|
1079
|
+
if (seenRoots.has(resolvedRoot))
|
|
1080
|
+
return;
|
|
1081
|
+
seenRoots.add(resolvedRoot);
|
|
1082
|
+
addDomainRootCandidates({ candidates, seenIds, root: resolvedRoot, source });
|
|
1083
|
+
};
|
|
1084
|
+
addRoot(path.join(projectRoot, ".onto", "domains"), "project");
|
|
1085
|
+
addRoot(path.join(os.homedir(), ".onto", "domains"), "user");
|
|
1086
|
+
if (typeof ontoHome === "string" && ontoHome.length > 0) {
|
|
1087
|
+
try {
|
|
1088
|
+
addRoot(resolveInstallationPath("domains", ontoHome), "installation");
|
|
1089
|
+
}
|
|
1090
|
+
catch {
|
|
1091
|
+
// No installation domain seat available.
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
if (isOntoRoot(projectRoot)) {
|
|
1095
|
+
try {
|
|
1096
|
+
addRoot(resolveInstallationPath("domains", projectRoot), "dev_install");
|
|
1097
|
+
}
|
|
1098
|
+
catch {
|
|
1099
|
+
// Not a canonical install domain seat.
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
return candidates;
|
|
1103
|
+
}
|
|
1104
|
+
function tokenizeForDomainInference(text) {
|
|
1105
|
+
return text
|
|
1106
|
+
.toLowerCase()
|
|
1107
|
+
.replace(/[-_/.:]+/g, " ")
|
|
1108
|
+
.split(/[^\p{L}\p{N}]+/u)
|
|
1109
|
+
.map((token) => token.trim())
|
|
1110
|
+
.filter((token) => token.length >= 3 &&
|
|
1111
|
+
!DOMAIN_INFERENCE_STOPWORDS.has(token) &&
|
|
1112
|
+
!/^\d+$/.test(token));
|
|
1113
|
+
}
|
|
1114
|
+
async function readFilePrefix(filePath, maxBytes) {
|
|
1115
|
+
let handle;
|
|
1116
|
+
try {
|
|
1117
|
+
const stats = await fs.stat(filePath);
|
|
1118
|
+
const byteLength = Math.min(stats.size, maxBytes);
|
|
1119
|
+
if (byteLength <= 0)
|
|
1120
|
+
return "";
|
|
1121
|
+
handle = await fs.open(filePath, "r");
|
|
1122
|
+
const buffer = Buffer.alloc(byteLength);
|
|
1123
|
+
const { bytesRead } = await handle.read(buffer, 0, byteLength, 0);
|
|
1124
|
+
return buffer.subarray(0, bytesRead).toString("utf8");
|
|
1125
|
+
}
|
|
1126
|
+
catch {
|
|
1127
|
+
return "";
|
|
1128
|
+
}
|
|
1129
|
+
finally {
|
|
1130
|
+
await handle?.close();
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
async function collectDirectorySignalPaths(root, maxEntries = DOMAIN_INFERENCE_MAX_DIRECTORY_ENTRIES, maxDepth = DOMAIN_INFERENCE_MAX_DIRECTORY_DEPTH) {
|
|
1134
|
+
const collected = [];
|
|
1135
|
+
async function walk(current, depth) {
|
|
1136
|
+
if (collected.length >= maxEntries || depth > maxDepth)
|
|
1137
|
+
return;
|
|
1138
|
+
let entries;
|
|
1139
|
+
try {
|
|
1140
|
+
entries = await fs.readdir(current, { withFileTypes: true });
|
|
1141
|
+
}
|
|
1142
|
+
catch {
|
|
1143
|
+
return;
|
|
1144
|
+
}
|
|
1145
|
+
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
1146
|
+
for (const entry of entries) {
|
|
1147
|
+
if (collected.length >= maxEntries)
|
|
1148
|
+
return;
|
|
1149
|
+
const relative = path.relative(root, path.join(current, entry.name));
|
|
1150
|
+
const normalizedRelative = relative.split(path.sep).join(path.posix.sep);
|
|
1151
|
+
if (DOMAIN_INFERENCE_EXCLUDED_NAMES.has(entry.name) ||
|
|
1152
|
+
DOMAIN_INFERENCE_EXCLUDED_NAMES.has(normalizedRelative)) {
|
|
1153
|
+
continue;
|
|
1154
|
+
}
|
|
1155
|
+
if (entry.isDirectory()) {
|
|
1156
|
+
await walk(path.join(current, entry.name), depth + 1);
|
|
1157
|
+
continue;
|
|
1158
|
+
}
|
|
1159
|
+
if (entry.isFile()) {
|
|
1160
|
+
collected.push(normalizedRelative);
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
await walk(root, 0);
|
|
1165
|
+
return collected;
|
|
1166
|
+
}
|
|
1167
|
+
async function buildTargetDomainSignal(args) {
|
|
1168
|
+
const pathParts = [
|
|
1169
|
+
args.requestedTarget,
|
|
1170
|
+
path.relative(args.projectRoot, args.targetPath),
|
|
1171
|
+
...args.resolvedTargetRefs.map((ref) => path.relative(args.projectRoot, ref)),
|
|
1172
|
+
].map((part) => part.split(path.sep).join(path.posix.sep));
|
|
1173
|
+
const contentParts = [args.requestText, ...pathParts];
|
|
1174
|
+
let hasCodeSignal = false;
|
|
1175
|
+
let hasOntologyPathSignal = pathParts.some((part) => part === ".onto" ||
|
|
1176
|
+
part.startsWith(".onto/") ||
|
|
1177
|
+
part.includes("/ontology/") ||
|
|
1178
|
+
part.includes("ontology"));
|
|
1179
|
+
for (const ref of args.resolvedTargetRefs) {
|
|
1180
|
+
try {
|
|
1181
|
+
const stats = await fs.stat(ref);
|
|
1182
|
+
if (stats.isDirectory()) {
|
|
1183
|
+
const listedPaths = await collectDirectorySignalPaths(ref);
|
|
1184
|
+
contentParts.push(...listedPaths);
|
|
1185
|
+
hasCodeSignal ||= listedPaths.some((listedPath) => DOMAIN_INFERENCE_CODE_EXTENSIONS.has(path.extname(listedPath)));
|
|
1186
|
+
hasOntologyPathSignal ||= listedPaths.some((listedPath) => listedPath.startsWith(".onto/") ||
|
|
1187
|
+
listedPath.includes("/ontology/") ||
|
|
1188
|
+
listedPath.includes("ontology"));
|
|
1189
|
+
continue;
|
|
1190
|
+
}
|
|
1191
|
+
hasCodeSignal ||= DOMAIN_INFERENCE_CODE_EXTENSIONS.has(path.extname(ref));
|
|
1192
|
+
contentParts.push(await readFilePrefix(ref, DOMAIN_INFERENCE_MAX_FILE_BYTES));
|
|
1193
|
+
}
|
|
1194
|
+
catch {
|
|
1195
|
+
// Target binding already validated refs; inference remains best-effort.
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
return {
|
|
1199
|
+
text: contentParts.join("\n"),
|
|
1200
|
+
pathText: pathParts.join("\n"),
|
|
1201
|
+
hasCodeSignal,
|
|
1202
|
+
hasOntologyPathSignal,
|
|
1203
|
+
};
|
|
1204
|
+
}
|
|
1205
|
+
async function readDomainCandidateText(candidate) {
|
|
1206
|
+
const preferredFiles = [
|
|
1207
|
+
"domain_scope.md",
|
|
1208
|
+
"concepts.md",
|
|
1209
|
+
"competency_qs.md",
|
|
1210
|
+
"structure_spec.md",
|
|
1211
|
+
"logic_rules.md",
|
|
1212
|
+
];
|
|
1213
|
+
const parts = [candidate.id, candidate.id.replace(/-/g, " ")];
|
|
1214
|
+
for (const filename of preferredFiles) {
|
|
1215
|
+
const filePath = path.join(candidate.dir, filename);
|
|
1216
|
+
if (!fsSync.existsSync(filePath))
|
|
1217
|
+
continue;
|
|
1218
|
+
parts.push(await readFilePrefix(filePath, 24 * 1024));
|
|
1219
|
+
}
|
|
1220
|
+
return parts.join("\n");
|
|
1221
|
+
}
|
|
1222
|
+
function formatInferenceReason(args) {
|
|
1223
|
+
const reason = args.signalReasons.length > 0
|
|
1224
|
+
? args.signalReasons.join("; ")
|
|
1225
|
+
: "it had the strongest lexical overlap with the target and intent";
|
|
1226
|
+
return `No explicit domain token or configured domain was provided. Selected ${args.domainToken} because ${reason}.`;
|
|
1227
|
+
}
|
|
1228
|
+
async function inferDomainFromReviewTarget(args) {
|
|
1229
|
+
const candidates = collectAvailableDomainCandidates(args.projectRoot, args.ontoHome);
|
|
1230
|
+
if (candidates.length === 0)
|
|
1231
|
+
return null;
|
|
1232
|
+
const signal = await buildTargetDomainSignal(args);
|
|
1233
|
+
const targetTokens = new Set(tokenizeForDomainInference(signal.text));
|
|
1234
|
+
const pathTokens = new Set(tokenizeForDomainInference(signal.pathText));
|
|
1235
|
+
const normalizedTargetText = signal.text.toLowerCase();
|
|
1236
|
+
const scored = await Promise.all(candidates.map(async (candidate, index) => {
|
|
1237
|
+
let score = 0;
|
|
1238
|
+
const signalReasons = [];
|
|
1239
|
+
const domainToken = `@${candidate.id}`;
|
|
1240
|
+
const domainIdTokens = tokenizeForDomainInference(candidate.id);
|
|
1241
|
+
if (normalizedTargetText.includes(candidate.id.toLowerCase())) {
|
|
1242
|
+
score += 80;
|
|
1243
|
+
signalReasons.push(`the target mentions "${candidate.id}"`);
|
|
1244
|
+
}
|
|
1245
|
+
const matchedIdTokens = domainIdTokens.filter((token) => targetTokens.has(token) || pathTokens.has(token));
|
|
1246
|
+
if (matchedIdTokens.length > 0) {
|
|
1247
|
+
score += matchedIdTokens.length * 30;
|
|
1248
|
+
signalReasons.push(`target path or intent matches domain token(s): ${matchedIdTokens.join(", ")}`);
|
|
1249
|
+
}
|
|
1250
|
+
if (candidate.id === "ontology" && signal.hasOntologyPathSignal) {
|
|
1251
|
+
score += 55;
|
|
1252
|
+
signalReasons.push("the target is inside or explicitly references ontology-owned material");
|
|
1253
|
+
}
|
|
1254
|
+
if (candidate.id === "software-engineering" && signal.hasCodeSignal) {
|
|
1255
|
+
score += 45;
|
|
1256
|
+
signalReasons.push("the target contains implementation/code material");
|
|
1257
|
+
}
|
|
1258
|
+
const domainText = await readDomainCandidateText(candidate);
|
|
1259
|
+
const domainTokens = new Set(tokenizeForDomainInference(domainText));
|
|
1260
|
+
const overlap = [...targetTokens].filter((token) => domainTokens.has(token));
|
|
1261
|
+
if (overlap.length > 0) {
|
|
1262
|
+
const weightedOverlap = Math.min(overlap.length * 2, 40);
|
|
1263
|
+
score += weightedOverlap;
|
|
1264
|
+
signalReasons.push(`target text overlaps domain document terms: ${overlap.slice(0, 5).join(", ")}`);
|
|
1265
|
+
}
|
|
1266
|
+
return {
|
|
1267
|
+
candidate,
|
|
1268
|
+
domainToken,
|
|
1269
|
+
score,
|
|
1270
|
+
index,
|
|
1271
|
+
signalReasons,
|
|
1272
|
+
};
|
|
1273
|
+
}));
|
|
1274
|
+
scored.sort((left, right) => right.score - left.score ||
|
|
1275
|
+
left.index - right.index ||
|
|
1276
|
+
left.candidate.id.localeCompare(right.candidate.id));
|
|
1277
|
+
const best = scored[0];
|
|
1278
|
+
if (!best || best.score < DOMAIN_INFERENCE_MIN_SCORE)
|
|
1279
|
+
return null;
|
|
1280
|
+
return {
|
|
1281
|
+
domainToken: best.domainToken,
|
|
1282
|
+
reason: formatInferenceReason({
|
|
1283
|
+
domainToken: best.domainToken,
|
|
1284
|
+
signalReasons: best.signalReasons,
|
|
1285
|
+
}),
|
|
1286
|
+
};
|
|
1287
|
+
}
|
|
999
1288
|
async function promptForDomainSelection(configuredDomainTokens) {
|
|
1000
1289
|
const optionTokens = configuredDomainTokens.includes("@-")
|
|
1001
1290
|
? [...configuredDomainTokens]
|
|
@@ -1035,31 +1324,54 @@ async function promptForDomainSelection(configuredDomainTokens) {
|
|
|
1035
1324
|
readline.close();
|
|
1036
1325
|
}
|
|
1037
1326
|
}
|
|
1038
|
-
async function resolveDomainSelection(requestedDomainToken, ontoConfig) {
|
|
1327
|
+
async function resolveDomainSelection(requestedDomainToken, ontoConfig, inferenceContext) {
|
|
1039
1328
|
if (requestedDomainToken.length > 0) {
|
|
1329
|
+
const domainFinalValue = normalizeDomainValue(requestedDomainToken);
|
|
1330
|
+
const reason = domainFinalValue === "none"
|
|
1331
|
+
? "Explicit no-domain token was provided; runtime will run without domain documents."
|
|
1332
|
+
: `Explicit domain token ${requestedDomainToken} was provided; runtime used it without target inference.`;
|
|
1040
1333
|
return {
|
|
1041
1334
|
domainRecommendation: requestedDomainToken,
|
|
1042
|
-
domainFinalValue
|
|
1335
|
+
domainFinalValue,
|
|
1043
1336
|
domainSelectionMode: "explicit_token",
|
|
1044
1337
|
domainSelectionRequired: false,
|
|
1338
|
+
domainSelectionReason: reason,
|
|
1339
|
+
bindingNotes: [reason],
|
|
1045
1340
|
};
|
|
1046
1341
|
}
|
|
1047
1342
|
const configuredDomainTokens = collectConfiguredDomainTokens(ontoConfig);
|
|
1048
1343
|
if (configuredDomainTokens.length === 0) {
|
|
1344
|
+
const inferred = await inferDomainFromReviewTarget(inferenceContext);
|
|
1345
|
+
if (inferred) {
|
|
1346
|
+
return {
|
|
1347
|
+
domainRecommendation: inferred.domainToken,
|
|
1348
|
+
domainFinalValue: normalizeDomainValue(inferred.domainToken),
|
|
1349
|
+
domainSelectionMode: "target_inferred",
|
|
1350
|
+
domainSelectionRequired: false,
|
|
1351
|
+
domainSelectionReason: inferred.reason,
|
|
1352
|
+
bindingNotes: [inferred.reason],
|
|
1353
|
+
};
|
|
1354
|
+
}
|
|
1355
|
+
const reason = "No explicit domain token, configured domain, or confident target-domain match was available; runtime will run without domain documents.";
|
|
1049
1356
|
return {
|
|
1050
1357
|
domainRecommendation: "@-",
|
|
1051
1358
|
domainFinalValue: "none",
|
|
1052
1359
|
domainSelectionMode: "no_domain_default",
|
|
1053
1360
|
domainSelectionRequired: false,
|
|
1361
|
+
domainSelectionReason: reason,
|
|
1362
|
+
bindingNotes: [reason],
|
|
1054
1363
|
};
|
|
1055
1364
|
}
|
|
1056
1365
|
if (configuredDomainTokens.length === 1) {
|
|
1057
1366
|
const selectedToken = configuredDomainTokens[0];
|
|
1367
|
+
const reason = `Single configured domain ${selectedToken} is available; runtime used the configured default.`;
|
|
1058
1368
|
return {
|
|
1059
1369
|
domainRecommendation: selectedToken,
|
|
1060
1370
|
domainFinalValue: normalizeDomainValue(selectedToken),
|
|
1061
1371
|
domainSelectionMode: "project_default",
|
|
1062
1372
|
domainSelectionRequired: false,
|
|
1373
|
+
domainSelectionReason: reason,
|
|
1374
|
+
bindingNotes: [reason],
|
|
1063
1375
|
};
|
|
1064
1376
|
}
|
|
1065
1377
|
const domainRecommendation = configuredDomainTokens[0];
|
|
@@ -1071,11 +1383,14 @@ async function resolveDomainSelection(requestedDomainToken, ontoConfig) {
|
|
|
1071
1383
|
].join("\n"));
|
|
1072
1384
|
}
|
|
1073
1385
|
const selectedToken = await promptForDomainSelection(configuredDomainTokens);
|
|
1386
|
+
const reason = `Interactive domain selection chose ${selectedToken} from configured domains: ${configuredDomainTokens.join(", ")}.`;
|
|
1074
1387
|
return {
|
|
1075
1388
|
domainRecommendation,
|
|
1076
1389
|
domainFinalValue: normalizeDomainValue(selectedToken),
|
|
1077
1390
|
domainSelectionMode: "interactive_selection",
|
|
1078
1391
|
domainSelectionRequired: true,
|
|
1392
|
+
domainSelectionReason: reason,
|
|
1393
|
+
bindingNotes: [reason],
|
|
1079
1394
|
};
|
|
1080
1395
|
}
|
|
1081
1396
|
function resolveReviewMode(argv, ontoConfig) {
|
|
@@ -1268,7 +1583,7 @@ async function resolveBundleTargetInput(args) {
|
|
|
1268
1583
|
filesystemAllowedRoots,
|
|
1269
1584
|
};
|
|
1270
1585
|
}
|
|
1271
|
-
async function resolveReviewInvokeInputs(argv, ontoConfig, projectRoot, sessionId) {
|
|
1586
|
+
async function resolveReviewInvokeInputs(argv, ontoConfig, projectRoot, sessionId, ontoHome) {
|
|
1272
1587
|
const parsedPositionals = parseHostFacingPositionals(splitArgvIntoOptionsAndPositionals(argv, [...KNOWN_INVOKE_ONLY_OPTION_NAMES, ...KNOWN_PASSTHROUGH_OPTION_NAMES], [...KNOWN_INVOKE_ONLY_FLAG_NAMES, ...KNOWN_PASSTHROUGH_FLAG_NAMES]).positionals);
|
|
1273
1588
|
const explicitRequestedTarget = readSingleOptionValueFromArgv(argv, "requested-target");
|
|
1274
1589
|
const explicitTargetScopeKind = requireOptionalTargetScopeKind(readSingleOptionValueFromArgv(argv, "target-scope-kind"));
|
|
@@ -1347,7 +1662,6 @@ async function resolveReviewInvokeInputs(argv, ontoConfig, projectRoot, sessionI
|
|
|
1347
1662
|
const requestedDomainToken = readSingleOptionValueFromArgv(argv, "requested-domain-token") ??
|
|
1348
1663
|
(canonicalDomainToken.length > 0 ? canonicalDomainToken : undefined) ??
|
|
1349
1664
|
"";
|
|
1350
|
-
const resolvedDomainSelection = await resolveDomainSelection(requestedDomainToken, ontoConfig);
|
|
1351
1665
|
let reviewMode = resolveReviewMode(argv, ontoConfig);
|
|
1352
1666
|
const explicitLensIds = readMultiOptionValuesFromArgv(argv, "lens-id");
|
|
1353
1667
|
// Phase 3: standalone LLM-based complexity assessment (Step 1.5)
|
|
@@ -1497,6 +1811,15 @@ async function resolveReviewInvokeInputs(argv, ontoConfig, projectRoot, sessionI
|
|
|
1497
1811
|
if (resolvedLensIds.length === 0) {
|
|
1498
1812
|
throw new Error("No lens IDs resolved. Specify at least one --lens-id or use --review-mode full|core-axis.");
|
|
1499
1813
|
}
|
|
1814
|
+
const resolvedDomainSelection = await resolveDomainSelection(requestedDomainToken, ontoConfig, {
|
|
1815
|
+
projectRoot,
|
|
1816
|
+
...(ontoHome ? { ontoHome } : {}),
|
|
1817
|
+
requestedTarget: requestedTarget ?? explicitPrimaryRef ?? absoluteTargetPath,
|
|
1818
|
+
requestText,
|
|
1819
|
+
targetPath: absoluteTargetPath,
|
|
1820
|
+
targetScopeKind,
|
|
1821
|
+
resolvedTargetRefs,
|
|
1822
|
+
});
|
|
1500
1823
|
return {
|
|
1501
1824
|
requestedTarget: requestedTarget ?? explicitPrimaryRef ?? absoluteTargetPath,
|
|
1502
1825
|
targetPath: absoluteTargetPath,
|
|
@@ -1509,6 +1832,8 @@ async function resolveReviewInvokeInputs(argv, ontoConfig, projectRoot, sessionI
|
|
|
1509
1832
|
domainFinalValue: resolvedDomainSelection.domainFinalValue,
|
|
1510
1833
|
domainSelectionMode: resolvedDomainSelection.domainSelectionMode,
|
|
1511
1834
|
domainSelectionRequired: resolvedDomainSelection.domainSelectionRequired,
|
|
1835
|
+
domainSelectionReason: resolvedDomainSelection.domainSelectionReason,
|
|
1836
|
+
bindingNotes: resolvedDomainSelection.bindingNotes,
|
|
1512
1837
|
...(bundleKind ? { bundleKind } : {}),
|
|
1513
1838
|
reviewMode,
|
|
1514
1839
|
reviewModeRecommendation: reviewMode,
|
|
@@ -1537,6 +1862,15 @@ function appendReviewInvokeDerivedArgs(argv, resolvedInputs) {
|
|
|
1537
1862
|
appended.push(`--${optionName}`, value);
|
|
1538
1863
|
}
|
|
1539
1864
|
};
|
|
1865
|
+
const appendMissingMulti = (optionName, values) => {
|
|
1866
|
+
const existingValues = new Set(readMultiOptionValuesFromArgv(appended, optionName));
|
|
1867
|
+
for (const value of values) {
|
|
1868
|
+
if (existingValues.has(value))
|
|
1869
|
+
continue;
|
|
1870
|
+
appended.push(`--${optionName}`, value);
|
|
1871
|
+
existingValues.add(value);
|
|
1872
|
+
}
|
|
1873
|
+
};
|
|
1540
1874
|
appendSingleIfAbsent("requested-target", resolvedInputs.requestedTarget);
|
|
1541
1875
|
appendSingleIfAbsent("target-scope-kind", resolvedInputs.targetScopeKind);
|
|
1542
1876
|
appendSingleIfAbsent("primary-ref", resolvedInputs.targetPath);
|
|
@@ -1555,6 +1889,7 @@ function appendReviewInvokeDerivedArgs(argv, resolvedInputs) {
|
|
|
1555
1889
|
appendMultiIfAbsent("filesystem-allowed-root", resolvedInputs.filesystemAllowedRoots);
|
|
1556
1890
|
appendMultiIfAbsent("lens-id", resolvedInputs.resolvedLensIds);
|
|
1557
1891
|
appendMultiIfAbsent("materialized-ref", resolvedInputs.resolvedTargetRefs);
|
|
1892
|
+
appendMissingMulti("binding-note", resolvedInputs.bindingNotes);
|
|
1558
1893
|
if (resolvedInputs.targetScopeKind === "bundle") {
|
|
1559
1894
|
appendMultiIfAbsent("member-ref", resolvedInputs.resolvedTargetRefs.slice(1));
|
|
1560
1895
|
if (typeof resolvedInputs.bundleKind === "string" &&
|
|
@@ -1569,7 +1904,7 @@ function appendReviewInvokeDerivedArgs(argv, resolvedInputs) {
|
|
|
1569
1904
|
}
|
|
1570
1905
|
return appended;
|
|
1571
1906
|
}
|
|
1572
|
-
async function readOptionalReviewSummary(sessionRoot) {
|
|
1907
|
+
export async function readOptionalReviewSummary(sessionRoot) {
|
|
1573
1908
|
const bindingPath = path.join(sessionRoot, "binding.yaml");
|
|
1574
1909
|
const reviewRecordPath = path.join(sessionRoot, "review-record.yaml");
|
|
1575
1910
|
const binding = (await fileExists(bindingPath))
|
|
@@ -1657,7 +1992,7 @@ function appendDirectoryListingConfigArgs(targetArgv, originalArgv, ontoConfig)
|
|
|
1657
1992
|
}
|
|
1658
1993
|
return result;
|
|
1659
1994
|
}
|
|
1660
|
-
async function resolveReviewInvokeSetup(argv) {
|
|
1995
|
+
export async function resolveReviewInvokeSetup(argv) {
|
|
1661
1996
|
rejectRemovedFlags(argv);
|
|
1662
1997
|
const argvWithSessionId = ensureSessionIdArg(argv);
|
|
1663
1998
|
const sessionId = requireString(readSingleOptionValueFromArgv(argvWithSessionId, "session-id"), "session-id");
|
|
@@ -1667,7 +2002,7 @@ async function resolveReviewInvokeSetup(argv) {
|
|
|
1667
2002
|
const ontoConfig = ontoHome
|
|
1668
2003
|
? await resolveSettingsChain(ontoHome, projectRoot)
|
|
1669
2004
|
: await readOntoConfig(projectRoot);
|
|
1670
|
-
const resolvedInvokeInputs = await resolveReviewInvokeInputs(argvWithSessionId, ontoConfig, projectRoot, sessionId);
|
|
2005
|
+
const resolvedInvokeInputs = await resolveReviewInvokeInputs(argvWithSessionId, ontoConfig, projectRoot, sessionId, ontoHome);
|
|
1671
2006
|
const maxConcurrentLenses = Math.max(1, resolvedInvokeInputs.resolvedLensIds.length);
|
|
1672
2007
|
const { optionTokens: argvWithoutPositionals } = splitArgvIntoOptionsAndPositionals(argvWithSessionId, [...KNOWN_INVOKE_ONLY_OPTION_NAMES, ...KNOWN_PASSTHROUGH_OPTION_NAMES], [...KNOWN_INVOKE_ONLY_FLAG_NAMES, ...KNOWN_PASSTHROUGH_FLAG_NAMES]);
|
|
1673
2008
|
const normalizedStartArgv = appendReviewInvokeDerivedArgs(stripOptionsFromArgv(argvWithoutPositionals, [...KNOWN_INVOKE_ONLY_OPTION_NAMES], [...KNOWN_INVOKE_ONLY_FLAG_NAMES]), resolvedInvokeInputs);
|
|
@@ -1708,21 +2043,15 @@ async function resolveReviewInvokeSetup(argv) {
|
|
|
1708
2043
|
* values written into the prepared session artifacts.
|
|
1709
2044
|
*/
|
|
1710
2045
|
export async function reviewPrepareOnly(argv) {
|
|
1711
|
-
|
|
1712
|
-
const startResult = await startReviewSession(setup.startArgv);
|
|
1713
|
-
const sessionRoot = path.resolve(startResult.session_root);
|
|
1714
|
-
const profile = setup.executionProfile;
|
|
1715
|
-
return {
|
|
1716
|
-
prepare_only: true,
|
|
1717
|
-
session_root: sessionRoot,
|
|
1718
|
-
request_text: setup.resolvedInvokeInputs.requestText,
|
|
1719
|
-
execution_realization: profile.execution_realization,
|
|
1720
|
-
host_runtime: profile.host_runtime,
|
|
1721
|
-
review_mode: setup.resolvedInvokeInputs.reviewMode,
|
|
1722
|
-
};
|
|
2046
|
+
return prepareReviewInvocationArgv(argv);
|
|
1723
2047
|
}
|
|
1724
2048
|
export async function runReviewInvokeCli(argv) {
|
|
1725
2049
|
const prepareOnly = hasOptionFlag(argv, "prepare-only");
|
|
2050
|
+
if (!prepareOnly) {
|
|
2051
|
+
const output = await runReviewInvocationArgv(argv);
|
|
2052
|
+
console.log(JSON.stringify(output, null, 2));
|
|
2053
|
+
return 0;
|
|
2054
|
+
}
|
|
1726
2055
|
const setup = await resolveReviewInvokeSetup(argv);
|
|
1727
2056
|
const resolvedProjectRoot = path.resolve(readSingleOptionValueFromArgv(setup.startArgv, "project-root") ?? ".");
|
|
1728
2057
|
const rawOntoHome = readSingleOptionValueFromArgv(setup.startArgv, "onto-home");
|
|
@@ -1944,6 +2273,7 @@ export async function runReviewInvokeCli(argv) {
|
|
|
1944
2273
|
target: setup.resolvedInvokeInputs.requestedTarget,
|
|
1945
2274
|
target_scope_kind: setup.resolvedInvokeInputs.targetScopeKind,
|
|
1946
2275
|
domain: setup.resolvedInvokeInputs.domainFinalValue,
|
|
2276
|
+
domain_selection_reason: setup.resolvedInvokeInputs.domainSelectionReason,
|
|
1947
2277
|
},
|
|
1948
2278
|
coverage: {
|
|
1949
2279
|
planned_lens_count: setup.resolvedInvokeInputs.resolvedLensIds.length,
|
|
@@ -1963,6 +2293,7 @@ export async function runReviewInvokeCli(argv) {
|
|
|
1963
2293
|
target: setup.resolvedInvokeInputs.requestedTarget,
|
|
1964
2294
|
targetScopeKind: setup.resolvedInvokeInputs.targetScopeKind,
|
|
1965
2295
|
domain: setup.resolvedInvokeInputs.domainFinalValue,
|
|
2296
|
+
domainSelectionReason: setup.resolvedInvokeInputs.domainSelectionReason,
|
|
1966
2297
|
status: recordStatus,
|
|
1967
2298
|
deliberationStatus,
|
|
1968
2299
|
reviewMode: setup.resolvedInvokeInputs.reviewMode,
|
|
@@ -1987,6 +2318,7 @@ export async function runReviewInvokeCli(argv) {
|
|
|
1987
2318
|
: null,
|
|
1988
2319
|
domain_selection_required: setup.resolvedInvokeInputs.domainSelectionRequired,
|
|
1989
2320
|
domain_selection_mode: setup.resolvedInvokeInputs.domainSelectionMode,
|
|
2321
|
+
domain_selection_reason: setup.resolvedInvokeInputs.domainSelectionReason,
|
|
1990
2322
|
domain_final_value: setup.resolvedInvokeInputs.domainFinalValue,
|
|
1991
2323
|
review_mode: setup.resolvedInvokeInputs.reviewMode,
|
|
1992
2324
|
},
|