fix(kyberforge): tell an unparsable Contributing-files block from an explicit (none)

parse_contributing_files documented that callers depend on None vs [], because a
parse failure returning [] would silently disable the check. Only check 8
honoured it; checks 4/5 (skill-audit) and 3/4 (agent-audit) used a truthiness
test, so an unreadable block disabled them without a word.

Two live corpus entries were skipping this way. A sweep of all 32 sources.md
found 134 entries, exactly 2 parsing to None, both in gitea-files: one heading
carried an inline parenthetical that defeated both regexes, and one (none) was
written without its leading bullet. Also pins EMPTY_SOURCE_KEYS_RE to the two
indents parse_source_keys actually reads.

agent-audit had no INFO tier at all, so it gains one rather than reporting a
check that could not run as a FAIL.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EJJrm5YmacbwMdzZpXcoti
This commit is contained in:
2026-08-31 19:46:05 +00:00
parent c232e69645
commit 00daf285ec
8 changed files with 418 additions and 32 deletions

View File

@@ -21,7 +21,10 @@ Checks performed:
3 source_keys in references/*.md → slug exists in sources.md (INFO if no
source_keys; an explicit 'source_keys: []' declares the file house-authored
and passes silently)
4 Contributing files listed in sources.md exist on disk
4 Contributing files listed in sources.md exist on disk. An explicit
'(none)' skips silently; a Contributing files block this parser cannot
read is reported as an INFO saying checks 4 and 5 did not run, never
skipped silently.
5 Contributing files back-reference the parent slug in their source_keys
6 Research doc field present and not placeholder
7 Slug in sources.md present in upstream research doc (INFO only). A section
@@ -104,7 +107,13 @@ def parse_source_keys(fm):
# claims that then have to be maintained in sources.md as well. A bare
# `source_keys:` with nothing after it is NOT accepted here — that reads as a
# truncated or half-written entry, not a decision.
EMPTY_SOURCE_KEYS_RE = re.compile(r'^\s*source_keys:\s*\[\s*\]\s*$')
#
# The indent is pinned to the two positions parse_source_keys() actually reads
# — column 0, or two spaces under `metadata:`. A permissive `^\s*` matched a
# `source_keys: []` nested at ANY depth under an unrelated key, which
# parse_source_keys() never reads, so a stray nested key silenced the check-3
# INFO for a file that had declared nothing.
EMPTY_SOURCE_KEYS_RE = re.compile(r'^(?: )?source_keys:\s*\[\s*\]\s*$')
def declares_empty_source_keys(fm):
"""True when frontmatter carries an explicit, empty `source_keys: []`."""
@@ -436,9 +445,25 @@ repo_root = find_repo_root(skill_dir)
research_docs_seen = {} # abs_path → set of slugs in sources.md that reference it
for slug in parse_h2_slugs(sources_content):
# Check 4: Contributing files exist
# Checks 4 and 5: Contributing files exist, and back-reference the slug.
# `[]` and None are NOT the same answer here. `[]` is the author writing
# "(none)" — there is nothing to check and the skip is correct. None is a
# Contributing-files block this parser cannot read, and skipping THAT
# silently disables both checks on the one entry least likely to be right,
# which is the failure mode parse_contributing_files' own docstring warns
# about. Say so out loud instead, the same way an unresolvable Research doc
# value does.
cf_files = parse_contributing_files(sources_content, slug)
if cf_files:
if cf_files is None:
emit_info(
f"Contributing-file checks skipped for '{slug}' — the Contributing files block could not be parsed",
f"references/sources.md (## {slug})",
f"The '## {slug}' entry has no Contributing files list this parser can read — a missing field, a bare heading, '*' bullets, a numbered list, or prose all read as unparsable rather than as an empty declaration. "
f"Checks 4 and 5 did not run for this slug, so nothing verified that its contributing files exist or name it back. "
f"Write the value as '- **Contributing files:** <comma-separated paths>', or as a '**Contributing files:**' heading followed by '- ' bullets — "
f"or record '(none)' if this source contributed no files."
)
elif cf_files:
for cf_rel in cf_files:
cf_abs = os.path.join(skill_dir, cf_rel)
if not os.path.isfile(cf_abs):