Purpose placeholder check: case-insensitive `TODO` false-positives on the Spanish word "Todo"
Summary
validate --strict reports PURPOSE_IS_PLACEHOLDER for a Purpose that is fully written, when the prose happens to begin with the Spanish word "Todo" followed by a space. The leading-marker check is case-insensitive, so the ordinary word Todo is read as the English marker TODO.
This is the mirror of #1670: the check added to stop --strict from passing a real placeholder now fails authored prose in non-English specs.
Version
@fission-ai/[email protected]
Where
dist/core/validation/purpose-placeholder.js
const LEADING_MARKER = /^(?:TBD|TODO)(?![\p{L}\p{N}\p{M}_])/iu;Two things combine:
- the
iflag makesTODOmatchTodo,todo,ToDo; - the lookahead only rejects a letter, digit, mark or underscore — a space passes it.
So "Todo el conocimiento del producto…" matches, and the section is reported as an unwritten placeholder.
Reproduce
A main spec whose Purpose is authored prose:
## Purpose
Todo el conocimiento del producto vive del otro lado, en el repo hermano.
Esta pieza es el único puente: una conexión de solo lectura al catálogo.
## Requirements
...openspec validate <capability> --type spec --strict →
⚠ [WARNING] overview: Purpose section is still a placeholder rather than a
Purpose anyone wrote (the sentence `openspec archive` writes for a new
capability, or a `TBD`/`TODO` marker left in its place).The reported line is the first line of authored prose.
Confirming the mechanism against the regex directly:
const LEADING_MARKER = /^(?:TBD|TODO)(?![\p{L}\p{N}\p{M}_])/iu;
LEADING_MARKER.test("Todo el conocimiento del producto…") // true ← false positive
LEADING_MARKER.test("TODO: write this") // true ← correct
LEADING_MARKER.test("TBD") // true ← correct
LEADING_MARKER.test("Todos los candidatos…") // false ← the "s" saves it
LEADING_MARKER.test("El conocimiento del producto…") // falseNote how arbitrary the boundary is: Todo trips it, Todos does not.
Impact
Any spec written in a language where todo is a common word — Spanish and Portuguese most obviously, where it is an extremely frequent sentence opener ("Todo el…", "Todo o…"). OpenSpec does not require specs to be in English, and ours are in Spanish by project convention.
The finding is a WARNING, but it makes the capability invalid and validate --all --strict exits with a failure, so it blocks adopting --strict in CI. In our repo it is 1 failing capability out of 34, entirely from this.
The only workaround is to reword authored prose to appease the linter, which is the wrong way round.
Suggested fix
Either would do; the first looks closer to the check's own intent.
1. Make the leading-marker check case-sensitive. Placeholder markers are conventionally uppercase, and the generated sentence this check also looks for is literally TBD - created by archiving change . Dropping i (or accepting only TBD/TODO/Tbd/Todo… — really just the uppercase forms) removes the collision with ordinary words in any language.
2. Require marker punctuation rather than merely "not a word character". A marker is written TODO:, TODO -, TBD, or alone on its line; it is not written TODO el conocimiento. Requiring [\s]*[:\-–—] or end-of-line after the marker, instead of a negative lookahead that a plain space satisfies, keeps the intent and drops the false positive.
Happy to send a PR for either if you have a preference.
Source: Fission-AI/OpenSpec