Módulo 7: Strategy To Roadmap

El puente estrategia-roadmap

Descripción

Todo lo que construiste en este módulo —la traducción a apuestas (lección 2), el filtro (lección 3), la trampa del RICE alto (lección 4), la coherencia (lección 5), el NO explícito (lección 6)— converge en esta lección hacia una sola pregunta final: una vez que el filtro decidió quién compite, ¿qué decide el orden? La respuesta no es nueva — es, literalmente, el riceScore que ya conoces de product-thinking-for-engineers-guide. Lo único que cambia es cuándo se aplica: nunca antes del filtro, siempre después.

Conexión con el módulo. Esta lección no construye ningún mecanismo nuevo — conecta, de forma explícita y con código, dos piezas que hasta ahora vivían en guías distintas: strategicFilter (esta guía) decide quién entra a la conversación de prioridad; riceScore y prioritize (product-thinking-for-engineers-guide, módulo 3) deciden en qué orden, solo entre quienes ya entraron. Es el puente literal que le da nombre al módulo.

Una analogía cotidiana: la carrera de relevos, calificación antes que orden de llegada

Antes de que una carrera de relevos empiece, cada equipo tiene que calificar: cumplir el reglamento de la categoría —número correcto de corredores, edad, peso del equipo, lo que sea que la categoría exija—. La calificación no le importa nada del tiempo que el equipo puede correr; solo pregunta si tiene derecho a estar en la pista. Una vez que los equipos calificados están alineados en la línea de salida, entra un criterio completamente distinto: el cronómetro, que decide, entre los que sí calificaron, quién llega primero.

Un equipo con el mejor tiempo de práctica de toda la temporada, que no calificó por no cumplir el reglamento, no corre — sin importar cuán rápido sea. Y un equipo que apenas calificó, con un tiempo de práctica modesto, sí tiene la oportunidad de correr y, quién sabe, sorprender el día de la carrera. La calificación y el cronómetro son dos preguntas distintas, en dos momentos distintos, y ningún juez serio las mezcla. El filtro estratégico es la calificación. RICE es el cronómetro. Esta lección es la pista donde, por fin, ves a los dos trabajando juntos, en el orden correcto.

Ejemplo trabajado: el filtro decide quién corre, RICE decide en qué orden

Corremos las dos funciones en secuencia, sin mezclarlas nunca: primero strategicFilter sobre el backlog completo, para obtener la lista de apuestas elegibles; después prioritize —la misma función, sin cambios, de product-thinking-for-engineers-guide, módulo 3— aplicada solo sobre esa lista de elegibles, para obtener el roadmap final ya ordenado.

function riceScore({ reach, impact, confidence, effort }) {
  return (reach * impact * confidence) / effort;
}

function strategicFilter(backlog, strategy) {
  return backlog.map((bet) => {
    const reinforces = bet.servesDimensions.filter((d) => strategy.winOn.includes(d));
    const conflicts = bet.servesDimensions.filter((d) => strategy.avoid.includes(d));
    return {
      feature: bet.feature,
      servesDimensions: bet.servesDimensions,
      reinforces,
      conflicts,
      inStrategy: reinforces.length > 0 && conflicts.length === 0,
      riceScore: Number(riceScore(bet.rice).toFixed(2)),
    };
  });
}

// prioritize() es la misma funcion de product-thinking-for-engineers-guide
// (modulo 3), sin cambios -- aqui solo se aplica DESPUES del filtro, no antes.
function prioritize(items) {
  return items.slice().sort((a, b) => b.riceScore - a.riceScore);
}

const mercadoStrategy = { winOn: ['curatedDiscovery', 'sellerTrust'], avoid: ['price'] };

const backlog = [
  { feature: 'fasterCheckout', servesDimensions: ['convenience'], rice: { reach: 8000, impact: 2, confidence: 0.8, effort: 2 } },
  { feature: 'recommendations', servesDimensions: ['curatedDiscovery'], rice: { reach: 5000, impact: 1, confidence: 0.5, effort: 3 } },
  { feature: 'sellerTools', servesDimensions: ['sellerTrust'], rice: { reach: 1200, impact: 2, confidence: 0.8, effort: 2 } },
  { feature: 'reviews', servesDimensions: ['sellerTrust'], rice: { reach: 6000, impact: 0.5, confidence: 0.8, effort: 1 } },
  { feature: 'improvedSearch', servesDimensions: ['catalogBreadth'], rice: { reach: 9000, impact: 1, confidence: 0.5, effort: 3 } },
  { feature: 'lowestPriceMatch', servesDimensions: ['price'], rice: { reach: 9500, impact: 3, confidence: 0.8, effort: 3 } },
];

