Auto-author a changelog with AML
AML maintains its own SDK and CLI changelogs with the workflow in scripts/changelog.aml.tsx.
The workflow is two AML trees joined by one typed draft:
<Agent read-write> gather authoritative commits and investigate them <FollowUp>return DraftSchema</FollowUp></Agent> ↓ structured draft<Agent read-write> publish the draft <FollowUp>review, correct, and format</FollowUp></Agent>Author from repository evidence
Section titled “Author from repository evidence”The first Agent has repository access and begins with the exact deterministic evidence command:
const draft = await evaluate( <Agent provider={provider} permissions={{ filesystem: "read-write", network: false, shell: true }}> <System> You maintain AML's public changelog. Be factual, specific, and useful to readers. Never invent behavior, commits, versions, or documentation routes. Do not modify files while drafting. Treat a topmost `Next release` section as the authoritative editorial seed. </System> Author the next package changelog entry. Begin by running the supplied `release-notes.ts` command exactly as written, then inspect commits whose subjects do not explain their user impact. <FollowUp> Return the structured changelog draft with a title, overall summary, and reader-oriented highlights. </FollowUp> </Agent>, DraftSchema)The repository-owned script keeps commit selection deterministic. The Agent owns its invocation, investigation, and editorial judgment. <FollowUp /> keeps investigation and authoring in one provider-owned session, and its final response is validated by DraftSchema. A pre-authored Next release entry supplies the intended emphasis; repository evidence remains authoritative when a claim needs correction.
Keep one useful authoring schema
Section titled “Keep one useful authoring schema”const DraftSchema = z.object({ title: z.string().trim().min(1), summary: z.string().trim().min(1), highlights: z .array( z.object({ title: z.string().trim().min(1), details: z.string().trim().min(1), links: z.array( z.object({ label: z.string().trim().min(1), href: z.string().trim().startsWith("/docs/"), }) ), }) ) .min(1),})The schema defines the editorial handoff. It does not create a document parser or restrict Markdown inside the authored fields.
Publish and review in a second tree
Section titled “Publish and review in a second tree”The second Agent receives the structured draft and the exact target paths:
return ( <Agent provider={provider} permissions={{ filesystem: "read-write", network: false, shell: true }}> <System> Work only on the requested changelog. Preserve its frontmatter, introduction, existing entries, and newest-first ordering. Finalize one topmost `Next release` draft in place when the manifest has advanced. Do not change package versions, tags, or other files. </System> Publish the supplied draft for the current package version. <FollowUp> Review the entry against the draft, package version, authoritative commits, existing style, and MDX syntax. Correct issues, run Oxfmt, and inspect the final diff. </FollowUp> </Agent>)The publication Agent first checks the visible headings. An existing entry for the manifest’s exact version is an idempotent stop. Otherwise, one topmost Next release section is finalized in place; a duplicate or misplaced draft stops without an edit; only the absence of both a current-version entry and a draft permits a new entry at the insertion marker. Published entries remain ordinary MDX with visible version headings rather than hidden per-release delimiters.
Pre-author the next release
Section titled “Pre-author the next release”Maintainers can write the important release narrative before package versions move by placing exactly one draft at the top of the changelog:
## Next release — A reader-focused title
Next release.
Summarize the intended release.
### Breaking changes
- Explain migrations explicitly.
### Highlights
- Describe the new behavior.Commit the draft like any other documentation change. While the manifest still names the already-published version, the exact-version guard leaves this section untouched. After release-it bumps the package, the same workflow replaces the draft heading and status with the exact manifest version and release date, reconciles its contents and commit list against repository evidence, and verifies that it did not append a duplicate.
- The Agent runs
release-notes.tsto collect lane-specific commits from the latest matching tag. - The authoring Agent investigates the package and repository.
- Its
<FollowUp />returnsDraftSchema. - The publication Agent either finalizes the topmost
Next releaseentry in place, inserts a new entry, or stops under the duplicate guards. - Its
<FollowUp />preserves a stop decision or reviews, corrects, and formats the permitted edit.
Run manually or during release
Section titled “Run manually or during release”OPENCODE_API_KEY=... npm run changelog:sdkOPENCODE_API_KEY=... npm run changelog:cliThese are the same commands used by the release hooks, so running one manually exercises the real workflow. Review or discard the changelog diff afterward. If the manifest still has an existing changelog entry, the publication Agent stops without consuming a Next release draft. During a release, changelog authoring runs immediately after release-it changes the package version, so that draft can be finalized for the bumped version. A ten-minute deadline stops a stalled provider before release commit, tag, push, npm publication, or GitHub release.