[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M7CQ77DRPWYT8YA24ZRJ0YRH":3,"skill-same:01M7CQ77DRPWYT8YA24ZRJ0YRH":43},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":18,"linkOnly":19,"markdownContent":20,"markdownBody":21,"frontMatter":22,"refName":23,"commitSha":24,"skillDirectory":25,"forksCount":13,"repositoryHtmlUrl":26,"repositoryHomepageUrl":6,"ownerHtmlUrl":27,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":28,"install":29,"resources":42},"01M7CQ77DRPWYT8YA24ZRJ0YRH","task-new",null,"Use to create one story in a stream of a project from the stream profile's story template - link it from its scope screens, update the generated files and open a merge request - or one projectless workspace task in tasks\u002F.","maximk777\u002Fopencode-config","maximk777","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F205286132?v=4","01M7CQ4VVPFQ3MDCXJBFB0HPTZ","01M7CQ4VWA2GG0H2CNNREZ9AN9",0,"MIT","https:\u002F\u002Fgithub.com\u002Fmaximk777\u002Fopencode-config\u002Fblob\u002Fmain\u002Fkits\u002Fworkspace\u002F.agents\u002Fskills\u002Ftask-new\u002FSKILL.md",[],[],"2026-11-15 14:19:17",false,"---\nname: task-new\ndescription: Use to create one story in a stream of a project from the stream profile's story template - link it from its scope screens, update the generated files and open a merge request - or one projectless workspace task in tasks\u002F.\n---\n# Create a story or a workspace task\n\n## Steps\n1. Go to the workspace root: the nearest directory, walking up from where you are, where `test -f .agents\u002Fkit.json` succeeds. Run every command below from there.\n2. Ask the person which kind to create, unless they already said it:\n   - a story in a stream of a project: go to step 3;\n   - a projectless workspace task in `tasks\u002F`: go to step 21.\n   The types `epic` and `story` belong to a stream: create them only through the story flow. The task flow offers `task`, `bug`, `spike`, `architecture` and `e2e` only.\n\n## Story flow\n3. Collect these values:\n   - `project`: the project folder name in `projects\u002F`, for example `abs`.\n   - `domain`: the domain folder name in `projects\u002F\u003Cproject>\u002Fdomains\u002F`, for example `operations`.\n   - `stream`: the stream folder name in `projects\u002F\u003Cproject>\u002Fdomains\u002F\u003Cdomain>\u002Fstreams\u002F`, for example `migration`.\n   - `slug`: the story name, lowercase letters, digits and `-` only (`[a-z0-9-]+`), for example `reports`.\n   - scope keys: one or more element keys of the form `\u003Cprefix>:\u003Cproject>\u002F\u003Cdomain>\u002F\u003Cslug>`, for example `screen:abs\u002Foperations\u002Freports`. Or, when the story covers no element (for example BFF defects), no keys and a one-line unmapped reason. The reason must not contain `|` and must not start with `[`, `{`, `\"` or `'`.\n   - `wave`: a number, for example `2`.\n   - depends: story keys this story waits for, for example `story:abs\u002Foperations\u002Flogin`, or none.\n   - repos: repository keys, for example `repo:reports-bff`, or none.\n   - `title`: the story title for the `# ` title line of the story template, for example `Reports`. Only needed when the template has such a line (step 6 chooses the template), for example `# [СО] \u003CНазвание стори>` in `story.ru.md`.\n\n   Use every value the person gave. Derive the others from the files by the rules below, and do not ask the person to confirm a derived value: the person corrects derived values in the merge request review. Ask the person only for a value that is neither given nor derivable, and wait for the answer. Never invent a value.\n   - Stream. When the person named the project, the domain and the stream, use them. Otherwise run `ls projects\u002F*\u002Fdomains\u002F*\u002Fstreams\u002F*\u002Fstream.json`; each printed path `projects\u002F\u003Cproject>\u002Fdomains\u002F\u003Cdomain>\u002Fstreams\u002F\u003Cstream>\u002Fstream.json` is one stream. Keep the streams whose project folder, domain folder, stream folder or `key` in `stream.json` the request names. When the request names no stream, keep instead the streams that have an uncovered scope key (see Scope). When exactly one stream is left, take its `\u003Cproject>`, `\u003Cdomain>` and `\u003Cstream>`. When several or none are left, ask the person for the project, the domain and the stream.\n   - Scope. When the person named element keys, use them. When the request asks for the element or elements that have no story yet, read the `scope` list of `projects\u002F\u003Cproject>\u002Fdomains\u002F\u003Cdomain>\u002Fstreams\u002F\u003Cstream>\u002Fstream.json` and, for each key in it, run `grep -lxF -e '  - \u003Ckey>' projects\u002F\u003Cproject>\u002Fdomains\u002F\u003Cdomain>\u002Fstreams\u002F\u003Cstream>\u002Fstories\u002F*\u002Fstory.md 2>\u002Fdev\u002Fnull`. The key is uncovered when the command prints no path. The scope keys are the uncovered keys, in the order of the `scope` list. When no key is uncovered, stop, tell the person every scope key of the stream has a story, and change nothing. When the request asks for a story that covers no element, ask the person for the unmapped reason.\n   - `wave`. For each scope key, open its element file (step 9 gives the path) and read its `wave:` line. Take the lowest number. Without scope keys, ask the person.\n   - `slug`. When the scope has exactly one key, take the text after the last `\u002F` in that key, for example `card` for `screen:abs\u002Fdemo\u002Fcard`; step 8 checks that it is free. Otherwise ask the person.\n   - depends and repos: none, unless the person named them.\n   - `title`. When the person gave a title, use it. Otherwise, when the scope has exactly one key, take the `label:` value of its element file (step 9 gives the path). Otherwise (several keys, no keys, or an empty `label:`) ask the person for the title. Never invent a title.\n   - `type`, `tracker`, `decisions` and `mockups` are not asked: step 13 keeps `type`, `decisions` and `mockups` from the template, keeps `status`, `owner` and `started` as the template has them, and `tracker` stays empty unless step 6 needs one.\n4. Check the slug: run `printf '%s\\n' '\u003Cslug>' | grep -Ex '[a-z0-9-]+'`. When it prints nothing, ask the person for another slug.\n5. Find the workspace default branch: run `git symbolic-ref --short refs\u002Fremotes\u002Forigin\u002FHEAD` and remove the `origin\u002F` prefix; when the command fails, use `main`. Call it `\u003Cdefault>`. Then run, one by one:\n   - `git switch \u003Cdefault>`\n   - `GIT_TERMINAL_PROMPT=0 git pull --ff-only`\n   The checks in steps 6 to 10 run after the pull, so they see the fresh default branch.\n6. Run `test -f projects\u002F\u003Cproject>\u002Fdomains\u002F\u003Cdomain>\u002Fstreams\u002F\u003Cstream>\u002Fstream.json`. When it fails, stop, tell the person the stream does not exist, and change nothing. Otherwise read the file and take `profile`, `stage` and the `scope` list.\n   - Find the workspace language `\u003Clanguage>`: open `.agents\u002Fkit.json` and read `params.language`. When the file, `params` or `language` is missing, `\u003Clanguage>` is `en`.\n   - Find the story template `\u003Ctemplate>`: when `\u003Clanguage>` is not `en` and `test -f .agents\u002Fprofiles\u002F\u003Cprofile>\u002Fstory.\u003Clanguage>.md` succeeds, it is `.agents\u002Fprofiles\u002F\u003Cprofile>\u002Fstory.\u003Clanguage>.md`; otherwise `.agents\u002Fprofiles\u002F\u003Cprofile>\u002Fstory.md`. For language `ru` in profile `ui-migration` it is `story.ru.md`.\n   - Values in `.agents\u002Fprofiles\u002F\u003Cprofile>\u002Fprofile.json` may be language objects such as `{\"en\": \"Open questions\", \"ru\": \"Открытые вопросы\"}`. Wherever this skill reads a value from `profile.json`, take the `\u003Clanguage>` value of such an object, or its `en` value when it has no `\u003Clanguage>` key.\n   - Find the open questions section `\u003Copen questions>`: the `section` of the gate `\"gate\": \"no_open_questions\"` in `stages` of `profile.json`, for example `Open questions` (en) or `Открытые вопросы` (ru). When no such gate exists, there is no open questions section.\n   - When `stage` is `goal`, `map`, `decomposition` or `ready`: the story gets no tracker id. Go to step 7.\n   - When `stage` is `delivery` or `done`: the `ready` stage is closed, so its `tracker_ids` gate requires a tracker id for the new story too. Ask the person for the tracker id `\u003Ctracker>` and wait for the answer. When the person gives none, stop, tell them a stream at stage `\u003Cstage>` needs a tracker id for every story, and change nothing. Do not create any file or branch.\n   - Check `\u003Ctracker>`: read `tracker\u002Ftrackers.json`. Every entry of `trackers` carries `key` and `id_pattern`; JSON doubles every backslash, so `\\\\d` in the file means `\\d`. Rewrite each pattern for `grep -E` (write every `\\d` as `[0-9]`) and run `printf '%s\\n' '\u003Ctracker>' | grep -Ex '\u003Crewritten pattern>'` entry by entry until one matches. When no entry matches, ask the person for another id. When `tracker\u002Ftrackers.json` has no `trackers` list, or no entry has an `id_pattern`, stop, tell the person, and change nothing.\n   - When `\u003Ctracker>` contains a `\"` or a `\\` character, ask the person for another id: `.agents\u002Findex.json` stores such ids escaped, so the next check cannot find them.\n   - Run `grep -F '  \"\u003Ctracker>\":' .agents\u002Findex.json 2>\u002Fdev\u002Fnull`. When it prints a line, the id belongs to another task: ask the person for another id.\n7. For each scope key from step 3, check that it is one of the strings in the `scope` list of `stream.json`, exactly. When a key is not in that list, stop, tell the person which key is outside the stream scope, and change nothing. Do not create any file or branch.\n   - When step 3 found the scope keys as uncovered keys, run its `grep` again for each of them. When it now prints a path, that story covers the key since the pull: stop, tell the person the path, and change nothing.\n8. Run `ls -d projects\u002F\u003Cproject>\u002Fdomains\u002F\u003Cdomain>\u002Fstreams\u002F*\u002Fstories\u002F\u003Cslug>`. When it prints a path, the slug already exists: stop, tell the person the path, and change nothing. When step 3 derived the slug, ask the person for another slug and continue from step 4 with the answer.\n9. For each scope key, find its element file:\n   - The key has the form `\u003Cprefix>:\u003Celement project>\u002F\u003Celement domain>\u002F\u003Celement slug>`. Open `.agents\u002Fprofiles\u002F\u003Cprofile>\u002Fprofile.json` and find the entry of `elements` whose `prefix` equals `\u003Cprefix>`. Its `dir` gives the path `projects\u002F\u003Celement project>\u002Fdomains\u002F\u003Celement domain>\u002F\u003Cdir>\u002F\u003Celement slug>.md`. For `screen:abs\u002Foperations\u002Freports` in profile `ui-migration` it is `projects\u002Fabs\u002Fdomains\u002Foperations\u002Fmap\u002Freports.md`.\n   - Run `test -f \u003Cpath>`. When it fails, stop, tell the person the element file is missing, and change nothing.\n10. Check depends and repos:\n    - For each depends key `story:\u003Cd>\u002F\u003Cdd>\u002F\u003Cs>`, run `ls projects\u002F\u003Cd>\u002Fdomains\u002F\u003Cdd>\u002Fstreams\u002F*\u002Fstories\u002F\u003Cs>\u002Fstory.md 2>\u002Fdev\u002Fnull`. It must print exactly one path.\n    - For each repos key `repo:\u003Cname>`, run `grep -F '\"name\": \"\u003Cname>\"' repos.json`. It must print a line.\n    - Correct or drop, together with the person, every key that fails. Never keep a key that does not exist.\n11. Run `git switch -c story-\u003Cdomain>-\u003Cslug>`.\n12. Run `mkdir -p projects\u002F\u003Cproject>\u002Fdomains\u002F\u003Cdomain>\u002Fstreams\u002F\u003Cstream>\u002Fstories\u002F\u003Cslug> && cp \u003Ctemplate> projects\u002F\u003Cproject>\u002Fdomains\u002F\u003Cdomain>\u002Fstreams\u002F\u003Cstream>\u002Fstories\u002F\u003Cslug>\u002Fstory.md`.\n13. Edit the frontmatter of the new `story.md`. Keep every line of the template in its order and change only these lines:\n    - `key: story:\u003Cproject>\u002F\u003Cdomain>\u002F\u003Cslug>`;\n    - keep `status: waiting` and the empty `owner:` and `started:` lines exactly as the template has them: a new story waits, unowned and not started - `task-start` writes those three lines later;\n    - `wave: \u003Cwave>`;\n    - `scope`: with keys, the line `scope:` followed by one line `  - \u003Ckey>` per key (two spaces, `-`, space), in the order of step 3; without keys, the line `scope: []` and directly below it the line `unmapped: \u003Creason>`. The `unmapped:` line is the only line the template does not have; write it only when the scope is empty;\n    - `depends` and `repos`: the same form, `\u003Cfield>:` followed by `  - \u003Ckey>` lines, or `\u003Cfield>: []` when empty;\n    - `tracker`: when step 6 gave a `\u003Ctracker>`, `tracker: \u003Ctracker>`; otherwise leave `tracker:` empty;\n    - leave `type`, `decisions` and `mockups` as the template has them.\n    Keep every `## ` heading of the template and replace the placeholder text under each of them. The sections are those of `\u003Ctemplate>`, in their order; their names are the `story.sections` list of `profile.json`. When the template has a `# ` title line, replace its placeholder in angle brackets with `\u003Ctitle>` from step 3 and keep the rest of the line: `# [СО] \u003CНазвание стори>` becomes `# [СО] Отчёты` for title `Отчёты`. Where the person gave you the words for a section, write those words. Otherwise write:\n    - the summary section: the section named by `story.summary_section` of `profile.json` (in `\u003Clanguage>` as step 6 says), or the first item of `story.sections` when `summary_section` is absent. It gets the goal. With scope keys, one line `Deliver \u003Ckey> (\u003Clabel>, \u003Croute>).`, listing every scope key as `\u003Ckey> (\u003Clabel>, \u003Croute>)` joined with `, `; without keys, the line `\u003Creason>.`;\n    - the section whose template text names the covered screens (it mentions `screen:` keys or the `scope` field): with scope keys, one line `\u003Ckey>: \u003Clabel>, \u003Croute>` per key; without keys, the line `Unmapped: \u003Creason>`;\n    - `## \u003Copen questions>`: `None.`;\n    - every other section: the one line `Written in the merge request review.`.\n    Take `\u003Clabel>` and `\u003Croute>` from the `label:` and `route:` lines of the element file from step 9. When the element file has no such line or it is empty, leave that part out, for example `\u003Ckey>` alone. For `screen:abs\u002Fdemo\u002Fcard` with label `Card` and route `\u002Fcard`, the screens section gets `screen:abs\u002Fdemo\u002Fcard: Card, \u002Fcard`. When `stage` is `delivery` or `done`, the text under `## \u003Copen questions>` must be `None.` or nothing: keep `None.` and write no questions there, and tell the person in the report to resolve open questions before merging.\n\n    Sections without text from the person, for scope `screen:abs\u002Fdemo\u002Fcard` with label `Card` and route `\u002Fcard`:\n\n    | English (`story.md`) | Russian (`story.ru.md`) | Text |\n    |---|---|---|\n    | no title line | `# [СО] \u003CНазвание стори>` | the title: `# [СО] Card` |\n    | `## Goal` (summary section) | `## Цель` (summary section) | `Deliver screen:abs\u002Fdemo\u002Fcard (Card, \u002Fcard).` |\n    | `## Scope` | `## Функциональные требования` | `screen:abs\u002Fdemo\u002Fcard: Card, \u002Fcard` |\n    | `## Acceptance criteria`, `## Verification`, `## Out of scope` | `## Заинтересованные стороны`, `## Описание бизнес-потребности`, `## Нефункциональные требования`, `## Задачи внутри стори`, `## Этапы` | `Written in the merge request review.` |\n    | `## Open questions` | `## Открытые вопросы` | `None.` |\n\n    Example with a scope:\n    ```\n    ---\n    key: story:abs\u002Foperations\u002Freports\n    type: story\n    status: waiting\n    owner:\n    started:\n    wave: 2\n    tracker:\n    scope:\n      - screen:abs\u002Foperations\u002Freports\n    depends:\n      - story:abs\u002Foperations\u002Flogin\n    repos: []\n    decisions: []\n    mockups: []\n    ---\n    ```\n    Example without a scope:\n    ```\n    ---\n    key: story:abs\u002Foperations\u002Fbff-defects\n    type: story\n    status: waiting\n    owner:\n    started:\n    wave: 3\n    tracker:\n    scope: []\n    unmapped: BFF returns wrong totals, no screen changes\n    depends: []\n    repos:\n      - repo:reports-bff\n    decisions: []\n    mockups: []\n    ---\n    ```\n14. Link the scope elements. For each element file from step 9, find its frontmatter line `story:`.\n    - When the line is exactly `story:` (empty), change it to `story: story:\u003Cproject>\u002F\u003Cdomain>\u002F\u003Cslug>`.\n    - When the line already names a story, leave it unchanged and tell the person in the report.\n    - Change nothing else in the element file.\n    Remember the element files you changed.\n15. Update the generated files. If `command -v python3` prints a path, run `python3 tools\u002Fgenerate.py`. It rewrites the stream's `BREAKDOWN.md`, the story cells of the domain `MAP.md` files, `.agents\u002Findex.json` and `STATUS.md`. Otherwise do all three:\n    - apply `## Recipe: BREAKDOWN.md row`;\n    - apply `## Recipe: index entry`;\n    - for each element file you changed in step 14, change one cell in `projects\u002F\u003Celement project>\u002Fdomains\u002F\u003Celement domain>\u002FMAP.md`. Find the begin marker of the element kind (`\u003C!-- map:screens:begin -->` for `screen`) and its end marker. When `MAP.md` or the marker pair is absent, skip this element. Between the markers, the first line is the header, for example `| key | route | kind | section | parent | access | label | wave | story |`; count which column is `story`. Find the row that starts with `| \u003Celement key> |`. In that row, replace only the text of the `story` cell: the empty cell `|  |` (two spaces between the bars) becomes `| story:\u003Cproject>\u002F\u003Cdomain>\u002F\u003Cslug> |`. Change nothing else. When there is no such row, do not add one; tell the person the table is stale and needs `python3 tools\u002Fgenerate.py`.\n\n      Row before, in `projects\u002Fabs\u002Fdomains\u002Foperations\u002FMAP.md`:\n      ```\n      | screen:abs\u002Foperations\u002Freports | \u002Freports | place | Reports |  | reports.read | Reports | 2 |  |\n      ```\n      Row after creating `story:abs\u002Foperations\u002Freports`:\n      ```\n      | screen:abs\u002Foperations\u002Freports | \u002Freports | place | Reports |  | reports.read | Reports | 2 | story:abs\u002Foperations\u002Freports |\n      ```\n16. Run the check. First run `command -v python3`.\n    - When it prints a path (Python is present): run `python3 tools\u002Fcheck.py` at most three times in total. After each run, look only at findings that name a file this skill changed: the new `story.md`, the element files from step 14, `projects\u002F\u003Celement project>\u002Fdomains\u002F\u003Celement domain>\u002FMAP.md`, `projects\u002F\u003Cproject>\u002Fdomains\u002F\u003Cdomain>\u002Fstreams\u002F\u003Cstream>\u002FBREAKDOWN.md`, `.agents\u002Findex.json` and `STATUS.md`.\n      - Fix such a finding only when the fix needs no new value, for example a wrong line format, order or comma, or a stale generated file (run `python3 tools\u002Fgenerate.py`). Then run the check again.\n      - When such a finding needs a value only the person has (for example a tracker id, a scope key, or answers to open questions), do not fix it and do not invent the value. Stop: do not commit, list these findings for the person, and wait.\n      - When no finding names these files, go on to step 17.\n      - When the third run still has findings in these files, stop: do not commit, list the findings for the person, and wait.\n      - Findings in other files: do not fix them; list them in the report.\n    - When it prints nothing (Python is missing): do not run the check. Remember the line `check not run: python3 missing` for the report.\n17. Commit: run `git status --short --untracked-files=all` in the workspace.\n    - Stage every path whose status is not `??`: run `git add` for each of them.\n    - Stage every `??` path this skill created: the new story folder `projects\u002F\u003Cproject>\u002Fdomains\u002F\u003Cdomain>\u002Fstreams\u002F\u003Cstream>\u002Fstories\u002F\u003Cslug>\u002F`, and `projects\u002F\u003Cproject>\u002Fdomains\u002F\u003Cdomain>\u002Fstreams\u002F\u003Cstream>\u002FBREAKDOWN.md` when `## Recipe: BREAKDOWN.md row` created it because it did not exist yet.\n    - Stage every other `??` path that is a generated file: its path starts with `.claude\u002F`, `.opencode\u002F` or `.cursor\u002F`, or it is exactly `CLAUDE.md`, `.agents\u002Findex.json`, `REPOSITORIES.md` or `STATUS.md`, or it matches `projects\u002F*\u002Fdomains\u002F*\u002Fstreams\u002F*\u002FBREAKDOWN.md`.\n    - Do not stage any other `??` path; mention it in the report to the person.\n    - Run `git commit -m \"docs(story): add \u003Cproject>\u002F\u003Cdomain>\u002F\u003Cslug>\"`.\n18. Run `GIT_TERMINAL_PROMPT=0 git pull --rebase origin \u003Cdefault>`. On conflicts follow `## Conflicts`. After the rebase has finished, run step 16 again. When step 16 stops, do not amend and do not push; wait for the person. When it made you fix a file, run `git add \u003Cfile>` for each fixed file, then `git commit --amend --no-edit`.\n19. Push and open the merge request by `.agents\u002Frules\u002Fmerge-requests.md`, with branch `story-\u003Cdomain>-\u003Cslug>` and title `Add story \u003Cproject>\u002F\u003Cdomain>\u002F\u003Cslug>`. Use `GIT_TERMINAL_PROMPT=0` before `git push`.\n20. Report to the person:\n    - the story file `projects\u002F\u003Cproject>\u002Fdomains\u002F\u003Cdomain>\u002Fstreams\u002F\u003Cstream>\u002Fstories\u002F\u003Cslug>\u002Fstory.md`, and its tracker id when step 6 gave one;\n    - the values step 3 derived, and that the person corrects them and writes the section text in the merge request review;\n    - the element files whose `story` you set, and the ones you left because they already named a story;\n    - the branch `story-\u003Cdomain>-\u003Cslug>`;\n    - the merge request link, or the instruction to open it;\n    - the remaining check findings in other files, when there are any;\n    - as the last line, the check result, or `check not run: python3 missing`.\n\n## Workspace task flow\n21. Collect these values:\n    - `slug`: the task name, lowercase letters, digits and `-` only (`[a-z0-9-]+`), for example `billing-architecture`. It is the last part of the key `task:\u003Cslug>`.\n    - `type`: ask the person to choose one of `task`, `bug`, `spike`, `architecture`, `e2e`. When they name `epic` or `story`, tell them these types live in a stream and offer the story flow (step 3) instead.\n    - `tracker`: optional. When the person gives none, the `tracker:` line stays empty. When they give one, check it the way step 6 does: pattern entry by entry, then the `\"` and `\\` rule, then the duplicate check in `.agents\u002Findex.json`. Every failed check asks the person for another id or for none.\n    - a one-line summary for the title, for example `Split billing into two services`.\n22. Check the slug: `printf '%s\\n' '\u003Cslug>' | grep -Ex '[a-z0-9-]+'` must print the slug, and `test -e tasks\u002F\u003Cslug>` must fail. When the folder already exists, stop, tell the person `tasks\u002F\u003Cslug>\u002F` already exists, and change nothing. When the slug has another form, ask for another slug.\n23. Find the workspace default branch as step 5 does, then run `git switch \u003Cdefault>` and `GIT_TERMINAL_PROMPT=0 git pull --ff-only`.\n24. Run `git switch -c task-\u003Cslug>`.\n25. Run `mkdir -p tasks\u002F\u003Cslug> && cp .agents\u002Ftemplates\u002Ftask.md tasks\u002F\u003Cslug>\u002Ftask.md`.\n26. Edit the new `task.md`. Keep every line of the template in its order and change only these lines:\n    - `key: task:\u003Cslug>`;\n    - `type: \u003Ctype>` from step 21;\n    - keep `status: waiting` and the empty `owner:` and `started:` lines exactly as the template has them: a new task waits, unowned and not started - `task-start` writes those three lines later;\n    - `tracker: \u003Ctracker>` when step 21 gave one; otherwise leave `tracker:` empty.\n    Replace the title line `# \u003Cslug>: \u003Cone-line summary>` with the slug and the summary of step 21. Keep every `## ` heading. Where the person gave you the words for a section, write those words under it; otherwise keep the template text under that heading and say in the report that the person fills the sections before starting the task.\n27. Update the generated files. If `command -v python3` prints a path, run `python3 tools\u002Fgenerate.py`. It rewrites `.agents\u002Findex.json` (the `task:\u003Cslug>` entry, and the tracker alias when one was set) and `STATUS.md` (the row in the `workspace` group of the waiting section). Otherwise apply `## Recipe: index entry` for `task:\u003Cslug>`.\n28. Run the check as step 16 does, at most three times in total, looking only at findings that name `tasks\u002F\u003Cslug>\u002Ftask.md`, `.agents\u002Findex.json` or `STATUS.md`, with the same fix, stop and report rules.\n29. Commit as step 17 does, with these differences: the created folder is `tasks\u002F\u003Cslug>\u002F`; no `BREAKDOWN.md` is created; the commit message is `git commit -m \"docs(task): add \u003Cslug>\"`.\n30. Run `GIT_TERMINAL_PROMPT=0 git pull --rebase origin \u003Cdefault>`. On conflicts follow `## Conflicts`. After the rebase has finished, run step 28 again. When step 28 stops, do not amend and do not push; wait for the person. When it made you fix a file, run `git add \u003Cfile>` for each fixed file, then `git commit --amend --no-edit`.\n31. Push and open the merge request by `.agents\u002Frules\u002Fmerge-requests.md`, with branch `task-\u003Cslug>` and title `Add task \u003Cslug>`. Use `GIT_TERMINAL_PROMPT=0` before `git push`.\n32. Report to the person:\n    - the task file `tasks\u002F\u003Cslug>\u002Ftask.md`, and its tracker id when step 21 gave one;\n    - that the person fills the sections that still carry the template text before starting the task;\n    - the branch `task-\u003Cslug>`;\n    - the merge request link, or the instruction to open it;\n    - the remaining check findings in other files, when there are any;\n    - as the last line, the check result, or `check not run: python3 missing`.\n\n## Recipe: BREAKDOWN.md row\nUse this only when `python3` is missing. The result equals what `python3 tools\u002Fgenerate.py` writes.\n\n1. Build the row from the frontmatter of the new `story.md`, copying values verbatim (without surrounding quotes):\n\n   `| story:\u003Cproject>\u002F\u003Cdomain>\u002F\u003Cslug> | \u003Cwave> | \u003Cscope joined with \", \"> | \u003Cunmapped> | \u003Ctracker> | \u003Cdepends joined with \", \"> |`\n\n   An empty value leaves an empty cell with two spaces between the bars: `|  |`. For example scope `[]` with unmapped `BFF defects` and no tracker and no depends gives `| story:abs\u002Foperations\u002Fbff-defects | 3 |  | BFF defects |  |  |`.\n2. Open `projects\u002F\u003Cproject>\u002Fdomains\u002F\u003Cdomain>\u002Fstreams\u002F\u003Cstream>\u002FBREAKDOWN.md`. When it does not exist, create it with exactly these six lines, each ending with a newline:\n   ```\n   # \u003Ctitle> stream:\u003Cproject>\u002F\u003Cdomain>\u002F\u003Cstream>\n\n   \u003Cnote>\n\n   | \u003Ccolumn 1> | \u003Ccolumn 2> | \u003Ccolumn 3> | \u003Ccolumn 4> | \u003Ccolumn 5> | \u003Ccolumn 6> |\n   |---|---|---|---|---|---|\n   ```\n   Take `\u003Ctitle>`, `\u003Cnote>` and the six columns from the `breakdown` block of `.agents\u002Fprofiles\u002F\u003Cprofile>\u002Fprofile.json` (`title`, `note` and `columns` in their order), in `\u003Clanguage>` as step 6 says. When `profile.json` has no `breakdown` block, use title `Breakdown of`, note `Generated by tools\u002Fgenerate.py from stories\u002F*\u002Fstory.md. Do not edit.` and columns `Story`, `Wave`, `Scope`, `Unmapped`, `Tracker`, `Depends`. The row cells keep the order of step 1 whatever the column names are.\n\n   English (`en`, and every profile without a `breakdown` block):\n   ```\n   # Breakdown of stream:demo\u002Foperations\u002Fmigration\n\n   Generated by tools\u002Fgenerate.py from stories\u002F*\u002Fstory.md. Do not edit.\n\n   | Story | Wave | Scope | Unmapped | Tracker | Depends |\n   |---|---|---|---|---|---|\n   ```\n   Russian (`ru`, profile `ui-migration`):\n   ```\n   # Разбивка stream:demo\u002Foperations\u002Fmigration\n\n   Сгенерировано tools\u002Fgenerate.py из stories\u002F*\u002Fstory.md. Не редактировать.\n\n   | Стори | Волна | Экраны | Без экрана | Трекер | Зависит от |\n   |---|---|---|---|---|---|\n   ```\n\n   (The blank lines count: the file starts with the title line, a blank line, the note line, a blank line, the header line and the separator line.)\n3. Rows follow the separator line in ascending slug order. Compare your slug with the slug of each row (the text after the last `\u002F` in its first cell) character by character from the left; the first different character decides in this order: `-`, then digits `0` to `9`, then letters `a` to `z`. When one slug is the start of the other, the shorter one comes first. So `login` \u003C `reports` \u003C `reports-v2` \u003C `reports2`.\n4. Insert your row directly above the first row whose slug comes after yours. When no row comes after yours, add it as the last line of the file. Change nothing else. The file ends with a newline.\n\nExample. `BREAKDOWN.md` before:\n```\n# Breakdown of stream:demo\u002Foperations\u002Fmigration\n\nGenerated by tools\u002Fgenerate.py from stories\u002F*\u002Fstory.md. Do not edit.\n\n| Story | Wave | Scope | Unmapped | Tracker | Depends |\n|---|---|---|---|---|---|\n| story:demo\u002Foperations\u002Flogin | 1 | screen:demo\u002Foperations\u002Flogin |  | DEMO-101 |  |\n| story:demo\u002Foperations\u002Fusers | 2 | screen:demo\u002Foperations\u002Fusers, screen:demo\u002Foperations\u002Fuser-view |  |  | story:demo\u002Foperations\u002Flogin |\n```\nAfter creating `story:demo\u002Foperations\u002Freports` with wave `2`, scope `screen:demo\u002Foperations\u002Freports`, depends `story:demo\u002Foperations\u002Flogin`:\n```\n# Breakdown of stream:demo\u002Foperations\u002Fmigration\n\nGenerated by tools\u002Fgenerate.py from stories\u002F*\u002Fstory.md. Do not edit.\n\n| Story | Wave | Scope | Unmapped | Tracker | Depends |\n|---|---|---|---|---|---|\n| story:demo\u002Foperations\u002Flogin | 1 | screen:demo\u002Foperations\u002Flogin |  | DEMO-101 |  |\n| story:demo\u002Foperations\u002Freports | 2 | screen:demo\u002Foperations\u002Freports |  |  | story:demo\u002Foperations\u002Flogin |\n| story:demo\u002Foperations\u002Fusers | 2 | screen:demo\u002Foperations\u002Fusers, screen:demo\u002Foperations\u002Fuser-view |  |  | story:demo\u002Foperations\u002Flogin |\n```\n\n## Recipe: index entry\nUse this only when `python3` is missing. The result equals what `python3 tools\u002Fgenerate.py` writes.\n\n`.agents\u002Findex.json` is one JSON object with one entry per line, two spaces of indentation, in this order: `adr:` entries, then `diagram:` and `mockup:` entries, then the `story:` and `task:` entries ascending by key - every `story:` entry comes before every `task:` entry -, then tracker ids ascending by id. A tracker id entry maps the task's `tracker` value to the same task file path.\n\nAscending means: compare two keys character by character from the left; the first different character decides in this order: `-`, `.`, `\u002F`, digits `0` to `9`, `:`, upper-case letters `A` to `Z`, `_`, lower-case letters `a` to `z`. When one key is the start of the other, the shorter one comes first. So `story:demo\u002Foperations\u002Flogin` \u003C `story:demo\u002Foperations\u002Freports`, `story:demo-new\u002Fa` \u003C `story:demo\u002Fa`, and `DEMO-145` \u003C `DEMO-99` (not number order).\n\n1. Build your entry line. A story: `  \"story:\u003Cproject>\u002F\u003Cdomain>\u002F\u003Cslug>\": \"projects\u002F\u003Cproject>\u002Fdomains\u002F\u003Cdomain>\u002Fstreams\u002F\u003Cstream>\u002Fstories\u002F\u003Cslug>\u002Fstory.md\"`. A workspace task: `  \"task:\u003Cslug>\": \"tasks\u002F\u003Cslug>\u002Ftask.md\"`.\n2. Find its position among the lines starting with `  \"story:` or `  \"task:`:\n   - When the file has such lines, insert your line directly above the first of them whose key comes after yours. When none comes after yours, insert it directly after the last of them.\n   - When there is no `  \"story:` or `  \"task:` line, insert it directly after the last line starting with `  \"adr:`, `  \"diagram:` or `  \"mockup:`.\n   - When there is none of those either, insert it as the first entry, directly after the line `{`.\n   - When the whole file is the single line `{}`, replace that line with three lines: `{`, your line, `}`.\n3. Only when the task's `tracker` is not empty (step 6 sets it for a stream at stage `delivery` or `done`, step 21 whenever the person gives one): build the line `  \"\u003Ctracker>\": \"\u003Ctask file path>\"` with the same path as your entry line, writing `\"` as `\\\"` and `\\` as `\\\\` inside the id. Tracker lines are the entry lines after the last `  \"story:` or `  \"task:` line. When a line with the same id already exists, add nothing and tell the person the id is used by another task. Otherwise insert your line directly above the first tracker line whose id comes after yours; when none comes after yours, insert it as the last entry, directly above the line `}`.\n4. Commas: every entry line ends with `,` except the last entry, directly above `}`. After inserting, add the missing `,` to the line above your line, and end your line with `,` unless it is the last entry.\n5. Keep no trailing spaces. The file ends with `}` and a newline. Change nothing else.\n\nExample 1. The index is `{}`. After creating `story:demo\u002Foperations\u002Freports` in stream `migration`:\n```\n{\n  \"story:demo\u002Foperations\u002Freports\": \"projects\u002Fdemo\u002Fdomains\u002Foperations\u002Fstreams\u002Fmigration\u002Fstories\u002Freports\u002Fstory.md\"\n}\n```\n\nExample 2. Before:\n```\n{\n  \"adr:0001\": \"docs\u002Fadr\u002F0001-use-kafka.md\",\n  \"mockup:demo\u002Foperations\u002Flogin\": \"https:\u002F\u002Fdesign.example.org\u002Ffile\u002Flogin\",\n  \"story:demo\u002Foperations\u002Flogin\": \"projects\u002Fdemo\u002Fdomains\u002Foperations\u002Fstreams\u002Fmigration\u002Fstories\u002Flogin\u002Fstory.md\",\n  \"story:demo\u002Foperations\u002Fusers\": \"projects\u002Fdemo\u002Fdomains\u002Foperations\u002Fstreams\u002Fmigration\u002Fstories\u002Fusers\u002Fstory.md\",\n  \"task:billing-architecture\": \"tasks\u002Fbilling-architecture\u002Ftask.md\",\n  \"DEMO-101\": \"projects\u002Fdemo\u002Fdomains\u002Foperations\u002Fstreams\u002Fmigration\u002Fstories\u002Flogin\u002Fstory.md\"\n}\n```\nAfter creating `story:demo\u002Foperations\u002Freports` in stream `migration`:\n```\n{\n  \"adr:0001\": \"docs\u002Fadr\u002F0001-use-kafka.md\",\n  \"mockup:demo\u002Foperations\u002Flogin\": \"https:\u002F\u002Fdesign.example.org\u002Ffile\u002Flogin\",\n  \"story:demo\u002Foperations\u002Flogin\": \"projects\u002Fdemo\u002Fdomains\u002Foperations\u002Fstreams\u002Fmigration\u002Fstories\u002Flogin\u002Fstory.md\",\n  \"story:demo\u002Foperations\u002Freports\": \"projects\u002Fdemo\u002Fdomains\u002Foperations\u002Fstreams\u002Fmigration\u002Fstories\u002Freports\u002Fstory.md\",\n  \"story:demo\u002Foperations\u002Fusers\": \"projects\u002Fdemo\u002Fdomains\u002Foperations\u002Fstreams\u002Fmigration\u002Fstories\u002Fusers\u002Fstory.md\",\n  \"task:billing-architecture\": \"tasks\u002Fbilling-architecture\u002Ftask.md\",\n  \"DEMO-101\": \"projects\u002Fdemo\u002Fdomains\u002Foperations\u002Fstreams\u002Fmigration\u002Fstories\u002Flogin\u002Fstory.md\"\n}\n```\n\n## Conflicts\nFor this skill a conflicted file counts as generated when it is `.agents\u002Findex.json`, `STATUS.md`, a stream `BREAKDOWN.md`, or a `MAP.md` whose conflicts all lie between `map:` markers (see step 2). Every other file, including `story.md`, `task.md`, element files and `stream.json`, is not generated.\n\n1. List all conflicted files: `git diff --name-only --diff-filter=U`. Write the list down before you change anything.\n2. For each `MAP.md` in the list, run `grep -n -e '^\u003C\u003C\u003C\u003C\u003C\u003C\u003C' -e '^>>>>>>>' -e '\u003C!-- map:' \u003Cfile>`. The file counts as generated only when every `\u003C\u003C\u003C\u003C\u003C\u003C\u003C` line and the `>>>>>>>` line after it both lie between one `:begin -->` line and the next `:end -->` line. Otherwise it is not generated.\n3. First check the whole list for any file that is not generated. If there is one:\n   - Run `git rebase --abort`. Do not touch any file first, not even the generated ones.\n   - For each file that is not generated, show the person both versions with these labels:\n     - \"default branch\": the output of `git show origin\u002F\u003Cdefault>:\u003Cfile>`;\n     - \"your branch\": the output of `git show \u003Cbranch>:\u003Cfile>`, where `\u003Cbranch>` is `story-\u003Cdomain>-\u003Cslug>` in the story flow and `task-\u003Cslug>` in the task flow.\n     When one of the two commands fails, tell the person that side has no such file.\n   - Stop and wait for the person.\n4. Only when every file in the list is generated:\n   - For each file in the list, run `git checkout --ours -- \u003Cfile>`. During a rebase `--ours` is the default branch version, so your own change in that file is gone.\n   - Regenerate: if `command -v python3` prints a path, run `python3 tools\u002Fgenerate.py`. Otherwise apply again, to the files in the list, what step 15 does for a story (`## Recipe: BREAKDOWN.md row`, `## Recipe: index entry`, the `story` cell change in `MAP.md`) and step 27 for a task (`## Recipe: index entry`).\n   - For each file in the list, run `git add \u003Cfile>`. Also `git add` any other generated file the regeneration changed.\n   - Run `GIT_EDITOR=true git rebase --continue`. When it stops on conflicts again, go back to step 1.\n\n## Without Python\n1. Skip `python3 tools\u002Fgenerate.py` and `python3 tools\u002Fcheck.py` everywhere, including `## Conflicts`. Instead apply, at step 15 for a story and at step 27 for a task, the recipes named there.\n2. `STATUS.md` is generated, and this kit version ships no hand recipe for adding a waiting row yet. After step 15 or step 27, do not commit and do not push: tell the person to run `python3 tools\u002Fgenerate.py`, and continue from step 17 or step 29 after they have.\n3. End the report with the line:\n\ncheck not run: python3 missing\n","# Create a story or a workspace task\n\n## Steps\n1. Go to the workspace root: the nearest directory, walking up from where you are, where `test -f .agents\u002Fkit.json` succeeds. Run every command below from there.\n2. Ask the person which kind to create, unless they already said it:\n   - a story in a stream of a project: go to step 3;\n   - a projectless workspace task in `tasks\u002F`: go to step 21.\n   The types `epic` and `story` belong to a stream: create them only through the story flow. The task flow offers `task`, `bug`, `spike`, `architecture` and `e2e` only.\n\n## Story flow\n3. Collect these values:\n   - `project`: the project folder name in `projects\u002F`, for example `abs`.\n   - `domain`: the domain folder name in `projects\u002F\u003Cproject>\u002Fdomains\u002F`, for example `operations`.\n   - `stream`: the stream folder name in `projects\u002F\u003Cproject>\u002Fdomains\u002F\u003Cdomain>\u002Fstreams\u002F`, for example `migration`.\n   - `slug`: the story name, lowercase letters, digits and `-` only (`[a-z0-9-]+`), for example `reports`.\n   - scope keys: one or more element keys of the form `\u003Cprefix>:\u003Cproject>\u002F\u003Cdomain>\u002F\u003Cslug>`, for example `screen:abs\u002Foperations\u002Freports`. Or, when the story covers no element (for example BFF defects), no keys and a one-line unmapped reason. The reason must not contain `|` and must not start with `[`, `{`, `\"` or `'`.\n   - `wave`: a number, for example `2`.\n   - depends: story keys this story waits for, for example `story:abs\u002Foperations\u002Flogin`, or none.\n   - repos: repository keys, for example `repo:reports-bff`, or none.\n   - `title`: the story title for the `# ` title line of the story template, for example `Reports`. Only needed when the template has such a line (step 6 chooses the template), for example `# [СО] \u003CНазвание стори>` in `story.ru.md`.\n\n   Use every value the person gave. Derive the others from the files by the rules below, and do not ask the person to confirm a derived value: the person corrects derived values in the merge request review. Ask the person only for a value that is neither given nor derivable, and wait for the answer. Never invent a value.\n   - Stream. When the person named the project, the domain and the stream, use them. Otherwise run `ls projects\u002F*\u002Fdomains\u002F*\u002Fstreams\u002F*\u002Fstream.json`; each printed path `projects\u002F\u003Cproject>\u002Fdomains\u002F\u003Cdomain>\u002Fstreams\u002F\u003Cstream>\u002Fstream.json` is one stream. Keep the streams whose project folder, domain folder, stream folder or `key` in `stream.json` the request names. When the request names no stream, keep instead the streams that have an uncovered scope key (see Scope). When exactly one stream is left, take its `\u003Cproject>`, `\u003Cdomain>` and `\u003Cstream>`. When several or none are left, ask the person for the project, the domain and the stream.\n   - Scope. When the person named element keys, use them. When the request asks for the element or elements that have no story yet, read the `scope` list of `projects\u002F\u003Cproject>\u002Fdomains\u002F\u003Cdomain>\u002Fstreams\u002F\u003Cstream>\u002Fstream.json` and, for each key in it, run `grep -lxF -e '  - \u003Ckey>' projects\u002F\u003Cproject>\u002Fdomains\u002F\u003Cdomain>\u002Fstreams\u002F\u003Cstream>\u002Fstories\u002F*\u002Fstory.md 2>\u002Fdev\u002Fnull`. The key is uncovered when the command prints no path. The scope keys are the uncovered keys, in the order of the `scope` list. When no key is uncovered, stop, tell the person every scope key of the stream has a story, and change nothing. When the request asks for a story that covers no element, ask the person for the unmapped reason.\n   - `wave`. For each scope key, open its element file (step 9 gives the path) and read its `wave:` line. Take the lowest number. Without scope keys, ask the person.\n   - `slug`. When the scope has exactly one key, take the text after the last `\u002F` in that key, for example `card` for `screen:abs\u002Fdemo\u002Fcard`; step 8 checks that it is free. Otherwise ask the person.\n   - depends and repos: none, unless the person named them.\n   - `title`. When the person gave a title, use it. Otherwise, when the scope has exactly one key, take the `label:` value of its element file (step 9 gives the path). Otherwise (several keys, no keys, or an empty `label:`) ask the person for the title. Never invent a title.\n   - `type`, `tracker`, `decisions` and `mockups` are not asked: step 13 keeps `type`, `decisions` and `mockups` from the template, keeps `status`, `owner` and `started` as the template has them, and `tracker` stays empty unless step 6 needs one.\n4. Check the slug: run `printf '%s\\n' '\u003Cslug>' | grep -Ex '[a-z0-9-]+'`. When it prints nothing, ask the person for another slug.\n5. Find the workspace default branch: run `git symbolic-ref --short refs\u002Fremotes\u002Forigin\u002FHEAD` and remove the `origin\u002F` prefix; when the command fails, use `main`. Call it `\u003Cdefault>`. Then run, one by one:\n   - `git switch \u003Cdefault>`\n   - `GIT_TERMINAL_PROMPT=0 git pull --ff-only`\n   The checks in steps 6 to 10 run after the pull, so they see the fresh default branch.\n6. Run `test -f projects\u002F\u003Cproject>\u002Fdomains\u002F\u003Cdomain>\u002Fstreams\u002F\u003Cstream>\u002Fstream.json`. When it fails, stop, tell the person the stream does not exist, and change nothing. Otherwise read the file and take `profile`, `stage` and the `scope` list.\n   - Find the workspace language `\u003Clanguage>`: open `.agents\u002Fkit.json` and read `params.language`. When the file, `params` or `language` is missing, `\u003Clanguage>` is `en`.\n   - Find the story template `\u003Ctemplate>`: when `\u003Clanguage>` is not `en` and `test -f .agents\u002Fprofiles\u002F\u003Cprofile>\u002Fstory.\u003Clanguage>.md` succeeds, it is `.agents\u002Fprofiles\u002F\u003Cprofile>\u002Fstory.\u003Clanguage>.md`; otherwise `.agents\u002Fprofiles\u002F\u003Cprofile>\u002Fstory.md`. For language `ru` in profile `ui-migration` it is `story.ru.md`.\n   - Values in `.agents\u002Fprofiles\u002F\u003Cprofile>\u002Fprofile.json` may be language objects such as `{\"en\": \"Open questions\", \"ru\": \"Открытые вопросы\"}`. Wherever this skill reads a value from `profile.json`, take the `\u003Clanguage>` value of such an object, or its `en` value when it has no `\u003Clanguage>` key.\n   - Find the open questions section `\u003Copen questions>`: the `section` of the gate `\"gate\": \"no_open_questions\"` in `stages` of `profile.json`, for example `Open questions` (en) or `Открытые вопросы` (ru). When no such gate exists, there is no open questions section.\n   - When `stage` is `goal`, `map`, `decomposition` or `ready`: the story gets no tracker id. Go to step 7.\n   - When `stage` is `delivery` or `done`: the `ready` stage is closed, so its `tracker_ids` gate requires a tracker id for the new story too. Ask the person for the tracker id `\u003Ctracker>` and wait for the answer. When the person gives none, stop, tell them a stream at stage `\u003Cstage>` needs a tracker id for every story, and change nothing. Do not create any file or branch.\n   - Check `\u003Ctracker>`: read `tracker\u002Ftrackers.json`. Every entry of `trackers` carries `key` and `id_pattern`; JSON doubles every backslash, so `\\\\d` in the file means `\\d`. Rewrite each pattern for `grep -E` (write every `\\d` as `[0-9]`) and run `printf '%s\\n' '\u003Ctracker>' | grep -Ex '\u003Crewritten pattern>'` entry by entry until one matches. When no entry matches, ask the person for another id. When `tracker\u002Ftrackers.json` has no `trackers` list, or no entry has an `id_pattern`, stop, tell the person, and change nothing.\n   - When `\u003Ctracker>` contains a `\"` or a `\\` character, ask the person for another id: `.agents\u002Findex.json` stores such ids escaped, so the next check cannot find them.\n   - Run `grep -F '  \"\u003Ctracker>\":' .agents\u002Findex.json 2>\u002Fdev\u002Fnull`. When it prints a line, the id belongs to another task: ask the person for another id.\n7. For each scope key from step 3, check that it is one of the strings in the `scope` list of `stream.json`, exactly. When a key is not in that list, stop, tell the person which key is outside the stream scope, and change nothing. Do not create any file or branch.\n   - When step 3 found the scope keys as uncovered keys, run its `grep` again for each of them. When it now prints a path, that story covers the key since the pull: stop, tell the person the path, and change nothing.\n8. Run `ls -d projects\u002F\u003Cproject>\u002Fdomains\u002F\u003Cdomain>\u002Fstreams\u002F*\u002Fstories\u002F\u003Cslug>`. When it prints a path, the slug already exists: stop, tell the person the path, and change nothing. When step 3 derived the slug, ask the person for another slug and continue from step 4 with the answer.\n9. For each scope key, find its element file:\n   - The key has the form `\u003Cprefix>:\u003Celement project>\u002F\u003Celement domain>\u002F\u003Celement slug>`. Open `.agents\u002Fprofiles\u002F\u003Cprofile>\u002Fprofile.json` and find the entry of `elements` whose `prefix` equals `\u003Cprefix>`. Its `dir` gives the path `projects\u002F\u003Celement project>\u002Fdomains\u002F\u003Celement domain>\u002F\u003Cdir>\u002F\u003Celement slug>.md`. For `screen:abs\u002Foperations\u002Freports` in profile `ui-migration` it is `projects\u002Fabs\u002Fdomains\u002Foperations\u002Fmap\u002Freports.md`.\n   - Run `test -f \u003Cpath>`. When it fails, stop, tell the person the element file is missing, and change nothing.\n10. Check depends and repos:\n    - For each depends key `story:\u003Cd>\u002F\u003Cdd>\u002F\u003Cs>`, run `ls projects\u002F\u003Cd>\u002Fdomains\u002F\u003Cdd>\u002Fstreams\u002F*\u002Fstories\u002F\u003Cs>\u002Fstory.md 2>\u002Fdev\u002Fnull`. It must print exactly one path.\n    - For each repos key `repo:\u003Cname>`, run `grep -F '\"name\": \"\u003Cname>\"' repos.json`. It must print a line.\n    - Correct or drop, together with the person, every key that fails. Never keep a key that does not exist.\n11. Run `git switch -c story-\u003Cdomain>-\u003Cslug>`.\n12. Run `mkdir -p projects\u002F\u003Cproject>\u002Fdomains\u002F\u003Cdomain>\u002Fstreams\u002F\u003Cstream>\u002Fstories\u002F\u003Cslug> && cp \u003Ctemplate> projects\u002F\u003Cproject>\u002Fdomains\u002F\u003Cdomain>\u002Fstreams\u002F\u003Cstream>\u002Fstories\u002F\u003Cslug>\u002Fstory.md`.\n13. Edit the frontmatter of the new `story.md`. Keep every line of the template in its order and change only these lines:\n    - `key: story:\u003Cproject>\u002F\u003Cdomain>\u002F\u003Cslug>`;\n    - keep `status: waiting` and the empty `owner:` and `started:` lines exactly as the template has them: a new story waits, unowned and not started - `task-start` writes those three lines later;\n    - `wave: \u003Cwave>`;\n    - `scope`: with keys, the line `scope:` followed by one line `  - \u003Ckey>` per key (two spaces, `-`, space), in the order of step 3; without keys, the line `scope: []` and directly below it the line `unmapped: \u003Creason>`. The `unmapped:` line is the only line the template does not have; write it only when the scope is empty;\n    - `depends` and `repos`: the same form, `\u003Cfield>:` followed by `  - \u003Ckey>` lines, or `\u003Cfield>: []` when empty;\n    - `tracker`: when step 6 gave a `\u003Ctracker>`, `tracker: \u003Ctracker>`; otherwise leave `tracker:` empty;\n    - leave `type`, `decisions` and `mockups` as the template has them.\n    Keep every `## ` heading of the template and replace the placeholder text under each of them. The sections are those of `\u003Ctemplate>`, in their order; their names are the `story.sections` list of `profile.json`. When the template has a `# ` title line, replace its placeholder in angle brackets with `\u003Ctitle>` from step 3 and keep the rest of the line: `# [СО] \u003CНазвание стори>` becomes `# [СО] Отчёты` for title `Отчёты`. Where the person gave you the words for a section, write those words. Otherwise write:\n    - the summary section: the section named by `story.summary_section` of `profile.json` (in `\u003Clanguage>` as step 6 says), or the first item of `story.sections` when `summary_section` is absent. It gets the goal. With scope keys, one line `Deliver \u003Ckey> (\u003Clabel>, \u003Croute>).`, listing every scope key as `\u003Ckey> (\u003Clabel>, \u003Croute>)` joined with `, `; without keys, the line `\u003Creason>.`;\n    - the section whose template text names the covered screens (it mentions `screen:` keys or the `scope` field): with scope keys, one line `\u003Ckey>: \u003Clabel>, \u003Croute>` per key; without keys, the line `Unmapped: \u003Creason>`;\n    - `## \u003Copen questions>`: `None.`;\n    - every other section: the one line `Written in the merge request review.`.\n    Take `\u003Clabel>` and `\u003Croute>` from the `label:` and `route:` lines of the element file from step 9. When the element file has no such line or it is empty, leave that part out, for example `\u003Ckey>` alone. For `screen:abs\u002Fdemo\u002Fcard` with label `Card` and route `\u002Fcard`, the screens section gets `screen:abs\u002Fdemo\u002Fcard: Card, \u002Fcard`. When `stage` is `delivery` or `done`, the text under `## \u003Copen questions>` must be `None.` or nothing: keep `None.` and write no questions there, and tell the person in the report to resolve open questions before merging.\n\n    Sections without text from the person, for scope `screen:abs\u002Fdemo\u002Fcard` with label `Card` and route `\u002Fcard`:\n\n    | English (`story.md`) | Russian (`story.ru.md`) | Text |\n    |---|---|---|\n    | no title line | `# [СО] \u003CНазвание стори>` | the title: `# [СО] Card` |\n    | `## Goal` (summary section) | `## Цель` (summary section) | `Deliver screen:abs\u002Fdemo\u002Fcard (Card, \u002Fcard).` |\n    | `## Scope` | `## Функциональные требования` | `screen:abs\u002Fdemo\u002Fcard: Card, \u002Fcard` |\n    | `## Acceptance criteria`, `## Verification`, `## Out of scope` | `## Заинтересованные стороны`, `## Описание бизнес-потребности`, `## Нефункциональные требования`, `## Задачи внутри стори`, `## Этапы` | `Written in the merge request review.` |\n    | `## Open questions` | `## Открытые вопросы` | `None.` |\n\n    Example with a scope:\n    ```\n    ---\n    key: story:abs\u002Foperations\u002Freports\n    type: story\n    status: waiting\n    owner:\n    started:\n    wave: 2\n    tracker:\n    scope:\n      - screen:abs\u002Foperations\u002Freports\n    depends:\n      - story:abs\u002Foperations\u002Flogin\n    repos: []\n    decisions: []\n    mockups: []\n    ---\n    ```\n    Example without a scope:\n    ```\n    ---\n    key: story:abs\u002Foperations\u002Fbff-defects\n    type: story\n    status: waiting\n    owner:\n    started:\n    wave: 3\n    tracker:\n    scope: []\n    unmapped: BFF returns wrong totals, no screen changes\n    depends: []\n    repos:\n      - repo:reports-bff\n    decisions: []\n    mockups: []\n    ---\n    ```\n14. Link the scope elements. For each element file from step 9, find its frontmatter line `story:`.\n    - When the line is exactly `story:` (empty), change it to `story: story:\u003Cproject>\u002F\u003Cdomain>\u002F\u003Cslug>`.\n    - When the line already names a story, leave it unchanged and tell the person in the report.\n    - Change nothing else in the element file.\n    Remember the element files you changed.\n15. Update the generated files. If `command -v python3` prints a path, run `python3 tools\u002Fgenerate.py`. It rewrites the stream's `BREAKDOWN.md`, the story cells of the domain `MAP.md` files, `.agents\u002Findex.json` and `STATUS.md`. Otherwise do all three:\n    - apply `## Recipe: BREAKDOWN.md row`;\n    - apply `## Recipe: index entry`;\n    - for each element file you changed in step 14, change one cell in `projects\u002F\u003Celement project>\u002Fdomains\u002F\u003Celement domain>\u002FMAP.md`. Find the begin marker of the element kind (`\u003C!-- map:screens:begin -->` for `screen`) and its end marker. When `MAP.md` or the marker pair is absent, skip this element. Between the markers, the first line is the header, for example `| key | route | kind | section | parent | access | label | wave | story |`; count which column is `story`. Find the row that starts with `| \u003Celement key> |`. In that row, replace only the text of the `story` cell: the empty cell `|  |` (two spaces between the bars) becomes `| story:\u003Cproject>\u002F\u003Cdomain>\u002F\u003Cslug> |`. Change nothing else. When there is no such row, do not add one; tell the person the table is stale and needs `python3 tools\u002Fgenerate.py`.\n\n      Row before, in `projects\u002Fabs\u002Fdomains\u002Foperations\u002FMAP.md`:\n      ```\n      | screen:abs\u002Foperations\u002Freports | \u002Freports | place | Reports |  | reports.read | Reports | 2 |  |\n      ```\n      Row after creating `story:abs\u002Foperations\u002Freports`:\n      ```\n      | screen:abs\u002Foperations\u002Freports | \u002Freports | place | Reports |  | reports.read | Reports | 2 | story:abs\u002Foperations\u002Freports |\n      ```\n16. Run the check. First run `command -v python3`.\n    - When it prints a path (Python is present): run `python3 tools\u002Fcheck.py` at most three times in total. After each run, look only at findings that name a file this skill changed: the new `story.md`, the element files from step 14, `projects\u002F\u003Celement project>\u002Fdomains\u002F\u003Celement domain>\u002FMAP.md`, `projects\u002F\u003Cproject>\u002Fdomains\u002F\u003Cdomain>\u002Fstreams\u002F\u003Cstream>\u002FBREAKDOWN.md`, `.agents\u002Findex.json` and `STATUS.md`.\n      - Fix such a finding only when the fix needs no new value, for example a wrong line format, order or comma, or a stale generated file (run `python3 tools\u002Fgenerate.py`). Then run the check again.\n      - When such a finding needs a value only the person has (for example a tracker id, a scope key, or answers to open questions), do not fix it and do not invent the value. Stop: do not commit, list these findings for the person, and wait.\n      - When no finding names these files, go on to step 17.\n      - When the third run still has findings in these files, stop: do not commit, list the findings for the person, and wait.\n      - Findings in other files: do not fix them; list them in the report.\n    - When it prints nothing (Python is missing): do not run the check. Remember the line `check not run: python3 missing` for the report.\n17. Commit: run `git status --short --untracked-files=all` in the workspace.\n    - Stage every path whose status is not `??`: run `git add` for each of them.\n    - Stage every `??` path this skill created: the new story folder `projects\u002F\u003Cproject>\u002Fdomains\u002F\u003Cdomain>\u002Fstreams\u002F\u003Cstream>\u002Fstories\u002F\u003Cslug>\u002F`, and `projects\u002F\u003Cproject>\u002Fdomains\u002F\u003Cdomain>\u002Fstreams\u002F\u003Cstream>\u002FBREAKDOWN.md` when `## Recipe: BREAKDOWN.md row` created it because it did not exist yet.\n    - Stage every other `??` path that is a generated file: its path starts with `.claude\u002F`, `.opencode\u002F` or `.cursor\u002F`, or it is exactly `CLAUDE.md`, `.agents\u002Findex.json`, `REPOSITORIES.md` or `STATUS.md`, or it matches `projects\u002F*\u002Fdomains\u002F*\u002Fstreams\u002F*\u002FBREAKDOWN.md`.\n    - Do not stage any other `??` path; mention it in the report to the person.\n    - Run `git commit -m \"docs(story): add \u003Cproject>\u002F\u003Cdomain>\u002F\u003Cslug>\"`.\n18. Run `GIT_TERMINAL_PROMPT=0 git pull --rebase origin \u003Cdefault>`. On conflicts follow `## Conflicts`. After the rebase has finished, run step 16 again. When step 16 stops, do not amend and do not push; wait for the person. When it made you fix a file, run `git add \u003Cfile>` for each fixed file, then `git commit --amend --no-edit`.\n19. Push and open the merge request by `.agents\u002Frules\u002Fmerge-requests.md`, with branch `story-\u003Cdomain>-\u003Cslug>` and title `Add story \u003Cproject>\u002F\u003Cdomain>\u002F\u003Cslug>`. Use `GIT_TERMINAL_PROMPT=0` before `git push`.\n20. Report to the person:\n    - the story file `projects\u002F\u003Cproject>\u002Fdomains\u002F\u003Cdomain>\u002Fstreams\u002F\u003Cstream>\u002Fstories\u002F\u003Cslug>\u002Fstory.md`, and its tracker id when step 6 gave one;\n    - the values step 3 derived, and that the person corrects them and writes the section text in the merge request review;\n    - the element files whose `story` you set, and the ones you left because they already named a story;\n    - the branch `story-\u003Cdomain>-\u003Cslug>`;\n    - the merge request link, or the instruction to open it;\n    - the remaining check findings in other files, when there are any;\n    - as the last line, the check result, or `check not run: python3 missing`.\n\n## Workspace task flow\n21. Collect these values:\n    - `slug`: the task name, lowercase letters, digits and `-` only (`[a-z0-9-]+`), for example `billing-architecture`. It is the last part of the key `task:\u003Cslug>`.\n    - `type`: ask the person to choose one of `task`, `bug`, `spike`, `architecture`, `e2e`. When they name `epic` or `story`, tell them these types live in a stream and offer the story flow (step 3) instead.\n    - `tracker`: optional. When the person gives none, the `tracker:` line stays empty. When they give one, check it the way step 6 does: pattern entry by entry, then the `\"` and `\\` rule, then the duplicate check in `.agents\u002Findex.json`. Every failed check asks the person for another id or for none.\n    - a one-line summary for the title, for example `Split billing into two services`.\n22. Check the slug: `printf '%s\\n' '\u003Cslug>' | grep -Ex '[a-z0-9-]+'` must print the slug, and `test -e tasks\u002F\u003Cslug>` must fail. When the folder already exists, stop, tell the person `tasks\u002F\u003Cslug>\u002F` already exists, and change nothing. When the slug has another form, ask for another slug.\n23. Find the workspace default branch as step 5 does, then run `git switch \u003Cdefault>` and `GIT_TERMINAL_PROMPT=0 git pull --ff-only`.\n24. Run `git switch -c task-\u003Cslug>`.\n25. Run `mkdir -p tasks\u002F\u003Cslug> && cp .agents\u002Ftemplates\u002Ftask.md tasks\u002F\u003Cslug>\u002Ftask.md`.\n26. Edit the new `task.md`. Keep every line of the template in its order and change only these lines:\n    - `key: task:\u003Cslug>`;\n    - `type: \u003Ctype>` from step 21;\n    - keep `status: waiting` and the empty `owner:` and `started:` lines exactly as the template has them: a new task waits, unowned and not started - `task-start` writes those three lines later;\n    - `tracker: \u003Ctracker>` when step 21 gave one; otherwise leave `tracker:` empty.\n    Replace the title line `# \u003Cslug>: \u003Cone-line summary>` with the slug and the summary of step 21. Keep every `## ` heading. Where the person gave you the words for a section, write those words under it; otherwise keep the template text under that heading and say in the report that the person fills the sections before starting the task.\n27. Update the generated files. If `command -v python3` prints a path, run `python3 tools\u002Fgenerate.py`. It rewrites `.agents\u002Findex.json` (the `task:\u003Cslug>` entry, and the tracker alias when one was set) and `STATUS.md` (the row in the `workspace` group of the waiting section). Otherwise apply `## Recipe: index entry` for `task:\u003Cslug>`.\n28. Run the check as step 16 does, at most three times in total, looking only at findings that name `tasks\u002F\u003Cslug>\u002Ftask.md`, `.agents\u002Findex.json` or `STATUS.md`, with the same fix, stop and report rules.\n29. Commit as step 17 does, with these differences: the created folder is `tasks\u002F\u003Cslug>\u002F`; no `BREAKDOWN.md` is created; the commit message is `git commit -m \"docs(task): add \u003Cslug>\"`.\n30. Run `GIT_TERMINAL_PROMPT=0 git pull --rebase origin \u003Cdefault>`. On conflicts follow `## Conflicts`. After the rebase has finished, run step 28 again. When step 28 stops, do not amend and do not push; wait for the person. When it made you fix a file, run `git add \u003Cfile>` for each fixed file, then `git commit --amend --no-edit`.\n31. Push and open the merge request by `.agents\u002Frules\u002Fmerge-requests.md`, with branch `task-\u003Cslug>` and title `Add task \u003Cslug>`. Use `GIT_TERMINAL_PROMPT=0` before `git push`.\n32. Report to the person:\n    - the task file `tasks\u002F\u003Cslug>\u002Ftask.md`, and its tracker id when step 21 gave one;\n    - that the person fills the sections that still carry the template text before starting the task;\n    - the branch `task-\u003Cslug>`;\n    - the merge request link, or the instruction to open it;\n    - the remaining check findings in other files, when there are any;\n    - as the last line, the check result, or `check not run: python3 missing`.\n\n## Recipe: BREAKDOWN.md row\nUse this only when `python3` is missing. The result equals what `python3 tools\u002Fgenerate.py` writes.\n\n1. Build the row from the frontmatter of the new `story.md`, copying values verbatim (without surrounding quotes):\n\n   `| story:\u003Cproject>\u002F\u003Cdomain>\u002F\u003Cslug> | \u003Cwave> | \u003Cscope joined with \", \"> | \u003Cunmapped> | \u003Ctracker> | \u003Cdepends joined with \", \"> |`\n\n   An empty value leaves an empty cell with two spaces between the bars: `|  |`. For example scope `[]` with unmapped `BFF defects` and no tracker and no depends gives `| story:abs\u002Foperations\u002Fbff-defects | 3 |  | BFF defects |  |  |`.\n2. Open `projects\u002F\u003Cproject>\u002Fdomains\u002F\u003Cdomain>\u002Fstreams\u002F\u003Cstream>\u002FBREAKDOWN.md`. When it does not exist, create it with exactly these six lines, each ending with a newline:\n   ```\n   # \u003Ctitle> stream:\u003Cproject>\u002F\u003Cdomain>\u002F\u003Cstream>\n\n   \u003Cnote>\n\n   | \u003Ccolumn 1> | \u003Ccolumn 2> | \u003Ccolumn 3> | \u003Ccolumn 4> | \u003Ccolumn 5> | \u003Ccolumn 6> |\n   |---|---|---|---|---|---|\n   ```\n   Take `\u003Ctitle>`, `\u003Cnote>` and the six columns from the `breakdown` block of `.agents\u002Fprofiles\u002F\u003Cprofile>\u002Fprofile.json` (`title`, `note` and `columns` in their order), in `\u003Clanguage>` as step 6 says. When `profile.json` has no `breakdown` block, use title `Breakdown of`, note `Generated by tools\u002Fgenerate.py from stories\u002F*\u002Fstory.md. Do not edit.` and columns `Story`, `Wave`, `Scope`, `Unmapped`, `Tracker`, `Depends`. The row cells keep the order of step 1 whatever the column names are.\n\n   English (`en`, and every profile without a `breakdown` block):\n   ```\n   # Breakdown of stream:demo\u002Foperations\u002Fmigration\n\n   Generated by tools\u002Fgenerate.py from stories\u002F*\u002Fstory.md. Do not edit.\n\n   | Story | Wave | Scope | Unmapped | Tracker | Depends |\n   |---|---|---|---|---|---|\n   ```\n   Russian (`ru`, profile `ui-migration`):\n   ```\n   # Разбивка stream:demo\u002Foperations\u002Fmigration\n\n   Сгенерировано tools\u002Fgenerate.py из stories\u002F*\u002Fstory.md. Не редактировать.\n\n   | Стори | Волна | Экраны | Без экрана | Трекер | Зависит от |\n   |---|---|---|---|---|---|\n   ```\n\n   (The blank lines count: the file starts with the title line, a blank line, the note line, a blank line, the header line and the separator line.)\n3. Rows follow the separator line in ascending slug order. Compare your slug with the slug of each row (the text after the last `\u002F` in its first cell) character by character from the left; the first different character decides in this order: `-`, then digits `0` to `9`, then letters `a` to `z`. When one slug is the start of the other, the shorter one comes first. So `login` \u003C `reports` \u003C `reports-v2` \u003C `reports2`.\n4. Insert your row directly above the first row whose slug comes after yours. When no row comes after yours, add it as the last line of the file. Change nothing else. The file ends with a newline.\n\nExample. `BREAKDOWN.md` before:\n```\n# Breakdown of stream:demo\u002Foperations\u002Fmigration\n\nGenerated by tools\u002Fgenerate.py from stories\u002F*\u002Fstory.md. Do not edit.\n\n| Story | Wave | Scope | Unmapped | Tracker | Depends |\n|---|---|---|---|---|---|\n| story:demo\u002Foperations\u002Flogin | 1 | screen:demo\u002Foperations\u002Flogin |  | DEMO-101 |  |\n| story:demo\u002Foperations\u002Fusers | 2 | screen:demo\u002Foperations\u002Fusers, screen:demo\u002Foperations\u002Fuser-view |  |  | story:demo\u002Foperations\u002Flogin |\n```\nAfter creating `story:demo\u002Foperations\u002Freports` with wave `2`, scope `screen:demo\u002Foperations\u002Freports`, depends `story:demo\u002Foperations\u002Flogin`:\n```\n# Breakdown of stream:demo\u002Foperations\u002Fmigration\n\nGenerated by tools\u002Fgenerate.py from stories\u002F*\u002Fstory.md. Do not edit.\n\n| Story | Wave | Scope | Unmapped | Tracker | Depends |\n|---|---|---|---|---|---|\n| story:demo\u002Foperations\u002Flogin | 1 | screen:demo\u002Foperations\u002Flogin |  | DEMO-101 |  |\n| story:demo\u002Foperations\u002Freports | 2 | screen:demo\u002Foperations\u002Freports |  |  | story:demo\u002Foperations\u002Flogin |\n| story:demo\u002Foperations\u002Fusers | 2 | screen:demo\u002Foperations\u002Fusers, screen:demo\u002Foperations\u002Fuser-view |  |  | story:demo\u002Foperations\u002Flogin |\n```\n\n## Recipe: index entry\nUse this only when `python3` is missing. The result equals what `python3 tools\u002Fgenerate.py` writes.\n\n`.agents\u002Findex.json` is one JSON object with one entry per line, two spaces of indentation, in this order: `adr:` entries, then `diagram:` and `mockup:` entries, then the `story:` and `task:` entries ascending by key - every `story:` entry comes before every `task:` entry -, then tracker ids ascending by id. A tracker id entry maps the task's `tracker` value to the same task file path.\n\nAscending means: compare two keys character by character from the left; the first different character decides in this order: `-`, `.`, `\u002F`, digits `0` to `9`, `:`, upper-case letters `A` to `Z`, `_`, lower-case letters `a` to `z`. When one key is the start of the other, the shorter one comes first. So `story:demo\u002Foperations\u002Flogin` \u003C `story:demo\u002Foperations\u002Freports`, `story:demo-new\u002Fa` \u003C `story:demo\u002Fa`, and `DEMO-145` \u003C `DEMO-99` (not number order).\n\n1. Build your entry line. A story: `  \"story:\u003Cproject>\u002F\u003Cdomain>\u002F\u003Cslug>\": \"projects\u002F\u003Cproject>\u002Fdomains\u002F\u003Cdomain>\u002Fstreams\u002F\u003Cstream>\u002Fstories\u002F\u003Cslug>\u002Fstory.md\"`. A workspace task: `  \"task:\u003Cslug>\": \"tasks\u002F\u003Cslug>\u002Ftask.md\"`.\n2. Find its position among the lines starting with `  \"story:` or `  \"task:`:\n   - When the file has such lines, insert your line directly above the first of them whose key comes after yours. When none comes after yours, insert it directly after the last of them.\n   - When there is no `  \"story:` or `  \"task:` line, insert it directly after the last line starting with `  \"adr:`, `  \"diagram:` or `  \"mockup:`.\n   - When there is none of those either, insert it as the first entry, directly after the line `{`.\n   - When the whole file is the single line `{}`, replace that line with three lines: `{`, your line, `}`.\n3. Only when the task's `tracker` is not empty (step 6 sets it for a stream at stage `delivery` or `done`, step 21 whenever the person gives one): build the line `  \"\u003Ctracker>\": \"\u003Ctask file path>\"` with the same path as your entry line, writing `\"` as `\\\"` and `\\` as `\\\\` inside the id. Tracker lines are the entry lines after the last `  \"story:` or `  \"task:` line. When a line with the same id already exists, add nothing and tell the person the id is used by another task. Otherwise insert your line directly above the first tracker line whose id comes after yours; when none comes after yours, insert it as the last entry, directly above the line `}`.\n4. Commas: every entry line ends with `,` except the last entry, directly above `}`. After inserting, add the missing `,` to the line above your line, and end your line with `,` unless it is the last entry.\n5. Keep no trailing spaces. The file ends with `}` and a newline. Change nothing else.\n\nExample 1. The index is `{}`. After creating `story:demo\u002Foperations\u002Freports` in stream `migration`:\n```\n{\n  \"story:demo\u002Foperations\u002Freports\": \"projects\u002Fdemo\u002Fdomains\u002Foperations\u002Fstreams\u002Fmigration\u002Fstories\u002Freports\u002Fstory.md\"\n}\n```\n\nExample 2. Before:\n```\n{\n  \"adr:0001\": \"docs\u002Fadr\u002F0001-use-kafka.md\",\n  \"mockup:demo\u002Foperations\u002Flogin\": \"https:\u002F\u002Fdesign.example.org\u002Ffile\u002Flogin\",\n  \"story:demo\u002Foperations\u002Flogin\": \"projects\u002Fdemo\u002Fdomains\u002Foperations\u002Fstreams\u002Fmigration\u002Fstories\u002Flogin\u002Fstory.md\",\n  \"story:demo\u002Foperations\u002Fusers\": \"projects\u002Fdemo\u002Fdomains\u002Foperations\u002Fstreams\u002Fmigration\u002Fstories\u002Fusers\u002Fstory.md\",\n  \"task:billing-architecture\": \"tasks\u002Fbilling-architecture\u002Ftask.md\",\n  \"DEMO-101\": \"projects\u002Fdemo\u002Fdomains\u002Foperations\u002Fstreams\u002Fmigration\u002Fstories\u002Flogin\u002Fstory.md\"\n}\n```\nAfter creating `story:demo\u002Foperations\u002Freports` in stream `migration`:\n```\n{\n  \"adr:0001\": \"docs\u002Fadr\u002F0001-use-kafka.md\",\n  \"mockup:demo\u002Foperations\u002Flogin\": \"https:\u002F\u002Fdesign.example.org\u002Ffile\u002Flogin\",\n  \"story:demo\u002Foperations\u002Flogin\": \"projects\u002Fdemo\u002Fdomains\u002Foperations\u002Fstreams\u002Fmigration\u002Fstories\u002Flogin\u002Fstory.md\",\n  \"story:demo\u002Foperations\u002Freports\": \"projects\u002Fdemo\u002Fdomains\u002Foperations\u002Fstreams\u002Fmigration\u002Fstories\u002Freports\u002Fstory.md\",\n  \"story:demo\u002Foperations\u002Fusers\": \"projects\u002Fdemo\u002Fdomains\u002Foperations\u002Fstreams\u002Fmigration\u002Fstories\u002Fusers\u002Fstory.md\",\n  \"task:billing-architecture\": \"tasks\u002Fbilling-architecture\u002Ftask.md\",\n  \"DEMO-101\": \"projects\u002Fdemo\u002Fdomains\u002Foperations\u002Fstreams\u002Fmigration\u002Fstories\u002Flogin\u002Fstory.md\"\n}\n```\n\n## Conflicts\nFor this skill a conflicted file counts as generated when it is `.agents\u002Findex.json`, `STATUS.md`, a stream `BREAKDOWN.md`, or a `MAP.md` whose conflicts all lie between `map:` markers (see step 2). Every other file, including `story.md`, `task.md`, element files and `stream.json`, is not generated.\n\n1. List all conflicted files: `git diff --name-only --diff-filter=U`. Write the list down before you change anything.\n2. For each `MAP.md` in the list, run `grep -n -e '^\u003C\u003C\u003C\u003C\u003C\u003C\u003C' -e '^>>>>>>>' -e '\u003C!-- map:' \u003Cfile>`. The file counts as generated only when every `\u003C\u003C\u003C\u003C\u003C\u003C\u003C` line and the `>>>>>>>` line after it both lie between one `:begin -->` line and the next `:end -->` line. Otherwise it is not generated.\n3. First check the whole list for any file that is not generated. If there is one:\n   - Run `git rebase --abort`. Do not touch any file first, not even the generated ones.\n   - For each file that is not generated, show the person both versions with these labels:\n     - \"default branch\": the output of `git show origin\u002F\u003Cdefault>:\u003Cfile>`;\n     - \"your branch\": the output of `git show \u003Cbranch>:\u003Cfile>`, where `\u003Cbranch>` is `story-\u003Cdomain>-\u003Cslug>` in the story flow and `task-\u003Cslug>` in the task flow.\n     When one of the two commands fails, tell the person that side has no such file.\n   - Stop and wait for the person.\n4. Only when every file in the list is generated:\n   - For each file in the list, run `git checkout --ours -- \u003Cfile>`. During a rebase `--ours` is the default branch version, so your own change in that file is gone.\n   - Regenerate: if `command -v python3` prints a path, run `python3 tools\u002Fgenerate.py`. Otherwise apply again, to the files in the list, what step 15 does for a story (`## Recipe: BREAKDOWN.md row`, `## Recipe: index entry`, the `story` cell change in `MAP.md`) and step 27 for a task (`## Recipe: index entry`).\n   - For each file in the list, run `git add \u003Cfile>`. Also `git add` any other generated file the regeneration changed.\n   - Run `GIT_EDITOR=true git rebase --continue`. When it stops on conflicts again, go back to step 1.\n\n## Without Python\n1. Skip `python3 tools\u002Fgenerate.py` and `python3 tools\u002Fcheck.py` everywhere, including `## Conflicts`. Instead apply, at step 15 for a story and at step 27 for a task, the recipes named there.\n2. `STATUS.md` is generated, and this kit version ships no hand recipe for adding a waiting row yet. After step 15 or step 27, do not commit and do not push: tell the person to run `python3 tools\u002Fgenerate.py`, and continue from step 17 or step 29 after they have.\n3. End the report with the line:\n\ncheck not run: python3 missing\n",{"name":5,"description":7},"main","84be7f584d7d6998f014342de57ee511e9596cd2","kits\u002Fworkspace\u002F.agents\u002Fskills\u002Ftask-new","https:\u002F\u002Fgithub.com\u002Fmaximk777\u002Fopencode-config","https:\u002F\u002Fgithub.com\u002Fmaximk777","2026-10-30 20:22:07",{"source":8,"skillName":5,"commands":30,"prompt":40,"zipAvailable":41},[31,34,37],{"tool":32,"command":33},"npx","npx skills add maximk777\u002Fopencode-config --skill task-new",{"tool":35,"command":36},"bunx","bunx skills add maximk777\u002Fopencode-config --skill task-new",{"tool":38,"command":39},"pnpm","pnpm dlx skills add maximk777\u002Fopencode-config --skill task-new","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fmaximk777\u002Fopencode-config\u002Fblob\u002Fmain\u002Fkits\u002Fworkspace\u002F.agents\u002Fskills\u002Ftask-new\u002FSKILL.md",true,[],[44,51,58,64,71,78],{"skillNo":45,"name":46,"nameZh":6,"description":47,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":48,"categories":49,"keywords":50,"publishedAt":18},"01M7CQCJ5WYEQM6E1T0RDVKWAY","verify","Use when a change in __SERVICE__ must be checked before review","https:\u002F\u002Fgithub.com\u002Fmaximk777\u002Fopencode-config\u002Fblob\u002Fmain\u002Ftests\u002Ffixtures\u002Fworkspace-repo-kits\u002Fkit-1.1.0\u002Ffiles\u002Fskills\u002Fverify\u002FSKILL.md",[],[],{"skillNo":52,"name":53,"nameZh":6,"description":54,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":55,"categories":56,"keywords":57,"publishedAt":18},"01M7CQCG5MCSNDNS98TGAGXP7E","work-record","Use when you finished work on a tracker task and it must be recorded in the workspace through a merge request.","https:\u002F\u002Fgithub.com\u002Fmaximk777\u002Fopencode-config\u002Fblob\u002Fmain\u002Ftests\u002Ffixtures\u002Fnormalize-team\u002F.claude\u002Fskills\u002Fwork-record\u002FSKILL.md",[],[],{"skillNo":59,"name":5,"nameZh":6,"description":60,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":61,"categories":62,"keywords":63,"publishedAt":18},"01M7CQCDGQBT2GXCKQAC1B5R0R","Use to create one story in a stream from the stream profile's story template, link it from its scope screens and open a merge request.","https:\u002F\u002Fgithub.com\u002Fmaximk777\u002Fopencode-config\u002Fblob\u002Fmain\u002Ftests\u002Ffixtures\u002Fnormalize-team\u002F.claude\u002Fskills\u002Ftask-new\u002FSKILL.md",[],[],{"skillNo":65,"name":66,"nameZh":6,"description":67,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":68,"categories":69,"keywords":70,"publishedAt":18},"01M7CQC93WN986EY48RFPZHZM7","task-decompose","Use to split a stream at the decomposition stage into stories - list scope screens without a story, create the accepted stories and close the stage through a merge request.","https:\u002F\u002Fgithub.com\u002Fmaximk777\u002Fopencode-config\u002Fblob\u002Fmain\u002Ftests\u002Ffixtures\u002Fnormalize-team\u002F.claude\u002Fskills\u002Ftask-decompose\u002FSKILL.md",[],[],{"skillNo":72,"name":73,"nameZh":6,"description":74,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":75,"categories":76,"keywords":77,"publishedAt":18},"01M7CQC5FZQWPTBK0J0FHWS513","task-context","Use to gather the context of a story key or a tracker id - its story, stream stage, scope screens, repositories, decisions, mockups and work records.","https:\u002F\u002Fgithub.com\u002Fmaximk777\u002Fopencode-config\u002Fblob\u002Fmain\u002Ftests\u002Ffixtures\u002Fnormalize-team\u002F.claude\u002Fskills\u002Ftask-context\u002FSKILL.md",[],[],{"skillNo":79,"name":80,"nameZh":6,"description":81,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":82,"categories":83,"keywords":84,"publishedAt":18},"01M7CQC1Q2YECCM2N9TPJAAJQA","repos-sync","Use to update clones of your repositories under repos\u002F and see their branch, lag and uncommitted changes.","https:\u002F\u002Fgithub.com\u002Fmaximk777\u002Fopencode-config\u002Fblob\u002Fmain\u002Ftests\u002Ffixtures\u002Fnormalize-team\u002F.claude\u002Fskills\u002Frepos-sync\u002FSKILL.md",[],[]]