v0.2.0
Added
- This changelog.
CONTRIBUTING.mdwith contribution and pull-request guidance.- README sections: Questions, bugs, and feature requests, How you can contribute, and Changelog.
- Modular architecture and design (a Core plus four feature modules) documented in
docs/architecture.md, theCONTEXT.mdglossary and architecture decision records underdocs/adr/. - The coding standard is now materialised in the repository under
agents.d/coding-standard/– one module per language axis (general, PHP, WordPress and Bash) plus a privatemanifest.jsonsnapshot – and loaded on demand rather than held in context every session. - On-demand agent guides under
agents.d/:writing-standard.md,releasing.mdandtesting.md, each linked from theAGENTS.mdReferences index. - Step 1.3 specification for Release 1 – the Markdown alternate – with concrete Core-slice and module contracts in
docs/spec/markdown-alternate.md. - Core foundation for Release 1: the
Moduleboot contract and theCoreservice facade; an artifact-provider registry with its identity, request, serve-pattern and link-relation value objects; a file-backed artifact cache and an early, hardened serve router that contains every request inside the cache directory (adversarially tested against path traversal, encoded traversal, null bytes and symlink escape); a zero-config settings registry over the singlekntnt_ai_visibilityoption; and a visitor-silent logger. - Markdown-alternate generation: the shared Page-Markdown service that renders a post through
the_content, converts the HTML to GitHub-Flavored Markdown (tables and strikethrough included) with relative URLs absolutised against the site, and assembles the YAML front-matter (title,canonical_url,date,author, and conditionalfeatured_image,categories,tags) followed by the page's visible H1 and body, with single-flight caching; plus the Markdown-alternate provider and its eligibility rule (single, public, published, front-end-viewable entries — including pages, posts and public custom post types — with the static-home/index.md), resolving the target viaurl_to_postid()with hierarchical-page and published-post-slug fallbacks so a.mdrequest still resolves when the rewrite has steered WordPress's main query to the front page. - Markdown-alternate serving and discovery: the request handler with strict content negotiation (
.mdURL >?format=markdown>Accept: text/markdown), the inline uncachedAcceptform carryingVary: Acceptand a steering alternate link,Content-Type/Content-Length/Last-Modified/ETagheaders with conditional304s, a403for password-protected content, a301for a trailing-slashed.mdURL, and canonical-redirect suppression; the per-page<link rel="alternate" type="text/markdown">discovery tag onwp_head; delete-on-change invalidation (per entry on save and status transition, whole-cache flush on theme switch and settings change) with a cache-version stamp; and a filterable TTL safety net on the serve router. - The Markdown-alternate module is now wired into the plugin: the
Pluginbootstrap builds the Core service graph and boots the module, and the early serve router runs from the main plugin file before WordPress routing — a cached.mdrequest is served straight from disk and the WordPress lifecycle skipped, while a miss falls through to lazy generation. - A content-type settings section on the plugin's settings page: a Core-owned capability matrix — one row per front-end-viewable post type with a checkbox column per artifact kind a module registers (the Markdown
.mdcolumn to begin with) — replacing the Markdown post-type text field, with the.mdselection mirrored by thekntnt_ai_visibility_eligible_post_typesfilter and defaulting to every viewable type, plus a Clear cache button beside it that flushes every cached file. - Release-2 specification for the llms.txt module – the singleton
llms.txtandllms-full.txtartifacts and the Core extensions they need (the content-type matrix, the markdown-alternate locator, the single-flight materialiser and the exact-path serve router) – indocs/spec/llms-txt.md. - A behavioural WordPress Playground end-to-end test (
tests/Integration/playground-e2e.sh) that boots a real Playground HTTP server with the plugin mounted and fixtures seeded, then drives the request lifecycle over HTTP — a real.md(200,text/markdown, front-matter, the converted and absolutised body),?format=markdown,Acceptnegotiation (Vary, the steering alternateLink),/index.md, a 404 for ineligible content, a 403 for password-protected content, a 301 for a trailing slash, and path-traversal payloads that never leak; and the llms singletons —/llms.txt(200,text/plain, the curated index with its sections and.mdlinks, no canonical orVary),/llms-full.txt(the concatenated Pages-only full text), the early-router cache hit with a stableETagand a conditional304,HEAD, the password-protected and draft content absent from both files, and traversal/evasion payloads against the singletons — wired intorun-tests.shand the CI e2e job alongside the boot smoke test. - The Playground e2e now also covers an invalidation round-trip — a mid-run content change (through a test-only mu-plugin endpoint) bumps the cache version, the rebuilt
/llms.txtreflects the change and the orphaned previous-version aggregate is pruned — and a second, separate boot under a/subsubdirectory (tests/Integration/playground-e2e-subdir.sh) that proves the per-page.mdand the llms singletons resolve home-relative and stay contained when WordPress lives under a path. - Subdirectory-install support: cache keys and request resolution are taken relative to the WordPress home (the serve router strips the same base path), so both per-page
.mdand the home/index.mdresolve and cache correctly when WordPress lives under a path such as/blog/, not only at the domain root. - The llms.txt module – two discoverable, machine-readable files for AI agents.
/llms.txtis a curated Markdown index: an H1 site name, the tagline, an intro line pointing at the full file, then one section per content type listing each page as a link to its.mdalternate followed by its excerpt (titles escaped so they cannot break the link, excerpts stripped and length-capped)./llms-full.txtis the site's selected pages concatenated as Markdown, assembled from the per-page.mdalternates and never re-rendered. Both are served astext/plain; charset=utf-8straight from the early cache router on a warm hit – which gains an exact-path match mode alongside the.mdsuffix match, with the same path-traversal hardening – and generated lazily on a miss; they are invalidated by a cache-version bump when a public post is published, edited, unpublished or trashed (so a page that leaves public view is dropped promptly), with the existing TTL as a safety net, and never include password-protected content. Which content types appear in each file is the In llms.txt and In llms-full.txt columns of the content-type matrix (every viewable type inllms.txt, Pages only inllms-full.txtby default), each mirrored by a developer filter (kntnt_ai_visibility_llms_post_types,…_llms_full_post_types), with per-entry, title, summary, intro, sections and whole-document filters for full customisation. - README section Serving cached Markdown directly documenting the optional web-server tier (nginx and Apache
try_filesexamples) that serves the cached.mdfiles straight from disk, bypassing PHP entirely, with a fall-through to WordPress on a miss; it also notes that/llms.txtand/llms-full.txtare early-served from the PHP cache but, because their cache filename carries a version stamp a static rule cannot resolve, are not eligible for that no-PHP static tier.
Changed
- The llms request handler now prunes the stale, version-stamped aggregate cache files that a cache-version bump orphans (for example
llms-txt/llms-v7.mdafter a bump to v8), instead of leaving them until the TTL safety net or a cache flush removes them; pruning is scoped to the one aggregate directory and contained within the cache base, so it never touches the per-page.mdcache. - Release tags are now
v-prefixed (vX.Y.Z) and the GitHub-release notes are taken from the matchingCHANGELOG.mdsection rather than GitHub's auto-generated digest (ADR-0011; ADR-0005 amended): the release workflow matchesv[0-9]+.[0-9]+.[0-9]+, strips thevfor the header-versus-tag check, andbuild-release-zip.sh --createpublishes the changelog section as the release body. - Activation now registers the
.mdand the/llms.txt//llms-full.txtrewrite rules and flushes them once; deactivation flushes the rewrite rules and clears the file cache while preserving the settings option; uninstall deletes thekntnt_ai_visibilityoption and the cache-version option and removes the file cache directory — replacing the scaffold's transient-based cleanup, since the cache is files under uploads rather than transients. - Documentation now follows British English via the
kntnt-text-skills:writing-rules en_GBstandard; the README uses spaced en-dashes ( – ) throughout. - Bumped
actions/checkoutandactions/setup-nodeto v5 (Node 24 runtime). AGENTS.mdslimmed to an always-loaded canon – authoritative ground rules, the non-obvious project facts and a References index – andCLAUDE.mdreduced to a single@AGENTS.mdbridge, cutting the always-loaded agent context by about 95 %.README.mdandCONTRIBUTING.mdnow point atagents.d/coding-standard/for the coding standard and describe the agent-context files accurately.
Removed
docs/coding-standards.md– the monolithic coding standard, superseded by the on-demand modules underagents.d/coding-standard/.
Full changelog: https://github.com/Kntnt/kntnt-ai-visibility/blob/v0.2.0/CHANGELOG.md