@sppg2001/atomize 2.0.0 → 3.0.0
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/README.md +93 -551
- package/{templates/mixins/docs.yaml → catalog/mixins/documentation.atomize.yaml} +1 -1
- package/{templates/mixins/security.yaml → catalog/mixins/security-review.atomize.yaml} +1 -1
- package/{templates/mixins/testing.yaml → catalog/mixins/test-coverage.atomize.yaml} +1 -1
- package/{templates/templates/custom-saved-query.yaml → catalog/templates/agile-story-breakdown-saved-query.atomize.yaml} +2 -2
- package/{templates/templates/custom.yaml → catalog/templates/agile-story-breakdown.atomize.yaml} +2 -2
- package/{templates/templates/bug.yaml → catalog/templates/bug-fix.atomize.yaml} +1 -1
- package/{templates/templates/feature.yaml → catalog/templates/feature-development.atomize.yaml} +1 -1
- package/dist/cli/index.js +17866 -21738
- package/package.json +19 -16
- package/LICENSE +0 -21
- package/docs/Auth-Guide.md +0 -257
- package/docs/Cli-Reference.md +0 -959
- package/docs/Common-Validation-Errors.md +0 -556
- package/docs/Getting-Started.md +0 -540
- package/docs/Platform-Guide.md +0 -662
- package/docs/Story-Learner.md +0 -324
- package/docs/Template-Reference.md +0 -743
- package/docs/Validation-Modes.md +0 -252
- package/docs/template-wizard-guide.md +0 -738
- package/examples/README.md +0 -220
- package/examples/advanced-filtering.yaml +0 -113
- package/examples/backend.yaml +0 -124
- package/examples/conditional-dependencies-template.yaml +0 -145
- package/examples/conditional-percentage-template.yaml +0 -167
- package/examples/frontend.yaml +0 -123
- package/examples/fullstack.yaml +0 -167
- /package/{templates/templates/backend-api.yaml → catalog/templates/backend-api.atomize.yaml} +0 -0
|
@@ -1,743 +0,0 @@
|
|
|
1
|
-
# Template Reference
|
|
2
|
-
|
|
3
|
-
Complete reference for Atomize YAML template files.
|
|
4
|
-
|
|
5
|
-
## Table of Contents
|
|
6
|
-
|
|
7
|
-
- [Overview](#overview)
|
|
8
|
-
- [Top-Level Fields](#top-level-fields)
|
|
9
|
-
- [Composition](#composition)
|
|
10
|
-
- [filter](#filter)
|
|
11
|
-
- [tasks](#tasks)
|
|
12
|
-
- [Task Fields](#task-fields)
|
|
13
|
-
- [Variable Interpolation](#variable-interpolation)
|
|
14
|
-
- [Assignment Patterns](#assignment-patterns)
|
|
15
|
-
- [Task Custom Fields](#task-custom-fields)
|
|
16
|
-
- [Conditional Tasks](#conditional-tasks)
|
|
17
|
-
- [Conditional Estimation](#conditional-estimation)
|
|
18
|
-
- [Task Dependencies](#task-dependencies)
|
|
19
|
-
- [estimation](#estimation)
|
|
20
|
-
- [validation](#validation)
|
|
21
|
-
- [metadata](#metadata)
|
|
22
|
-
- [Complete Example](#complete-example)
|
|
23
|
-
|
|
24
|
-
---
|
|
25
|
-
|
|
26
|
-
## Overview
|
|
27
|
-
|
|
28
|
-
Templates are YAML files that define how Atomize breaks down user stories into tasks. Each template specifies:
|
|
29
|
-
|
|
30
|
-
1. **Which work items to target** (via `filter`)
|
|
31
|
-
2. **What tasks to create** (via `tasks`)
|
|
32
|
-
3. **How to distribute estimations** (via `estimation`)
|
|
33
|
-
4. **Optional constraints** (via `validation`)
|
|
34
|
-
5. **Optional metadata** (via `metadata`)
|
|
35
|
-
|
|
36
|
-
---
|
|
37
|
-
|
|
38
|
-
## Top-Level Fields
|
|
39
|
-
|
|
40
|
-
```yaml
|
|
41
|
-
version: "1.0" # Required. Always "1.0"
|
|
42
|
-
name: "Template Name" # Required. Human-readable name (max 200 chars)
|
|
43
|
-
description: "..." # Optional. What this template is for (max 500 chars)
|
|
44
|
-
author: "Your Name" # Optional. Author name or team
|
|
45
|
-
tags: ["tag1", "tag2"] # Optional. Categorization tags
|
|
46
|
-
extends: "backend-api" # Optional. Inherit from a catalog template
|
|
47
|
-
mixins: # Optional. Mix in reusable task groups
|
|
48
|
-
- "security-review-tasks"
|
|
49
|
-
- "release-checklist"
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
| Field | Required | Type | Description |
|
|
53
|
-
|-------|----------|------|-------------|
|
|
54
|
-
| `version` | Yes | string | Template schema version. Use `"1.0"` |
|
|
55
|
-
| `name` | Yes | string | Template display name |
|
|
56
|
-
| `description` | No | string | Detailed description |
|
|
57
|
-
| `author` | No | string | Author name or team |
|
|
58
|
-
| `tags` | No | string[] | Tags for categorization |
|
|
59
|
-
| `extends` | No | string | Catalog template name or file path to inherit from |
|
|
60
|
-
| `mixins` | No | string[] | Catalog mixin names or file paths to merge into this template |
|
|
61
|
-
|
|
62
|
-
---
|
|
63
|
-
|
|
64
|
-
## Composition
|
|
65
|
-
|
|
66
|
-
Templates can inherit from other templates and mix in reusable task groups. This lets you build a library of building blocks and assemble them without duplication.
|
|
67
|
-
|
|
68
|
-
### Inheritance (`extends`)
|
|
69
|
-
|
|
70
|
-
A template that declares `extends` inherits the `filter`, `tasks`, `estimation`, `validation`, and `metadata` of its base. Fields defined in the child override the corresponding fields in the base.
|
|
71
|
-
|
|
72
|
-
```yaml
|
|
73
|
-
version: "1.0"
|
|
74
|
-
name: "Secure Backend API"
|
|
75
|
-
extends: "backend-api" # inherits all tasks and filter from backend-api
|
|
76
|
-
|
|
77
|
-
tasks:
|
|
78
|
-
- id: "pen-test"
|
|
79
|
-
title: "Penetration Testing"
|
|
80
|
-
estimationPercent: 10
|
|
81
|
-
activity: "Testing"
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
The resolved template merges the child's `tasks` list on top of the base's, then re-validates the combined result. Use `atomize template resolve` to see the merged output before using it.
|
|
85
|
-
|
|
86
|
-
### Mixins (`mixins`)
|
|
87
|
-
|
|
88
|
-
A mixin is a partial template — typically a group of related tasks — that can be mixed into any template. The tasks from all listed mixins are appended to the template's own task list before validation.
|
|
89
|
-
|
|
90
|
-
```yaml
|
|
91
|
-
version: "1.0"
|
|
92
|
-
name: "Feature With Release Checks"
|
|
93
|
-
extends: "feature"
|
|
94
|
-
mixins:
|
|
95
|
-
- "security-review-tasks"
|
|
96
|
-
- "release-checklist"
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
Mixins are installed and managed with the `template` commands:
|
|
100
|
-
|
|
101
|
-
```bash
|
|
102
|
-
# Install a mixin from a URL
|
|
103
|
-
atomize template install https://example.com/mixins/security-tasks.yaml
|
|
104
|
-
|
|
105
|
-
# List available mixins
|
|
106
|
-
atomize template list --type mixin
|
|
107
|
-
|
|
108
|
-
# Create a new mixin
|
|
109
|
-
atomize template create --type mixin --save-as security-review-tasks
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
### Resolution order
|
|
113
|
-
|
|
114
|
-
When Atomize processes a composed template:
|
|
115
|
-
1. Base template (`extends`) is loaded and fully resolved first
|
|
116
|
-
2. Mixin task lists are appended in declaration order
|
|
117
|
-
3. Child template fields override the merged base
|
|
118
|
-
4. The final result is validated as a single flat template
|
|
119
|
-
|
|
120
|
-
Use `atomize template resolve <template>` to inspect the final merged YAML at any point.
|
|
121
|
-
|
|
122
|
-
### Compatibility
|
|
123
|
-
|
|
124
|
-
Templates using `extends` or `mixins` require Atomize v2.0.0 or later. Older versions will reject them with a schema error. If you share composed templates with users on older versions, they must upgrade first or you can share the resolved output from `atomize template resolve --quiet > resolved.yaml`.
|
|
125
|
-
|
|
126
|
-
---
|
|
127
|
-
|
|
128
|
-
## filter
|
|
129
|
-
|
|
130
|
-
Defines which work items this template applies to. All criteria are combined with AND logic.
|
|
131
|
-
|
|
132
|
-
```yaml
|
|
133
|
-
filter:
|
|
134
|
-
team: "Backend Team" # Override team from the selected profile
|
|
135
|
-
workItemTypes: ["User Story", "Bug"]
|
|
136
|
-
states: ["New", "Active"]
|
|
137
|
-
statesExclude: ["Done", "Removed"] # Exclude items in these states
|
|
138
|
-
statesWereEver: ["In Review"] # Items that were ever in these states
|
|
139
|
-
tags:
|
|
140
|
-
include: ["backend"]
|
|
141
|
-
exclude: ["deprecated"]
|
|
142
|
-
areaPaths: ["MyProject\\Backend"]
|
|
143
|
-
areaPathsUnder: ["MyProject\\Backend"] # Match area path and all descendants
|
|
144
|
-
iterations: ["MyProject\\Sprint 23"]
|
|
145
|
-
iterationsUnder: ["MyProject\\Release 2"] # Match iteration and all descendants
|
|
146
|
-
assignedTo: ["user@company.com", "@Me"]
|
|
147
|
-
changedAfter: "@Today-7" # Changed in the last 7 days
|
|
148
|
-
createdAfter: "@Today-30" # Created in the last 30 days
|
|
149
|
-
priority:
|
|
150
|
-
min: 1
|
|
151
|
-
max: 3
|
|
152
|
-
excludeIfHasTasks: true
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
### Filter Fields
|
|
156
|
-
|
|
157
|
-
| Field | Type | Description |
|
|
158
|
-
|-------|------|-------------|
|
|
159
|
-
| `team` | string | Override the team from the selected Azure DevOps profile for this template |
|
|
160
|
-
| `workItemTypes` | string[] | Work item types to match (e.g., `"User Story"`, `"Bug"`) |
|
|
161
|
-
| `states` | string[] | Work item states to include (e.g., `"New"`, `"Active"`) |
|
|
162
|
-
| `statesExclude` | string[] | Work item states to exclude (e.g., `"Done"`, `"Removed"`) |
|
|
163
|
-
| `statesWereEver` | string[] | Match items that were ever in these states |
|
|
164
|
-
| `tags.include` | string[] | Must have at least one of these tags |
|
|
165
|
-
| `tags.exclude` | string[] | Must not have any of these tags |
|
|
166
|
-
| `areaPaths` | string[] | Area paths to match exactly (case-sensitive). Use `"@TeamAreas"` for the team's areas |
|
|
167
|
-
| `areaPathsUnder` | string[] | Area paths — matches the path and all descendants (UNDER query) |
|
|
168
|
-
| `iterations` | string[] | Iteration paths to match. Use `"@CurrentIteration"` for the team's current sprint |
|
|
169
|
-
| `iterationsUnder` | string[] | Iteration paths — matches the iteration and all descendants (UNDER query) |
|
|
170
|
-
| `assignedTo` | string[] | Assigned user emails, or `"@Me"` for the current user |
|
|
171
|
-
| `changedAfter` | string | Only match items changed on or after this date. Supports `@Today` macros |
|
|
172
|
-
| `createdAfter` | string | Only match items created on or after this date. Supports `@Today` macros |
|
|
173
|
-
| `priority.min` | number | Minimum priority (1 = highest) |
|
|
174
|
-
| `priority.max` | number | Maximum priority |
|
|
175
|
-
| `excludeIfHasTasks` | boolean | Skip work items that already have child tasks |
|
|
176
|
-
|
|
177
|
-
### Special Values
|
|
178
|
-
|
|
179
|
-
Some filter fields accept special macro values:
|
|
180
|
-
|
|
181
|
-
| Value | Used in | Behavior |
|
|
182
|
-
|-------|---------|----------|
|
|
183
|
-
| `"@Me"` | `assignedTo` | Resolves to the currently authenticated user's email |
|
|
184
|
-
| `"@TeamAreas"` | `areaPaths` | Resolves to all area paths owned by the configured team |
|
|
185
|
-
| `"@CurrentIteration"` | `iterations` | Resolves to the team's current sprint/iteration |
|
|
186
|
-
|
|
187
|
-
### Date Filters
|
|
188
|
-
|
|
189
|
-
`changedAfter` and `createdAfter` accept either a literal date string or an `@Today` macro for relative dates.
|
|
190
|
-
|
|
191
|
-
**`@Today` macro syntax:** `@Today`, `@Today-N`, `@Today+N`
|
|
192
|
-
|
|
193
|
-
```yaml
|
|
194
|
-
filter:
|
|
195
|
-
changedAfter: "@Today-7" # Changed in the last 7 days
|
|
196
|
-
changedAfter: "@Today-30" # Changed in the last 30 days
|
|
197
|
-
createdAfter: "@Today" # Created today
|
|
198
|
-
createdAfter: "2026-01-01" # Created on or after a specific date
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
**Other supported macros:** `@StartOfDay`, `@StartOfWeek`, `@StartOfMonth`, `@StartOfYear` (also support `±N` offsets)
|
|
202
|
-
|
|
203
|
-
### Area Paths: exact vs. descendants
|
|
204
|
-
|
|
205
|
-
Use `areaPaths` for exact matches and `areaPathsUnder` to include all sub-areas:
|
|
206
|
-
|
|
207
|
-
```yaml
|
|
208
|
-
# Only items directly in "MyProject\Backend"
|
|
209
|
-
filter:
|
|
210
|
-
areaPaths: ["MyProject\\Backend"]
|
|
211
|
-
|
|
212
|
-
# Items in "MyProject\Backend" AND any sub-area (e.g. "MyProject\Backend\API")
|
|
213
|
-
filter:
|
|
214
|
-
areaPathsUnder: ["MyProject\\Backend"]
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
### Iterations: exact vs. descendants
|
|
218
|
-
|
|
219
|
-
Use `iterations` for exact matches and `iterationsUnder` to include all child iterations:
|
|
220
|
-
|
|
221
|
-
```yaml
|
|
222
|
-
# Only items in Sprint 23
|
|
223
|
-
filter:
|
|
224
|
-
iterations: ["MyProject\\Sprint 23"]
|
|
225
|
-
|
|
226
|
-
# All sprints under Release 2 (e.g. Sprint 1, Sprint 2, ...)
|
|
227
|
-
filter:
|
|
228
|
-
iterationsUnder: ["MyProject\\Release 2"]
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
### savedQuery
|
|
232
|
-
|
|
233
|
-
Delegate query composition entirely to an existing Azure DevOps saved query. Atomize resolves the query via the ADO Queries API, executes its WIQL, and pipes the results into the standard task-creation pipeline.
|
|
234
|
-
|
|
235
|
-
Reference by ID (most stable — unaffected by renames or moves):
|
|
236
|
-
|
|
237
|
-
```yaml
|
|
238
|
-
filter:
|
|
239
|
-
savedQuery:
|
|
240
|
-
id: "a1b2c3d4-0000-0000-0000-000000000000"
|
|
241
|
-
```
|
|
242
|
-
|
|
243
|
-
Reference by path (human-readable, matches the query browser hierarchy):
|
|
244
|
-
|
|
245
|
-
```yaml
|
|
246
|
-
filter:
|
|
247
|
-
savedQuery:
|
|
248
|
-
path: "Shared Queries/Teams/Backend Team/Sprint Active Stories"
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
**Rules:**
|
|
252
|
-
|
|
253
|
-
- `id` and `path` are mutually exclusive — provide exactly one.
|
|
254
|
-
- `id` must be a valid UUID (visible in the ADO query URL).
|
|
255
|
-
- Only **flat (Work Items)** queries are supported. Tree and one-hop queries are rejected at runtime with a clear error.
|
|
256
|
-
- `savedQuery` takes precedence over all structured filter fields (`workItemTypes`, `states`, `tags`, etc.). A validator warning is emitted if both are present.
|
|
257
|
-
|
|
258
|
-
**Post-processing still applies:** `excludeIfHasTasks` still applies to the query results after resolution, and you can still cap execution with the CLI `--limit` option.
|
|
259
|
-
|
|
260
|
-
```yaml
|
|
261
|
-
filter:
|
|
262
|
-
savedQuery:
|
|
263
|
-
path: "Shared Queries/All Active Stories"
|
|
264
|
-
excludeIfHasTasks: true
|
|
265
|
-
```
|
|
266
|
-
|
|
267
|
-
```bash
|
|
268
|
-
atomize generate my-template.yaml --limit 20
|
|
269
|
-
```
|
|
270
|
-
|
|
271
|
-
**Permission requirements:**
|
|
272
|
-
|
|
273
|
-
The PAT used by Atomize must have **Work Items (Read)** scope on the project containing the query. Only shared queries are accessible — private queries owned by another user will return a "Query not found" error even if the ID is correct.
|
|
274
|
-
|
|
275
|
-
**Permission error reference:**
|
|
276
|
-
|
|
277
|
-
| Scenario | Error |
|
|
278
|
-
|----------|-------|
|
|
279
|
-
| Query ID or path does not exist | `Query not found: "...". Verify the ID or path and that the query has been shared with your account.` |
|
|
280
|
-
| PAT lacks read permission | `Access denied to query "...". Ensure your PAT includes the Work Items (Read) scope.` |
|
|
281
|
-
| Resolved path is a folder | `"..." is a query folder, not a runnable query.` |
|
|
282
|
-
| Tree or one-hop query type | `Only flat (Work Items) queries are supported. "..." is a tree or one-hop query.` |
|
|
283
|
-
|
|
284
|
-
**Tip:** Use `atomize queries list` to browse available query paths and IDs without leaving the terminal.
|
|
285
|
-
|
|
286
|
-
---
|
|
287
|
-
|
|
288
|
-
## tasks
|
|
289
|
-
|
|
290
|
-
Defines the tasks to create for each matching work item. Tasks are created as child items.
|
|
291
|
-
|
|
292
|
-
```yaml
|
|
293
|
-
tasks:
|
|
294
|
-
- id: "design"
|
|
295
|
-
title: "Design: ${story.title}"
|
|
296
|
-
description: "Design and planning phase"
|
|
297
|
-
estimationPercent: 20
|
|
298
|
-
activity: "Design"
|
|
299
|
-
tags: ["design"]
|
|
300
|
-
assignTo: "@ParentAssignee"
|
|
301
|
-
priority: 2
|
|
302
|
-
condition:
|
|
303
|
-
field: "tags"
|
|
304
|
-
operator: "contains"
|
|
305
|
-
value: "backend"
|
|
306
|
-
dependsOn: []
|
|
307
|
-
acceptanceCriteria:
|
|
308
|
-
- "Criteria 1"
|
|
309
|
-
- "Criteria 2"
|
|
310
|
-
```
|
|
311
|
-
|
|
312
|
-
### Task Fields
|
|
313
|
-
|
|
314
|
-
| Field | Required | Type | Description |
|
|
315
|
-
|-------|----------|------|-------------|
|
|
316
|
-
| `title` | Yes | string | Task title (max 500 chars). Supports variable interpolation |
|
|
317
|
-
| `id` | No | string | Unique identifier for dependencies (max 30 chars) |
|
|
318
|
-
| `description` | No | string | Task description (max 2000 chars) |
|
|
319
|
-
| `estimationPercent` | No | number | Percentage of parent story points (0-100) |
|
|
320
|
-
| `estimationFixed` | No | number | Fixed point value regardless of parent estimation |
|
|
321
|
-
| `estimationPercentCondition` | No | array | Conditional estimation rules (see below) |
|
|
322
|
-
| `activity` | No | string | Activity type (e.g., `"Development"`, `"Testing"`, `"Design"`) |
|
|
323
|
-
| `tags` | No | string[] | Tags to apply to the task |
|
|
324
|
-
| `assignTo` | No | string | Who to assign the task to (see assignment patterns) |
|
|
325
|
-
| `priority` | No | number | Task priority (1-4) |
|
|
326
|
-
| `condition` | No | object | Structured condition to conditionally create this task |
|
|
327
|
-
| `dependsOn` | No | string[] | IDs of tasks this task depends on |
|
|
328
|
-
| `acceptanceCriteria` | No | string[] | List of acceptance criteria |
|
|
329
|
-
| `customFields` | No | object | Task-level Azure DevOps field values keyed by reference name |
|
|
330
|
-
|
|
331
|
-
### Variable Interpolation
|
|
332
|
-
|
|
333
|
-
Use story data dynamically in task titles and descriptions:
|
|
334
|
-
|
|
335
|
-
| Variable | Description |
|
|
336
|
-
|----------|-------------|
|
|
337
|
-
| `${story.title}` | Story title |
|
|
338
|
-
| `${story.id}` | Story ID (e.g., `STORY-123`) |
|
|
339
|
-
| `${story.description}` | Story description |
|
|
340
|
-
| `${story.estimation}` | Story points |
|
|
341
|
-
| `${story.tags}` | Story tags (semicolon-separated) |
|
|
342
|
-
|
|
343
|
-
**Example:**
|
|
344
|
-
|
|
345
|
-
```yaml
|
|
346
|
-
tasks:
|
|
347
|
-
- title: "Design API: ${story.title}"
|
|
348
|
-
description: |
|
|
349
|
-
Design the REST API for: ${story.title}
|
|
350
|
-
|
|
351
|
-
Story ID: ${story.id}
|
|
352
|
-
Estimation: ${story.estimation} points
|
|
353
|
-
```
|
|
354
|
-
|
|
355
|
-
Task custom field values also support story custom-field interpolation using moustache syntax:
|
|
356
|
-
|
|
357
|
-
```yaml
|
|
358
|
-
tasks:
|
|
359
|
-
- title: "Backend Implementation"
|
|
360
|
-
customFields:
|
|
361
|
-
Custom.ReleaseVersion: "{{ story.customFields['Custom.ReleaseVersion'] }}"
|
|
362
|
-
```
|
|
363
|
-
|
|
364
|
-
### Assignment Patterns
|
|
365
|
-
|
|
366
|
-
The `assignTo` field supports special patterns in addition to email addresses:
|
|
367
|
-
|
|
368
|
-
| Value | Behavior |
|
|
369
|
-
|-------|----------|
|
|
370
|
-
| `@ParentAssignee` | Inherit assignment from the parent story |
|
|
371
|
-
| `@Inherit` | Same as `@ParentAssignee` |
|
|
372
|
-
| `@Me` | Assign to the currently authenticated user |
|
|
373
|
-
| `@Unassigned` | Leave the task unassigned |
|
|
374
|
-
| `"user@company.com"` | Assign to a specific user by email |
|
|
375
|
-
|
|
376
|
-
```yaml
|
|
377
|
-
tasks:
|
|
378
|
-
- title: "Implementation"
|
|
379
|
-
assignTo: "@ParentAssignee" # Inherit from story
|
|
380
|
-
|
|
381
|
-
- title: "Code Review"
|
|
382
|
-
assignTo: "lead@company.com" # Specific person
|
|
383
|
-
|
|
384
|
-
- title: "Testing"
|
|
385
|
-
assignTo: "@Me" # Whoever runs the command
|
|
386
|
-
```
|
|
387
|
-
|
|
388
|
-
### Task Custom Fields
|
|
389
|
-
|
|
390
|
-
Use `customFields` to set Azure DevOps fields when Atomize creates tasks. Keys are always ADO reference names such as `Custom.ClientTier` or `Microsoft.VSTS.Common.Priority`.
|
|
391
|
-
|
|
392
|
-
```yaml
|
|
393
|
-
tasks:
|
|
394
|
-
- id: "backend"
|
|
395
|
-
title: "Backend Implementation"
|
|
396
|
-
customFields:
|
|
397
|
-
Custom.ClientTier: "Enterprise"
|
|
398
|
-
Custom.ReleaseVersion: "{{ story.customFields['Custom.ReleaseVersion'] }}"
|
|
399
|
-
Custom.IsBillable: true
|
|
400
|
-
Custom.TierRank: 3
|
|
401
|
-
Custom.ReleaseDate: "@Today"
|
|
402
|
-
```
|
|
403
|
-
|
|
404
|
-
**Supported value types:**
|
|
405
|
-
|
|
406
|
-
| ADO field type | Template value type | Notes |
|
|
407
|
-
|----------------|---------------------|-------|
|
|
408
|
-
| Text (single line) | string | Free-form string |
|
|
409
|
-
| Text (multi-line) | string | Multi-line values are allowed |
|
|
410
|
-
| Boolean | boolean | `true` or `false` |
|
|
411
|
-
| Date/Time | string | ISO 8601 date/time or supported macros such as `@Today` |
|
|
412
|
-
| Decimal | number | Floating-point values |
|
|
413
|
-
| Identity | string | Email address or values such as `@Me` when supported by ADO |
|
|
414
|
-
| Integer | number | Whole-number values |
|
|
415
|
-
| Picklist (String) | string | Must match one of the allowed values |
|
|
416
|
-
| Picklist (Integer) | number | Must match one of the allowed values |
|
|
417
|
-
|
|
418
|
-
**Validation behavior:**
|
|
419
|
-
- `atomize validate` without `--profile` checks structure only and warns that custom fields were not verified against ADO
|
|
420
|
-
- `atomize validate --profile <name>` connects to ADO and validates field names, read-only status, types, and picklist values
|
|
421
|
-
- `atomize generate` always validates custom fields against live ADO field metadata before creating work items
|
|
422
|
-
|
|
423
|
-
Use `atomize fields list` to browse available field names and types for a project before authoring templates.
|
|
424
|
-
|
|
425
|
-
### Conditional Tasks
|
|
426
|
-
|
|
427
|
-
Tasks with a `condition` are only created when the condition evaluates to `true`. Conditions are structured objects evaluated against the parent story at generate time. When a conditional task is skipped, its estimation is redistributed to other tasks proportionally.
|
|
428
|
-
|
|
429
|
-
```yaml
|
|
430
|
-
tasks:
|
|
431
|
-
- title: "Security Review"
|
|
432
|
-
estimationPercent: 10
|
|
433
|
-
condition:
|
|
434
|
-
field: "tags"
|
|
435
|
-
operator: "contains"
|
|
436
|
-
value: "security"
|
|
437
|
-
|
|
438
|
-
- title: "Database Migration"
|
|
439
|
-
estimationPercent: 15
|
|
440
|
-
condition:
|
|
441
|
-
all:
|
|
442
|
-
- field: "tags"
|
|
443
|
-
operator: "contains"
|
|
444
|
-
value: "database"
|
|
445
|
-
- field: "estimation"
|
|
446
|
-
operator: "gt"
|
|
447
|
-
value: 5
|
|
448
|
-
```
|
|
449
|
-
|
|
450
|
-
**Simple clause fields:**
|
|
451
|
-
|
|
452
|
-
| Property | Description |
|
|
453
|
-
|----------|-------------|
|
|
454
|
-
| `field` | Built-in story field such as `title`, `tags`, or `estimation` |
|
|
455
|
-
| `customField` | Parent story custom field reference name such as `Custom.ClientTier` |
|
|
456
|
-
| `operator` | One of `equals`, `not-equals`, `contains`, `not-contains`, `gt`, `lt`, `gte`, `lte` |
|
|
457
|
-
| `value` | String, number, or boolean to compare against |
|
|
458
|
-
|
|
459
|
-
**Compound clauses:**
|
|
460
|
-
- `{ all: [...] }` means every nested clause must match
|
|
461
|
-
- `{ any: [...] }` means at least one nested clause must match
|
|
462
|
-
|
|
463
|
-
```yaml
|
|
464
|
-
tasks:
|
|
465
|
-
- title: "Enterprise Review"
|
|
466
|
-
condition:
|
|
467
|
-
customField: "Custom.ClientTier"
|
|
468
|
-
operator: "equals"
|
|
469
|
-
value: "Enterprise"
|
|
470
|
-
```
|
|
471
|
-
|
|
472
|
-
### Conditional Estimation
|
|
473
|
-
|
|
474
|
-
Use `estimationPercentCondition` to adapt a task's percentage based on story properties. Rules are evaluated in order; the first matching rule wins. The `estimationPercent` field serves as the fallback.
|
|
475
|
-
|
|
476
|
-
```yaml
|
|
477
|
-
tasks:
|
|
478
|
-
- title: "Implementation"
|
|
479
|
-
estimationPercent: 50 # Default/fallback
|
|
480
|
-
estimationPercentCondition:
|
|
481
|
-
- condition:
|
|
482
|
-
field: "tags"
|
|
483
|
-
operator: "contains"
|
|
484
|
-
value: "critical"
|
|
485
|
-
percent: 60 # Higher weight for critical stories
|
|
486
|
-
- condition:
|
|
487
|
-
field: "estimation"
|
|
488
|
-
operator: "gte"
|
|
489
|
-
value: 13
|
|
490
|
-
percent: 55 # More work for large stories
|
|
491
|
-
- condition:
|
|
492
|
-
field: "tags"
|
|
493
|
-
operator: "contains"
|
|
494
|
-
value: "fullstack"
|
|
495
|
-
percent: 40 # Less backend work for fullstack stories
|
|
496
|
-
```
|
|
497
|
-
|
|
498
|
-
**Key behaviors:**
|
|
499
|
-
- Rules are evaluated in order; first match wins
|
|
500
|
-
- If no condition matches, `estimationPercent` is used
|
|
501
|
-
- Normalization uses the resolved percentages (including skipped tasks)
|
|
502
|
-
- Conditional percentages participate correctly in the 100% distribution
|
|
503
|
-
|
|
504
|
-
### Task Dependencies
|
|
505
|
-
|
|
506
|
-
Define execution order by referencing other task IDs in `dependsOn`. Atomize creates dependency links between tasks in the platform.
|
|
507
|
-
|
|
508
|
-
```yaml
|
|
509
|
-
tasks:
|
|
510
|
-
- id: "design"
|
|
511
|
-
title: "Design API"
|
|
512
|
-
estimationPercent: 15
|
|
513
|
-
|
|
514
|
-
- id: "implement"
|
|
515
|
-
title: "Implement API"
|
|
516
|
-
estimationPercent: 50
|
|
517
|
-
dependsOn: ["design"] # Cannot start until "design" is done
|
|
518
|
-
|
|
519
|
-
- id: "test"
|
|
520
|
-
title: "Write Tests"
|
|
521
|
-
estimationPercent: 25
|
|
522
|
-
dependsOn: ["implement"]
|
|
523
|
-
|
|
524
|
-
- id: "review"
|
|
525
|
-
title: "Code Review & Documentation"
|
|
526
|
-
estimationPercent: 10
|
|
527
|
-
dependsOn: ["implement", "test"] # Multiple dependencies
|
|
528
|
-
```
|
|
529
|
-
|
|
530
|
-
**Rules:**
|
|
531
|
-
- `id` is required on any task that other tasks depend on
|
|
532
|
-
- `id` is required on any task that uses `dependsOn`
|
|
533
|
-
- Circular dependencies are a validation error
|
|
534
|
-
- IDs must be unique within a template
|
|
535
|
-
|
|
536
|
-
---
|
|
537
|
-
|
|
538
|
-
## estimation
|
|
539
|
-
|
|
540
|
-
Controls how story points are distributed across tasks.
|
|
541
|
-
|
|
542
|
-
```yaml
|
|
543
|
-
estimation:
|
|
544
|
-
strategy: "percentage" # How to calculate task points
|
|
545
|
-
rounding: "nearest" # How to round calculated values
|
|
546
|
-
minimumTaskPoints: 0.5 # Minimum points per task
|
|
547
|
-
ifParentHasNoEstimation: "skip" # What to do if parent has no points
|
|
548
|
-
defaultParentEstimation: 8 # Used when parent has no estimation (if not "skip")
|
|
549
|
-
```
|
|
550
|
-
|
|
551
|
-
| Field | Type | Default | Options | Description |
|
|
552
|
-
|-------|------|---------|---------|-------------|
|
|
553
|
-
| `strategy` | string | `"percentage"` | `"percentage"` | How to calculate task estimations |
|
|
554
|
-
| `rounding` | string | `"nearest"` | `nearest`, `up`, `down`, `none` | How to round decimal point values |
|
|
555
|
-
| `minimumTaskPoints` | number | `0` | any non-negative number | Minimum points for any task |
|
|
556
|
-
| `ifParentHasNoEstimation` | string | `"skip"` | `skip`, `warn`, `use-default` | Behavior when parent story has no estimation |
|
|
557
|
-
| `defaultParentEstimation` | number | `8` | any positive number | Fallback estimation when parent has none |
|
|
558
|
-
|
|
559
|
-
**Rounding options:**
|
|
560
|
-
- `nearest` - Round to nearest whole number (0.5 → 1, 0.4 → 0)
|
|
561
|
-
- `up` - Always round up (0.1 → 1)
|
|
562
|
-
- `down` - Always round down (0.9 → 0)
|
|
563
|
-
- `none` - Keep decimal values
|
|
564
|
-
|
|
565
|
-
---
|
|
566
|
-
|
|
567
|
-
## validation
|
|
568
|
-
|
|
569
|
-
Optional rules that validate the template before use. See [Validation Modes](./Validation-Modes.md) for details on strict vs lenient behavior.
|
|
570
|
-
|
|
571
|
-
```yaml
|
|
572
|
-
validation:
|
|
573
|
-
mode: "lenient" # lenient or strict
|
|
574
|
-
totalEstimationMustBe: 100 # Total must equal exactly this
|
|
575
|
-
totalEstimationRange: # OR use a range instead
|
|
576
|
-
min: 95
|
|
577
|
-
max: 105
|
|
578
|
-
minTasks: 3 # Minimum number of tasks required
|
|
579
|
-
maxTasks: 10 # Maximum number of tasks allowed
|
|
580
|
-
taskEstimationRange: # Each task must fall in this range
|
|
581
|
-
min: 0.5
|
|
582
|
-
max: 8
|
|
583
|
-
requiredTasks: # Tasks that must be present
|
|
584
|
-
- title: "Code Review"
|
|
585
|
-
id: "review"
|
|
586
|
-
```
|
|
587
|
-
|
|
588
|
-
| Field | Type | Description |
|
|
589
|
-
|-------|------|-------------|
|
|
590
|
-
| `mode` | string | `"lenient"` (default) or `"strict"`. In strict mode, warnings become errors |
|
|
591
|
-
| `totalEstimationMustBe` | number | Total estimation percentage must equal this value |
|
|
592
|
-
| `totalEstimationRange` | object | Total estimation must fall within `min`-`max` range |
|
|
593
|
-
| `minTasks` | number | Minimum number of tasks required |
|
|
594
|
-
| `maxTasks` | number | Maximum number of tasks allowed |
|
|
595
|
-
| `taskEstimationRange` | object | Each individual task's resolved estimation must fall within this range |
|
|
596
|
-
| `requiredTasks` | array | Tasks that must exist (matched by `id` or `title`) |
|
|
597
|
-
|
|
598
|
-
> **Note:** `totalEstimationMustBe` and `totalEstimationRange` are mutually exclusive.
|
|
599
|
-
|
|
600
|
-
---
|
|
601
|
-
|
|
602
|
-
## metadata
|
|
603
|
-
|
|
604
|
-
Optional metadata to help others discover and use your template.
|
|
605
|
-
|
|
606
|
-
```yaml
|
|
607
|
-
metadata:
|
|
608
|
-
category: "Backend"
|
|
609
|
-
difficulty: "intermediate" # beginner, intermediate, advanced
|
|
610
|
-
recommendedFor:
|
|
611
|
-
- "API development"
|
|
612
|
-
- "Microservices"
|
|
613
|
-
estimationGuidelines: "Based on typical backend API workflows for 5-13 point stories."
|
|
614
|
-
examples:
|
|
615
|
-
- "Implement user authentication endpoint"
|
|
616
|
-
- "Build REST API for product catalog"
|
|
617
|
-
```
|
|
618
|
-
|
|
619
|
-
| Field | Type | Description |
|
|
620
|
-
|-------|------|-------------|
|
|
621
|
-
| `category` | string | Template category (e.g., `"Backend"`, `"Frontend"`) |
|
|
622
|
-
| `difficulty` | string | `"beginner"`, `"intermediate"`, or `"advanced"` |
|
|
623
|
-
| `recommendedFor` | string[] | Descriptions of when to use this template |
|
|
624
|
-
| `estimationGuidelines` | string | Guidance on estimation sizing for this template |
|
|
625
|
-
| `examples` | string[] | Example story titles this template works well for |
|
|
626
|
-
|
|
627
|
-
---
|
|
628
|
-
|
|
629
|
-
## Complete Example
|
|
630
|
-
|
|
631
|
-
```yaml
|
|
632
|
-
version: "1.0"
|
|
633
|
-
name: "Backend API Development"
|
|
634
|
-
description: "Standard workflow for developing RESTful API endpoints"
|
|
635
|
-
author: "Platform Team"
|
|
636
|
-
tags: ["backend", "api", "rest"]
|
|
637
|
-
|
|
638
|
-
filter:
|
|
639
|
-
workItemTypes: ["User Story"]
|
|
640
|
-
states: ["New", "Active"]
|
|
641
|
-
tags:
|
|
642
|
-
include: ["backend", "api"]
|
|
643
|
-
exclude: ["deprecated"]
|
|
644
|
-
priority:
|
|
645
|
-
min: 1
|
|
646
|
-
max: 3
|
|
647
|
-
excludeIfHasTasks: true
|
|
648
|
-
|
|
649
|
-
tasks:
|
|
650
|
-
- id: "design"
|
|
651
|
-
title: "Design API: ${story.title}"
|
|
652
|
-
description: "Design REST endpoints, request/response schemas, and error handling"
|
|
653
|
-
estimationPercent: 15
|
|
654
|
-
activity: "Design"
|
|
655
|
-
tags: ["design", "api"]
|
|
656
|
-
assignTo: "@ParentAssignee"
|
|
657
|
-
|
|
658
|
-
- id: "db-schema"
|
|
659
|
-
title: "Database Schema"
|
|
660
|
-
description: "Create or update database schema and migrations"
|
|
661
|
-
estimationPercent: 15
|
|
662
|
-
estimationPercentCondition:
|
|
663
|
-
- condition:
|
|
664
|
-
field: "tags"
|
|
665
|
-
operator: "contains"
|
|
666
|
-
value: "complex-db"
|
|
667
|
-
percent: 25
|
|
668
|
-
activity: "Development"
|
|
669
|
-
dependsOn: ["design"]
|
|
670
|
-
|
|
671
|
-
- id: "implement"
|
|
672
|
-
title: "Implement Core Logic: ${story.title}"
|
|
673
|
-
description: "Implement business logic, validation, and API endpoints"
|
|
674
|
-
estimationPercent: 35
|
|
675
|
-
activity: "Development"
|
|
676
|
-
assignTo: "@ParentAssignee"
|
|
677
|
-
dependsOn: ["design", "db-schema"]
|
|
678
|
-
|
|
679
|
-
- id: "unit-tests"
|
|
680
|
-
title: "Unit Tests"
|
|
681
|
-
estimationPercent: 15
|
|
682
|
-
activity: "Testing"
|
|
683
|
-
dependsOn: ["implement"]
|
|
684
|
-
|
|
685
|
-
- id: "integration-tests"
|
|
686
|
-
title: "Integration Tests"
|
|
687
|
-
estimationPercent: 10
|
|
688
|
-
activity: "Testing"
|
|
689
|
-
dependsOn: ["implement"]
|
|
690
|
-
|
|
691
|
-
- id: "security-review"
|
|
692
|
-
title: "Security Review"
|
|
693
|
-
estimationPercent: 10
|
|
694
|
-
activity: "Testing"
|
|
695
|
-
condition:
|
|
696
|
-
any:
|
|
697
|
-
- field: "tags"
|
|
698
|
-
operator: "contains"
|
|
699
|
-
value: "security"
|
|
700
|
-
- field: "tags"
|
|
701
|
-
operator: "contains"
|
|
702
|
-
value: "auth"
|
|
703
|
-
dependsOn: ["implement"]
|
|
704
|
-
|
|
705
|
-
- id: "review"
|
|
706
|
-
title: "Code Review & Documentation"
|
|
707
|
-
estimationPercent: 10
|
|
708
|
-
activity: "Documentation"
|
|
709
|
-
assignTo: "@Me"
|
|
710
|
-
dependsOn: ["unit-tests", "integration-tests"]
|
|
711
|
-
|
|
712
|
-
estimation:
|
|
713
|
-
strategy: "percentage"
|
|
714
|
-
rounding: "nearest"
|
|
715
|
-
minimumTaskPoints: 0.5
|
|
716
|
-
ifParentHasNoEstimation: "skip"
|
|
717
|
-
|
|
718
|
-
validation:
|
|
719
|
-
mode: "strict"
|
|
720
|
-
totalEstimationMustBe: 100
|
|
721
|
-
minTasks: 3
|
|
722
|
-
maxTasks: 10
|
|
723
|
-
|
|
724
|
-
metadata:
|
|
725
|
-
category: "Backend"
|
|
726
|
-
difficulty: "intermediate"
|
|
727
|
-
recommendedFor:
|
|
728
|
-
- "REST API development"
|
|
729
|
-
- "Microservice endpoints"
|
|
730
|
-
- "Data service implementation"
|
|
731
|
-
estimationGuidelines: "Works best with stories between 5-13 story points."
|
|
732
|
-
```
|
|
733
|
-
|
|
734
|
-
---
|
|
735
|
-
|
|
736
|
-
## See Also
|
|
737
|
-
|
|
738
|
-
- [CLI Reference](./Cli-Reference.md) - Commands for validating, installing, and using templates
|
|
739
|
-
- [Validation Modes](./Validation-Modes.md) - Strict vs lenient validation explained
|
|
740
|
-
- [Common Validation Errors](./Common-Validation-Errors.md) - Fix validation failures
|
|
741
|
-
- [Story Learner](./Story-Learner.md) - Generate templates from existing work items
|
|
742
|
-
- [Template Wizard Guide](./template-wizard-guide.md) - Interactive template creation
|
|
743
|
-
- [Examples](../examples/) - Real-world template examples
|