console.log('=== Paso 1 (este modulo): el filtro estrategico decide QUIEN compite ===\n');
const filtered = strategicFilter(backlog, mercadoStrategy);
const eligible = filtered.filter((b) => b.inStrategy);
console.log('Elegibles para el roadmap: ' + eligible.map((b) => b.feature).join(', '));

console.log('\n=== Paso 2 (product-thinking, modulo 3): RICE decide el ORDEN, solo entre elegibles ===\n');
const roadmap = prioritize(eligible);
console.table(roadmap.map((b) => ({ feature: b.feature, riceScore: b.riceScore })));

console.log('El roadmap final de Mercado: ' + roadmap.map((b) => b.feature).join(' > ') + '.');

Qué esperar. Al correr el archivo con Node, la salida es exactamente esta:

=== Paso 1 (este modulo): el filtro estrategico decide QUIEN compite ===

Elegibles para el roadmap: recommendations, sellerTools, reviews

=== Paso 2 (product-thinking, modulo 3): RICE decide el ORDEN, solo entre elegibles ===

┌─────────┬───────────────────┬───────────┐
│ (index) │      feature      │ riceScore │
├─────────┼───────────────────┼───────────┤
│    0    │     'reviews'     │   2400    │
│    1    │   'sellerTools'   │    960    │
│    2    │ 'recommendations' │  833.33   │
└─────────┴───────────────────┴───────────┘
El roadmap final de Mercado: reviews > sellerTools > recommendations.

Fíjate en el orden exacto de las dos secciones del código, porque es el argumento entero de esta lección, hecho estructura: strategicFilter corre primero y produce eligible — tres apuestas, sin ningún orden todavía entre ellas—. Solo después, prioritize recibe esa lista ya filtrada, nunca el backlog completo, y produce el orden final: reviews primero (el mejor riceScore entre los elegibles, 2400), después sellerTools (960), después recommendations (833.33). Si compararas este roadmap final con el ranking íntegro de la lección 4 —donde lowestPriceMatch y fasterCheckout ocupaban el primer y segundo lugar—, vas a notar que ninguna de esas dos apuestas aparece aquí, en ningún lugar del roadmap, ni siquiera al final. No están "de últimas" — están fuera, porque nunca llegaron a competir por un lugar en el orden.

Ese es, en una frase, el puente completo: product-thinking-for-engineers-guide te enseñó a construir el cronómetro (riceScore, prioritize) con precisión y honestidad. Esta guía te enseñó a construir la línea de calificación (strategicFilter) que decide quién tiene derecho a correr. Ningún equipo serio de producto usa solo uno de los dos — el cronómetro sin calificación premia lo más rápido, sin importar si pertenece a la carrera; la calificación sin cronómetro te dice quién puede correr, pero nunca en qué orden.

Profundización: por qué el orden de las dos funciones nunca se invierte

Vale la pena preguntarse qué pasaría si invirtieras el orden: correr prioritize sobre el backlog completo primero, y aplicar strategicFilter después, solo sobre el resultado ya ordenado. Numéricamente, el conjunto final de apuestas elegibles sería idéntico —strategicFilter no depende del orden en que llegan las apuestas, solo evalúa cada una por separado—. Pero el proceso sería peor, y de una forma muy concreta: si el equipo ve primero el ranking completo por RICE, con lowestPriceMatch liderando por un margen enorme, ese número ya generó una expectativa, una conversación, quizás hasta una promesa a un stakeholder, antes de que nadie pregunte si pertenece a la estrategia. El filtro, aplicado después, tendría que revertir una decisión que ya empezó a tomar forma, en vez de prevenirla desde el inicio.

Esta es la razón por la que la lección 4 insistió tanto en que la etiqueta servesDimensions se decide antes de calcular RICE, y por la que esta lección corre strategicFilter como el primer paso, sin excepción. No es solo una preferencia de estilo de código — es una disciplina de proceso: la pregunta de pertenencia tiene que hacerse cuando todavía no hay un número atractivo compitiendo por la atención de nadie.

