roadmapsmith 0.9.11 → 0.9.12
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/validator/index.js +28 -30
package/package.json
CHANGED
package/src/validator/index.js
CHANGED
|
@@ -50,26 +50,23 @@ const GENERIC_TASK_TOKENS = new Set([
|
|
|
50
50
|
'phrases', 'conceptual',
|
|
51
51
|
]);
|
|
52
52
|
|
|
53
|
-
//
|
|
54
|
-
//
|
|
55
|
-
//
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
]);
|
|
53
|
+
// Patterns that indicate the task describes work still to be done, not completed work.
|
|
54
|
+
// Regex form catches verb and noun forms ("Manejo") and two-word constructions ("Recovery path")
|
|
55
|
+
// that an exact-match Set would miss. When a task matches, code token overlap alone cannot pass
|
|
56
|
+
// it — either an Evidence line or high-confidence evidence (code + test) is required.
|
|
57
|
+
const CHANGE_VERB_PATTERNS = [
|
|
58
|
+
// Spanish — verb and noun forms of pending-work descriptions
|
|
59
|
+
/^(agregar|añadir|implementar|configurar|reemplazar|cambiar|corregir|manejar|manejo|proteger|sanitizar|validar|deshabilitar|mostrar|generar|expandir|reducir|completar|crear|eliminar|migrar|refactorizar|recovery\s+path)\b/i,
|
|
60
|
+
// English
|
|
61
|
+
/^(add|implement|configure|replace|change|fix|handle|protect|sanitize|validate|disable|show|generate|expand|reduce|complete|create|remove|migrate|refactor|recovery\s+path)\b/i,
|
|
62
|
+
];
|
|
64
63
|
|
|
65
|
-
function
|
|
64
|
+
function taskDescribesChange(taskText) {
|
|
66
65
|
const normalized = String(taskText)
|
|
67
|
-
.replace(
|
|
68
|
-
.replace(
|
|
69
|
-
.trim()
|
|
70
|
-
|
|
71
|
-
const firstWord = normalized.split(/[\s,;:()[\]]+/)[0] || '';
|
|
72
|
-
return ACTION_VERBS.has(firstWord);
|
|
66
|
+
.replace(/^\*\*\[.*?\]\*\*\s*/, '')
|
|
67
|
+
.replace(/^\[.*?\]\s*/, '')
|
|
68
|
+
.trim();
|
|
69
|
+
return CHANGE_VERB_PATTERNS.some((p) => p.test(normalized));
|
|
73
70
|
}
|
|
74
71
|
|
|
75
72
|
const CANONICAL_FILES = {
|
|
@@ -201,6 +198,7 @@ function hasFileExtension(token) {
|
|
|
201
198
|
|
|
202
199
|
function isLikelyPath(token) {
|
|
203
200
|
if (token.includes('*') || token.includes('?')) return false; // glob/wildcard
|
|
201
|
+
if (/^\/api\//i.test(token)) return false; // HTTP API route paths are not file paths
|
|
204
202
|
if (/^\.{1,2}\/|^\//.test(token)) {
|
|
205
203
|
// Bare "/" or "./" with nothing after is not a real path (e.g. "API / ESC-POS" → "/")
|
|
206
204
|
return /[A-Za-z0-9_]/.test(token);
|
|
@@ -1195,9 +1193,11 @@ function validateTask(task, context, config, plugins) {
|
|
|
1195
1193
|
let confidence = 'low';
|
|
1196
1194
|
if (authoritativeEvidence.passed) {
|
|
1197
1195
|
confidence = authoritativeEvidence.confidence || 'medium';
|
|
1198
|
-
} else if (meetsStrongThreshold) {
|
|
1196
|
+
} else if (meetsStrongThreshold && evidence.test) {
|
|
1197
|
+
// 'high' requires code + test — code + feature-surface alone is 'medium'
|
|
1198
|
+
// so that action-verb tasks (path hint exists but no test) stay gated.
|
|
1199
1199
|
confidence = 'high';
|
|
1200
|
-
} else if (strongEvidenceCount === 1 || hasDirectReferencePass || hasArtifactTaskPass || hasTrustedRuleEvidencePass) {
|
|
1200
|
+
} else if (meetsStrongThreshold || strongEvidenceCount === 1 || hasDirectReferencePass || hasArtifactTaskPass || hasTrustedRuleEvidencePass) {
|
|
1201
1201
|
confidence = 'medium';
|
|
1202
1202
|
}
|
|
1203
1203
|
|
|
@@ -1241,24 +1241,22 @@ function validateTask(task, context, config, plugins) {
|
|
|
1241
1241
|
passed = false;
|
|
1242
1242
|
}
|
|
1243
1243
|
|
|
1244
|
-
// Action-verb gate (Causa 3): unchecked tasks
|
|
1245
|
-
// (Agregar, Configurar, Add, Fix, …) cannot pass on code token overlap alone.
|
|
1246
|
-
//
|
|
1247
|
-
//
|
|
1248
|
-
//
|
|
1249
|
-
// c) grant-evidence from a config rule (hasTrustedRuleEvidencePass), or
|
|
1250
|
-
// d) canonical artifact evidence (hasArtifactTaskPass — e.g. "Add SECURITY.md").
|
|
1244
|
+
// Action-verb gate (Causa 3): unchecked tasks that describe a change to be made
|
|
1245
|
+
// (Agregar, Configurar, Add, Fix, Manejo, Recovery path, …) cannot pass on code token overlap alone.
|
|
1246
|
+
// Requires either: an Evidence line (authoritativeEvidence.passed), high-confidence evidence
|
|
1247
|
+
// (code + test), grant-evidence from config (hasTrustedRuleEvidencePass), or canonical artifact
|
|
1248
|
+
// evidence (hasArtifactTaskPass — e.g. "Add SECURITY.md").
|
|
1251
1249
|
if (
|
|
1252
1250
|
!task.checked &&
|
|
1253
1251
|
passed &&
|
|
1254
|
-
|
|
1252
|
+
taskDescribesChange(task.text) &&
|
|
1255
1253
|
!authoritativeEvidence.passed &&
|
|
1256
1254
|
!hasTrustedRuleEvidencePass &&
|
|
1257
1255
|
!hasArtifactTaskPass &&
|
|
1258
|
-
|
|
1256
|
+
confidence !== 'high'
|
|
1259
1257
|
) {
|
|
1260
1258
|
passed = false;
|
|
1261
|
-
const actionVerbReason = 'action
|
|
1259
|
+
const actionVerbReason = 'action task requires Evidence line or high-confidence evidence (code + test) to be marked complete';
|
|
1262
1260
|
if (!uniqueReasons.includes(actionVerbReason)) {
|
|
1263
1261
|
uniqueReasons.push(actionVerbReason);
|
|
1264
1262
|
}
|