@evomap/evolver 1.69.12 → 1.69.13

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.
@@ -110,18 +110,51 @@ function geneToSkillMd(gene) {
110
110
  if (gene.strategy && gene.strategy.length > 0) {
111
111
  lines.push('## Strategy');
112
112
  lines.push('');
113
- gene.strategy.forEach(function (step, i) {
113
+ var stepIdx = 0;
114
+ gene.strategy.forEach(function (step) {
114
115
  var text = String(step);
116
+ // Defensive: legacy genes may still carry "AVOID: ..." steps from
117
+ // pre-2026-04-21 distillations. Skip them from Strategy -- the dedicated
118
+ // "## Avoid" section below renders them correctly.
119
+ if (/^\s*AVOID\s*[:\-]/i.test(text)) return;
120
+ stepIdx += 1;
115
121
  var verb = extractStepVerb(text);
116
122
  if (verb) {
117
- lines.push((i + 1) + '. **' + verb + '** -- ' + stripLeadingVerb(text));
123
+ lines.push(stepIdx + '. **' + verb + '** -- ' + stripLeadingVerb(text));
118
124
  } else {
119
- lines.push((i + 1) + '. ' + text);
125
+ lines.push(stepIdx + '. ' + text);
120
126
  }
121
127
  });
122
128
  lines.push('');
123
129
  }
124
130
 
131
+ // -- Avoid (anti-patterns, pitfalls, hard "do not" rules) --
132
+ // Prefer the top-level `avoid` field (post-2026-04-21 genes). Fall back to
133
+ // legacy "AVOID: ..." steps embedded in strategy so pre-existing genes still
134
+ // surface their anti-patterns in the right section.
135
+ var avoidItems = [];
136
+ if (Array.isArray(gene.avoid)) {
137
+ gene.avoid.forEach(function (a) {
138
+ var s = String(a || '').trim();
139
+ if (s) avoidItems.push(s);
140
+ });
141
+ }
142
+ if (avoidItems.length === 0 && Array.isArray(gene.strategy)) {
143
+ gene.strategy.forEach(function (step) {
144
+ var text = String(step);
145
+ var m = text.match(/^\s*AVOID\s*[:\-]\s*(.+)$/i);
146
+ if (m) avoidItems.push(m[1].trim());
147
+ });
148
+ }
149
+ if (avoidItems.length > 0) {
150
+ lines.push('## Avoid');
151
+ lines.push('');
152
+ avoidItems.forEach(function (a) {
153
+ lines.push('- ' + a);
154
+ });
155
+ lines.push('');
156
+ }
157
+
125
158
  // -- Constraints --
126
159
  if (gene.constraints) {
127
160
  lines.push('## Constraints');
@@ -171,11 +204,23 @@ function geneToSkillMd(gene) {
171
204
  * e.g. "Verify Cursor CLI installation" -> "Verify"
172
205
  * "Run `npm test` to check" -> "Run"
173
206
  * "Configure non-interactive mode" -> "Configure"
207
+ *
208
+ * Excludes anti-pattern markers ("AVOID", "DON'T", "NEVER", ...) so they never
209
+ * get bolded as if they were real action verbs. These should be rendered as
210
+ * anti-pattern list items in the dedicated "## Avoid" section instead.
174
211
  */
175
212
  function extractStepVerb(step) {
213
+ var ANTI_PATTERN_MARKERS = /^(AVOID|DO|DON'?T|NEVER|NOT|STOP|SKIP|IGNORE|FORBIDDEN|WARN|WARNING|CAUTION|NOTE)\b/i;
214
+ if (ANTI_PATTERN_MARKERS.test(step)) return '';
176
215
  // Only match a capitalized verb at the very start (no leading backtick/special chars)
177
216
  var match = step.match(/^([A-Z][a-z]+)/);
178
- return match ? match[1] : '';
217
+ if (!match) return '';
218
+ // Extra safety: do not treat single-capital-letter + no-lowercase abbreviations
219
+ // (already filtered by the [a-z]+ requirement) or common non-verbs like
220
+ // "The", "This", "These", "Those" as verbs.
221
+ var DETERMINERS = new Set(['The', 'This', 'These', 'Those', 'That', 'A', 'An']);
222
+ if (DETERMINERS.has(match[1])) return '';
223
+ return match[1];
179
224
  }
180
225
 
181
226
  /**