Bug Description
templates/commands/taskstoissues.md and templates/commands/converge.md disagree on the task-ID format, so /speckit.taskstoissues silently skips convergence tasks numbered T1000 and above.
Producer — converge.md:206 assigns IDs with:
zero-padded IDs `T{M+1:03d}, T{M+2:03d}, …`
03d is a minimum field width, not a cap, so once the task count passes 999 this correctly produces 4-digit IDs (T999 → T1000).
Consumer — taskstoissues.md:67 defines task IDs as "a T followed by three digits, e.g. T001" and matches issue titles with:
task ID pattern `\bT\d{3}\b`
\d{3} with a trailing \b matches exactly three digits. Given T1000, the \b after \d{3} fails (position between 0 and 0 is not a word boundary), so there is no match at all.
The consequence is a silent no-op rather than an error: affected tasks are neither deduplicated against existing issues nor converted into new ones.
Steps to Reproduce
- In a project whose
tasks.md already contains more than 999 tasks, run /speckit.converge.
- Convergence appends a
## Phase N: Convergence section with IDs at T1000+ (per converge.md step 3).
- Run
/speckit.taskstoissues.
- No issues are created for the
T1000+ tasks, and re-running does not report them as already having issues.
A large tasks.md is awkward to stage by hand; the mismatch is also visible directly by testing the documented pattern against the documented ID format:
import re
re.search(r"\bT\d{3}\b", "T1000: example task") # -> None
re.search(r"\bT\d{3,}\b", "T1000: example task") # -> matches "T1000"
Expected Behavior
Any task ID that converge.md can emit should be recognized by taskstoissues.md — including IDs longer than three digits — so dedup and issue creation cover every task.
Actual Behavior
Tasks with IDs >= T1000 are invisible to taskstoissues: not extracted, not deduplicated, not converted. No warning or error is emitted, so the run appears to have succeeded completely.
Proposed Fix
Widen the quantifier to three-or-more digits in taskstoissues.md:
-task ID pattern `\bT\d{3}\b`
+task ID pattern `\bT\d{3,}\b`
and update the accompanying prose from "a T followed by three digits" to "at least three digits".
One note on the existing rationale, which reads:
word boundaries so tokens like ST001 or T0010 are not matched by mistake
Both guards still hold under \d{3,}, but for slightly different reasons, so the comment is worth rewording:
ST001 — still unmatched. There is no \b between S and T (both word characters), independent of the quantifier.
T0010 — now captured as the whole token T0010 rather than being rejected. The trailing \b forces the full digit run to be consumed, so T001 can never match as a prefix of T0010. This is safe because matched IDs are intersected with the ID set built from tasks.md, so a token that is not a real task ID matches nothing.
It may also be worth stating the ID contract explicitly in converge.md (that 03d is a floor and consumers must accept \bT\d{3,}\b), so the producer and consumer cannot drift apart again.
Happy to open a PR for this if useful.
Specify CLI Version
0.14.3 (templates installed recorded 0.14.5.dev0). Also confirmed present on main today and in v0.14.4: templates/commands/taskstoissues.md:67 and templates/commands/converge.md:206.
AI Agent
Claude Code
Operating System
Windows 11 (10.0.22631)
Python Version
Python 3.14.6
Additional Context
Found during review of a fresh specify init rather than at runtime, so the T1000+ threshold was never actually hit in our project — the impact is latent for anyone whose tasks.md grows past 999 tasks. Severity is low for that reason, but the failure mode is silent, which makes it easy to miss when it does occur.
Bug Description
templates/commands/taskstoissues.mdandtemplates/commands/converge.mddisagree on the task-ID format, so/speckit.taskstoissuessilently skips convergence tasks numberedT1000and above.Producer —
converge.md:206assigns IDs with:03dis a minimum field width, not a cap, so once the task count passes 999 this correctly produces 4-digit IDs (T999→T1000).Consumer —
taskstoissues.md:67defines task IDs as "aTfollowed by three digits, e.g.T001" and matches issue titles with:\d{3}with a trailing\bmatches exactly three digits. GivenT1000, the\bafter\d{3}fails (position between0and0is not a word boundary), so there is no match at all.The consequence is a silent no-op rather than an error: affected tasks are neither deduplicated against existing issues nor converted into new ones.
Steps to Reproduce
tasks.mdalready contains more than 999 tasks, run/speckit.converge.## Phase N: Convergencesection with IDs atT1000+ (perconverge.mdstep 3)./speckit.taskstoissues.T1000+ tasks, and re-running does not report them as already having issues.A large
tasks.mdis awkward to stage by hand; the mismatch is also visible directly by testing the documented pattern against the documented ID format:Expected Behavior
Any task ID that
converge.mdcan emit should be recognized bytaskstoissues.md— including IDs longer than three digits — so dedup and issue creation cover every task.Actual Behavior
Tasks with IDs
>= T1000are invisible totaskstoissues: not extracted, not deduplicated, not converted. No warning or error is emitted, so the run appears to have succeeded completely.Proposed Fix
Widen the quantifier to three-or-more digits in
taskstoissues.md:and update the accompanying prose from "a
Tfollowed by three digits" to "at least three digits".One note on the existing rationale, which reads:
Both guards still hold under
\d{3,}, but for slightly different reasons, so the comment is worth rewording:ST001— still unmatched. There is no\bbetweenSandT(both word characters), independent of the quantifier.T0010— now captured as the whole tokenT0010rather than being rejected. The trailing\bforces the full digit run to be consumed, soT001can never match as a prefix ofT0010. This is safe because matched IDs are intersected with the ID set built fromtasks.md, so a token that is not a real task ID matches nothing.It may also be worth stating the ID contract explicitly in
converge.md(that03dis a floor and consumers must accept\bT\d{3,}\b), so the producer and consumer cannot drift apart again.Happy to open a PR for this if useful.
Specify CLI Version
0.14.3 (templates installed recorded
0.14.5.dev0). Also confirmed present onmaintoday and inv0.14.4:templates/commands/taskstoissues.md:67andtemplates/commands/converge.md:206.AI Agent
Claude Code
Operating System
Windows 11 (10.0.22631)
Python Version
Python 3.14.6
Additional Context
Found during review of a fresh
specify initrather than at runtime, so the T1000+ threshold was never actually hit in our project — the impact is latent for anyone whosetasks.mdgrows past 999 tasks. Severity is low for that reason, but the failure mode is silent, which makes it easy to miss when it does occur.