Errores comunes

Confundir el filtro estratégico con la priorización táctica. Qué pasa: un equipo trata strategicFilter y prioritize como si fueran la misma pregunta con dos nombres distintos, o peor, cree que aplicar RICE ya incluye, de alguna forma, la evaluación estratégica. Por qué pasa: ambas funciones terminan produciendo un orden o una lista, y esa similitud superficial de forma —ambas devuelven "las apuestas que importan"— esconde que responden preguntas completamente distintas con inputs completamente distintos. Cómo detectarlo: pregunta a tu equipo, sobre cualquier apuesta del roadmap actual, "¿pasó primero por una evaluación de pertenencia estratégica, o solo por un cálculo de RICE?" — si nadie puede distinguir las dos evaluaciones, probablemente solo se hizo una. Cómo corregirlo: mantén los dos pasos separados y en el orden de esta lección, siempre — filtro primero, sin excepción, RICE después, solo entre quienes pasaron.

Correr RICE antes del filtro "para no perder tiempo". Qué pasa: bajo presión de tiempo, un equipo calcula RICE sobre el backlog completo primero —es más rápido, ya tienen la fórmula automatizada— con la intención de "filtrar después, si hace falta", y termina, en la práctica, nunca volviendo a aplicar el filtro porque el ranking por RICE ya se sintió como una decisión tomada. Por qué pasa: calcular RICE es mecánico y rápido; evaluar pertenencia estratégica exige juicio, y bajo presión, lo mecánico siempre gana el turno primero. Cómo detectarlo: si tu proceso de planeación de trimestre empieza con una hoja de cálculo de RICE y el filtro estratégico aparece, si acaso, como una revisión posterior opcional, el orden ya está invertido. Cómo corregirlo: haz del filtro estratégico el primer paso obligatorio del proceso de planeación, no una revisión de conciencia que se hace "si sobra tiempo" — la lección 4 mostró exactamente cuánto cuesta invertir el orden.

Aplicar el filtro una sola vez al trimestre y no revisarlo cuando la estrategia cambia. Qué pasa: el equipo define mercadoStrategy una vez, la codifica, y sigue usándola sin cuestionarla trimestre tras trimestre, incluso después de que el módulo 5 (competencia) o el módulo 6 (moats) de esta misma guía revelaran que el panorama cambió. Por qué pasa: una vez que strategicFilter está funcionando y produciendo resultados consistentes, se siente como una pieza de infraestructura terminada, no como una hipótesis viva que necesita revisión. Cómo detectarlo: si winOn y avoid no han cambiado en más de un año, a pesar de que el panorama competitivo sí cambió (como viste en el módulo 5, con la proyección a tres años de competitiveMap), el filtro puede estar corriendo sobre una estrategia obsoleta. Cómo corregirlo: revisa mercadoStrategy con la misma cadencia con la que revisas el panorama competitivo y los moats — el filtro es tan bueno como la estrategia que lo alimenta, y una estrategia que ya no refleja el terreno real deja de proteger contra nada.

Ejercicios

Ejercicio 1 — Verifica el resultado sin correr Node. Sin ejecutar el código, calcula a mano el riceScore de las tres apuestas elegibles (recommendations, sellerTools, reviews) y ordénalas. ¿Coincide tu resultado con la salida del ejemplo trabajado?

Ver solución

recommendations: (5000 × 1 × 0.5) / 3 = 2500 / 3 = 833.33. sellerTools: (1200 × 2 × 0.8) / 2 = 1920 / 2 = 960. reviews: (6000 × 0.5 × 0.8) / 1 = 2400 / 1 = 2400. Ordenadas de mayor a menor: reviews (2400) > sellerTools (960) > recommendations (833.33) — exactamente el orden de la tabla del ejemplo trabajado. El ejercicio confirma algo importante: prioritize, aplicado sobre las tres apuestas elegibles, es la misma fórmula de siempre, sin ningún ajuste especial — el filtro no cambia cómo se calcula RICE, solo decide sobre qué subconjunto se calcula.

