fix(reasoning): preserve ready material question target
This commit is contained in:
@@ -1982,6 +1982,41 @@ function selectPatternCompatibleUnknownCandidate({
|
||||
]);
|
||||
}
|
||||
|
||||
function hasUnresolvedSameProposalDependsOnPrerequisite({
|
||||
graph,
|
||||
proposal,
|
||||
targetNodeId,
|
||||
}) {
|
||||
const addedNodeIds = new Set(
|
||||
(proposal?.addedNodes || []).map((node) => node.id),
|
||||
);
|
||||
if (!addedNodeIds.has(targetNodeId)) return false;
|
||||
|
||||
const targetNode = findNodeById(graph, targetNodeId);
|
||||
if (!targetNode) return false;
|
||||
|
||||
const directPrerequisiteIds = new Set();
|
||||
|
||||
for (const dependencyId of targetNode.dependsOn || []) {
|
||||
directPrerequisiteIds.add(dependencyId);
|
||||
}
|
||||
|
||||
for (const edge of graph.edges || []) {
|
||||
if (
|
||||
edge.relationship === "depends_on" &&
|
||||
edge.fromNodeId === targetNodeId &&
|
||||
edge.toNodeId
|
||||
) {
|
||||
directPrerequisiteIds.add(edge.toNodeId);
|
||||
}
|
||||
}
|
||||
|
||||
return [...directPrerequisiteIds].some(
|
||||
(nodeId) =>
|
||||
addedNodeIds.has(nodeId) && isSelectableUnresolvedUnknown(graph, nodeId),
|
||||
);
|
||||
}
|
||||
|
||||
function collectPatternCompatibilityDiagnostics({
|
||||
graph,
|
||||
activePattern,
|
||||
@@ -3677,6 +3712,35 @@ export function applyValidatedProposal({
|
||||
const interactionSummary = propagationResult.interactionSummary;
|
||||
const propagationReason = propagationResult.reason;
|
||||
|
||||
// Bounded model-selection honour: prefer a model-selected target only when it
|
||||
// is still valid, was added in this proposal turn, and has no unresolved
|
||||
// same-proposal-added unknown prerequisite via depends_on. Otherwise fall
|
||||
// through to existing deterministic selection unchanged.
|
||||
if (validatedProposal.selectedQuestion?.nodeId) {
|
||||
const candidateNodeId = validatedProposal.selectedQuestion.nodeId;
|
||||
|
||||
const candidateWasAddedThisProposal = (
|
||||
validatedProposal.addedNodes || []
|
||||
).some((node) => node.id === candidateNodeId);
|
||||
|
||||
if (
|
||||
isSelectableUnresolvedUnknown(updatedSituationGraph, candidateNodeId) &&
|
||||
candidateWasAddedThisProposal &&
|
||||
!hasUnresolvedSameProposalDependsOnPrerequisite({
|
||||
graph: updatedSituationGraph,
|
||||
proposal: validatedProposal,
|
||||
targetNodeId: candidateNodeId,
|
||||
})
|
||||
) {
|
||||
deterministicSelection = {
|
||||
status: "selected",
|
||||
nodeId: candidateNodeId,
|
||||
reason:
|
||||
"Honoured the model-selected unresolved unknown as preferred target because it was added in this proposal and has no unresolved same-proposal depends_on prerequisite.",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
deterministicSelection?.status === "selected" &&
|
||||
deterministicSelection?.nodeId
|
||||
|
||||
@@ -116,7 +116,7 @@ The JSON object must contain exactly these top-level fields:
|
||||
13a. For every new unknown node, include at least one added edge that connects it to an existing updated/resolved node or to a newly added non-unknown node introduced from the answer.
|
||||
14. Do not invent evidence.
|
||||
15. Do not create unsupported causal edges.
|
||||
16. When your proposal adds one or more new unresolved unknowns (status !== 'resolved'), you MUST include a selectedQuestion identifying one of those as a candidate unknown node. The engine validates your candidate and retains deterministic final-priority selection; your candidate does not need to be the highest-scoring unknown — it only needs to be a valid unresolved unknown that exists in the graph or in addedNodes.
|
||||
16. When your proposal adds one or more new unresolved unknowns (status !== 'resolved'), you MUST include a selectedQuestion identifying one of those as a candidate unknown node. The engine validates your candidate and retains deterministic prerequisite ordering, fallback selection, and formulation authority; prefer nodes with no unresolved depends_on prerequisites from same-proposal additions. Your candidate does not need to be the highest-scoring unknown — it only needs to be a valid unresolved unknown that exists in the graph or in addedNodes.
|
||||
17. selectedQuestion.nodeId must reference an unresolved unknown node that exists either already in the graph or in addedNodes.
|
||||
18. selectedQuestion.question must be one narrow non-compound question about that one unknown.
|
||||
19. Do not prioritise downstream implementation, pricing, optimisation, or speculative branches ahead of prerequisite definitions, actors, success criteria, constraints, measures, or terminology.
|
||||
@@ -169,7 +169,7 @@ When answerMeaning.userSupportedMeaning is populated you MUST set structuralActi
|
||||
- If the answer creates a more specific decision situation, add the smallest set of new nodes and edges needed to represent that situation and only its most consequential unknowns.
|
||||
- If you add a new unknown, do not leave it floating: connect it with an added edge to the relevant decision/context node created or updated from the answer.
|
||||
- If you add a new unknown, its description must do two jobs in one sentence: what is unknown, and why resolving it matters for the case.
|
||||
- When selectedQuestion is provided, your role ends at supplying one valid unresolved unknown node from the graph or addedNodes — the engine retains deterministic final-priority selection and may choose a different question if multiple candidates exist.
|
||||
- When selectedQuestion is provided, identify the specific material continuation factor as selectedQuestion.nodeId; the engine retains deterministic prerequisite ordering, validation, and formulation authority — it favours your selected node when it has no unresolved depends_on prerequisites from same-proposal additions, falls back to existing deterministic selection otherwise, and may choose a different question if structural constraints require.
|
||||
- If rule #6 does not apply (the answer contains no user-supported meaning that requires graph progress) and there is no other justification for change, return empty arrays for every category.
|
||||
- If rule #6 applies but you choose an update/refinement of existing structure, resolve an existing unknown, or add justified new structure, your structural proposal plus answerMeaning together represent the complete response — answerMeaning preserves semantic fidelity while structural mutation handles graph progress; neither replaces the other.
|
||||
- If you add a new unknown with addedNodes, connect it with at least one addedEdge to an existing updated/resolved node or to a newly added non-unknown node from the answer.
|
||||
|
||||
Reference in New Issue
Block a user