docs: add an AI policy and agent instructions - #5377
Conversation
…correct two claims
There was a problem hiding this comment.
Pull request overview
This PR adds contributor-facing guidance and GitHub Copilot cloud-agent configuration so AI-assisted contributions follow project expectations and Copilot sessions start with a working, reproducible ReSpec toolchain.
Changes:
- Add an
AI_POLICY.mdand link to it fromREADME.mdandCONTRIBUTING.md. - Add Copilot agent instructions in
.github/copilot-instructions.mddescribing build/test and project conventions. - Add a Copilot setup workflow to preinstall dependencies/builds and validate puppeteer availability, plus ignore the local puppeteer cache directory.
Reviewed changes
Copilot reviewed 5 out of 7 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| README.md | Adds a pointer to the new AI policy for prospective AI-assisted contributors. |
| CONTRIBUTING.md | Updates contributor guidance to include AI policy and adds an illustrative image. |
| AI_POLICY.md | Introduces the project’s AI contribution policy and maintainer standards. |
| .gitignore | Ignores the repo-local puppeteer cache directory used by Copilot setup. |
| .github/workflows/copilot-setup-steps.yml | Adds Copilot setup steps to install deps, build bundles, and validate puppeteer browser availability. |
| .github/copilot-instructions.md | Documents how Copilot should build/test and follow house style in this repo. |
Suppressed comments (1)
.github/workflows/copilot-setup-steps.yml:49
- The puppeteer browser check should run with the same
PUPPETEER_CACHE_DIRas the install step; otherwise it may validate a different cache location than the one the agent will rely on (and if Copilot ignores job-levelenv, this step won't see it either). Set the cache dir explicitly on this step.
# Fails the setup loudly if puppeteer has no usable browser, rather than
# leaving the agent to discover it mid-task.
- name: Check puppeteer has a browser
run: |
node -e "
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 7 changed files in this pull request and generated no new comments.
Suppressed comments (1)
AI_POLICY.md:32
- This sentence is missing a verb (“If AI generated logic…”), which makes it ungrammatical and harder to understand. Consider rephrasing to include the missing verb and (optionally) hyphenating “AI-generated”.
If AI generated logic in your contribution, say so in the pull request
description. Generated logic means an agent, a function, an algorithm, a test, a
feature: something you would otherwise have had to work out.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 8 changed files in this pull request and generated 1 comment.
Suppressed comments (2)
AI_POLICY.md:6
- The image alt text is extremely detailed and includes non-essential scene description. For accessibility, alt text should focus on what matters to a reader (the "AI is welcome here" message) and stay concise.
<img src="assets/ai-is-welcome-here.png" alt="A cheerful pixel-art robot smiling straight at the camera while a forest burns orange behind it. The caption reads "AI is welcome here."" width="320">
CONTRIBUTING.md:1
- The image alt text is very long and includes incidental background detail. For accessibility, consider using concise alt text that conveys the purpose/message of the image.
<img src="assets/ai-is-welcome-here.png" alt="A cheerful pixel-art robot smiling straight at the camera while a forest burns orange behind it. The caption reads "AI is welcome here."" width="220" align="right">
|
Also acted on the two suppressed comments, since both were right. The puppeteer check step now sets And Two things running it afterwards found that the review could not have predicted. Putting the browser inside the workspace means eslint walks it, producing 12 errors from Chrome's own bundled scripts, including The other is that the workspace cache is about 340 MB and is not shared between checkouts. That is the right trade for an ephemeral agent environment, but wrong for a human with several worktrees, so the instructions now say to skip the export if you already have a browser in puppeteer's default cache. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 8 changed files in this pull request and generated no new comments.
Suppressed comments (1)
.github/workflows/copilot-setup-steps.yml:64
puppeteeris ESM-only in v25+, sorequire('puppeteer')in thenode -echeck will throw and make the setup fail even when the browser is installed. Use a dynamicimport('puppeteer')instead.
Promise.resolve(require('puppeteer').executablePath())
Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 8 changed files in this pull request and generated no new comments.
Suppressed comments (1)
.github/copilot-instructions.md:96
- This bullet summary contradicts AI_POLICY.md: AI_POLICY says a
Co-Authored-Bytrailer naming the model is welcome, but these instructions say to never add one. Since this section explicitly points to AI_POLICY as the source of truth, the summary here should match it (or drop the conflicting guidance).
- Commit messages are one imperative subject line, lowercase after any prefix, no
trailing period, and no body unless the diff cannot be understood without one.
Never add `Co-Authored-By` for a model.
Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 9 changed files in this pull request and generated no new comments.
Suppressed comments (2)
AI_POLICY.md:78
- The commit-message guidance here says a
Co-Authored-Bytrailer naming the model is welcome, but .github/copilot-instructions.md later says "Never addCo-Authored-Byfor a model." Having both rules in-repo is contradictory and will confuse contributors/agents about the expected house style. Consider aligning the policy with the Copilot instructions (or vice-versa) so there is a single rule.
**The commit message** is one imperative subject line, lowercase after any
prefix, no trailing period. A body only when the diff genuinely cannot be
understood without one, and then a sentence or two. No bullet lists, no
"Summary", no recap of what the diff already shows. A `Co-Authored-By` trailer
naming the model that wrote it is welcome, and consistent with what already
appears in this project's history.
.github/workflows/copilot-setup-steps.yml:70
- The catch handler assumes the rejection reason has a
.messageproperty. If the promise rejects with a non-Error (string, null, etc.), this will throw inside the catch, making the failure output less reliable. Coerce the error to a string (or narrow to Error) before logging so this step always fails loudly with a useful message.
import('puppeteer')
.then(p => p.default.executablePath())
.then(p => { fs.accessSync(p); console.log('browser ok:', p); })
.catch(e => { console.error('no usable browser:', e.message); process.exit(1); })
Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 9 changed files in this pull request and generated no new comments.
Suppressed comments (1)
AI_POLICY.md:78
- AI_POLICY.md says a
Co-Authored-Bytrailer naming the model is welcome, but .github/copilot-instructions.md explicitly says to never addCo-Authored-Byfor a model. These docs should be consistent so contributors (and agents) don’t get conflicting guidance.
"Summary", no recap of what the diff already shows. A `Co-Authored-By` trailer
naming the model that wrote it is welcome, and consistent with what already
appears in this project's history.
Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 9 changed files in this pull request and generated no new comments.
Suppressed comments (3)
CLAUDE.md:33
- The Key modules table row includes an inline example
` | var | `containing pipe characters. In GitHub Flavored Markdown tables,|inside a cell can be parsed as a column separator, which can break the table rendering. Use escaping or raw HTML to render the pipes literally inside the cell.
| `src/core/inlines.js` | All inline shorthand syntax: `[= =]`, `{{ }}`, `[[SPEC]]`, `[[[...]]]`, ` | var | ` |
.github/workflows/copilot-setup-steps.yml:69
- The puppeteer probe logs
e.message, but the caught value is not guaranteed to be an Error. If it’s a string or another value,e.messagewill be undefined and the workflow will emit an unhelpful error. Normalize the message before logging so failures are always actionable.
.catch(e => { console.error('no usable browser:', e.message); process.exit(1); })
.github/copilot-instructions.md:96
- This guidance on commit messages contradicts AI_POLICY.md: the policy says a
Co-Authored-Bytrailer naming the model is welcome, but these agent instructions say to never add it. Since this file points readers to AI_POLICY.md as the source of house style, these should be consistent to avoid confusing contributors/agents.
- Commit messages are one imperative subject line, lowercase after any prefix, no
trailing period, and no body unless the diff cannot be understood without one.
Never add `Co-Authored-By` for a model.
| need that line, and you should skip it: the workspace copy is around 340 MB and does | ||
| not get shared between checkouts. | ||
|
|
||
| Karma reads the bundles in `builds/`, not `src/`. A source change has no effect on |
There was a problem hiding this comment.
Note: Except for unit tests - which use src directly. Faster flow.
| spelling alone when it is load-bearing, such as an established identifier or a | ||
| verbatim quotation. | ||
|
|
||
| Run `npx prettier --write` on changed files. CI fails on unformatted code. |
| the first line. | ||
| - `Closes #N` only when every ask in the issue is delivered, otherwise `Refs #N`. | ||
| Confirm the number is an issue and not a pull request before citing it. | ||
| - Commit messages are one imperative subject line, lowercase after any prefix, no |
There was a problem hiding this comment.
Also mention the pull request title format.
|
|
||
| ## Adding a module | ||
|
|
||
| A new module under `src/core/` exports `name` and a `run(conf)`. `run` may be |
There was a problem hiding this comment.
If a module is meant for only certain profile, add to profile folder instead of core.
Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 9 changed files in this pull request and generated no new comments.
Suppressed comments (1)
.github/workflows/copilot-setup-steps.yml:69
- The puppeteer probe logs
e.messagewithout ensuring the rejection value is anError. If a non-Error is thrown/rejected, this will printundefined(or itself throw ifeis nullish), making the setup failure harder to diagnose. Coerce to a string (or narrow withinstanceof Error) before logging.
.catch(e => { console.error('no usable browser:', e.message); process.exit(1); })
|
|
||
| Build, test, code style, and the house style for pull requests, commits and comments live in the file below, shared with other agents rather than duplicated: | ||
|
|
||
| @.github/copilot-instructions.md |
There was a problem hiding this comment.
This can be too much in context. Claude might not even read the full file.
| @@ -1,3 +1,7 @@ | |||
| Everyone is welcome to contribute. | |||
| <img src="assets/ai-is-welcome-here.png" alt="Pixel-art robot grinning in front of a burning forest, captioned "AI is welcome here."" width="220" align="right"> | |||
There was a problem hiding this comment.
Let's not add this image here. It's enough in AI Policy.
| errorFilters, | ||
| warningFilters, | ||
| } from "../SpecHelper.js"; | ||
| const errors = errorFilters.filter("module/name"); |
There was a problem hiding this comment.
const pluginErrors = errorFilters.filter("module/name");
// ...
const errors = pluginErrors(doc);|
|
||
| Almost always caused by the branch being behind main. Fix: | ||
|
|
||
| 1. `git rebase main` (resolve conflicts — for `builds/` files, always take `--ours`) |
There was a problem hiding this comment.
Maybe suggest reject any changes to builds/ and build again, instead of trying to rebase (consumes less tokens, is faster).
| Almost always caused by the branch being behind main. Fix: | ||
|
|
||
| 1. `git rebase main` (resolve conflicts — for `builds/` files, always take `--ours`) | ||
| 2. `git diff main --name-only | xargs npx prettier --write` |
There was a problem hiding this comment.
| 2. `git diff main --name-only | xargs npx prettier --write` | |
| 2. `git diff main --name-only | xargs pnpm format --write` |
|
|
||
| Do NOT commit `builds/` files — CI rebuilds them. On rebase conflicts in build artifacts, take main's version. | ||
|
|
||
| ## Pre-PR checklist (learned from Copilot reviews) |
There was a problem hiding this comment.
| ## Pre-PR checklist (learned from Copilot reviews) | |
| ## Pre-PR checklist |
|
|
||
| Do NOT commit `builds/` files — CI rebuilds them. On rebase conflicts in build artifacts, take main's version. | ||
|
|
||
| ## Pre-PR checklist (learned from Copilot reviews) |
There was a problem hiding this comment.
Perhaps don't recommend automatic pushes (keep in CLAUDE.local.md). This will encourage will be send PRs manually, which reduces spam/low quality chances.
| ## Cross-spec headings API | ||
|
|
||
| `POST /xref/headings` on respec.org looks up section heading text by `{spec, id}`, sourced from w3c/webref `ed/headings/`. This is what lets `[[[SPEC#id]]]` render the actual heading rather than just the spec title. |
There was a problem hiding this comment.
This is more of spec writing, then ReSpec.
Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Copilot <noreply@github.com>
Adds an AI policy, and the two files GitHub documents for telling a coding agent how this project works.
The policy asks for disclosure, one concern per pull request, an honest accounting of what an issue asked for, and that a test offered as proof of a fix can actually fail without it. It also says what the maintainers hold themselves to when we generate work ourselves, which is stricter than what we ask of anyone else, and it asks nothing of contributors beyond one model and their own judgment.
CONTRIBUTING.mdpoints at it, since that is the file an agent reads first..github/copilot-instructions.mdcarries the things an agent cannot infer: that karma loads bundles frombuilds/and there is one per profile, so a source change does nothing until it is rebuilt, and thatBROWSERSmust be set or the suite hangs after printingSTART:with nothing explaining why..github/workflows/copilot-setup-steps.ymlpre-installs dependencies and keeps puppeteer's browser inside the workspace, since the default cache location is not guaranteed to survive into the agent's session.Reviewed by Gemini and Copilot as well as by hand. Between them they found a contradiction between two sections of the policy, a labeling rule that required triage access most contributors do not have, a missing privacy rule, and the hang above, which was the worst of them.
Written with AI: Claude drafted the policy and the two configuration files, Gemini and Copilot reviewed them, and I read and ran everything before pushing. Per AI_POLICY.md.