Skip to content

The documentation is published as a skill an agent can install, and checked against the pages it was made from - #16

Merged
fabeat merged 6 commits into
mainfrom
feature/agent-skill
Oct 29, 2026
Merged

fabeat merged 6 commits into
mainfrom
feature/agent-skill

Conversation

@fabeat

@fabeat fabeat commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

An agent asked to turn Markdown into a Word document has to know four things: what the library can do, how to build a document with it, how to look at what it built, and how to use a design that already exists. None of that was addressed to an agent, and the two questions an agent gets wrong most often — does this text fit, and does this look right — are the two the documentation was worst at.

So the site publishes a skill.

What is published

/skills/mdword.zip the whole bundle, one file
/skills/mdword/ every file, fetchable
/skills/index.json the catalogue OpenCode reads over the network

OpenCode installs it with one line in opencode.json; everyone else unpacks it where their agent looks for one — ~/.agents/skills/ for Codex and OpenCode, a symlink for Claude Code and GitHub Copilot.

It is a copy, and the copy is made by the build

The reference files are the pages themselves with their frontmatter off, and each {% example %} block expanded into a named entry: the Markdown it was written as, the document it was built into, and the pictures of it. The examples are the site's own and the library's twenty-three. The scripts are the library's own, copied rather than rewritten.

It cannot say anything the site does not say, because it is made by the same build out of the same sources.

What holds it to that

tools/check-skill.php, which fails the build when:

  • a reference file is not the page it carries — the text of the page must be in it, and every example expanded exactly once;
  • a page of a section the bundle covers is not carried;
  • a file in the bundle is not named in the catalogue, or the catalogue names a file that is not there;
  • a path a reference file names does not exist;
  • the skill has no description, does not say when to use it, or does not point at a reference file it carries;
  • a script has drifted from the one the library ships;
  • a path the install page names does not resolve;
  • the library's README does not point at the skill page — the address read out of the site's own page, so a page that moves does not leave the README pointing at nothing.

The client the bundle carries

scripts/render.php talks to WordCraft or DeckCraft over a socket. It opens a document with one request that carries the path, and asks for the other application's method only when the first is refused as unknown — it used to find out whether a method existed by calling it with no parameters and throwing the answer away. It checks the id of the reply, because the protocol says a reply carries the id of the request it answers.

An application that speaks the protocol stands in for the real one in the tests, so both are held to: the client is asked what it says, and it is refused when the answer is to another question.

Also

A new page, /word/templates/: the site documented the frontmatter route to a Word template and not the other one — MarkdownTemplate with the styleIds of the template's own styles, which is how a company's Word design actually comes in. Six claims about it, each checked against the library that has to do it.

The site documented the frontmatter route to a Word template -- template_file:
and fields: -- and not the other one: MarkdownTemplate with the styleIds of the
template's own styles, which is how a company's Word design actually comes in.

So the page is new, and it says what the library makes of a template: the
control is matched on its tag rather than on its alias, a filled field is
unlinked, a template with no control takes the content at the end of its body
or refuses, and the result is a document whatever went in. Each is a claim, and
each is checked against the library that has to do it.

The templates in the tests are built rather than carried: a template is a .docx
with a content control in it and sometimes a MERGEFIELD, and both are a few
lines of XML. The control's alias says something else on purpose -- a library
that matched on the alias would not find it, and the content would go to the
end of the body instead of into the control.
An agent asked to turn Markdown into a Word document has to know four things:
what the library can do, how to build a document with it, how to *look* at what
it built, and how to use a design that already exists. None of that was
addressed to an agent, and the two questions an agent gets wrong most often --
does this text fit, and does this look right -- are the two the documentation
was worst at.

So the site publishes a skill: /skills/mdword.zip, and /skills/mdword/ file by
file, with /skills/index.json as the catalogue OpenCode reads over the network.
One line in opencode.json, and an agent has the documentation, the examples and
the render tools.

**It is built by the same build, out of the same sources**, so it cannot say
anything the site does not say. The reference files are the pages themselves
with their frontmatter off and each example expanded into a named entry -- the
Markdown it was written as, the document it was built into, and the pictures of
it. tools/check-skill.php is what holds it to that: a reference file that is
not the page it carries fails the build, a page added to a section the bundle
covers and not carried fails the build, and a script that has drifted from the
one the library ships fails the build.

The scripts are the library's own, copied rather than rewritten, and the Word
half's new render tools are among them: Word where it can be used, WordCraft
where Word cannot, LibreOffice last, and a run that falls back says so.
Thirty-one of them, and every one of them was a real thing:

- a dedicated exception rather than the generic one, in the checker's own words and in
  the script the bundle carries
- the literals that were written down three, four, five and seven times, named once
- the arguments read with a cursor rather than by moving the loop's own counter, which is
  a counter that is wrong once
- the slug's two anchored replacements rather than one alternation, which backtracks
- the archive made by a command at a fixed place rather than one the path decides
- the sort compared by name rather than by code unit, which is what it was for
- the copies read together and the files hashed in order, because the digest is of the
  bundle and not of the order the files happened to be read in
The slug's trailing dashes are taken off one at a time, which is enough because
the run of them has already collapsed into one -- and a regex that cannot
backtrack is a regex that cannot take the build down on a long title.

And the comparison the files are sorted by is a statement of its own rather than
a ternary inside a ternary.
@fabeat fabeat changed the title The documentation is published as a skill an agent can install The documentation is published as a skill an agent can install, and checked against the pages it was made from Oct 29, 2026
…the tool that renders a template

**The client no longer probes by calling.** It found out whether an application
knew file.open by sending file.open with no parameters and throwing the answer
away: a request that may do something, whose failure was discarded, and on
WordCraft a failure for the wrong reason -- a missing parameter rather than an
unknown command -- so the answer was "yes" by accident.

So the document is opened with one request that carries the path, and app.open
is asked for only when the first answer says the method is unknown, which is
the one failure that means "ask the other one".

**The id of the reply is checked.** The protocol says a reply carries the id of
the request it answers, and every request used to carry the same one, so a
reply to an earlier request could not be told from the answer to this one.

An application that speaks the protocol stands in for the real one in the
tests, so both are held to: the client is asked what it says, and it is
refused when the answer is to another question.

**The bundle carries the tool that turns a template into a document**, because
the AppleScript it carries calls it.
Nine of them, and every one was a real thing:

- a dedicated exception for the tests' own machinery, because a test whose stand-in
  did not start has failed for a reason of its own and not because of the code
  under test
- the flags the client takes, named once rather than written down four times
- the client's key finder named the way the house names things
@sonarqubecloud

Copy link
Copy Markdown

@fabeat
fabeat merged commit 39d40f0 into main Oct 29, 2026
3 checks passed
@fabeat
fabeat deleted the feature/agent-skill branch October 29, 2026 20:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant