fix: reconcile the feature-container convention with the depends validator
`format.md` told a child issue to link back to its container through its own `depends:`, while the validator wanted the container to list its children. Satisfying both made a cycle, caught as an ERROR, so every `type/feature` with a filled `## Issues` ended in either a warning or a hard failure — no third option. Variant B is chosen: the container depends on its children, and a child never names its container. "The container is closed when its children are closed" IS a dependency relation, so it belongs in the graph; "a child belongs to a feature" is membership, and membership does not. The code already walked the edge that way — `## Issues` is an edge source pointing container -> child — so this rewrites the documentation to match instead of inverting the graph, and the tree draws containers as roots for free. - format.md: the `type/feature` template states the direction, shows the container's `depends:`, and says why the reverse cycles; the Dependencies section names `## Issues` as the second edge source. - issue.py: `body_dep_ref_sections()` carries the section each reference came from, so the desync warning names `## Issues` on a container rather than a `## Depends on` that is not in the file. `body_dep_refs()` stays as a thin wrapper — `skills/sync/scripts/map.py` calls it and is untouched. - tests/test_container_edges.py: the repo's first tests. Stdlib unittest, `python3 -m unittest discover -s tests`. issue_check.py's cycle detector and issue_tree.py need no change: with the edge pointing down there is no cycle to break and the container is already the root. Refs claude-skills/tea#14 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -145,6 +145,11 @@ you — `issue_check.py` warns when the section names an id that `depends:` does
|
||||
not list. Omit the section when there are no dependencies; never write an empty
|
||||
one.
|
||||
|
||||
A `type/feature` container writes the same relation under `## Issues` instead
|
||||
(see the template below). Same direction, same rule: every id named there also
|
||||
belongs in that issue's `depends:`. The warning names whichever of the two
|
||||
sections the reference actually came from.
|
||||
|
||||
Draw the graph with `issue_tree.py`. The reverse direction is a grep:
|
||||
|
||||
```bash
|
||||
@@ -258,9 +263,31 @@ grep -ln 'depends:.*migrate-schema' tmp/issues/*.md
|
||||
## Template: `type/feature`
|
||||
|
||||
A container: one unit of business value delivered by several child issues.
|
||||
Child issues carry their own `type/*` (`task`, `bug`, `test`, …) and link back
|
||||
via their `depends:`. Keep implementation detail in the children; the feature
|
||||
body stays at business level.
|
||||
Child issues carry their own `type/*` (`task`, `bug`, `test`, …) and know
|
||||
nothing about the container.
|
||||
|
||||
**The container depends on its children, never the reverse.** Every child id
|
||||
goes in the container's own `depends:` and, as prose, in its `## Issues`
|
||||
section; a child's `depends:` is for that child's real dependencies and must
|
||||
not point back at the container. Keep implementation detail in the children;
|
||||
the feature body stays at business level.
|
||||
|
||||
That direction is not a convention picked at random. "The container is closed
|
||||
when its children are closed" *is* a dependency relation. "This child belongs
|
||||
to that feature" is a membership relation, and membership has no place in a
|
||||
dependency graph. Pointed the other way the two rules contradict each other:
|
||||
the moment the container listed a child that already depended on it,
|
||||
`issue_check.py` would report `ERROR cycle`. With the edge going down, the
|
||||
graph reads as nesting — `issue_tree.py` draws the container as the root with
|
||||
its children beneath it — and the check is green.
|
||||
|
||||
So the container's metadata block carries the children:
|
||||
|
||||
```markdown
|
||||
depends: [wire-sqlc-appclick, add-pool-cfg]
|
||||
```
|
||||
|
||||
and its body repeats them for a human:
|
||||
|
||||
```markdown
|
||||
## Summary
|
||||
@@ -274,7 +301,7 @@ body stays at business level.
|
||||
|
||||
## Issues
|
||||
- [ ] wire-sqlc-appclick — краткое описание части
|
||||
- [ ] …
|
||||
- [ ] add-pool-cfg — краткое описание части
|
||||
|
||||
## Acceptance criteria
|
||||
- [ ] все дочерние issues закрыты
|
||||
|
||||
Reference in New Issue
Block a user