Wire availableLibraries into taskitem generation dispatch
This commit is contained in:
@@ -39,6 +39,9 @@
|
||||
#include "ASTFeatureExtractor.h"
|
||||
#include "LanguageIdiomProfile.h"
|
||||
#include "LanguageFitnessScorer.h"
|
||||
#include "TaskitemLibraryAnnotator.h"
|
||||
#include "Sprint286IntegrationSummary.h"
|
||||
#include "Sprint288IntegrationSummary.h"
|
||||
#include "PolyglotProjectSpec.h"
|
||||
#include "ABIBoundaryExtractor.h"
|
||||
#include "FFIGlueDispatcher.h"
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
{"description", "Normalized requirements from whetstone_architect_intake."}}},
|
||||
{"conflicts", {{"type", "array"},
|
||||
{"description", "Optional requirement conflicts from whetstone_architect_intake."}}},
|
||||
{"availableLibraries", {{"type", "array"},
|
||||
{"description", "Optional candidate libraries for deterministic library/API dispatch."}}},
|
||||
{"strictExecutionContract", {{"type", "boolean"},
|
||||
{"description", "Require concrete execution contract metadata (stepIds/files/tools/tests)."}}}
|
||||
}}, {"required", json::array({"normalizedRequirements"})}}
|
||||
@@ -477,10 +479,50 @@
|
||||
};
|
||||
}
|
||||
|
||||
std::vector<std::string> availableLibraries;
|
||||
if (args.contains("availableLibraries")) {
|
||||
if (!args["availableLibraries"].is_array()) {
|
||||
return {
|
||||
{"success", false},
|
||||
{"error", "available_libraries_not_array"}
|
||||
};
|
||||
}
|
||||
for (const auto& libJson : args["availableLibraries"]) {
|
||||
if (!libJson.is_string()) {
|
||||
return {
|
||||
{"success", false},
|
||||
{"error", "available_library_entry_not_string"}
|
||||
};
|
||||
}
|
||||
const std::string lib = libJson.get<std::string>();
|
||||
if (lib.empty()) continue;
|
||||
bool seen = false;
|
||||
for (const auto& existing : availableLibraries) {
|
||||
if (existing == lib) {
|
||||
seen = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!seen) availableLibraries.push_back(lib);
|
||||
}
|
||||
}
|
||||
const bool libraryDispatchEnabled = !availableLibraries.empty();
|
||||
auto capabilityLedger = whetstone::Sprint286IntegrationSummary::buildSeedLedger();
|
||||
auto symbolCatalog = whetstone::Sprint288IntegrationSummary::buildSeedCatalog();
|
||||
whetstone::TaskitemLibraryAnnotator libraryAnnotator;
|
||||
std::string libraryDispatchContext;
|
||||
for (const auto& requirement : normalized.requirements) {
|
||||
if (!requirement.normalizedText.empty()) {
|
||||
if (!libraryDispatchContext.empty()) libraryDispatchContext.push_back(' ');
|
||||
libraryDispatchContext += requirement.normalizedText;
|
||||
}
|
||||
}
|
||||
|
||||
const bool strictExecutionContract = args.value("strictExecutionContract", false);
|
||||
const json executionHints = collectExecutionHints(normalized.requirements);
|
||||
int escalateCount = 0;
|
||||
int missingContractCount = 0;
|
||||
int enrichedTaskCount = 0;
|
||||
json tasksJson = json::array();
|
||||
for (const auto& task : annotated) {
|
||||
json taskJson = {
|
||||
@@ -496,6 +538,31 @@
|
||||
{"reasons", task.reasons}
|
||||
};
|
||||
json contract = buildExecutionContract(task, executionHints, strictExecutionContract);
|
||||
if (libraryDispatchEnabled) {
|
||||
std::string dispatchText = task.base.title;
|
||||
if (!libraryDispatchContext.empty()) {
|
||||
dispatchText += " ";
|
||||
dispatchText += libraryDispatchContext;
|
||||
}
|
||||
auto enriched = libraryAnnotator.annotate(dispatchText, availableLibraries, capabilityLedger, symbolCatalog);
|
||||
if (enriched.isEnriched()) {
|
||||
contract["selectedLibrary"] = enriched.selectedLibrary;
|
||||
contract["operationDomain"] = enriched.operationDomain;
|
||||
contract["capabilityScore"] = enriched.capabilityScore;
|
||||
contract["preferredAPIs"] = enriched.preferredAPIs;
|
||||
contract["justification"] = enriched.justification;
|
||||
json avoided = json::array();
|
||||
for (const auto& item : enriched.avoidedLibraries) {
|
||||
avoided.push_back({
|
||||
{"name", item.name},
|
||||
{"reason", item.reason},
|
||||
{"score", item.score}
|
||||
});
|
||||
}
|
||||
contract["avoidedLibraries"] = avoided;
|
||||
++enrichedTaskCount;
|
||||
}
|
||||
}
|
||||
taskJson["executionContract"] = contract;
|
||||
taskJson["resourceLocks"] = inferResourceLocks(task);
|
||||
if (strictExecutionContract && contract.value("executionSpecificityScore", 0) < 60) {
|
||||
@@ -522,7 +589,12 @@
|
||||
{"ambiguousRequirementCount", countAmbiguousRequirements(normalized.requirements)},
|
||||
{"escalateCount", escalateCount},
|
||||
{"strictExecutionContract", strictExecutionContract},
|
||||
{"missingExecutionContractCount", missingContractCount}
|
||||
{"missingExecutionContractCount", missingContractCount},
|
||||
{"libraryDispatch", {
|
||||
{"enabled", libraryDispatchEnabled},
|
||||
{"availableLibraries", availableLibraries},
|
||||
{"enrichedTaskCount", enrichedTaskCount}
|
||||
}}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -279,6 +279,27 @@ if [[ "$SEMANTIC_PLANNING_BRIDGE" == "1" && "$SEMANTIC_INTAKE_AUGMENT" == "1" &&
|
||||
else
|
||||
MARKDOWN_CONTENT="$(cat "$INPUT_FILE")"
|
||||
fi
|
||||
AVAILABLE_LIBRARIES_JSON="${WSTONE_AVAILABLE_LIBRARIES_JSON:-}"
|
||||
if [[ -z "$AVAILABLE_LIBRARIES_JSON" ]]; then
|
||||
AVAILABLE_LIBRARIES_JSON="$(cat "$INPUT_FILE" | python3 -c '
|
||||
import json, re, sys
|
||||
text = sys.stdin.read()
|
||||
libs = []
|
||||
for line in text.splitlines():
|
||||
m = re.search(r"available libraries\s*:\s*(.+)$", line, re.IGNORECASE)
|
||||
if not m:
|
||||
continue
|
||||
for part in m.group(1).split(","):
|
||||
name = part.strip().strip("`").strip()
|
||||
if name and name not in libs:
|
||||
libs.append(name)
|
||||
print(json.dumps(libs))
|
||||
')"
|
||||
fi
|
||||
if ! printf '%s' "$AVAILABLE_LIBRARIES_JSON" | jq -e 'type == "array"' >/dev/null 2>&1; then
|
||||
echo "error: available libraries must be a JSON array (WSTONE_AVAILABLE_LIBRARIES_JSON)" >&2
|
||||
exit 21
|
||||
fi
|
||||
INTAKE_ARGS="$(jq -nc --arg md "$MARKDOWN_CONTENT" '{markdown:$md}')"
|
||||
INTAKE_RESP_RAW="$(call_tool "whetstone_architect_intake" "$INTAKE_ARGS")"
|
||||
printf '%s\n' "$INTAKE_RESP_RAW" > "$OUT_DIR/01_intake_raw.ndjson.json"
|
||||
@@ -402,8 +423,8 @@ else
|
||||
NATIVE_RAW_TEMPLATE_CONTROL_PACK_JSON='{"enabled":false}'
|
||||
fi
|
||||
CONFLICTS="$(printf '%s' "$INTAKE_JSON" | jq '.conflicts // []')"
|
||||
GEN_ARGS="$(jq -nc --argjson nr "$NORMALIZED_REQS" --argjson cf "$CONFLICTS" --arg strict "$STRICT_EXECUTION_CONTRACT" \
|
||||
'{normalizedRequirements:$nr,conflicts:$cf,strictExecutionContract:($strict == "1")}')"
|
||||
GEN_ARGS="$(jq -nc --argjson nr "$NORMALIZED_REQS" --argjson cf "$CONFLICTS" --argjson libs "$AVAILABLE_LIBRARIES_JSON" --arg strict "$STRICT_EXECUTION_CONTRACT" \
|
||||
'{normalizedRequirements:$nr,conflicts:$cf,availableLibraries:$libs,strictExecutionContract:($strict == "1")}')"
|
||||
GEN_RESP_RAW="$(call_tool "whetstone_generate_taskitems" "$GEN_ARGS")"
|
||||
printf '%s\n' "$GEN_RESP_RAW" > "$OUT_DIR/02_generate_taskitems_raw.ndjson.json"
|
||||
GEN_JSON="$(extract_tool_text_json "$GEN_RESP_RAW")"
|
||||
@@ -426,8 +447,8 @@ if [[ "$NATIVE_DECOMP_RETRY" == "1" && "$native_task_count_initial" -lt "$NATIVE
|
||||
ambiguous: false
|
||||
}]
|
||||
')"
|
||||
RETRY_GEN_ARGS="$(jq -nc --argjson nr "$RETRY_REQS" --argjson cf "$CONFLICTS" --arg strict "$STRICT_EXECUTION_CONTRACT" \
|
||||
'{normalizedRequirements:$nr,conflicts:$cf,strictExecutionContract:($strict == "1")}')"
|
||||
RETRY_GEN_ARGS="$(jq -nc --argjson nr "$RETRY_REQS" --argjson cf "$CONFLICTS" --argjson libs "$AVAILABLE_LIBRARIES_JSON" --arg strict "$STRICT_EXECUTION_CONTRACT" \
|
||||
'{normalizedRequirements:$nr,conflicts:$cf,availableLibraries:$libs,strictExecutionContract:($strict == "1")}')"
|
||||
RETRY_GEN_RESP_RAW="$(call_tool "whetstone_generate_taskitems" "$RETRY_GEN_ARGS")"
|
||||
printf '%s\n' "$RETRY_GEN_RESP_RAW" > "$OUT_DIR/02aa_generate_taskitems_retry_raw.ndjson.json"
|
||||
RETRY_GEN_JSON="$(extract_tool_text_json "$RETRY_GEN_RESP_RAW")"
|
||||
@@ -539,8 +560,8 @@ if [[ "$NATIVE_RAW_CANDIDATE_SEARCH" == "1" ]]; then
|
||||
while [[ "$variant" -lt "$max_variants" && "$idx" -lt "$variant_total" ]]; do
|
||||
req_bundle="$(printf '%s' "$VARIANTS_JSON" | jq ".variants[$idx]")"
|
||||
cand_reqs="$(jq -nc --argjson base "$NORMALIZED_REQS" --argjson bundle "$req_bundle" '$base + $bundle')"
|
||||
cand_args="$(jq -nc --argjson nr "$cand_reqs" --argjson cf "$CONFLICTS" --arg strict "$STRICT_EXECUTION_CONTRACT" \
|
||||
'{normalizedRequirements:$nr,conflicts:$cf,strictExecutionContract:($strict == "1")}')"
|
||||
cand_args="$(jq -nc --argjson nr "$cand_reqs" --argjson cf "$CONFLICTS" --argjson libs "$AVAILABLE_LIBRARIES_JSON" --arg strict "$STRICT_EXECUTION_CONTRACT" \
|
||||
'{normalizedRequirements:$nr,conflicts:$cf,availableLibraries:$libs,strictExecutionContract:($strict == "1")}')"
|
||||
cand_raw="$(call_tool "whetstone_generate_taskitems" "$cand_args")"
|
||||
printf '%s\n' "$cand_raw" > "$OUT_DIR/02ae_candidate_${variant}_raw.ndjson.json"
|
||||
cand_json="$(extract_tool_text_json "$cand_raw")"
|
||||
@@ -603,8 +624,8 @@ if [[ "$NATIVE_RAW_CANDIDATE_SEARCH" == "1" ]]; then
|
||||
--out-report "$OUT_DIR/02af_raw_adaptive_retry_requirements_report.json" >/dev/null
|
||||
retry_top_gap_reqs="$(cat "$OUT_DIR/02af_raw_adaptive_retry_requirements.json")"
|
||||
retry_cand_reqs="$(jq -nc --argjson base "$NORMALIZED_REQS" --argjson extra "$retry_top_gap_reqs" '$base + $extra')"
|
||||
retry_cand_args="$(jq -nc --argjson nr "$retry_cand_reqs" --argjson cf "$CONFLICTS" --arg strict "$STRICT_EXECUTION_CONTRACT" \
|
||||
'{normalizedRequirements:$nr,conflicts:$cf,strictExecutionContract:($strict == "1")}')"
|
||||
retry_cand_args="$(jq -nc --argjson nr "$retry_cand_reqs" --argjson cf "$CONFLICTS" --argjson libs "$AVAILABLE_LIBRARIES_JSON" --arg strict "$STRICT_EXECUTION_CONTRACT" \
|
||||
'{normalizedRequirements:$nr,conflicts:$cf,availableLibraries:$libs,strictExecutionContract:($strict == "1")}')"
|
||||
retry_raw="$(call_tool "whetstone_generate_taskitems" "$retry_cand_args")"
|
||||
printf '%s\n' "$retry_raw" > "$OUT_DIR/02af_raw_adaptive_retry_raw.ndjson.json"
|
||||
retry_json="$(extract_tool_text_json "$retry_raw")"
|
||||
@@ -791,8 +812,8 @@ if [[ "$NATIVE_MULTISHOT_DECOMP" == "1" ]]; then
|
||||
'[($prof.profiles[]? | select(.id == $pid) | .required_execution_contract[]?) // empty]')"
|
||||
|
||||
shot_reqs="$(jq -nc --argjson base "$NORMALIZED_REQS" --argjson req "$req_i" '$base + [$req]')"
|
||||
shot_args="$(jq -nc --argjson nr "$shot_reqs" --argjson cf "$CONFLICTS" --arg strict "$STRICT_EXECUTION_CONTRACT" \
|
||||
'{normalizedRequirements:$nr,conflicts:$cf,strictExecutionContract:($strict == "1")}')"
|
||||
shot_args="$(jq -nc --argjson nr "$shot_reqs" --argjson cf "$CONFLICTS" --argjson libs "$AVAILABLE_LIBRARIES_JSON" --arg strict "$STRICT_EXECUTION_CONTRACT" \
|
||||
'{normalizedRequirements:$nr,conflicts:$cf,availableLibraries:$libs,strictExecutionContract:($strict == "1")}')"
|
||||
shot_raw="$(call_tool "whetstone_generate_taskitems" "$shot_args")"
|
||||
printf '%s\n' "$shot_raw" > "$OUT_DIR/02ac_generate_taskitems_multishot_${i}_raw.ndjson.json"
|
||||
shot_json="$(extract_tool_text_json "$shot_raw")"
|
||||
|
||||
Reference in New Issue
Block a user