Version Packages - #190
Open
github-actions[bot] wants to merge 1 commit into
Open
Conversation
github-actions
Bot
force-pushed
the
changeset-release/main
branch
from
August 19, 2026 21:55
60d8461 to
5708316
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.
Releases
leadtype@0.5.0
Minor Changes
4c1b962: Add a canonical config vocabulary and one resolved-config normalizer.
defineLeadtypeConfignames the project/site config inleadtype.config.ts, alongsidedefineDocsConfigfor a source repo's content-owneddocs.config.ts. Three collection fields are renamed:prefix→routePrefix,sourceConfig→inheritConfig,schema→frontmatterSchema.Every existing config keeps working. Both spellings normalize to one internal
ResolvedDocsConfigthat generate, sync, lint, score, and the runtime source all read, so no subsystem re-derives the project from raw config. The resolved shape adds a deduped source graph — collections sharing a(repository, ref)resolve to one acquisition — and per-field provenance recording whether each value was authored, inherited from a source repo, inferred, or defaulted.Deprecated fields carry
@deprecatedguidance in the IDE and warn once per config file at load. Setting an old name and its replacement together is an error naming both rather than a silent precedence rule. Nothing is removed before 1.0.5aa8d2b: Derive navigation and the
llms.txtbody when they aren't authored, so a new project reaches useful output from identity alone.Navigation is derived from the content tree — root pages at the root, one section per top-level directory titled from its
indexpage, orderedindexfirst then frontmatterorderthen path, so it never depends on filesystem enumeration order. Thellms.txtbody becomes a "Best Starting Points" block built from that same resolved navigation, which keeps an agent's entry points from drifting from a reader's. Product name and tagline fall back topackage.json.Both
leadtype generateandcreateDocsSource()derive the same tree, so the rendered sidebar and the generated artifacts agree. Explicit configuration always wins: authoringnavigation,groups, orllms.sectionsturns inference off for that field, and inference never merges with or rewrites an authored value.leadtype generate --explainreports every derived value, what it was derived from, and the field that takes control of it. Ambiguous derivations — pages with no frontmattertitle, or more pages than the starting-points block lists — warn with the field to set.leadtype initnow scaffolds identity only.2fda088: Add
createDocsProject()— the resolved project config as a runtime source.createDocsSource()describes one content directory, so an app restates what its config already says: the content root, navigation, mounts, the frontmatter schema, and for a multi-collection project all of that per collection plus route prefixes and source-owned inheritance. Two descriptions of one project drift, and when they do the rendered site and the generated agent artifacts disagree about what exists.A project reads the same resolved config the artifact pipeline reads, and returns a superset of
DocsSource, so every first-party adapter accepts it unchanged:Multi-collection projects get one merged, route-aware page API —
listPages()tags each page with its collection,loadPage()accepts a collection-local slug or the full route — plusproject.collections,project.sources, andproject.getSource(key)for custom integrations. Source-owned config inheritance now runs through one shared implementation, so human rendering and generated artifacts cannot resolve it differently.Remote collections are cache-only: a missing, unverifiable, or wrong-revision cache fails with a diagnostic naming
leadtype syncrather than cloning inside a request. Route collisions name both collections.createDocsSource()stays fully supported and is what the project is built on.leadtype initnow scaffolds the project primitive.43883be: Add
gitSource()for declaring one git acquisition with its content collections beneath it.The flat
collectionsmap makes every collection carryrepository,ref, andcacheDireven when several come from the same repository — so a config repeats acquisition three times for one clone, and a reader has to know that matching(repository, ref)pairs are deduped. A source group declares the clone once:The source owns acquisition and the default inheritance policy; each collection owns its directory, route prefix, navigation, and any inheritance exception. Both forms normalize to the same source graph, and
sourcesmay be used alongsidecollections.Collection ids stay global rather than being scoped to their source, because they name staging mounts, error messages, and JSON output — two sources declaring the same id is an error naming both, not an auto-rename. So is declaring one
(repository, ref)under two source names.sparselimits a checkout to the repository paths you actually need, via a blobless partial clone — pinning a docs directory out of a monorepo no longer downloads the whole repository. Collections sharing an acquisition must agree on the path set, and the set is recorded in the sync manifest so adding a path re-clones rather than reusing an incomplete cache.leadtype syncnow reports each source id with its dependent collections, and warns when a source tracks a mutable ref instead of a pinned commit.leadtype generate --jsonreports the same acquisition graph, using the same ids — a named source keeps its authored name, an anonymous one is identified byrepository#ref.inheritConfig: falseopts a collection out of a source-level inheritance default.c21b6b9: Add
leadtype doctor— a read-only explanation of the resolved project.The other commands each answer a question about a project by doing something to it. None answered "what is this project, and why?" — which config was discovered, whether it resolved single-source or multi-repo, which values were authored versus inherited versus inferred, which collections share one clone, what routes will exist, and which command fixes what is currently wrong.
Doctor never clones, refreshes, writes, or generates, so an unsynced remote is a finding naming
leadtype syncrather than a fetch. Everything it reports comes from the same config loader and resolversgenerateandsyncuse, so a clean doctor run and a clean generate run cannot disagree.Checks cover config discovery and provenance, deprecated aliases, the deduped acquisition graph with pinned-versus-mutable refs and cache freshness, collection directories and include globs, the resolved navigation tree and pages that fall back to the root instead of being placed, expected output artifacts and their staleness, the detected framework adapter, and enabled agent surfaces.
Human output is concise and every finding names its owning config field and a concrete next command.
--jsoncarries stable finding ids and provenance so agents can act without parsing prose. Exit0when nothing is an error,1when a required input is missing or invalid.ba6ecdb: Reduce navigation config churn for large and repeated docs trees.
A curated tree earns its cost while every entry is a decision. It stops earning it when a section is mostly inventory — twenty pages where three must lead and the rest could be alphabetical — because then every new page is added twice, on disk and in the config, and the two drift.
navigation.fromDirectory()(fromleadtype/navigation) includes a directory without listing it, and the newpinoption on include entries keeps the pages whose position is a decision at the front:Pinned pages lead in the order given; the rest follow in
sortorder, so adding a page appends it to the tail and never displaces a deliberate choice. Explicit refs and an expansion can share onepagesarray. A pin matching nothing is an error rather than a silent no-op — that is almost always a rename the config missed. Expansion still happens once during navigation resolution, so one resolved tree keeps driving the sidebar,llms.txt,AGENTS.md, the sitemap, and Agent Readability metadata.leadtype navprints the tree your config actually resolves to and reports drift: pages no curated entry places, pages two entries both claim, and pages whosegroup:names a group the config never declares. Human and--jsonoutput, per collection, read-only — it never writes config, moves content, or changes a public route.8e3c431: Add
resolveProject()— one function for the whole config pipeline.Answering "what is this project?" takes five ordered steps: discover the config, apply source-owned inheritance, normalize to canonical names, derive what wasn't authored, and resolve each collection's content directory through the sync cache.
generate,doctor,nav, andcreateDocsProjecteach assembled those by hand, anddoctorandnavshipped with the same two bugs as a result — both skipped inheritance, and both resolved a remote collection'sdiragainst the config directory rather than its checkout.They now read one resolved project. It throws only for a malformed config; everything environmental — an unsynced source, a missing directory, unreadable source config — is a diagnostic carrying a stable id, the owning config field, and the command that fixes it. That split is what lets
doctorreport a problem and keep going whilecreateDocsProjectrefuses to hand a renderer a source it cannot read.createDocsProject()no longer needs a config passed to it: it discoversleadtype.config.*ordocs.config.*the same way the CLI does, so an app with a config file doesn't import it just to hand it back.Config loading also moves out of the CLI into
leadtype's config module, so the runtime no longer reaches through the generate pipeline to answer which config describes a project.Patch Changes
d517dc5: Make the generated docs-skill and the
leadtype initAGENTS.md pointer describe documentation authoring, not just retrieval. A skill's description is the whole activation signal a client sees before loading it, so "read and search the docs" lost the most common docs task there is — writing, editing, reviewing, and restructuring the pages themselves.f9d2185: Hash
paths.lock.jsonentries from authored source, not generated markdown.The lockfile exists to remember published paths so a later generate can detect renames. Fingerprinting the generated
.mdmirror folded ExtractedTypeTable rows, expanded includes, and converter formatting into every hash — so working on unrelated types, running generate in--watch, or even regenerating with a slightly different pipeline rewrote a committed lockfile. Hashes now come from the source.mdx/.mdbody when one exists (frontmatter still excluded). Pages with no authored source, such as generated OpenAPI reference pages, still hash the mirror.redirectFromis still read from the generated mirror, soafterFrontmattertransformers that add it keep working.The next generate after upgrading rewrites hashes once. Old and new hashes cannot match, so a rename in that same generate will fail as an unmatched disappearance instead of auto-redirecting. Upgrade and rename in two separate generates (two commits). After the first rewrite, authored pages only change the lockfile when their source body or the path set changes.
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.