* fix(templates): open generated artifacts with a top-level heading
Generated proposal.md, design.md, spec.md and tasks.md started on a
section header, so every OpenSpec artifact tripped markdownlint MD041
("first line in a file should be a top-level heading") in editors that
run it. The files were also, literally, documents without a title.
Each packaged template now opens with `# Proposal`, `# Design`,
`# Spec Delta` or `# Tasks` followed by a blank line, and
`openspec schema init` scaffolds custom templates the same way. The
schema's own examples and the customization docs match.
Titles are inert to every reader downstream: the parsers anchor on `##`
and `###`, and archive builds a new main spec from the delta's sections,
so the main spec keeps its own generated `# <capability> Specification`
and only that one.
Closes#1138
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* test(templates): compare template headings on normalized line endings
The Windows runner checks out CRLF, so splitting the template on "\n"
left the blank second line as "\r" and the new guards failed there while
passing everywhere else. Normalize before splitting; verified against a
CRLF copy of the templates locally.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* test(templates): pin each template to its own title
Review feedback: the guards accepted any top-level heading, so a wrong
title would have passed, and the archive check counted `# ` lines only,
so a demoted `## Spec Delta` would have slipped through. Assert the exact
heading per artifact, the blank line under it in both guards, and that no
heading of any level named "Spec Delta" survives archive.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix(workflows): teach the artifact titles everywhere the shape is shown
The templates were only half the story. The onboarding walkthrough drafts
each artifact in the conversation and then saves what it drafted, so its
previews would have written untitled proposal.md, spec.md, design.md and
tasks.md whatever the template said. The sync workflow's delta format
reference had the same gap, sitting directly beneath a main-spec
reference that does carry a title. Both now show the template's title,
and `docs/opsx.md` no longer documents a `template` value the CLI never
returned.
Guards added:
- The template guard now enumerates every artifact of every packaged
schema from schema.yaml rather than a hardcoded list of four, and the
exact-title table must name every artifact the schema declares.
- A drift guard reads the titles out of the packaged templates and
requires the onboard and sync surfaces to show those same titles, so
guidance and template cannot part ways again.
- Parser tests pin the claim the fix rests on: a title is inert, and a
spec or proposal parses identically with and without one.
Regenerated the skill mirrors and parity hashes for the two workflows
touched; no other hash moved.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* docs: move the artifact-title update to the canonical docs-lab tree
The live site builds from docs-lab/, so the exact-format page there is the
one readers see. It still showed all four templates opening on a section
header and described the delta as starting with `## Purpose`.
- reference/schemas/spec-driven/index.md: each template block now matches
the shipped template byte for byte, and the quoted spec/tasks
instructions match schema.yaml again.
- customize/schemas.md: one line telling fork authors to keep the `#`
title on the first line.
Reverts the edits to docs/customization.md and docs/opsx.md: that tree is
no longer published and docs-lab/README.md keeps it as source material
only, so editing it would leave two versions of the same fact.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix(show): keep the change id as title for a bare `# Proposal` heading
The packaged proposal template now opens with `# Proposal`, which
`extractTitle` read as the change's title, so `show --json` and
`change list --json/--long` titled every templated change "Proposal"
instead of its id. Treat that bare heading as untitled.
Also re-quote the proposal and specs instructions in the canonical
docs-lab schema page after #1700 changed schema.yaml.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
* docs: rebuild docs site from docs-lab
Replace the docs site's source tree with docs-lab, a page-by-page rebuild
of the OpenSpec docs (40 pages: Start / Guides / Customize / Multi-repo /
Reference / Help).
- Point website/docs.sync.config.mjs at ../docs-lab and restructure the
sidebar into nested groups; sync script gains nested meta.json emission,
leading-quote descriptions, idempotent writes, and diagram asset copying
- Remove the marketing landing page; / now redirects to /docs
(meta-refresh page + Cloudflare _redirects)
- Add remark plugins (faq, file-steps, gfm-alert) and the FileSteps
component backing the new page formats
- Add install.md at the repo root, curled by docs-lab/start/installation.md
as an agent-executable install prompt
- Add the docs authoring skills (.agents/skills/{write,draft,verify}-
openspec-docs); docs-lab/README.md links into write-openspec-docs
The old docs/ tree is now unused by the site and left for a follow-up.
Claude-Session: https://claude.ai/code/session_01BMMLYNJQPKXx1QHpnDn4ho
* docs: hold back unwritten pages, add worksets, drop diagram drafts
- website: comment out Overview, Guides, Architecture, Help, Legacy in
docs.sync.config.mjs until those pages are written; temporary
/docs -> /docs/installation redirect (Cloudflare _redirects + static
export meta-refresh fallback in page.tsx)
- docs-lab: new multi-repo/worksets.md page, published under Multi-repo
- docs-lab: content revisions across start/, customize/, reference/,
help/, multi-repo/; add review notes (Notes.md)
- remove docs-lab/diagrams option-* drafts and their website copies
- write-openspec-docs skill: add spoken-flow sentence rule
* docs: address review on PR #1649
- sync-docs: read the existing output directly instead of exists-then-read
(CodeQL TOCTOU alert)
- hold back the headings-only Environment variables and Stores reference
pages until written; links to them fall back to their GitHub source
- sources.md: cutover keeps docs/ in place and points at public/_redirects
- setup.md: label the workflow tree as the default set plus two optional ones
* docs: two review nits (spoken-flow rule, XDG_DATA_HOME note)