Ejercicio 2 — Simula un cambio de capacidad. Con el roadmap final (reviews > sellerTools > recommendations, con effort de 1, 2 y 3 respectivamente) y una capacidad de 4 person-months este trimestre (menor que los 6 de product-thinking-for-engineers-guide), ¿qué apuestas entran, tomándolas en ese orden?

Ver solución

reviews (effort: 1, acumulado 1), sellerTools (effort: 2, acumulado 3), y de recommendations (effort: 3) solo cabría si quedara espacio — 3 + 3 = 6 > 4, así que no entra completa. Con 4 person-months, el equipo construye reviews y sellerTools, usando 3 de los 4 disponibles, y deja recommendations para el siguiente trimestre — no porque no pertenezca a la estrategia (si pertenece, pasó el filtro), sino por una razón puramente táctica de capacidad, exactamente la distinción que la lección 6 enseñó a comunicar con claridad.

Ejercicio 3 — Explica el puente completo a un ingeniero nuevo en el equipo. Un ingeniero que se acaba de unir a Mercado pregunta: "¿por qué no calculamos RICE directamente sobre todo el backlog, como dice la guía de product thinking?". Escribe, en un párrafo, la respuesta que conecta las dos guías.

Ver solución

Un ejemplo de respuesta: "product-thinking-for-engineers-guide te enseña a calcular RICE con rigor, y esa fórmula no cambia nunca, aquí ni en ningún otro lado. Lo que agregamos en esta guía es un paso obligatorio antes: antes de calcular RICE sobre ninguna apuesta, preguntamos si esa apuesta pertenece a la estrategia específica de Mercado — descubrimiento curado y confianza en el vendedor, no precio ni conveniencia genérica—. Si calculáramos RICE sobre todo el backlog sin ese filtro, apuestas como igualar el precio más bajo del mercado saldrían primero, con el mejor número de todos, simplemente porque las palancas de precio mueven a mucha gente — pero no porque nos acerquen al juego que elegimos jugar. El filtro decide quién compite; RICE, aplicado después, decide en qué orden compiten los que sí pertenecen. Las dos herramientas son necesarias, en ese orden, nunca al revés."

Resumen y siguiente paso

Esta lección conectó, con código y sin ambigüedad, las dos guías: strategicFilter decide quién compite por prioridad; prioritize —el mismo riceScore de product-thinking-for-engineers-guide, sin ningún cambio— decide el orden, aplicado exclusivamente sobre quienes ya pasaron el filtro. El roadmap final de Mercado —reviews > sellerTools > recommendations— es el resultado de aplicar las dos herramientas en el orden correcto, y ninguna de las dos apuestas de mayor RICE bruto (lowestPriceMatch, fasterCheckout) aparece en ningún lugar de ese roadmap.

Antes de avanzar deberías poder: explicar, con una frase, por qué el filtro estratégico y RICE nunca se aplican en el orden inverso, y describir qué se pierde si se invierten.

Con esto tienes las seis piezas completas del módulo. La lección 8 —el proyecto— las junta en una sola entrega: el filtro completo sobre el backlog de seis apuestas de Mercado, el roadmap final secuenciado, y la comparación explícita contra lo que RICE puro hubiera elegido, cerrando el arco completo de esta guía.

Recursos

  • Roger Martin, "Decoding the Strategy Choice Cascade" — rogermartin.medium.com/decoding-the-strategy-choice-cascade-475d40555eb1. La cascada completa de Martin termina en las capacidades y los sistemas de gestión concretos — el mismo tipo de puente entre la elección de arriba (estrategia) y la ejecución de abajo (roadmap, RICE) que esta lección construye en código. En inglés.
  • Itamar Gilad, "Why You Should Stop Using Product Roadmaps and Try GIST Planning" — itamargilad.medium.com/why-i-stopped-using-product-roadmaps-and-switched-to-gist-planning-3b7f54e271d1. El marco GIST de Gilad separa explícitamente las metas (Goals), de donde nace el filtro, de los pasos (Steps) y tareas concretas, donde se secuencia el trabajo — la misma separación de capas de esta lección, con otro vocabulario. En inglés.
  • Marty Cagan (Silicon Valley Product Group), "Product Strategy" — svpg.com/product-strategy-overview. Cagan describe el trabajo de estrategia de producto como el puente entre insight y acción del equipo — el puente exacto que esta lección hace explícito entre las dos guías. En inglés.