provenance: Research doc: slug and path conventions do not match what validate-provenance expects
#121
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found during the #99 ADR-0020 retrofit and the follow-up audit pass on
refactor/adr0020-skill-retrofit. Deliberately not fixed there, because half of it is a schema decision that has to be made before the other half can be mass-corrected.Context: the checks only just woke up
validate-provenance.shchecks 7 and 8 resolve eachsources.mdentry'sResearch doc:path and look for the entry's slug as an## H2inside it. Until commit27a7669(fix(kyberforge): stop the provenance checker skipping check 8 on unparsed input, addresses #111) both checks were dead across the whole git plugin — an unparsableContributing filesblock returned the same empty result as an explicit(none), so the checker read "nothing to check" and skipped rather than reporting that it could not tell.With them live, the corpus now reports 36 INFOs and 0 FAILs. Measured just now by running the script over all 39 skill directories:
Nothing is red. This issue is about deciding what the convention actually is, not about a broken gate.
Two distinct shapes
(a) 30 slug-vs-heading mismatches
The slug in
references/sources.mddoes not appear as an## H2in the fileResearch doc:names.core/agentsmd-auditgit/git-branchesgit/git-commitsgit/git-historygit/git-remotesgit/git-submodulesgit/git-workflowgit/git-worktreesgit/pc-authorgit/pc-rungitea/gitea-releasesThe
git-history3 pre-date the retrofit; the other 27 surfaced with the checks.Probable root cause, and it is mechanical.
skill-author/references/create.md:168specifies the field as:That is exactly the file whose H2s are the slugs. But 29 of these 30 point at a research topic file instead, whose H2s are section headings. Concretely,
git-branchesnamesplugins/git/docs/research/docs/git/gitflow.md, whose H2s are## Core Philosophy,## The Five Branch Types, … — whileplugins/git/docs/research/docs/git/sources.mdsitting beside it has## nvie-gitflow-post,## atlassian-gitflow-tutorial,## gitflow-cheatsheetand every other slug the git plugin uses. The same holds forplugins/gitea/docs/research/docs/gitea/sources.md(5 slugs) andplugins/git/docs/research/docs/pre-commit/sources.md(4 slugs). Repointing at the siblingsources.mdwould clear these mechanically.The 30th is a different case:
core/agentsmd-audit'sgovernance-secrets-hard-prohibitionpoints atcore/instructions/governance.md, annotated in-place as "org convention file, not a plugin research corpus entry". The path resolves, so check 7 runs and finds no matching H2 — a deliberate non-corpus pointer being measured against a corpus rule.(b) 6 values that are not a single path
These resolve to nothing, so checks 7 and 8 do not run at all and the script says so:
core/provider-adapter-authoradr-0002-0003-two-tier-claude-mddocs/adr/0002-….md, docs/adr/0003-���.md, providers/claude-code/CLAUDE.mdgit/git-commitsorg-commit-conventionscore/instructions/commits.md, core/instructions/git.mdgit/pc-authorcontext7-pre-commit-complugins/git/docs/research/docs/pre-commit/{overview,configuration,cli-reference,hook-authoring}.mdgit/pc-authorpre-commit-comgit/pc-runcontext7-pre-commit-complugins/git/docs/research/docs/pre-commit/{overview,cli-reference,troubleshooting}.mdgit/pc-runpre-commit-comTwo sub-shapes: comma-separated lists, and shell-style brace expansion. Both are humans writing "several documents" into a field whose only specified grammar is one path.
The decision to make first
Does
Research doc:accept a list? (b) cannot be fixed without answering that, and (a) should not be mass-corrected until it is — if the answer is "yes, a list", then the natural fix for (a) may be "point at the topic files and the sources.md", not "swap one path for another".Sub-questions the answer has to cover:
- **Research doc:**bullets? Brace expansion is the one form to reject outright — it is shell syntax in a markdown field and nothing expands it.core/instructions/*.md) a legal value at all, or does it need its own field / an explicit(none)-style declaration? Today it is legal-by-accident and produces an INFO that can never be cleared. Same shape as #111's problem: no honest way to declare the truthful thing.Files
plugins/kyberforge/.apm/skills/skill-audit/scripts/validate-provenance.sh— checks 6, 7, 8plugins/kyberforge/.apm/skills/skill-author/references/create.md:168— the only place the field's grammar is statedplugins/kyberforge/.apm/skills/skill-audit/references/file-structure.md:51— thereferences/sources.mdexemption, which explains why an unresolvable path is an INFO rather than a broken-reference FAILreferences/sources.mdfiles listed aboveRelated
Two more items for this issue, found while adding the regression tests for
27a7669(commit5b80f30).The same blind spot exists one function over
484357a/27a7669taughtparse_contributing_filesthe bullet form (- **Contributing files:**on its own line, entries beneath).parse_statusandparse_research_docwere not changed and still match only the inline spelling.This is not hypothetical:
plugins/gitea/.apm/skills/gitea-releases/references/sources.mdalready writes**Status:**with no leading hyphen. It is harmless today only by accident of scope —parse_statusis applied to research docs, and no research doc currently uses the bullet form. The moment one does, the status test silently reads as absent.That is the same failure shape this issue and #118 are about: a parser that returns "nothing found" and a caller that reads it as "nothing declared". Worth fixing in the same pass as shape (a), since both are edits to how
sources.mdand the research docs are read.A
Research doc:value can name two paths, and only the first is checkedgitea-releases' entry carries a semicolon-separated pair of annotated paths.strip_research_doc_annotation()keeps the first and drops the rest, so the second path is never resolved and checks 7-8 never run against it — silently, and with no INFO, because the first path resolves fine.This is the same schema question as shape (b) in the issue body (comma-separated lists and
{a,b,c}.mdbrace expansions), with a third separator. It strengthens the case for deciding the schema before mass-fixing shape (a): whateverResearch doc:is allowed to contain — one path, a list, or a glob — needs to be settled once, and the parser and the four skills writing multi-path values then follow from it.Both found while writing tests, not by any gate.
Automated note from the PR #135 review follow-up. This issue's own conclusion, state and labels are untouched — this comment only records paths that PR #135's branch renamed, so the issue stays actionable.
Paths this issue cites that have moved
skill-audithas been merged intofactory-audit(ADR-0025, commit620f20b).plugins/kyberforge/.apm/skills/skill-audit/scripts/validate-provenance.shis nowplugins/kyberforge/.apm/skills/factory-audit/scripts/validate-provenance.sh.skill-audit/references/file-structure.mdis nowfactory-audit/references/skill-file-structure.md. The filename changed, not just the directory — a path rewrite that only swaps the directory will still dangle.skill-author/references/create.md:168has drifted toskill-author/references/create.md:175.Nothing else in this issue was re-validated.
Co-Authored-By: Claude Opus 5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01NwD8Egs5r4ndqeFLmhusX2
Design decisions settled in a grill-with-docs session, implemented in PR #139 (branch
feat/121-research-doc-grammar). The ADR isdocs/adr/0028-research-doc-names-the-research-registry.md; the term is defined as Research registry inCONTEXT.md.Decisions
Research doc:refers to. The plugin's Research registry: the researchsources.mdwhose## H2headings are the source slugs. This is whatskill-author/references/create.mdalready specified and what check 7 already assumes. The 29 entries pointing at topic docs get repointed. A topic-doc pointer survives only as parenthetical free-text annotation and is not checked.Research doc:stays single-valued, so no list grammar is needed. Brace expansion, comma lists and semicolon pairs are gone. Shape (b) collapses: thepc-authorandpc-runbrace values are one registry,pre-commit/sources.md. An entry with no registry (ADRs,core/instructions/*.md) declaresResearch doc: noneplus a newBasis:field, one- **Basis:** <path>bullet per path, existence-checked.git-workflowalready writesnone, so this codifies existing practice.Research doc:, is a FAIL. A path that does not resolve stays INFO, so auditing a deployed copy elsewhere is not failed on something it cannot judge.validate-provenance.shacross the real corpus (onlycheck-scope-walkup-sync.shran it, on fixtures), so a FAIL tier would be inert. A pre-push sweep,scripts/check-provenance-corpus.sh, lands in the same change.Research doc:andBasis:parsers accept the inline, bullet and header-plus-bullets spellings, with regression tests.parse_statusis removed along with check 8.extractedregistry slug to appear in the skill'ssources.md. That is unsatisfiable when one registry serves many skills (git/sources.mdbacks 7), and it only ever looked satisfiable because topic-doc pointers kept it dormant. Check 7 already covers the direction that matters. An earlier draft of this comment listed check 8 as a FAIL; that was wrong.Basis:paths.core/instructions/git.mdandcommits.mdwere deleted in5deed07. ABasis:bullet annotated(removed in <sha>)skips the existence check. The sha is not verified, so the annotation can be written on any bullet to dodge the check; that weakness is accepted for a handful of entries.lintentry is removed.house-vale-3-15-2-repro(invale-configandvale-run) saidnoneand claimed six behaviours were established "against purpose-built fixtures in this repo". No such fixture or test exists in the tree or in history (added ind1afdbewith no test files; the only vale test ever deleted,4de5b6b, guards an unrelatedE100). The entry and itssource_keyscitations are removed; the behavioural rules stay.Result (PR #139)
factory-auditbats: 272/272. Fulltests/run-tests.sh --strict: 0 failed, 0 skipped.apm audit --ci,apm pack --check-clean, the new corpus gate and the ADR-0022 version-bump gate (16 skills bumped by one PATCH).vale-wrap.sh: 0 alerts across the 16 changedSKILL.mdfiles, which is all the repo's Vale hook covers.gitea-releases,agentsmd-audit,provider-adapter-author; the two lint entries removed.Open
configuration-reference.mdstill says its rows were "reproduced against Vale 3.15.2" and "house-verified". That wording now has no provenance entry behind it. Whether to soften it, or commit real reproduction fixtures, is not decided here.references/andsources.mdfiles are outside any configured Vale scope, so they are unlinted rather than clean. Extending Vale todocs/adr/would be a separate change.Paths follow the earlier rename comment:
factory-audit/scripts/validate-provenance.sh,create.md:175.