feat(graph): add structuralActionRequired contract (57J.67)
- Add structuralActionRequired field to graphUpdateSchema (optional boolean nullable) - Validate declaration consistency in validateGraphUpdate(): - true requires meaningful mutation (addedNodes/updatedNodes/addedEdges) - false permits intentional no-op when userSupportedMeaning populated - null/absent with meaning → reject - true/false mismatch on output shape → reject - preserve legacy no-op guard for non-contract paths - Update prompt-builder: add field to required list, insert contract section between rules and Additional Guidance with two mandatory sentences - 50 new tests: schema validation (4), prompt builder content checks (10), utils contract matrix (10), plus 26 existing suite migrations All 197 graph tests pass.
This commit is contained in:
@@ -80,6 +80,7 @@ The JSON object must contain exactly these top-level fields:
|
||||
- affectedNodeIds
|
||||
- selectedQuestion
|
||||
- answerMeaning
|
||||
- structuralActionRequired
|
||||
|
||||
## Required Shapes
|
||||
- addedNodes: array of nodes using these exact keys:
|
||||
@@ -95,6 +96,7 @@ The JSON object must contain exactly these top-level fields:
|
||||
nodeId, question, reason
|
||||
- answerMeaning: either null or an object using these exact keys:
|
||||
userSupportedMeaning, possibleInference, supportCategory, resolutionGuidance
|
||||
- structuralActionRequired: boolean (required when userSupportedMeaning is populated)
|
||||
|
||||
## Proposal Rules
|
||||
1. Propose changes only. Never return a replacement graph.
|
||||
@@ -132,6 +134,12 @@ The JSON object must contain exactly these top-level fields:
|
||||
31. If the answer explicitly states a hard constraint, state that directly in userSupportedMeaning.
|
||||
32. Populate resolutionGuidance when the user's meaning genuinely implies must_remain_unresolved, may_resolve, or must_resolve. Keep it null only when no existing resolution state actually applies.
|
||||
|
||||
## Contract: structuralActionRequired Declaration Rule
|
||||
|
||||
When answerMeaning.userSupportedMeaning is populated you MUST set structuralActionRequired to match what your proposal outputs:
|
||||
- Set structuralActionRequired = true if and only if your proposal adds nodes, updates node status/value, or modifies edges (addedNodes.length > 0, updatedNodes with a meaningful change, or addedEdges.length > 0).
|
||||
- Set structuralActionRequired = false if and only if your proposal has zero structural mutations — the two sentences are an intentional no-op declaration.
|
||||
|
||||
## Additional Guidance
|
||||
- If the answer only clarifies an existing unknown, prefer updatedNodes and resolvedUnknownNodeIds over creating duplicate nodes.
|
||||
- When rule #6 applies to explicitly unresolved uncertainty: first check whether an existing unresolved node already represents the same uncertainty; if so, update/refine that existing structure rather than adding a duplicate; if no such node exists, add a new unknown that directly represents the unresolved uncertainty; do not use an edge alone to represent a previously unrepresented uncertainty.
|
||||
|
||||
Reference in New Issue
Block a user