tools: command records, Types, instructions and docs group - one line per cause, examples, prohibitions (#142)
Files changed: - CHANGES.md - VERSION - tools/CONTRACT.md - tools/chemenu/commands/docs_verify.py - tools/chemenu/commands/instructions_cmd.py - tools/chemenu/commands/types_cmd.py
This commit is contained in:
1 parent
b9c22f783f
commit
9617d722de
6 files changed
+428
-137
No files matched your search
@@ -259,7 +259,9 @@ def check_command_contracts() -> list[str]:
|
||||
function by `@cli_contract.record(...)`. A record with no matching
|
||||
command, a command with no record, or a `GROUPS` entry appearing twice
|
||||
are the three ways that pairing can drift; each is its own issue so a
|
||||
session sees exactly which command needs attention.
|
||||
session sees exactly which command needs attention. Both directions are
|
||||
checked so that a command dropped from one side is not hidden by the
|
||||
other.
|
||||
"""
|
||||
registered = sorted(registered_commands())
|
||||
issues: list[str] = []
|
||||
@@ -1044,47 +1046,78 @@ def check_breaking_change_for_boundary() -> list[str]:
|
||||
atomic="Read-only",
|
||||
budget=cli_contract.Budget.COUNTED,
|
||||
),
|
||||
notes="Check the docs that mirror the code: every command has a `cli_contract` record and "
|
||||
"is listed in `cli_contract.GROUPS` (both directions, so a command dropped from one is not "
|
||||
"hidden by the other), every command's non-hidden flags appear in its record's SYNOPSIS and "
|
||||
"vice versa, `tools/CONTRACT.md`'s generated `<!-- wikitool:commands -->` region matches "
|
||||
"what `cli_contract.render_commands_region()` would write, no command's rendered "
|
||||
"`--help`/`-h` text cites an issue number, every directory under `kb/` has a "
|
||||
"`COLLECTION.md` and no directory outside it does, every collection declaring `profile:` "
|
||||
"and a `required_by_stack:` that agrees with the stack's own list, every type the stack "
|
||||
"lists (currently `source` and `project`) having a type-spec of that name whose schema "
|
||||
"requires the field the stack list also names (`raw_files:`/`state:`), `kb/CONVENTIONS.md` "
|
||||
"naming all three tool-owned section headings if it exists at all, every stage contract "
|
||||
"present, every file under `types/` declaring `type: types/type-spec.md` validating "
|
||||
"against `types/type-spec.schema.yaml`, no pre-migration `type: entity` blocks left in the "
|
||||
"contracts, the `.gitignore` canaries clear in both directions (nothing ignored under "
|
||||
"`raw/`/`kb/`, `incoming/` ignored, everything ignored under `reports/` and the published "
|
||||
"skill directories), and no `.md`/`.template` file `dist export` would ship citing an issue "
|
||||
"number - the tracker exists only in the origin repo, so such a number in a distributed "
|
||||
"instance is a reference its reader can neither resolve nor recognise as unresolvable (a "
|
||||
"`<!-- dist:strip-start/end -->` region is exempt: it is already gone from the text the "
|
||||
"check reads, which is the export plan's, not the working tree's), every reference file "
|
||||
"`docs toc` covers carrying the current table-of-contents region for its own headings - "
|
||||
"missing and stale are one check, because the generator is idempotent - and every relative "
|
||||
"markdown link in one of those same reference files resolving to a file that actually "
|
||||
"exists (a target's `#anchor` suffix is stripped first; code fences and inline code spans "
|
||||
"are masked before scanning, so a passage showing link syntax as an example is not mistaken "
|
||||
"for a real reference). The name is about documentation parity, not about the `docs/` "
|
||||
"directory - it neither reads nor requires one, the same way `kb/` predates the collection "
|
||||
"it now checks",
|
||||
failures=(cli_contract.Failure(
|
||||
label="",
|
||||
cause="A command, contract, or type-form mismatch was found, a type-spec's own "
|
||||
"frontmatter fails its schema, a shipped `.md`/`.template` cites an issue number, a "
|
||||
"reference file's table-of-contents region is missing or stale, or a reference file's "
|
||||
"relative markdown link does not resolve to an existing file",
|
||||
reaction="Fix the documentation it names, then re-run. For a type-spec's own frontmatter: "
|
||||
"fix the field, or add a matching line to `types/type-spec.schema.yaml` if the field is "
|
||||
"legitimately new. For an issue reference: say what was decided instead of pointing at "
|
||||
"where, or move the pointer behind a `<!-- dist:strip-start/end -->` block. For a table "
|
||||
"of contents: run `docs toc --apply` - never hand-write the region. For a dead link: "
|
||||
"fix the `../` count or the target's name",
|
||||
),),
|
||||
notes=(
|
||||
"Checks the docs that mirror the code. The name is about documentation parity, not the "
|
||||
"`docs/` directory - it neither reads nor requires one.",
|
||||
"Commands: every command has a `cli_contract` record and is listed in "
|
||||
"`cli_contract.GROUPS`, in both directions; every command's non-hidden flags appear in "
|
||||
"its record's SYNOPSIS and vice versa; `tools/CONTRACT.md`'s generated "
|
||||
"`<!-- wikitool:commands -->` region matches what `docs contract` would write; no "
|
||||
"command's rendered `--help`/`-h` text cites an issue number.",
|
||||
"Collections: every directory under `kb/` has a `COLLECTION.md` and no directory "
|
||||
"outside it does; every collection declares `profile:` and a `required_by_stack:` that "
|
||||
"agrees with the stack's own list.",
|
||||
"Types: every type the stack lists (currently `source` and `project`) has a type-spec "
|
||||
"of that name whose schema requires the field the stack list names "
|
||||
"(`raw_files:`/`state:`); every file under `types/` declaring `type: "
|
||||
"types/type-spec.md` validates against `types/type-spec.schema.yaml`; no "
|
||||
"pre-migration `type: entity` blocks are left in the contracts.",
|
||||
"`kb/CONVENTIONS.md`, if it exists at all, names all three tool-owned section headings; "
|
||||
"every stage contract is present.",
|
||||
"The `.gitignore` canaries clear in both directions: nothing ignored under "
|
||||
"`raw/`/`kb/`, `incoming/` ignored, everything ignored under `reports/` and the "
|
||||
"published skill directories.",
|
||||
"No `.md`/`.template` file `dist export` would ship cites an issue number. A "
|
||||
"`<!-- dist:strip-start/end -->` region is exempt: the check reads the export plan's "
|
||||
"text, from which it is already gone.",
|
||||
"Every reference file `docs toc` covers carries the current table-of-contents region "
|
||||
"for its own headings - missing and stale are one check.",
|
||||
"Every relative markdown link in one of those reference files resolves to an existing "
|
||||
"file. A target's `#anchor` suffix is stripped first, and code fences and inline code "
|
||||
"spans are masked before scanning, so link syntax shown as an example is not mistaken "
|
||||
"for a real reference.",
|
||||
"Read-only.",
|
||||
),
|
||||
failures=(
|
||||
cli_contract.Failure(
|
||||
cause="A command, contract, or type-form mismatch",
|
||||
reaction="Fix the documentation it names, then re-run",
|
||||
),
|
||||
cli_contract.Failure(
|
||||
cause="The `<!-- wikitool:commands -->` region of `tools/CONTRACT.md` is stale",
|
||||
reaction="Run `docs contract --apply`, then re-run",
|
||||
),
|
||||
cli_contract.Failure(
|
||||
cause="A type-spec's own frontmatter fails its schema",
|
||||
reaction="Fix the field, or add a matching line to `types/type-spec.schema.yaml` if "
|
||||
"the field is legitimately new",
|
||||
),
|
||||
cli_contract.Failure(
|
||||
cause="A shipped `.md`/`.template` cites an issue number",
|
||||
reaction="Say what was decided instead of pointing at where, or move the pointer "
|
||||
"behind a `<!-- dist:strip-start/end -->` block",
|
||||
),
|
||||
cli_contract.Failure(
|
||||
cause="A reference file's table-of-contents region is missing or stale",
|
||||
reaction="Run `docs toc --apply`, then re-run",
|
||||
),
|
||||
cli_contract.Failure(
|
||||
cause="A reference file's relative markdown link does not resolve to an existing "
|
||||
"file",
|
||||
reaction="Fix the `../` count or the target's name",
|
||||
),
|
||||
),
|
||||
examples=(
|
||||
"tools/wikitool docs verify",
|
||||
),
|
||||
never=(
|
||||
"Never hand-write a table-of-contents region or the commands region - regenerate it.",
|
||||
),
|
||||
see_also=(
|
||||
"`wikitool docs toc` - regenerates tables of contents",
|
||||
"`wikitool docs contract` - regenerates the commands region",
|
||||
"`wikitool instructions verify` - the same kind of check for `instructions/`",
|
||||
),
|
||||
))
|
||||
def verify():
|
||||
"""Check the docs that mirror the code."""
|
||||
@@ -1138,31 +1171,37 @@ def verify():
|
||||
"dry-run form is read-only",
|
||||
budget=cli_contract.Budget.COUNTED,
|
||||
),
|
||||
notes="On every reference file over 100 lines, in the scope Anthropic's skill-authoring "
|
||||
"guidance names for a file previewed rather than read in full: `AGENTS.md`, every stage "
|
||||
"contract, `kb/CONVENTIONS.md`, every `kb/*/COLLECTION.md`, every flat "
|
||||
"`instructions/**.md` file, every `types/*.md` type-spec, and every `docs/` page - each "
|
||||
"together with the `<name>.template` it ships as, where one exists. Computed from those "
|
||||
"categories rather than listed, so a file added later is in scope without a code change. A "
|
||||
"template is in scope because it is the same document one step earlier in its life: an "
|
||||
"instance adopts it by copying it back, so a region missing there is a region missing in "
|
||||
"the adopted file, which is how `kb/CONVENTIONS.md.template` came to grow past the "
|
||||
"threshold with no region and left every instance adopting it failing `docs verify` at the "
|
||||
"end of its own setup. `SKILL.md` is the one exception, and the same guidance is why: it "
|
||||
"places a skill body on the loading level that is read whole when the skill triggers, and "
|
||||
"aims its own TOC advice at the bundled reference files a skill points *at*. Human docs "
|
||||
"(`README.md`, `CHANGES.md`, `EVALS.md`, `INSTALL.md`, `tools/README.md`) are out of scope "
|
||||
"because AGENTS.md § File naming says no agent loads them as instruction. Dry-run by "
|
||||
"default (prints which files would change); `--apply` writes. `docs verify` checks the "
|
||||
"result stays current the same way it checks every other generated-from-code copy",
|
||||
notes=(
|
||||
"Creates, refreshes or removes the generated table-of-contents region on every "
|
||||
"reference file over 100 lines: `AGENTS.md`, every stage contract, "
|
||||
"`kb/CONVENTIONS.md`, every `kb/*/COLLECTION.md`, every flat `instructions/**.md` file, "
|
||||
"every `types/*.md` type-spec, and every `docs/` page - each together with the "
|
||||
"`<name>.template` it ships as, where one exists.",
|
||||
"The scope is computed from those categories rather than listed, so a file added later "
|
||||
"is in scope without a code change.",
|
||||
"Out of scope: every `SKILL.md`, and the human docs (`README.md`, `CHANGES.md`, "
|
||||
"`EVALS.md`, `INSTALL.md`, `tools/README.md`).",
|
||||
"Dry-run by default (prints which files would change); `--apply` writes. Idempotent: a "
|
||||
"re-run after an interruption converges rather than doubling a region.",
|
||||
"If `docs verify` still reports a stale region after `--apply`, the file's `##` "
|
||||
"headings changed in between; run it again.",
|
||||
),
|
||||
failures=(cli_contract.Failure(
|
||||
label="",
|
||||
cause="Never fails on content: a file with no `##` heading, or one at or under the "
|
||||
"threshold, is simply left without a region",
|
||||
reaction="Nothing to fix - re-run with `--apply` to write what the dry run listed. If "
|
||||
"`docs verify` still reports a stale region afterwards, the file's `##` headings "
|
||||
"changed in between; run it again",
|
||||
reaction="",
|
||||
code=0,
|
||||
),),
|
||||
examples=(
|
||||
"tools/wikitool docs toc",
|
||||
"tools/wikitool docs toc --apply",
|
||||
),
|
||||
never=(
|
||||
"Never hand-write or hand-edit a table-of-contents region.",
|
||||
),
|
||||
see_also=(
|
||||
"`wikitool docs verify` - checks every region is current",
|
||||
),
|
||||
))
|
||||
def toc_command(
|
||||
apply: bool = typer.Option(False, "--apply", help="Write changes; default is dry-run (preview only)"),
|
||||
@@ -1205,12 +1244,25 @@ def toc_command(
|
||||
atomic="Yes - the whole region is rewritten in one file write",
|
||||
budget=cli_contract.Budget.COUNTED,
|
||||
),
|
||||
notes="Rebuilds the region from `cli_contract.all_records()`: the index (one line per "
|
||||
"command, `GROUPS` order) followed by each `###`-group's commands as `#### <path>` "
|
||||
"man-page-shaped sections. Dry-run by default, like `docs toc`; `--apply` writes. "
|
||||
"`docs verify`'s `check_commands_region` checks the result stays current the same way it "
|
||||
"checks every other generated-from-code copy.",
|
||||
notes=(
|
||||
"Rebuilds the region from every `cli_contract` record: the index (one line per "
|
||||
"command, `GROUPS` order) followed by each `###` group's commands as `#### <path>` "
|
||||
"man-page-shaped sections.",
|
||||
"Dry-run by default (says whether the file would change); `--apply` writes.",
|
||||
"`docs verify` checks the result stays current.",
|
||||
),
|
||||
failures=(),
|
||||
examples=(
|
||||
"tools/wikitool docs contract",
|
||||
"tools/wikitool docs contract --apply",
|
||||
),
|
||||
never=(
|
||||
"Never hand-edit the region - change the record in code and re-run this.",
|
||||
),
|
||||
see_also=(
|
||||
"`tools/README.md` § Adding a command - how a command gets its record",
|
||||
"`wikitool docs verify` - checks the region is current",
|
||||
),
|
||||
))
|
||||
def contract_command(
|
||||
apply: bool = typer.Option(False, "--apply", help="Write changes; default is dry-run (preview only)"),
|
||||
|
||||
@@ -378,19 +378,38 @@ def check_skill_reference_paths() -> list[str]:
|
||||
"partial failure",
|
||||
budget=cli_contract.Budget.COUNTED,
|
||||
),
|
||||
notes="Publish every `instructions/<name>/SKILL.md` into `.agents/skills/` and "
|
||||
"`.claude/skills/` as **copies**, and delete published skills whose source is gone. Both "
|
||||
"targets are gitignored, so a fresh clone runs this once - see `instructions/bootstrap.md`. "
|
||||
"Re-running is also how a drifted copy is repaired: the source always wins. `--force` is "
|
||||
"required only to replace a target directory that is not a published skill at all (no "
|
||||
"`SKILL.md` in it)",
|
||||
failures=(cli_contract.Failure(
|
||||
label="",
|
||||
cause="No skills found under `instructions/`, or a target directory is not a "
|
||||
"published skill (no `SKILL.md`) and `--force` was not passed",
|
||||
reaction="Check whether the flagged target holds anything worth keeping, then re-run with "
|
||||
"`--force` if not; otherwise fix the named cause and retry",
|
||||
),),
|
||||
notes=(
|
||||
"Publishes every `instructions/<name>/SKILL.md` into `.agents/skills/` and "
|
||||
"`.claude/skills/` as **copies**, and deletes published skills whose source is gone.",
|
||||
"Both targets are gitignored, so a fresh clone runs this once.",
|
||||
"Re-running repairs a drifted copy: the source always wins.",
|
||||
"`--force` is required only to replace a target directory that is not a published "
|
||||
"skill at all (no `SKILL.md` in it).",
|
||||
"Each copy is idempotent, so a re-run converges even after a partial failure.",
|
||||
),
|
||||
failures=(
|
||||
cli_contract.Failure(
|
||||
cause="No skills found under `instructions/`",
|
||||
reaction="Fix the named cause and retry",
|
||||
),
|
||||
cli_contract.Failure(
|
||||
cause="A target directory is not a published skill (no `SKILL.md`) and `--force` was "
|
||||
"not passed",
|
||||
reaction="Check whether the flagged target holds anything worth keeping, then re-run "
|
||||
"with `--force` if not",
|
||||
),
|
||||
),
|
||||
examples=(
|
||||
"tools/wikitool instructions sync",
|
||||
),
|
||||
never=(
|
||||
"Never hand-edit a published copy under `.agents/skills/` or `.claude/skills/` - edit "
|
||||
"the source and re-run this.",
|
||||
),
|
||||
see_also=(
|
||||
"`instructions/bootstrap.md` - the fresh-clone procedure that runs this",
|
||||
"`wikitool instructions verify` - checks the copies match",
|
||||
),
|
||||
))
|
||||
def sync(
|
||||
force: bool = typer.Option(
|
||||
@@ -438,27 +457,57 @@ def sync(
|
||||
atomic="Read-only",
|
||||
budget=cli_contract.Budget.COUNTED,
|
||||
),
|
||||
notes="Flat instructions validate against `types/instruction.schema.yaml`, each `SKILL.md` "
|
||||
"carries the frontmatter its harness reads, no `SKILL.md` carries a relative markdown link "
|
||||
"(`sync` copies it to a different depth than the source, so a `SKILL.md` references a "
|
||||
"target as a repo-root-relative plain path instead - see `instructions/CONTRACT.md` § \"A "
|
||||
"skill's outbound reference is a plain path, not a link\"), every published copy is "
|
||||
"byte-identical to its source, no instruction is left that nothing references, and nothing "
|
||||
"under `instructions/dev/` is referenced from outside it (a "
|
||||
"`<!-- dist:strip-start/end -->` block is exempt - see `instructions/CONTRACT.md`). Missing "
|
||||
"*every* copy is reported as \"run sync\", not as drift - that is a clean checkout",
|
||||
failures=(cli_contract.Failure(
|
||||
label="",
|
||||
cause="Nothing found under `instructions/` at all, a malformed instruction or "
|
||||
"`SKILL.md`, a `SKILL.md` carrying a relative markdown link, a published copy that "
|
||||
"drifted from its source, an instruction nothing references (or, for `manual: true`, "
|
||||
"one that IS linked from AGENTS.md, CLAUDE.md, or a skill and so risks running "
|
||||
"implicitly), or something under `instructions/dev/` referenced from outside it and "
|
||||
"outside a `dist:strip` block",
|
||||
reaction="Fix the flagged file, then re-run. For a relative link in a `SKILL.md`, rewrite "
|
||||
"it as a repo-root-relative plain path instead. For drift, re-run `sync` instead of "
|
||||
"hand-editing the published copy - the source under `instructions/` always wins",
|
||||
),),
|
||||
notes=(
|
||||
"Flat instructions validate against `types/instruction.schema.yaml`, and each "
|
||||
"`SKILL.md` carries the frontmatter its harness reads.",
|
||||
"No `SKILL.md` carries a relative markdown link: `sync` copies it to a different depth "
|
||||
"than the source, so a `SKILL.md` references a target as a repo-root-relative plain "
|
||||
"path instead (`instructions/CONTRACT.md` § \"A skill's outbound reference is a plain "
|
||||
"path, not a link\").",
|
||||
"Every published copy is byte-identical to its source. Missing *every* copy is "
|
||||
"reported as \"run sync\", not as drift - that is a clean checkout.",
|
||||
"No instruction is left that nothing references; one marked `manual: true` must "
|
||||
"instead not be linked from AGENTS.md, CLAUDE.md or a skill.",
|
||||
"Nothing under `instructions/dev/` is referenced from outside it; a "
|
||||
"`<!-- dist:strip-start/end -->` block is exempt (`instructions/CONTRACT.md`).",
|
||||
"Read-only.",
|
||||
),
|
||||
failures=(
|
||||
cli_contract.Failure(
|
||||
cause="Nothing found under `instructions/` at all, or a malformed instruction or "
|
||||
"`SKILL.md`",
|
||||
reaction="Fix the flagged file, then re-run",
|
||||
),
|
||||
cli_contract.Failure(
|
||||
cause="A `SKILL.md` carries a relative markdown link",
|
||||
reaction="Rewrite it as a repo-root-relative plain path, then re-run",
|
||||
),
|
||||
cli_contract.Failure(
|
||||
cause="A published copy drifted from its source",
|
||||
reaction="Re-run `instructions sync` - the source under `instructions/` always wins",
|
||||
),
|
||||
cli_contract.Failure(
|
||||
cause="An instruction nothing references, or a `manual: true` one that IS linked "
|
||||
"from AGENTS.md, CLAUDE.md or a skill and so risks running implicitly",
|
||||
reaction="Link it from where it is used, or drop the link to a manual one, then "
|
||||
"re-run",
|
||||
),
|
||||
cli_contract.Failure(
|
||||
cause="Something under `instructions/dev/` is referenced from outside it and outside "
|
||||
"a `dist:strip` block",
|
||||
reaction="Remove the reference or wrap it in a `dist:strip` block, then re-run",
|
||||
),
|
||||
),
|
||||
examples=(
|
||||
"tools/wikitool instructions verify",
|
||||
),
|
||||
never=(
|
||||
"Never fix drift by hand-editing the published copy.",
|
||||
),
|
||||
see_also=(
|
||||
"`wikitool instructions sync` - publishes the copies",
|
||||
"`instructions/CONTRACT.md` - the rules this checks",
|
||||
),
|
||||
))
|
||||
def verify():
|
||||
"""Check instructions/ against its type, that no skill carries a relative markdown link, and every published copy against its source."""
|
||||
@@ -596,9 +645,20 @@ def verify():
|
||||
atomic="Read-only",
|
||||
budget=cli_contract.Budget.COUNTED,
|
||||
),
|
||||
notes="This is how the layer is discovered; `search` deliberately covers `kb/` only. Never "
|
||||
"fails - an empty `instructions/` prints \"No instructions found.\" Safe to retry freely.",
|
||||
notes=(
|
||||
"Lists the flat instructions with their descriptions - how the instruction layer is "
|
||||
"discovered; `search` covers `kb/` only.",
|
||||
"Never fails: an empty `instructions/` prints \"No instructions found.\" Read-only and "
|
||||
"safe to retry freely.",
|
||||
),
|
||||
failures=(),
|
||||
examples=(
|
||||
"tools/wikitool instructions list",
|
||||
"tools/wikitool instructions list --json",
|
||||
),
|
||||
see_also=(
|
||||
"`wikitool search` - the same question for `kb/`",
|
||||
),
|
||||
))
|
||||
def list_instructions(
|
||||
json_out: bool = typer.Option(False, "--json", help="Print the listing as JSON"),
|
||||
|
||||
@@ -35,9 +35,22 @@ app = typer.Typer(help="Discover and describe Chemenu type-spec contracts.")
|
||||
atomic="Read-only",
|
||||
budget=cli_contract.Budget.COUNTED,
|
||||
),
|
||||
notes="Name, schema path, subtype field, and description - discover what page types exist "
|
||||
"without reading `types/*.md` directly. Never fails. Safe to retry freely.",
|
||||
notes=(
|
||||
"Lists every type-spec under `types/`: name, schema path, subtype field, and "
|
||||
"description - which page types exist, without reading `types/*.md` directly.",
|
||||
"Never fails; read-only and safe to retry freely.",
|
||||
),
|
||||
failures=(),
|
||||
examples=(
|
||||
"tools/wikitool types list",
|
||||
"tools/wikitool types list --json",
|
||||
),
|
||||
never=(
|
||||
"Never pick a page's directory by hand - `types describe` and `new` compute it.",
|
||||
),
|
||||
see_also=(
|
||||
"`wikitool types describe <name>` - one type's full contract",
|
||||
),
|
||||
))
|
||||
def list_types_command(
|
||||
json_out: bool = typer.Option(False, "--json", help="Print raw findings as JSON")
|
||||
@@ -72,19 +85,29 @@ def list_types_command(
|
||||
atomic="Read-only",
|
||||
budget=cli_contract.Budget.COUNTED,
|
||||
),
|
||||
notes="Required/optional frontmatter fields with enums, its subtype field (if any), and its "
|
||||
"authoring body - composed with the stack-owned `types/<name>.guidance.md` where the "
|
||||
"type-spec declares `guidance:` (`--json` reports it separately as "
|
||||
"`guidance`/`guidance_path`, absent for a type with none), so a `root: kb` type's contract "
|
||||
"reads as one answer even though it may live in two files. A type-spec (or its guidance "
|
||||
"file) over the `docs toc` threshold carries a generated table-of-contents region; it is "
|
||||
"stripped from this output rather than echoed, since the whole body is being handed over "
|
||||
"and a navigation aid into it would be noise",
|
||||
notes=(
|
||||
"Prints one type's full contract: required and optional frontmatter fields with enums, "
|
||||
"its subtype field (if any), and its authoring body.",
|
||||
"Where the type-spec declares `guidance:`, the stack-owned `types/<name>.guidance.md` is "
|
||||
"composed in, so a `root: kb` type's contract reads as one answer even though it may "
|
||||
"live in two files. `--json` reports it separately as `guidance`/`guidance_path`, absent "
|
||||
"for a type with none.",
|
||||
"The generated table-of-contents region a long type-spec (or guidance file) carries is "
|
||||
"stripped from this output.",
|
||||
"Read-only.",
|
||||
),
|
||||
failures=(cli_contract.Failure(
|
||||
label="",
|
||||
cause="Unknown type name",
|
||||
reaction="Fix the name and retry",
|
||||
reaction="Fix the name (see `types list`) and retry",
|
||||
),),
|
||||
examples=(
|
||||
"tools/wikitool types describe source",
|
||||
"tools/wikitool types describe project --json",
|
||||
),
|
||||
see_also=(
|
||||
"`wikitool types list` - every type",
|
||||
"`wikitool new <type>` - scaffolds a page of the type",
|
||||
),
|
||||
))
|
||||
def describe_type_command(
|
||||
name: str = typer.Argument(..., help="Type name, e.g. 'entity' (see `types list`)"),
|
||||
|
||||
Reference in new issue
Block a user