@cleocode/skills 2026.5.121 → 2026.5.123
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.
package/package.json
CHANGED
package/skills/ct-cleo/SKILL.md
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
name: ct-cleo
|
|
3
3
|
description: CLEO task management protocol - session, task, and workflow guidance. Use when managing tasks, sessions, or multi-agent workflows with the CLEO CLI protocol.
|
|
4
4
|
metadata:
|
|
5
|
-
version: 2.
|
|
6
|
-
lastReviewed: 2026-05-
|
|
5
|
+
version: 2.5.0
|
|
6
|
+
lastReviewed: 2026-05-26
|
|
7
7
|
stability: stable
|
|
8
8
|
---
|
|
9
9
|
|
|
@@ -14,8 +14,8 @@ Full protocol content lives in `~/.cleo/templates/CLEO-INJECTION.md`.
|
|
|
14
14
|
Emit any section with: `cleo briefing inject --section <name>`
|
|
15
15
|
|
|
16
16
|
Supported sections: `session-start` · `work-loop` · `triggers` · `task-creation`
|
|
17
|
-
· `task-discovery` · `
|
|
18
|
-
· `playbooks` · `documents` · `error-handling` · `pre-complete-gate`
|
|
17
|
+
· `task-discovery` · `task-relationships` · `session-commands` · `memory` · `nexus`
|
|
18
|
+
· `orchestration` · `playbooks` · `documents` · `error-handling` · `pre-complete-gate`
|
|
19
19
|
· `spawn-tiers` · `rules` · `memory-jit` · `escalation`
|
|
20
20
|
|
|
21
21
|
## Quick Reference
|
|
@@ -23,235 +23,196 @@ Supported sections: `session-start` · `work-loop` · `triggers` · `task-creati
|
|
|
23
23
|
| Need | Command |
|
|
24
24
|
|------|---------|
|
|
25
25
|
| Start session | `cleo session status` → `cleo briefing` |
|
|
26
|
-
| Find work | `cleo next` → `cleo
|
|
26
|
+
| Find work | `cleo next` → `cleo focus <id>` |
|
|
27
27
|
| Search tasks | `cleo find "query"` |
|
|
28
28
|
| Complete task | `cleo verify T### --gate ... --evidence "..."` → `cleo complete T###` |
|
|
29
29
|
| Save memory | `cleo memory observe "..." --title "..."` |
|
|
30
30
|
| Spawn subagent | `cleo orchestrate spawn <taskId> --tier 2` |
|
|
31
|
-
| Create a Saga
|
|
32
|
-
|
|
|
31
|
+
| Create a Saga | `cleo saga create --title "..." --acceptance "..."` |
|
|
32
|
+
| Saga-level ready | `cleo orchestrate ready <sagaId>` |
|
|
33
|
+
| Saga-level waves | `cleo orchestrate waves <sagaId>` |
|
|
34
|
+
| Saga rollup | `cleo saga rollup <sagaId>` |
|
|
33
35
|
| List Saga members | `cleo saga members <sagaId>` |
|
|
34
36
|
|
|
35
37
|
## Skill-Specific Extensions
|
|
36
38
|
|
|
37
|
-
|
|
39
|
+
- Task hierarchy, Saga commands, add-batch decomposition, docs policy, and CLI output details live in CLEO-INJECTION.md; emit `task-creation`, `documents`, and `pre-complete-gate` when needed.
|
|
40
|
+
- For add-batch input, The top-level JSON MUST be an array of task objects, not an object wrapper like `{ "tasks": [...] }`.
|
|
41
|
+
- Dry-run count semantics: `/data/count` and `/data/wouldCreate` predict writes; `/data/insertedCount` must be `0` for dry-run.
|
|
42
|
+
- Mutation output paths: use `/data/created/0`, `/data/updated/0`, and `/data/deleted/0`; never parse legacy full records.
|
|
43
|
+
- Docs path policy and strict preflight: keep docs repo-relative, Do not pass arbitrary external absolute paths, and discover runtime kinds with `cleo docs list-types` / `DocKindRegistry`.
|
|
38
44
|
|
|
39
|
-
|
|
40
|
-
`type` column discriminates; prefixes (`SG-`, `E-`, `T-`) are display + import-mapping only.
|
|
45
|
+
### Task Relationship Systems — depends, blockedBy, relates
|
|
41
46
|
|
|
42
|
-
|
|
43
|
-
|---------|--------|-------------------------------------------------|----------------------|
|
|
44
|
-
| Saga | `SG-` | ≥2 Epics across ≥2 releases (themed grouping) | Orchestrator (read) |
|
|
45
|
-
| Epic | `E-` | One releasable slice; ≥1 PR to `main` | Orchestrator (HITL) |
|
|
46
|
-
| Task | `T-` | One atomic PR-sized change; single wave | Phase Lead |
|
|
47
|
-
| Subtask | (none) | One commit; ≤2 files; rolls up to Task's PR | Worker (leaf) |
|
|
47
|
+
CLEO has **three distinct relationship systems** with different storage, semantics, and CLI exposure. Do not conflate them.
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
| System | Storage | Semantics | CLI Exposure |
|
|
50
|
+
|--------|---------|-----------|--------------|
|
|
51
|
+
| `depends` | `task_dependencies` table (`task_id`, `depends_on`) | **Blocking dependency** — task cannot start until all `depends` tasks are `done` | `cleo add --depends T1,T2` / `cleo update --depends` / `--add-depends` / `--remove-depends` |
|
|
52
|
+
| `blockedBy` | `tasks.blocked_by` column (free-text) | **Human-readable reason** why a task is blocked (e.g. "waiting for API key") | `cleo update --blocked-by "reason"` / `--clear-blocked-by` |
|
|
53
|
+
| `relates` | `task_relations` table (`task_id`, `related_to`, `relation_type`, `reason`) | **Semantic, non-blocking** relationships: `blocks`, `related`, `duplicates`, `absorbs`, `fixes`, `extends`, `supersedes` | `cleo relates add <from> <to> <type> <reason>` / `cleo relates remove` / `cleo relates list` |
|
|
52
54
|
|
|
53
|
-
|
|
54
|
-
`.cleo/adrs/ADR-073-above-epic-naming.md` §1–§2. CLI commands for Sagas: see
|
|
55
|
-
CLEO-INJECTION.md `task-creation` section (`cleo briefing inject --section task-creation`).
|
|
55
|
+
#### Key distinction
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
- **`depends`** controls **execution order** (wave planning, `cleo next` eligibility). It is a hard dependency.
|
|
58
|
+
- **`blockedBy`** is a **status annotation** — it does NOT link to another task, it just explains why this task is `blocked`.
|
|
59
|
+
- **`relates`** is **informational linkage** — it does NOT block execution, but it records that two tasks have a semantic relationship (e.g. "T1001 supersedes T1002" or "T1003 duplicates T1004").
|
|
58
60
|
|
|
59
|
-
|
|
61
|
+
#### CRITICAL: Do NOT use `relates` for execution gates
|
|
60
62
|
|
|
61
|
-
|
|
62
|
-
Agents can route their own rendering off `envelope.data.kind` without re-parsing
|
|
63
|
-
the payload shape. Canonical patterns:
|
|
63
|
+
`relates` is **never** a blocking dependency. If task B must wait for task A to finish, use `--depends`:
|
|
64
64
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
| Force human render when JSON is the default | `cleo show T<id> --human` |
|
|
69
|
-
| Generic hierarchy walker from any root (B9 / T10134) | `cleo tree T<id>` |
|
|
65
|
+
```bash
|
|
66
|
+
# CORRECT — execution dependency
|
|
67
|
+
cleo add "Implement auth" --depends T1001,T1002
|
|
70
68
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
69
|
+
# WRONG — relates does NOT block execution
|
|
70
|
+
cleo relates add T1003 T1001 blocks "waiting for auth"
|
|
71
|
+
```
|
|
74
72
|
|
|
75
|
-
|
|
73
|
+
#### Common pitfall: using `blockedBy` for task IDs
|
|
76
74
|
|
|
77
|
-
`
|
|
75
|
+
`--blocked-by` expects a **string reason**, not task IDs. To express "this task is blocked until that task finishes", use `--depends`:
|
|
78
76
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
| `'table'` | `TableResponse<T>` (rows + schema) | `renderTable` |
|
|
83
|
-
| `'list'` | `ListResponse<T>` | `renderList` |
|
|
84
|
-
| `'grouped-list'` | `GroupedListResponse<T>` | `renderGroupedList` |
|
|
85
|
-
| `'section'` | `{icon, header, items}` | `renderSection` |
|
|
86
|
-
| `'single'` | single-record detail | per-command renderer |
|
|
87
|
-
| `'generic'` | fallback `Record<string, unknown>` | kv-block helper |
|
|
77
|
+
```bash
|
|
78
|
+
# CORRECT
|
|
79
|
+
cleo add "Implement auth" --depends T1001
|
|
88
80
|
|
|
89
|
-
|
|
81
|
+
# WRONG — blocked-by is free text, not a task reference
|
|
82
|
+
cleo update T1003 --blocked-by T1001
|
|
83
|
+
```
|
|
90
84
|
|
|
91
|
-
|
|
92
|
-
`packages/core/src/render/`. `packages/cleo/src/cli/renderers/index.ts` is a
|
|
93
|
-
~20-LOC thin dispatcher. Static UI primitives (Tree, Table, Section, Badge,
|
|
94
|
-
Legend) live under `packages/animations/render/`. Typed icon enums
|
|
95
|
-
(`StatusIcon`, `KindIcon`, `BadgeIcon`, `RelationIcon`) live in
|
|
96
|
-
`@cleocode/contracts/render/icon.ts`. Family renderers self-register at
|
|
97
|
-
module load via `registerRenderer(command, kind, fn)` — importing
|
|
98
|
-
`@cleocode/core/render` populates every slot via side-effect re-exports.
|
|
85
|
+
#### `cleo relates` command reference
|
|
99
86
|
|
|
100
|
-
|
|
87
|
+
```bash
|
|
88
|
+
# Add a semantic relationship
|
|
89
|
+
cleo relates add T1001 T1002 supersedes "T1002 is absorbed into the new auth flow"
|
|
101
90
|
|
|
102
|
-
|
|
91
|
+
# List relations for a task
|
|
92
|
+
cleo relates list T1001
|
|
103
93
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
This is the canonical pattern for epic decomposition; prefer it over N sequential `cleo add` calls.
|
|
94
|
+
# Remove a relation
|
|
95
|
+
cleo relates remove T1001 T1002
|
|
107
96
|
|
|
108
|
-
|
|
97
|
+
# Suggest related tasks based on shared attributes
|
|
98
|
+
cleo relates suggest T1001 --threshold=50
|
|
109
99
|
|
|
110
|
-
|
|
111
|
-
cleo
|
|
100
|
+
# Discover related tasks using various methods
|
|
101
|
+
cleo relates discover T1001
|
|
112
102
|
```
|
|
113
103
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
Create a `tasks.json` file (array of task objects):
|
|
117
|
-
|
|
118
|
-
```json
|
|
119
|
-
[
|
|
120
|
-
{
|
|
121
|
-
"title": "Research: survey add-batch prior art",
|
|
122
|
-
"acceptance": "Written summary of 3+ prior approaches|Coverage of rollback semantics"
|
|
123
|
-
},
|
|
124
|
-
{
|
|
125
|
-
"title": "Implement: add-batch CORE op with atomic semantics",
|
|
126
|
-
"acceptance": "All tasks inserted or none|Returns IDs of created tasks"
|
|
127
|
-
},
|
|
128
|
-
{
|
|
129
|
-
"title": "TF: teach add-batch in ct-cleo SKILL.md + CLEO-INJECTION",
|
|
130
|
-
"acceptance": "SKILL.md contains Decomposing an epic section|INJECTION Task Creation table includes add-batch row"
|
|
131
|
-
}
|
|
132
|
-
]
|
|
133
|
-
```
|
|
104
|
+
Valid relation types: `blocks`, `related`, `duplicates`, `absorbs`, `fixes`, `extends`, `supersedes`.
|
|
134
105
|
|
|
135
|
-
|
|
136
|
-
`kind`, `priority`, `size`, `labels`, `depends`). The `--parent` flag applies to all items.
|
|
106
|
+
#### Schema types mismatch note
|
|
137
107
|
|
|
138
|
-
|
|
108
|
+
The DB schema `TASK_RELATION_TYPES` (`related`, `blocks`, `duplicates`, `absorbs`, `fixes`, `extends`, `supersedes`) must match the runtime types. The CLI `cleo relates add` accepts the DB schema types. Always normalize to the DB enum before persisting.
|
|
139
109
|
|
|
140
|
-
|
|
141
|
-
|------|-------------|
|
|
142
|
-
| `--file <path>` | Path to JSON file (array of task objects) |
|
|
143
|
-
| `-` | Read JSON array from stdin (`echo '[...]' \| cleo add-batch --file - --parent <id>`) |
|
|
144
|
-
| `--parent <id>` | Parent epic/task ID. All created tasks become direct children. |
|
|
145
|
-
| `--dry-run` | Validate and preview all tasks without inserting. Shows what would be created. |
|
|
110
|
+
## Task Hierarchy (PM-Core V2 — ADR-088)
|
|
146
111
|
|
|
147
|
-
|
|
112
|
+
**Canonical source:** `docs/adr/ADR-088-pm-core-v2-workgraph-relations-completion-criteria.md`.
|
|
148
113
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
114
|
+
| Tier | Prefix | type value | Scope-of-change |
|
|
115
|
+
|---------|--------|------------|----------------------------------------------------|
|
|
116
|
+
| Saga | `SG-` | `saga` | Theme grouping ≥2 Epics across ≥2 releases |
|
|
117
|
+
| Epic | `E-` | `epic` | One releasable slice; ≥1 PR to `main` |
|
|
118
|
+
| Task | `T-` | `task` | One atomic PR-sized change; single wave |
|
|
119
|
+
| Subtask | (none) | `subtask` | One commit; ≤2 files; contributes to Task's PR |
|
|
152
120
|
|
|
153
|
-
|
|
154
|
-
|
|
121
|
+
**Containment (I1):** `tasks.parent_id` is the **only** containment edge. Direct children,
|
|
122
|
+
ancestor/descendant traversal, closure rollups, and default parent completion are all derived
|
|
123
|
+
from `parent_id`. The parent matrix is:
|
|
155
124
|
|
|
156
|
-
|
|
125
|
+
| Child type | Parent type |
|
|
126
|
+
|------------|-----------------|
|
|
127
|
+
| `subtask` | `task` |
|
|
128
|
+
| `task` | `epic` |
|
|
129
|
+
| `epic` | `saga` or `null`|
|
|
130
|
+
| `saga` | `null` |
|
|
157
131
|
|
|
158
|
-
|
|
159
|
-
(
|
|
160
|
-
input JSON — `cleo show <epicId>` acceptance criteria → tasks array → `cleo add-batch`.
|
|
132
|
+
**Storage (I2):** All IDs stored as `T####`; `type` column discriminates tier (not `label`).
|
|
133
|
+
Prefixes (`SG-`, `E-`) are DISPLAY + import-mapping only.
|
|
161
134
|
|
|
162
|
-
|
|
135
|
+
**Non-containment (I3):** `task_relations` is for secondary graph semantics ONLY — dependency,
|
|
136
|
+
ordering, cross-reference, evidence, supersession, provenance. `task_relations` MUST NOT satisfy
|
|
137
|
+
containment, child listing, ancestor/descendant traversal, parent rollup, parent completion,
|
|
138
|
+
nesting-budget, or closure semantics. The `groups` relation type is retired; do not use it for
|
|
139
|
+
hierarchy.
|
|
163
140
|
|
|
164
|
-
|
|
165
|
-
- Single task: `cleo add --type task --parent <id> --acceptance "..." --title "..."`
|
|
141
|
+
## Typed Completion Criteria (PM-Core V2)
|
|
166
142
|
|
|
167
|
-
|
|
143
|
+
`task_acceptance_criteria.kind` is one of:
|
|
168
144
|
|
|
169
|
-
|
|
145
|
+
| Kind | Requires `target_task_id` | Purpose |
|
|
146
|
+
|------|--------------------------|---------|
|
|
147
|
+
| `text` | No | Human-authored acceptance criterion |
|
|
148
|
+
| `child_task` | **Yes** | Deterministic projection from a direct `parent_id` child |
|
|
149
|
+
| `evidence_bound` | No | Gate-backed criterion (`implemented`, `testsPassed`, `qaPassed`) |
|
|
170
150
|
|
|
171
|
-
|
|
172
|
-
|
|
151
|
+
**Key rules:**
|
|
152
|
+
- A parent with children uses `child_task` criteria by default; these are **deterministic
|
|
153
|
+
projections** from `parent_id` containment.
|
|
154
|
+
- `text` and `evidence_bound` criteria must NOT use `target_task_id`.
|
|
155
|
+
- Cancelled children do NOT automatically satisfy parent completion.
|
|
156
|
+
- Adding child work under a done parent reopens affected ancestors.
|
|
173
157
|
|
|
174
|
-
|
|
175
|
-
blob lands in the MAIN repo's `tasks.db`. The file path is resolved
|
|
176
|
-
against the WORKTREE cwd (not the canonical root) before dispatch,
|
|
177
|
-
so relative paths like `docs/note.md` work as expected from inside
|
|
178
|
-
the worktree.
|
|
179
|
-
- `cleo changeset add --slug <slug> --tasks <ids> --kind <kind> --summary <text>` —
|
|
180
|
-
dual-writes to `<canonical-root>/.changeset/<slug>.md` AND the SSoT
|
|
181
|
-
blob store. The `.changeset/` file lands in the MAIN repo, never
|
|
182
|
-
the worktree.
|
|
158
|
+
## Saga Operations (PM-Core V2)
|
|
183
159
|
|
|
184
|
-
|
|
185
|
-
(
|
|
186
|
-
clear `rm -rf <worktree>/.cleo` remediation BEFORE the deeper DB
|
|
187
|
-
chokepoint guard fires.
|
|
160
|
+
Saga-level orchestration is first-class. Saga membership uses `parent_id`
|
|
161
|
+
containment (NOT `task_relations.groups`). Use saga IDs directly with orchestrate commands:
|
|
188
162
|
|
|
189
163
|
```bash
|
|
190
|
-
#
|
|
191
|
-
cleo
|
|
192
|
-
# stderr: [T10389] routing SSoT write from worktree cwd ... → canonical project root ...
|
|
193
|
-
# row lands in main repo's tasks.db, retrievable via `cleo docs fetch t10389-research`
|
|
194
|
-
```
|
|
164
|
+
# Saga-level ready frontier — parallel-safe tasks across all member epics
|
|
165
|
+
cleo orchestrate ready <sagaId>
|
|
195
166
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
build that ships the T10389 fix-pack (closes T10353 + T10354 + T10294
|
|
199
|
-
+ T10365). Suppress the routing log with `CLEO_QUIET=1` for clean
|
|
200
|
-
stderr in automation.
|
|
167
|
+
# Saga-level dependency waves — unified wave plan across all member epics
|
|
168
|
+
cleo orchestrate waves <sagaId>
|
|
201
169
|
|
|
202
|
-
|
|
170
|
+
# Saga status rollup — completion %, member counts
|
|
171
|
+
cleo saga rollup <sagaId>
|
|
203
172
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
`tail`/`jq`/`python` — every common shape has a first-class flag.
|
|
173
|
+
# Saga membership listing via parent_id containment
|
|
174
|
+
cleo saga members <sagaId>
|
|
175
|
+
```
|
|
208
176
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
| Affected count | `--output count` | `cleo list --parent EPIC --status pending --output count` |
|
|
214
|
-
| TSV (no header) | `--output table` | `cleo list --parent EPIC --output table` |
|
|
215
|
-
| Silent (exit code only) | `--output silent` | `cleo update T123 --status done --output silent` |
|
|
216
|
-
| 1-line per record | `--summary` | `cleo list --parent EPIC --summary` |
|
|
217
|
-
| Suppress stderr noise | `--quiet` | `id=$(cleo add 'X' --acceptance "..." --quiet --field /data/task/id)` |
|
|
218
|
-
| Full record (legacy) | `--full` | `cleo show T123 --full` |
|
|
177
|
+
**Epic-level fallback:** If saga-level orchestrate fails, enumerate member epics from
|
|
178
|
+
`cleo saga members <sagaId>` and call `cleo orchestrate ready <epicId>` for each member
|
|
179
|
+
individually. Do not use `task_relations.groups` as a fallback for hierarchy — it is
|
|
180
|
+
non-containment only per I3.
|
|
219
181
|
|
|
220
|
-
|
|
182
|
+
## WorkGraph (PM-Core V2)
|
|
221
183
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
minimal envelope `{success, data: {count, ids[]}}` (T9931). Use `--full`
|
|
225
|
-
to opt back into the full record set.
|
|
226
|
-
- **stdout** carries exactly ONE LAFS envelope terminated by a single
|
|
227
|
-
newline. Sub-step logs/progress/warnings route through Pino → stderr.
|
|
228
|
-
This is regression-locked by CI gates `lint-stdout-discipline` (T10135)
|
|
229
|
-
and `lint-stdout-write-allowlist` (T9924).
|
|
184
|
+
The WorkGraph subsystem provides scaffold validation, atomic application, and planning
|
|
185
|
+
document generation:
|
|
230
186
|
|
|
231
|
-
|
|
187
|
+
| Feature | What it does |
|
|
188
|
+
|---------|--------------|
|
|
189
|
+
| Scaffold Dry-Run Validator | Validates WorkGraph JSON payloads against schema invariants before mutation. Returns `wouldCreate`/`wouldUpdate`/`wouldDelete` without side effects. |
|
|
190
|
+
| Scaffold Apply Engine | Atomically applies validated WorkGraph scaffolds to the task database. Creates, updates, and deletes tasks/relations/ACs in a single transaction. Sibling-relation-based (SQLite trigger blocks parent-child relation edges). |
|
|
191
|
+
| Planning Doc Generator | `generatePlanningDoc()` produces structured markdown plans from the WorkGraph. Supports "agent" (compact) and "maintainer" (prose) output modes. |
|
|
232
192
|
|
|
193
|
+
Example — dry-run a scaffold before applying:
|
|
233
194
|
```bash
|
|
234
|
-
#
|
|
235
|
-
|
|
236
|
-
--field /data/task/id)
|
|
195
|
+
# Validate scaffold payload
|
|
196
|
+
cleo workgraph validate --file scaffold.json --dry-run
|
|
237
197
|
|
|
238
|
-
#
|
|
239
|
-
cleo
|
|
240
|
-
|
|
241
|
-
done
|
|
198
|
+
# Apply validated scaffold atomically
|
|
199
|
+
cleo workgraph apply --file scaffold.json
|
|
200
|
+
```
|
|
242
201
|
|
|
243
|
-
|
|
244
|
-
remaining=$(cleo list --parent T9927 --status pending --output count)
|
|
202
|
+
## Task Context (PM-Core V2)
|
|
245
203
|
|
|
246
|
-
|
|
247
|
-
cleo add-batch --file /tmp/batch.json --parent T9927 --quiet --output id
|
|
248
|
-
```
|
|
204
|
+
Bounded task context with token budgeting for agent ergonomics:
|
|
249
205
|
|
|
250
|
-
|
|
206
|
+
| Feature | What it does |
|
|
207
|
+
|---------|--------------|
|
|
208
|
+
| Task Context Pack | `coreTaskContext` returns targeted task information (identity, acceptance criteria, blockers, edges, activity) respecting a configurable token budget. Uses `TasksContextOmission` to track overages and provides expansion hints. |
|
|
209
|
+
| Saga Context & Readiness | Saga-level aggregate rollups: completion percentages, ready-frontiers, and blocker enumeration across all member epics via `parent_id` containment. |
|
|
251
210
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
211
|
+
Example — get task context for agent use:
|
|
212
|
+
```bash
|
|
213
|
+
# Full context with budget
|
|
214
|
+
cleo orchestrate report <taskId>
|
|
256
215
|
|
|
257
|
-
|
|
216
|
+
# Compact context for prompt injection
|
|
217
|
+
cleo focus <taskId>
|
|
218
|
+
```
|
|
@@ -72,6 +72,31 @@ describe('ct-cleo SKILL.md — command correctness', () => {
|
|
|
72
72
|
it('references cleo orchestrate spawn (the canonical spawn command)', () => {
|
|
73
73
|
expect(skillContent).toContain('cleo orchestrate spawn');
|
|
74
74
|
});
|
|
75
|
+
|
|
76
|
+
it('documents add-batch input as a top-level JSON array', () => {
|
|
77
|
+
expect(skillContent).toContain('The top-level JSON MUST be an array of task objects');
|
|
78
|
+
expect(skillContent).toContain('not an object wrapper like `{ "tasks": [...] }`');
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('uses mutation projection field paths instead of legacy full-record paths', () => {
|
|
82
|
+
expect(skillContent).toContain('/data/created/0');
|
|
83
|
+
expect(skillContent).toContain('/data/updated/0');
|
|
84
|
+
expect(skillContent).toContain('/data/deleted/0');
|
|
85
|
+
expect(skillContent).not.toContain('--field /data/task/id');
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('documents add-batch dry-run count semantics', () => {
|
|
89
|
+
expect(skillContent).toContain('/data/wouldCreate');
|
|
90
|
+
expect(skillContent).toContain('/data/insertedCount');
|
|
91
|
+
expect(skillContent).toContain('`0` for dry-run');
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('documents docs path policy and runtime doc kind discovery', () => {
|
|
95
|
+
expect(skillContent).toContain('Docs path policy and strict preflight');
|
|
96
|
+
expect(skillContent).toContain('Do not pass arbitrary external absolute paths');
|
|
97
|
+
expect(skillContent).toContain('cleo docs list-types');
|
|
98
|
+
expect(skillContent).toContain('DocKindRegistry');
|
|
99
|
+
});
|
|
75
100
|
});
|
|
76
101
|
|
|
77
102
|
// ---------------------------------------------------------------------------
|
|
@@ -117,4 +142,75 @@ describe('ct-cleo SKILL.md — phase coverage via emittable sections', () => {
|
|
|
117
142
|
it('mentions work-loop section (core workflow loop)', () => {
|
|
118
143
|
expect(skillContent).toContain('work-loop');
|
|
119
144
|
});
|
|
145
|
+
|
|
146
|
+
it('mentions task-relationships section (PM-Core V2 relationship systems)', () => {
|
|
147
|
+
expect(skillContent).toContain('task-relationships');
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
// ---------------------------------------------------------------------------
|
|
152
|
+
// PM-Core V2 doctrine coverage (T10645)
|
|
153
|
+
// ---------------------------------------------------------------------------
|
|
154
|
+
|
|
155
|
+
describe('ct-cleo SKILL.md — PM-Core V2 doctrine (T10645)', () => {
|
|
156
|
+
it('documents PM-Core V2 task hierarchy with type=saga canonical', () => {
|
|
157
|
+
expect(skillContent).toContain('PM-Core V2');
|
|
158
|
+
expect(skillContent).toContain('ADR-088');
|
|
159
|
+
// Table shows `saga` as the type value in the hierarchy table
|
|
160
|
+
expect(skillContent).toMatch(/`saga`/);
|
|
161
|
+
expect(skillContent).toContain('parent_id');
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it('documents I1 containment invariant (parent_id is only containment edge)', () => {
|
|
165
|
+
expect(skillContent).toContain('containment edge');
|
|
166
|
+
expect(skillContent).toContain('I1');
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it('documents I3 non-containment invariant (task_relations is secondary only)', () => {
|
|
170
|
+
expect(skillContent).toContain('I3');
|
|
171
|
+
expect(skillContent).toContain('MUST NOT satisfy containment');
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it('documents Saga operations via parent_id containment', () => {
|
|
175
|
+
expect(skillContent).toContain('cleo orchestrate ready <sagaId>');
|
|
176
|
+
expect(skillContent).toContain('cleo orchestrate waves <sagaId>');
|
|
177
|
+
expect(skillContent).toContain('cleo saga rollup <sagaId>');
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it('does NOT present task_relations.groups as active hierarchy guidance', () => {
|
|
181
|
+
// Migration context references (e.g. "T10638 migration removes legacy groups")
|
|
182
|
+
// are acceptable; active guidance must not recommend groups for hierarchy.
|
|
183
|
+
// Must contain explicit anti-groups guidance.
|
|
184
|
+
expect(skillContent).toMatch(/not.*task_relations\.groups|Do not use.*task_relations\.groups/);
|
|
185
|
+
expect(skillContent).not.toMatch(/^[^#]*use.*task_relations\.groups.*for hierarchy/);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it('documents Task Context subsystem (T10629/T10630/T10631)', () => {
|
|
189
|
+
expect(skillContent).toContain('Task Context');
|
|
190
|
+
expect(skillContent).toContain('T10629');
|
|
191
|
+
expect(skillContent).toContain('cleo context');
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
it('documents WorkGraph scaffold subsystem (T10632/T10633/T10634)', () => {
|
|
195
|
+
expect(skillContent).toContain('WorkGraph');
|
|
196
|
+
expect(skillContent).toContain('T10632');
|
|
197
|
+
expect(skillContent).toContain('cleo graph validate');
|
|
198
|
+
expect(skillContent).toContain('cleo graph apply');
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it('documents Completion Criteria with typed ACs (child_task / text / evidence_bound)', () => {
|
|
202
|
+
expect(skillContent).toContain('child_task');
|
|
203
|
+
expect(skillContent).toContain('evidence_bound');
|
|
204
|
+
expect(skillContent).toContain('typed acceptance criteria');
|
|
205
|
+
expect(skillContent).toContain('T10639');
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
it('indicates T10638 migration removed legacy groups hierarchy reads', () => {
|
|
209
|
+
expect(skillContent).toContain('T10638');
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
it('documents epic-level fallback for saga orchestrate', () => {
|
|
213
|
+
expect(skillContent).toContain('cleo saga members');
|
|
214
|
+
expect(skillContent).toMatch(/[Ee]pic-level/);
|
|
215
|
+
});
|
|
120
216
|
});
|
|
@@ -109,6 +109,26 @@ describe('CLEO-INJECTION.md — command correctness', () => {
|
|
|
109
109
|
it('contains "cleo find" command', () => {
|
|
110
110
|
expect(injectionContent).toContain('cleo find');
|
|
111
111
|
});
|
|
112
|
+
|
|
113
|
+
it('documents add-batch array input and dry-run count fields', () => {
|
|
114
|
+
expect(injectionContent).toContain('top-level JSON array of task objects');
|
|
115
|
+
expect(injectionContent).toContain('/data/wouldCreate');
|
|
116
|
+
expect(injectionContent).toContain('/data/insertedCount');
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('documents docs path policy, strict preflight, and runtime doc kinds', () => {
|
|
120
|
+
expect(injectionContent).toContain('repo-relative paths');
|
|
121
|
+
expect(injectionContent).toContain('arbitrary external absolute paths');
|
|
122
|
+
expect(injectionContent).toContain('cleo docs list-types');
|
|
123
|
+
expect(injectionContent).toContain('DocKindRegistry');
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('uses contract-backed mutate field paths', () => {
|
|
127
|
+
expect(injectionContent).toContain('/data/created/0');
|
|
128
|
+
expect(injectionContent).toContain('/data/updated/0');
|
|
129
|
+
expect(injectionContent).toContain('/data/deleted/0');
|
|
130
|
+
expect(injectionContent).not.toContain('--field /data/task/id');
|
|
131
|
+
});
|
|
112
132
|
});
|
|
113
133
|
|
|
114
134
|
// ---------------------------------------------------------------------------
|
|
@@ -105,18 +105,19 @@ that single PR. Subtasks never own a PR — if a unit warrants its own PR, it MU
|
|
|
105
105
|
When decomposing, ask: "does this unit need its own PR?" → Task. "Is this a commit inside a
|
|
106
106
|
larger PR?" → Subtask.
|
|
107
107
|
|
|
108
|
-
### Above-Epic: Sagas (ADR-
|
|
108
|
+
### Above-Epic: Sagas (PM-Core V2 — ADR-088)
|
|
109
109
|
|
|
110
110
|
A **Saga** groups multiple Epics into a multi-release theme. Use a Saga when the work spans
|
|
111
|
-
more than one releasable Epic and you want a stable handle for rollup/reporting. A Saga
|
|
112
|
-
|
|
113
|
-
|
|
111
|
+
more than one releasable Epic and you want a stable handle for rollup/reporting. A Saga uses
|
|
112
|
+
`type='saga'` (NOT `label='saga'`) — it is a peer type discriminator at the top of the
|
|
113
|
+
parent ladder. All IDs are stored as `T####`; prefixes (`SG-`, `E-`) are display-only.
|
|
114
|
+
Saga membership uses `parent_id` containment (NOT `task_relations.groups`).
|
|
114
115
|
|
|
115
116
|
```bash
|
|
116
117
|
cleo saga create --title "Auth Modernization" --description "..." --acceptance "ac1|ac2|ac3|ac4|ac5"
|
|
117
|
-
# returns SG-id (stored as T#### with
|
|
118
|
-
cleo saga add <sagaId> <epicId> #
|
|
119
|
-
cleo saga members <sagaId> # returns
|
|
118
|
+
# returns SG-id (stored as T#### with type=saga)
|
|
119
|
+
cleo saga add <sagaId> <epicId> # sets epic.parent_id = sagaId (containment edge)
|
|
120
|
+
cleo saga members <sagaId> # returns members via parent_id containment
|
|
120
121
|
cleo saga rollup <sagaId> # aggregates child statuses + completionPct
|
|
121
122
|
```
|
|
122
123
|
|
|
@@ -224,7 +224,7 @@ When operating without continuous HITL oversight, additional constraints apply:
|
|
|
224
224
|
| `cleo orchestrate spawn T1586 --json` | Generate resolved spawn prompt |
|
|
225
225
|
| `cleo orchestrate next --epic T1575` | Suggest next task |
|
|
226
226
|
| `cleo saga rollup <sagaId>` | Cross-Epic status aggregation when orchestrating a multi-Epic Saga (ADR-073) |
|
|
227
|
-
| `cleo saga members <sagaId>` | Member Epics of a Saga (
|
|
227
|
+
| `cleo saga members <sagaId>` | Member Epics of a Saga (parent_id containment — NOT `task_relations.groups`) |
|
|
228
228
|
| `cleo pipeline stage.status --epic T1575` | Current pipeline stage |
|
|
229
229
|
| `cleo pipeline stage.validate T1575 implementation` | Check gate before spawn |
|
|
230
230
|
| `cleo pipeline stage.gate.pass T1575 research` | Advance pipeline stage |
|