Skip to content

Commit 4d0dfa8

Browse files
committed
fix(agent-skills): generatedAt tracks the source, not the clock
`build-agent-skills-index.ts` sorted its entries with the comment "Sort alphabetically for deterministic output" and then, two lines later, stamped `generatedAt: new Date().toISOString()`. So every build rewrote a committed file whose content was otherwise byte-identical, and left the working tree dirty. I reverted that one-line diff by hand twice today before looking at why it kept coming back. The timestamp was churn dressed as information: it recorded when the build ran, which no consumer of a `.well-known` index can act on, while each skill entry already carries a `sha256` that answers the question that actually matters. Now derived from the newest source `SKILL.md` mtime, so it changes when a skill changes and not otherwise. Kept the field rather than dropping it: the `$schema` URL the file advertises — https://agentskills.io/schemas/v0.2.0/index.json — currently returns 404, so I could not confirm whether `generatedAt` is required, and removing a field from a published document on a guess is worse than making it truthful. That dead schema URL is worth its own look; we are pointing consumers at a document that does not exist. Verified by running the generator twice: identical output both times, and the committed file now carries the source mtime (2026-04-19) instead of a build clock. Tree stays clean across builds.
1 parent 890a809 commit 4d0dfa8

2 files changed

Lines changed: 22 additions & 2 deletions

File tree

apps/landing/public/.well-known/agent-skills/index.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"$schema": "https://agentskills.io/schemas/v0.2.0/index.json",
3-
"generatedAt": "2026-08-03T08:14:00.478Z",
3+
"generatedAt": "2026-04-19T21:41:28.109Z",
44
"skills": [
55
{
66
"name": "better-i18n",

apps/landing/scripts/build-agent-skills-index.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ function main(): void {
119119

120120
ensureDir(OUTPUT_DIR);
121121
const skills: SkillIndexEntry[] = [];
122+
/* Newest source SKILL.md, for `generatedAt` — see the note at the index. */
123+
let newestSourceMs = 0;
122124

123125
for (const entry of readdirSync(SOURCE_DIR)) {
124126
const entryPath = path.join(SOURCE_DIR, entry);
@@ -132,6 +134,7 @@ function main(): void {
132134
}
133135

134136
const body = readFileSync(skillFile, "utf-8");
137+
newestSourceMs = Math.max(newestSourceMs, statSync(skillFile).mtimeMs);
135138
const { meta } = parseFrontmatter(body);
136139
const name = meta.name ?? entry;
137140
const description =
@@ -159,9 +162,26 @@ function main(): void {
159162
// Sort alphabetically for deterministic output
160163
skills.sort((a, b) => a.name.localeCompare(b.name));
161164

165+
/*
166+
* `generatedAt` tracks the SOURCE, not the clock.
167+
*
168+
* It was `new Date().toISOString()`, two lines under a sort whose comment
169+
* says "for deterministic output" — so every build rewrote this committed
170+
* file with a new timestamp and left the working tree dirty, on a file whose
171+
* content was otherwise byte-identical. That is churn masquerading as
172+
* information: it says when the build ran, which nobody consuming a
173+
* well-known index can use, while each skill already carries a `sha256` that
174+
* answers the question that matters ("has this changed?").
175+
*
176+
* Taking the newest source `SKILL.md` mtime keeps the field (its presence may
177+
* be load-bearing for a consumer — the `$schema` URL above currently 404s, so
178+
* I could not confirm whether it is required, and dropping a field from a
179+
* published document on a guess is worse than keeping it honest) while making
180+
* it change only when a skill actually changes. Same input, same output.
181+
*/
162182
const index = {
163183
$schema: "https://agentskills.io/schemas/v0.2.0/index.json",
164-
generatedAt: new Date().toISOString(),
184+
generatedAt: new Date(newestSourceMs).toISOString(),
165185
skills,
166186
};
167187
writeFileSync(

0 commit comments

Comments
 (0)