agentxchain 2.155.30 → 2.155.31
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/package.json +1 -1
- package/src/lib/governed-state.js +68 -0
package/package.json
CHANGED
|
@@ -6967,6 +6967,12 @@ function evaluateIntentCoverage(turnResult, intakeContext, { state = null, confi
|
|
|
6967
6967
|
continue;
|
|
6968
6968
|
}
|
|
6969
6969
|
|
|
6970
|
+
const roadmapCoverage = evaluateRoadmapDerivedConditionalCoverage(item, turnResult, intakeContext, state);
|
|
6971
|
+
if (roadmapCoverage === true) {
|
|
6972
|
+
addressed.push(item);
|
|
6973
|
+
continue;
|
|
6974
|
+
}
|
|
6975
|
+
|
|
6970
6976
|
// Check 1: Structural — intent_response field with explicit status
|
|
6971
6977
|
const structuralEntry = responseMap.get(normalizedItem);
|
|
6972
6978
|
if (structuralEntry && ['addressed', 'deferred', 'rejected'].includes(structuralEntry.status)) {
|
|
@@ -7050,6 +7056,68 @@ function evaluateIdleExpansionConditionalCoverage(item, turnResult, intakeContex
|
|
|
7050
7056
|
return null;
|
|
7051
7057
|
}
|
|
7052
7058
|
|
|
7059
|
+
// ── Roadmap-derived intent conditional coverage (BUG-80) ────────────────────
|
|
7060
|
+
//
|
|
7061
|
+
// Roadmap-derived intents (charter starts with "[roadmap]") include literal
|
|
7062
|
+
// implementation text as acceptance items. PM turns in planning phase produce
|
|
7063
|
+
// charter/scoping artifacts, not implementation code, so the generic 50%
|
|
7064
|
+
// keyword-overlap check fails. This function provides phase-aware evaluation:
|
|
7065
|
+
// - "Evidence source:" items are metadata provenance → always addressed
|
|
7066
|
+
// - "Unchecked roadmap item completed:" in planning phase → milestone-mention check
|
|
7067
|
+
// - In implementation+ phases → falls through to normal semantic matching
|
|
7068
|
+
|
|
7069
|
+
function evaluateRoadmapDerivedConditionalCoverage(item, turnResult, intakeContext, state) {
|
|
7070
|
+
const charter = intakeContext?.charter || '';
|
|
7071
|
+
if (!charter.startsWith('[roadmap]')) {
|
|
7072
|
+
return null;
|
|
7073
|
+
}
|
|
7074
|
+
|
|
7075
|
+
const normalizedItem = typeof item === 'string' ? item.toLowerCase().trim() : '';
|
|
7076
|
+
|
|
7077
|
+
// "Evidence source:" items are provenance metadata, not deliverables.
|
|
7078
|
+
// No turn of any role can "address" a file path reference.
|
|
7079
|
+
if (normalizedItem.startsWith('evidence source:')) {
|
|
7080
|
+
return true;
|
|
7081
|
+
}
|
|
7082
|
+
|
|
7083
|
+
// "Unchecked roadmap item completed:" contains literal implementation text.
|
|
7084
|
+
// In planning phase, PM scopes the milestone — check for milestone mention
|
|
7085
|
+
// rather than requiring implementation-keyword overlap.
|
|
7086
|
+
// In implementation/qa/launch phases, fall through to normal semantic matching
|
|
7087
|
+
// so dev turns are still evaluated against actual implementation keywords.
|
|
7088
|
+
if (normalizedItem.startsWith('unchecked roadmap item completed:')) {
|
|
7089
|
+
const currentPhase = state?.phase || '';
|
|
7090
|
+
if (currentPhase !== 'planning') {
|
|
7091
|
+
return null;
|
|
7092
|
+
}
|
|
7093
|
+
|
|
7094
|
+
// Extract milestone section identifier from charter: "[roadmap] M28: ..."
|
|
7095
|
+
const sectionMatch = charter.match(/\[roadmap\]\s*(M\d+)/i);
|
|
7096
|
+
if (!sectionMatch) {
|
|
7097
|
+
return null;
|
|
7098
|
+
}
|
|
7099
|
+
|
|
7100
|
+
const milestoneId = sectionMatch[1].toLowerCase();
|
|
7101
|
+
|
|
7102
|
+
// Build a searchable corpus from the turn result
|
|
7103
|
+
const corpus = [
|
|
7104
|
+
turnResult.summary || '',
|
|
7105
|
+
...(turnResult.decisions || []).map(d => `${d.statement || ''} ${d.rationale || ''}`),
|
|
7106
|
+
...(turnResult.objections || []).map(o => o.statement || ''),
|
|
7107
|
+
...(turnResult.files_changed || []),
|
|
7108
|
+
...(turnResult.artifacts_created || []),
|
|
7109
|
+
...(Array.isArray(turnResult.intent_response)
|
|
7110
|
+
? turnResult.intent_response.map(r => `${r.item || ''} ${r.detail || ''}`)
|
|
7111
|
+
: []),
|
|
7112
|
+
].join('\n').toLowerCase();
|
|
7113
|
+
|
|
7114
|
+
// If the turn mentions the milestone section ID, the item is addressed
|
|
7115
|
+
return corpus.includes(milestoneId);
|
|
7116
|
+
}
|
|
7117
|
+
|
|
7118
|
+
return null;
|
|
7119
|
+
}
|
|
7120
|
+
|
|
7053
7121
|
export {
|
|
7054
7122
|
STATE_PATH,
|
|
7055
7123
|
HISTORY_PATH,
|