원클릭으로
check-docs-drift
Identify drift between docs/ folder and specification/schemas/code
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Identify drift between docs/ folder and specification/schemas/code
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
Detect drift between go-glx Go types and JSON schemas
Identify drift between specification markdown files and JSON schemas
Review example GLX archives for compliance with specification and code
Review the GLX specification for issues, contradictions, and ambiguities
SOC 직업 분류 기준
| name | check-docs-drift |
| description | Identify drift between docs/ folder and specification/schemas/code |
| allowed-tools | ["Read","Grep","Glob","Write","Bash(mktemp -d /tmp/glx-drift-*:*)","Bash(./bin/glx validate:*)","Bash(rm -rf /tmp/glx-drift-*:*)","Bash(git rev-parse:*)","Bash(gh issue list:*)"] |
| model | claude-opus-4-8 |
You are tasked with identifying any drift between the GLX user documentation and the source of truth (specification, schemas, and code).
Note: Example archives (docs/examples/) are checked separately by the check-examples skill. Auto-generated CLI pages (docs/cli/) are validated by .github/workflows/docs-drift.yml via make docs-cli — do not review them here. External GEDCOM PDFs (docs/gedcom-spec/) and historical Architecture Decision Records (docs/decisions/) are not in scope. This skill focuses only on hand-authored, user-facing documentation.
IMPORTANT: Documentation is derived from the source of truth:
Specification (*.md) → Schema (*.schema.json) → Go Code (types.go)
↓
User Docs
(quickstart,
guides/)
This means:
All findings — including a count of clean files — MUST be emitted in a single fenced findings-json block at the end of the run. See the schema at .claude/skills/check-suite/findings.schema.json and the shared severity rubric at .claude/skills/check-suite/severity-rubric.md. The eval harness greps for the info-string findings-json to extract this block; do not omit it.
The block must be one JSON object (not per-file fragments) with top-level keys:
command: "check-docs-drift" (literal string, required)commit: the HEAD SHA from git rev-parse HEAD (required)checked_files: the actual post-exclusion list of files read this run (required; lets the eval harness detect under-scoping)findings: array of finding objects — empty array when no drift detectedpositive_notes: array of strings for things confirmed correct (clean files go here, not in findings as info items)summary: object with critical, major, minor, info counts, and suppressed_as_duplicate_of_known_issue count from the cross-reference stepEach finding object requires:
file: repo-relative pathseverity: one of critical | major | minor | info (per the shared rubric — prefer info when uncertain)category: one of the values defined in the category table belowmessage: what drifted and why it mattersvalidator_caught: true if glx validate or CI already flags thisllm_only: true if only the LLM semantic pass surfaced it — must be the logical inverse of validator_caughtline: 1-based line number, or null when not line-addressablefix (optional): concrete suggested remediationCategory → default severity table (skill-specific, anchors to the shared rubric at .claude/skills/check-suite/severity-rubric.md):
| Category | Default severity | Notes |
|---|---|---|
example_validation | critical | glx validate non-zero exit on a doc code block — see fragment caveat below |
required_optional | major | Doc says required; spec says optional, or vice versa |
field_type | major | Field type mismatch between doc and spec |
field_presence | major | Field documented but not in spec, or in spec but undocumented with additionalProperties: false context |
cli_example | major | Documented CLI command/flag does not exist in code; or example no longer runs |
vocabulary | major | Referenced vocabulary type does not exist in specification/5-standard-vocabularies/ |
cross_reference | minor | Stale internal link; link uses .md extension in URL form |
validator_unavailable | info | ./bin/glx could not be found; build with make build-cli or go build -o bin/glx ./glx |
pedagogical | info | Minor wording mismatch where technical accuracy is preserved |
Before any file reading:
git rev-parse HEAD
Record the printed SHA; substitute it for <HEAD_SHA> in the final JSON block.
Use the Glob tool to enumerate docs/**/*.md. Exclude the following paths — they are either owned by other skills, auto-generated, or not derived from the GLX spec:
| Excluded path pattern | Reason |
|---|---|
docs/examples/** | Owned by check-examples |
docs/cli/** | Auto-generated by make docs-cli; drift validated by CI |
docs/decisions/** | Architecture Decision Records — historical records, not derived from current spec |
docs/gedcom-spec/** | External GEDCOM reference PDFs and ancillary files |
Additionally include these files that live outside docs/ but are user-facing:
specification/6-glossary.md is owned by check-spec, which has the dedicated glossary-consistency checks — it is intentionally not checked here. Specification entity-type files are also check-spec's responsibility.)Also read these cross-reference surfaces when checking CLI examples and sidebar coverage. Do NOT flag these as drifting documentation — they are source-of-truth surfaces, not documentation files:
glx/cli_commands.go — Cobra Use/Short/Long/Example declarations (the canonical CLI registry, per project CLAUDE.md)glx/*_runner.go — handler implementations where flags and runtime behaviour are definedwebsite/.vitepress/config.js — sidebar navigation; cross-check that every published doc appearsThe checked_files array is the complete post-exclusion glob result plus every cross-reference surface you actually open above (glx/cli_commands.go, the glx/*_runner.go files, website/.vitepress/config.js) — list what you read, so the provenance is complete and the eval harness can detect under-scoping.
This dynamic enumeration means new guides added to docs/ are automatically in scope on the next run without any prompt edits (resolving the recurring defect class tracked in GitHub issue #829).
Compare documented fields with specification/4-entity-types/*.md:
state_province not state)field_presence, field_type, required_optional as appropriateFor each YAML-tagged fenced code block in a documentation markdown file:
Extract the YAML body from the markdown source.
Classify the block by intent — only blocks that present a complete archive or entity get deterministically validated; partial illustrations must NOT be forced through validation (they would false-fail). glx validate <file> validates archive-shape input; glx validate --stdin --entity-type <type> (#910) validates a complete bare entity/vocabulary-entry body:
persons:, events:, …), vocabulary-collection keys, or metadata:. This also covers a single entity keyed by its ID under its collection (e.g. persons: → person-jane: → body). Validate as a whole archive (step 4a).person-jane: → body), use the value under that ID key as the body — do not feed the person-jane: wrapper to --stdin (the ID would become an unknown top-level property). Validate via --stdin --entity-type <type> (step 4b).participants: list, a properties: excerpt, a single date: field), omitting other required fields on purpose. This is the dominant false-positive source. Do not run structural validation — record a positive_notes note ("illustrative partial fragment — not structurally validated") and rely on the narrative checks in Steps 2 and 4.Create a unique scratch directory and capture its path:
mktemp -d /tmp/glx-drift-XXXXXX
Read the printed path (e.g. /tmp/glx-drift-aB3xYz); substitute it for <TMPDIR> in the remaining steps. Bash sessions don't persist between tool calls, so each subsequent command must use the literal path you captured.
Use the Write tool to save the extracted YAML body to <TMPDIR>/snippet.glx. Using Write rather than shelling out via cat/printf/heredoc avoids every shell-quoting concern around YAML bodies that contain $, backticks, or quotes — for both paths below. Then run the validator (do NOT mentally simulate schema validation):
4a — archive-shaped block:
./bin/glx validate <TMPDIR>/snippet.glx
4b — entity / vocabulary fragment (redirect the file into stdin so the body is never re-quoted on a pipe):
./bin/glx validate --stdin --entity-type <type> < <TMPDIR>/snippet.glx
<type> is the entity singular (person, event, …) or vocabulary-collection key (event_types, place_types, …) inferred from the block's context. --stdin runs Pass-1 structural validation only (no cross-reference resolution), which is exactly right for a context-free fragment.
rm -rf <TMPDIR>
Per-snippet cleanup keeps concurrent runs from racing on the /tmp/glx-drift-* namespace.
Classify the result deterministically by exit code alone:
positive_notes entry — do not emit a finding (a clean validation is not drift, and validator_caught: false + llm_only: false is not a valid finding combination). Still apply the narrative checks in steps 2 and 4 — the validator does not catch specification-prose drift.category: example_validation, default severity critical (validator_caught: true, llm_only: false); put the validator's stderr verbatim in message. Carve-out for partial illustrations: if the only errors are missing property '<field>' / missing properties … and the block is a focused/partial illustration (step 2), it was mis-classified as complete — this is not drift. Record a positive_notes "illustrative partial fragment" note instead of a finding. Keep critical when the failure shows additional properties … not allowed, a type mismatch, a pattern or array-length (minItems) violation, or a missing-required field on a block the page presents as its complete canonical example.--stdin path: unknown/missing --entity-type, or an empty body) → this means the skill picked the wrong --entity-type or mis-classified the block, not documentation drift. Re-classify (the block was usually a sub-object excerpt that step 2 should skip) and re-run, or record one category: validator_unavailable, severity: info note (with validator_caught: false, llm_only: true — see below). Never emit an exit-2 result as a critical example finding.If ./bin/glx is unavailable, emit one category: validator_unavailable, severity: info finding and build with make build-cli (or go build -o bin/glx ./glx) if needed before proceeding. Per the suite convention (.claude/skills/check-suite/README.md → Cross-finding conventions), a validator_unavailable finding carries validator_caught: false, llm_only: true — the schema's oneOf forbids false/false, and it is the LLM run, not the validator, that surfaced the gap.
Cross-reference against glx/cli_commands.go (Use/Short/Long/Example declarations) and glx/*_runner.go (handler implementations, where flags are registered):
glx/cli_commands.go*_runner.gocli_example for any mismatchNote: the glob pattern is glx/cli_commands.go plus glx/*_runner.go, NOT glx/cmd_*.go — the cmd_*.go pattern mostly matches test files and misses the 29 production command implementations (GitHub issue #800).
Check referenced vocabulary types against specification/5-standard-vocabularies/:
Use category vocabulary.
.md extension, per the project's documentation URL conventionUse category cross_reference.
Before finalizing the report, suppress findings that are already tracked:
gh issue list -R genealogix/glx --state open --limit 100 --json number,title --jq '.[] | "#\(.number) \(.title)"'
For each finding, scan the issue title list for overlap on the doc file path, field name, or command name. If the finding is already tracked in an open issue, omit it from findings but increment suppressed_as_duplicate_of_known_issue in summary. If the finding is not tracked, include it in full.
This prevents duplicate triage on every run.
After all checks and the cross-reference step, emit the human-readable summary followed by the machine-readable block.
Human-readable summary format:
# Documentation Drift Report
## Scope
- Commit: <HEAD_SHA>
- Files checked: N
### docs/quickstart.md
No drift detected.
### docs/guides/hands-on-cli-guide.md
Drift detected — documentation needs updates:
- Line 42: ...
Then emit the machine-readable block (the eval harness greps for the info-string):
{
"command": "check-docs-drift",
"commit": "<HEAD_SHA>",
"checked_files": ["docs/quickstart.md", "..."],
"findings": [
{
"file": "docs/quickstart.md",
"line": 42,
"severity": "major",
"category": "required_optional",
"message": "Documentation says `name` is required, specification says optional",
"fix": "Change 'required' to 'optional' in the field description at line 42",
"validator_caught": false,
"llm_only": true
}
],
"positive_notes": [
"docs/guides/best-practices.md: all field names and types match specification"
],
"summary": {
"critical": 0,
"major": 1,
"minor": 0,
"info": 0,
"suppressed_as_duplicate_of_known_issue": 2
}
}
glx/cli_commands.go and glx/*_runner.go)state vs state_province — the latter is the current field name).md extension in URL form (should be omitted per the project's URL convention)specification/6-glossary.md) is owned by check-spec, not this skill — do not check it here.claude/skills/check-suite/severity-rubric.md for the full shared severity scale; do not redefine it here.claude/skills/check-suite/findings.schema.json for the complete output schema