fix(extract): a declared section's outline mark keeps its depth; only the heading clips

K3-21 D. `_StsReader._walk` computed `level = min(depth, _ATX_MAX_LEVEL)`
once and wrote it into BOTH the ATX heading and the `OutlineMark`. The
heading keeps the clip -- markdown has six levels and `#######` matches
nothing -- and the mark now carries the declared `depth`: it is no heading,
the declared route builds `Candidate(level=mark.level)` from it, and
`OutlineMark`'s own docstring says the level is what the tree declares,
"reported rather than fixed up". The extracted text does not move one
character; only the mark's level does.

On one standard 9 of 2 761 titled sections sit at depth 7; `--shell-parent`
gave its two depth-7 shells (`36.73211`, `36.73212`) the ancestor one level
too high. The gate -- plan otherwise unchanged, concept count, goldens, the
regression bundles, hit@k and the other 708 pointers -- is measured in a
frozen export of this commit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-11 14:10:30 +02:00
commit bd13c5f00b

View file

@ -322,10 +322,10 @@ _XML_INLINE_TAGS = frozenset(
# stops at for the same reason. STS nesting goes DEEPER: 9 of the 2 761 titled # stops at for the same reason. STS nesting goes DEEPER: 9 of the 2 761 titled
# sections in that document sit at depth 7, and `#######` matches nothing at # sections in that document sit at depth 7, and `#######` matches nothing at
# all. The depth is CLIPPED rather than dropped -- a clipped heading still sets # all. The depth is CLIPPED rather than dropped -- a clipped heading still sets
# its boundary and states its nesting one level too shallow, where a dropped # its boundary, where a dropped one loses the section entirely. The clip is the
# one loses the section entirely. The cost shows up in frontmatter nesting, not # HEADING's alone (K3-21): the `OutlineMark` beside it carries the declared
# in the depth row, because that row is the source's own depth and not the ATX # depth, because the declared route builds its plan from the mark and a plan
# level we emitted. # reading 7 as 6 gave a depth-7 section the ancestor one level too high.
_ATX_MAX_LEVEL = 6 _ATX_MAX_LEVEL = 6
@ -590,7 +590,10 @@ class _XmlTextExtractor:
self.marks.append( self.marks.append(
OutlineMark( OutlineMark(
line=len(self._lines) - 1, line=len(self._lines) - 1,
level=level, # The DECLARED depth, never the clipped one: the mark
# is not a markdown heading, and the plan the declared
# route builds from it reads nesting off this level.
level=depth,
title=heading, title=heading,
description=self._spec_point(element), description=self._spec_point(element),
) )