If you use only org-headlines for TODO items then the headline element can only be ended by a headline on same or on higher hierarchy.
The section you are addressing to as "notes" unconditionally belongs to the last headline.
That follows from the syntax definition on worg.
I cite here the relevant section of that definition:
A headline contains directly one section (optionally), followed by any number of deeper level headlines.
A section contains directly any greater element or element. Only a headline can contain a section. As an exception, text before the first headline in the document also belongs to a section.
As an example, consider the following document:
An introduction.
* A Headline
Some text.
** Sub-Topic 1
** Sub-Topic 2
*** Additional entry
Its internal structure could be summarized as:
(document
(section)
(headline
(section)
(headline)
(headline
(headline))))
I don't know whether lists are an option for you.
You can indicate the TODO status in lists by checkboxes.
* Enclosing section [1/2]
- [ ] this work item is not done
- [X] this work item is done
- [X] first sub-item that is done
- [X] second sub-item that is done
Text belonging to the last list item.
Text following the list that does not belong to the last list item.
The list belongs to the enclosing section. Text following the list with lower indentation level belongs also to the enclosing section and not to the last list item.
You can add [%]
for the todo-percentage or [/]
for the todo-fraction to the enclosing headline. Changing the checkboxes with C-c C-c updates the todo-percentage or the todo-fraction, resp.
Pityingly, the checkboxes of list items do not appear in TODO-lists and fully checked lists in a headline element do not automatically change the TODO state of a headline.
If you install the following elisp-hack the TODO mark in the headline will be updated when the checkbox count cookie [/]
or [%]
changes.
(require 'cl-lib)
(require 'org-list)
(defun org-get-checkbox-count (&optional frac)
"If FRAC is nil get a list of checkbox counts either as percentage or as fraction.
If FRAC is non-nil return list with the numerator and the denominator.
Returns nil if the headline where the list is contained as element does not have a [%] and/or a [/] cookie."
(unwind-protect
;; Don't let `org-update-checkbox-count' modify the buffer
;; but collect the cookies instaed.
;; Works at least in org-version 9.0.5.
(let (ret
org-auto-align-tags)
(advice-add
#'insert
:override
(lambda (&rest args)
(setq ret (nconc ret args)))
'((name . "org-get-checkbox-count")))
(advice-add
#'delete-region
:override
#'ignore
'((name . "org-get-checkbox-count")))
(org-update-checkbox-count)
(if (and ret frac)
(or (and (setq frac (cl-find ?/ ret :test #'cl-find))
(mapcar #'string-to-number (split-string frac "[][/]" t)))
(list (string-to-number (substring (car ret) 1 -2)) 100))
ret))
(advice-remove #'insert "org-get-checkbox-count")
(advice-remove #'delete-region "org-get-checkbox-count")))
(defun org-checkbox-summary-todo ()
"Switch entry to DONE when all subentries are done, to TODO otherwise."
(cl-multiple-value-bind
(n-done n-overall) (org-get-checkbox-count t)
(when n-done
(org-todo (if (= n-done n-overall) "DONE" "TODO")))))
(add-hook 'org-checkbox-statistics-hook #'org-checkbox-summary-todo)