Repository navigation
cy-create-tasks can write an unquoted title containing a colon, and the spec-cycle importer then rejects the whole task set #663
Description
CompozyOS version
compozy 0.3.0-beta.27 (commit 7b62a7cd1)
Still present on the latest release. git log --oneline v0.3.0-beta.25..v0.3.0-beta.27 -- extensions/spec-cycle/ returns no commits, and the template still writes the field unquoted.
Operating system
Linux (x86_64)
Area
Core / daemon, Extensions
ACP agent
Claude Code via ACP
Model / provider
claude-opus-5. Not model-specific: the defect is in the file the skill writes.
Steps to reproduce
Context, since this arrives without one. I have been running a structured comparison of
agent-orchestration tools, and CompozyOS is one of them. This came out of an experiment where the
same task is planned twice and implemented by the same Loop both times. One arm stopped producing
any implementation at all, and this is why.
-
Ask a session to plan a feature whose natural task title contains a colon. Mine came out of
cy-create-specpluscy-create-taskswith no special prompting:Use the cy-create-spec skill and then cy-create-tasks to plan the work below under the slug 'logsum'. -
cy-create-taskswrites.compozy/tasks/logsum/task_01.mdwith this frontmatter:--- status: pending title: Resumo de log: nucleo e CLI (fatia 1 / MVP) type: feature complexity: medium ---
-
Run the Loop that consumes it:
compozy loop run --name implement-tasks --input slug=logsum
What happened, and what did you expect?
The task set cannot be imported, and the Loop never implements anything.
daemon: execute loop action run
task_id = loop.looprun-9e062214c7feff4d.g2.node.load_tasks.0
error = call action tool "ext__spec_cycle__import_tasks":
The task set for .compozy/tasks/logsum/task_*.md could not be imported.
The underlying parser error:
loop: validation failed: parse md_tasks task file "task_01.md":
yaml: line 2: mapping values are not allowed in this context
title: Resumo de log: nucleo e CLI is an unquoted YAML scalar containing : , which opens a
nested mapping. The value is not representable this way, so yaml.Unmarshal fails and the whole
directory is rejected.
So cy-create-tasks writes a file that the spec-cycle importer cannot read. The two halves of
the same bundled extension disagree about the format.
Minimal reproduction, with a negative control
I ran the real importer (importMarkdownTasks) against two directories that differ in one
character pair:
task_01.md frontmatter |
importMarkdownTasks |
|---|---|
title: Resumo de log: nucleo e CLI |
fails: yaml: line 2: mapping values are not allowed in this context |
title: "Resumo de log: nucleo e CLI" |
imports with no error |
Same manifest, same node ids, same everything else. Quoting is the entire difference.
How often it fires, measured rather than assumed
This is intermittent, not systematic, and I want to be precise about it because I got it wrong
in my own notes first.
It fires only when the title the agent chooses happens to contain : . I have since run two more
pre-registered experiments on this path, 14 rounds in total, each one invoking cy-create-spec
plus cy-create-tasks. It did not fire in any of them. Across those rounds the generated
titles were ordinary and colon-free, for example Tolerancia a log fora do formato and
Ranking de repeticao e --top.
So: a maintainer running this once may well not reproduce it. The minimal reproduction above,
with its negative control, is the reliable way to see it, and the template inspection is the
reason it can happen at all. I would not describe it as "the importer is broken"; I would describe
it as "the skill can emit a file the importer refuses, and nothing prevents it".
The experiments that produced this measurement, including the raw per-round records, are public
at https://github.com/jillesmc/spec-method-ab.
Why the skill produces it
extensions/spec-cycle/skills/cy-create-tasks/references/task-template.md shows the field
unquoted, on origin/main:
---
status: pending
title: [Task title]
type: [a standard work-type slug or an approved project-specific lowercase hyphenated slug]
complexity: [low, medium, high, critical]
---Nothing in task-template.md or task-context-schema.md mentions quoting, colons, or YAML
escaping. I searched both for quote, colon, escape and yaml, and the only hits are
structural references to the schema.
The schema also requires that title match the first H1 of the body. A heading like
# Task 1: Resumo de log: nucleo e CLI is completely ordinary prose, so the colon is not an
unusual input. In my runs it appeared on the first attempt, without me steering toward it.
The second-order effect, which may deserve its own issue
When the import fails, the Loop run does not reach a terminal state. Twenty-five minutes
later:
status = running
completion_state = complete
generation = 2
tokens_used = 0
started_at = 2026-09-15T16:46:12.703Z
last_progress_at = 2026-09-15T16:46:12.916Z
last_progress_at is 213 ms after started_at and never advances. The run is not in any of the
six terminal states, so nothing settles it, and concurrency: forbid means the next
implement-tasks start on that workspace is refused with active_loop_run_exists. An operator
waiting on the run waits forever.
I am reporting this as one issue because the second symptom is reached only through the first,
but they look independent to me: a load-time action failure should still produce failed, whatever
caused it. Happy to split it if you prefer.
What I expected
cy-create-tasks and the spec-cycle importer should agree on the file format. Any of these
would close it:
1 - Quote the value when it needs quoting. The skill owns the write, so the smallest fix is in
the template plus a line in the schema reference saying scalars containing : must be quoted.
2 - Or make the importer tolerant. Parse the frontmatter leniently for the four scalar fields,
since status, title, type and complexity are all plain strings and none of them is ever a
nested mapping.
3 - And settle the run either way. An action that fails at load should drive the run to
failed, so the operator sees a stopped run instead of one that reports running with zero
tokens forever.
I would pick 1 and 3. Option 2 alone would leave other YAML metacharacters in the same trap.
What I did not verify
I did not check which other generated files have the same exposure. _tasks.md carries a
workflow key and a display table, and SOUL.md and AGENT.md have their own strict
frontmatter. I only proved this path, with the importer, for task_NN.md.
Logs
# the file as written by cy-create-tasks, unmodified
$ sed -n '1,6p' .compozy/tasks/logsum/task_01.md
---
status: pending
title: Resumo de log: nucleo e CLI (fatia 1 / MVP)
type: feature
complexity: medium
---
# the manifest is fine; only the task file fails
$ sed -n '1,8p' .compozy/tasks/logsum/_tasks.md
---
schema_version: "compozy.tasks/v2"
workflow: logsum
graph:
nodes:
- id: task_01
file: task_01.md
# still unquoted on the latest code
$ git show origin/main:extensions/spec-cycle/skills/cy-create-tasks/references/task-template.md | sed -n '10p'
title: [Task title]
# and the importer still unmarshals straight into the struct
$ git show origin/main:extensions/spec-cycle/import_tasks_parser.go | grep -n 'yaml.Unmarshal'
if err := yaml.Unmarshal(parts.Metadata, &meta); err != nil {Duplicate search performed (title and body, open and closed, is:issue): import_tasks ·
task frontmatter · mapping values are not allowed · cy-create-tasks · compozy.tasks/v2 ·
yaml frontmatter. No hits.
Final checks
- I searched existing issues and this is not a duplicate.
- I can reproduce this on the latest release.
Metadata
Metadata
Assignees
Labels
Type
Fields
Projects
- StatusShow more project fieldsDone
Activity
jillesmc commentedon Sep 21, 2026
Context for this defect, including the experiments where I measured how often it fires: #664