Commit Graph

26 Commits

Author SHA1 Message Date
Clay Good e4e112d94f chore(deps): declare pnpm overrides only in pnpm-workspace.yaml (#1816)
The security overrides were declared twice: in pnpm-workspace.yaml, with
the advisory comments explaining each pin, and again under
package.json's pnpm.overrides. The copies are not additive — pnpm 10
uses package.json's block instead of the workspace list when both are
present — and Dependabot rewrites plain-name entries in package.json
whenever it bumps the same package. So a routine bump silently
displaces the pins that patch advisories, and fails the equality test
that guards them (#1812).

Keeps one declaration, in the file that carries the reasoning, and
asserts the mirror stays gone.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-09-09 17:47:22 +00:00
Clay Good 0b60a0ac1f chore(deps): bump the website-dependencies group in /website with 5 updates (#1815)
Applies dependabot's website bumps (#1812) and syncs the postcss
override in website/pnpm-workspace.yaml, which dependabot does not know
about, keeping the three override declarations in agreement.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-09-09 16:24:41 +00:00
Clay Good 9ec0a090b8 fix(security): patch fast-uri advisories (#1768) 2026-09-02 22:50:29 +00:00
dependabot[bot] 9dfffd87b3 chore(deps): bump the website-dependencies group across 1 directory with 7 updates (#1765)
* chore(deps): bump the website-dependencies group across 1 directory with 7 updates

Bumps the website-dependencies group with 7 updates in the /website directory:

| Package | From | To |
| --- | --- | --- |
| [fumadocs-core](https://github.com/fuma-nama/fumadocs) | `16.14.5` | `16.15.2` |
| [fumadocs-mdx](https://github.com/fuma-nama/fumadocs) | `15.2.3` | `15.3.1` |
| [fumadocs-ui](https://github.com/fuma-nama/fumadocs) | `16.14.5` | `16.15.2` |
| [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) | `1.31.0` | `1.34.0` |
| [next](https://github.com/vercel/next.js) | `16.3.1` | `16.3.3` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `26.2.0` | `26.3.0` |
| [@types/react-dom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-dom) | `19.2.4` | `19.2.5` |



Updates `fumadocs-core` from 16.14.5 to 16.15.2
- [Release notes](https://github.com/fuma-nama/fumadocs/releases)
- [Commits](https://github.com/fuma-nama/fumadocs/compare/fumadocs@16.14.5...fumadocs@16.15.2)

Updates `fumadocs-mdx` from 15.2.3 to 15.3.1
- [Release notes](https://github.com/fuma-nama/fumadocs/releases)
- [Commits](https://github.com/fuma-nama/fumadocs/compare/fumadocs-mdx@15.2.3...fumadocs-mdx@15.3.1)

Updates `fumadocs-ui` from 16.14.5 to 16.15.2
- [Release notes](https://github.com/fuma-nama/fumadocs/releases)
- [Commits](https://github.com/fuma-nama/fumadocs/compare/fumadocs@16.14.5...fumadocs@16.15.2)

Updates `lucide-react` from 1.31.0 to 1.34.0
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/1.34.0/packages/lucide-react)

Updates `next` from 16.3.1 to 16.3.3
- [Release notes](https://github.com/vercel/next.js/releases)
- [Commits](https://github.com/vercel/next.js/compare/v16.3.1...v16.3.3)

Updates `@types/node` from 26.2.0 to 26.3.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@types/react-dom` from 19.2.4 to 19.2.5
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react-dom)

---
updated-dependencies:
- dependency-name: fumadocs-core
  dependency-version: 16.15.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: website-dependencies
- dependency-name: fumadocs-mdx
  dependency-version: 15.3.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: website-dependencies
- dependency-name: fumadocs-ui
  dependency-version: 16.15.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: website-dependencies
- dependency-name: lucide-react
  dependency-version: 1.34.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: website-dependencies
- dependency-name: next
  dependency-version: 16.3.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: website-dependencies
- dependency-name: "@types/node"
  dependency-version: 26.3.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: website-dependencies
- dependency-name: "@types/react-dom"
  dependency-version: 19.2.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: website-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix(website): align esbuild build approval

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Clay Good <hi@claygood.com>
2026-09-02 22:22:14 +00:00
Jason Hindley 142b8a9203 fix(docs): route OpenSpec pixel through Pages (#1757)
* Route /openspec-pixel.svg to the docs Pages deployment

The docs nav logo is referenced via the root-relative path
/openspec-pixel.svg, which isn't matched by isDocsRoute() and so falls
through to the Astro landing site instead of the docs Pages project
that actually has the asset - a 404. /icon.svg already has this exact
special case; this adds the same for the pixel logo.

Fixes #1756

* fix(docs): route pixel logo through worker

---------

Co-authored-by: Clay Good <hi@claygood.com>
2026-09-02 19:31:59 +00:00
dependabot[bot] 6926ccb18a chore(deps): bump the website-dependencies group (#1719)
Bumps the website-dependencies group in /website with 2 updates: [fumadocs-core](https://github.com/fuma-nama/fumadocs) and [fumadocs-ui](https://github.com/fuma-nama/fumadocs).


Updates `fumadocs-core` from 16.14.4 to 16.14.5
- [Release notes](https://github.com/fuma-nama/fumadocs/releases)
- [Commits](https://github.com/fuma-nama/fumadocs/compare/fumadocs@16.14.4...fumadocs@16.14.5)

Updates `fumadocs-ui` from 16.14.4 to 16.14.5
- [Release notes](https://github.com/fuma-nama/fumadocs/releases)
- [Commits](https://github.com/fuma-nama/fumadocs/compare/fumadocs@16.14.4...fumadocs@16.14.5)

---
updated-dependencies:
- dependency-name: fumadocs-core
  dependency-version: 16.14.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: website-dependencies
- dependency-name: fumadocs-ui
  dependency-version: 16.14.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: website-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-24 14:00:04 +00:00
Tabish Bidiwale f1b521dffa docs: rebuild docs site from docs-lab (#1649)
* 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)
2026-08-21 20:45:19 +00:00
dependabot[bot] cfc74eeb05 chore(deps): bump the website-dependencies group (#1680)
Bumps the website-dependencies group in /website with 4 updates: [fumadocs-core](https://github.com/fuma-nama/fumadocs), [fumadocs-ui](https://github.com/fuma-nama/fumadocs), [next](https://github.com/vercel/next.js) and [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node).


Updates `fumadocs-core` from 16.14.0 to 16.14.4
- [Release notes](https://github.com/fuma-nama/fumadocs/releases)
- [Commits](https://github.com/fuma-nama/fumadocs/compare/fumadocs@16.14.0...fumadocs@16.14.4)

Updates `fumadocs-ui` from 16.14.0 to 16.14.4
- [Release notes](https://github.com/fuma-nama/fumadocs/releases)
- [Commits](https://github.com/fuma-nama/fumadocs/compare/fumadocs@16.14.0...fumadocs@16.14.4)

Updates `next` from 16.3.0 to 16.3.1
- [Release notes](https://github.com/vercel/next.js/releases)
- [Commits](https://github.com/vercel/next.js/compare/v16.3.0...v16.3.1)

Updates `@types/node` from 26.1.2 to 26.2.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: fumadocs-core
  dependency-version: 16.14.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: website-dependencies
- dependency-name: fumadocs-ui
  dependency-version: 16.14.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: website-dependencies
- dependency-name: next
  dependency-version: 16.3.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: website-dependencies
- dependency-name: "@types/node"
  dependency-version: 26.2.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: website-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-19 18:39:20 +00:00
dependabot[bot] 6d031f12f7 chore(deps): bump the website-dependencies group in /website with 2 updates (#1636)
* chore(deps): bump the website-dependencies group

Bumps the website-dependencies group in /website with 2 updates: [fumadocs-core](https://github.com/fuma-nama/fumadocs) and [fumadocs-ui](https://github.com/fuma-nama/fumadocs).


Updates `fumadocs-core` from 16.12.1 to 16.14.0
- [Release notes](https://github.com/fuma-nama/fumadocs/releases)
- [Commits](https://github.com/fuma-nama/fumadocs/compare/fumadocs@16.12.1...fumadocs@16.14.0)

Updates `fumadocs-ui` from 16.12.1 to 16.14.0
- [Release notes](https://github.com/fuma-nama/fumadocs/releases)
- [Commits](https://github.com/fuma-nama/fumadocs/compare/fumadocs@16.12.1...fumadocs@16.14.0)

---
updated-dependencies:
- dependency-name: fumadocs-core
  dependency-version: 16.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: website-dependencies
- dependency-name: fumadocs-ui
  dependency-version: 16.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: website-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix(website): migrate search to ZBSearch for fumadocs 16.14

fumadocs 16.14.0 replaced the Orama search engine with ZBSearch, which
broke the custom static search dialog's type-check (Orama instance no
longer assignable to the ZBSearch client) and failed the Cloudflare
Pages build.

Switch components/search.tsx to the new `staticClient` API and drop the
now-optional client-side DB init — ZBSearch restores the tokenizer from
the exported static data. Remove the direct `@orama/orama` dependency,
which is no longer imported anywhere.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Clay Good <hi@claygood.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-12 00:08:05 +00:00
Clay Good 3281f1f068 fix(deps): patch js-yaml and nanoid advisories via pnpm overrides (#1635)
Resolve all three open Dependabot alerts (all high severity):

- GHSA-5p4m-2wfm-xmqj — js-yaml quadratic-CPU !!omap DoS (#96, #97).
  Root tree carried js-yaml 3.15.0 (via read-yaml-file) and 4.3.0 (via
  @changesets/parse). Dev-only; never in the published CLI, which uses
  `yaml`, not `js-yaml`. Pinned to >=3.15.1 / >=4.3.1.
- GHSA-2v37-7h3g-55p8 / CVE-2026-67213 — nanoid size=0 infinite loop (#99).
  Present in both root (dev, via postcss<-vitest) and website (build-time,
  via postcss<-next) trees. Pinned to >=3.3.17 (resolves to 3.3.18).

Overrides added to all four override surfaces (pnpm-workspace.yaml +
package.json, root and website) to keep them in sync, each YAML entry
annotated with its advisory id and removal condition.

flake.nix pnpmDeps FOD hash regenerated for the root lockfile change
(verified via nix build; hash-mismatch-count 0). dependabot.yml gains a
note documenting the two surfaces Dependabot cannot manage (pnpm
overrides + the Nix flake).

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-11 23:12:15 +00:00
Clay Good b96b3e85cd chore(deps): bump safe website-dependencies subset (#1634)
* chore(deps): bump safe website-dependencies subset (defer fumadocs 16.14 / ZBSearch migration)

Ships the non-breaking bumps from dependabot PR #1631, holding back the
fumadocs 16.14 major that requires a website source migration.

Bumped:
- fumadocs-mdx  ^15.2.1 -> ^15.2.2 (resolves 15.2.3; builds cleanly)
- lucide-react  ^1.27.0 -> ^1.28.0 (resolves 1.31.0)
- next          16.2.12 -> 16.3.0
- postcss       ^8.5.25 -> ^8.5.26 (override ^8.5.22 governs resolution)

Held (defer to a dedicated migration PR):
- fumadocs-core ^16.12.1 (16.14 replaces Orama with ZBSearch)
- fumadocs-ui   ^16.12.1 (pairs with core)

fumadocs-mdx 15.2.3 does NOT pull core 16.14 transitively; type-check
and next build both pass. esbuild stays 0.28.1, so allowBuilds is
unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore(deps): apply the postcss bump for real (align override + lock to 8.5.26)

The manifest declared postcss ^8.5.26 but the pnpm override stayed ^8.5.22,
so the importer resolved 8.5.25 and the declared bump had no effect. Raise
the override (website/pnpm-workspace.yaml + website/package.json pnpm.overrides)
to ^8.5.26 and re-lock so postcss resolves 8.5.26 everywhere.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-11 23:12:11 +00:00
Ismet Togay 3e50944fb0 fix(build): allow esbuild install scripts (#1196)
* Add pnpm-workspace.yaml to allow esbuild build scripts

pnpm 10+ blocks all dependency build scripts by default unless explicitly
approved via allowBuilds or onlyBuiltDependencies in pnpm-workspace.yaml.

esbuild (transitive dependency of vitest -> vite) has a postinstall script
that downloads a platform-specific native binary. Without this config,
pnpm install exits non-zero with [ERR_PNPM_IGNORED_BUILDS], breaking any
downstream packaging (AUR, Nix, Docker) or local setup using pnpm >=10.

Refs: #1195

* fix(build): declare pnpm workspace root

* fix(build): harden pnpm workspace policies

---------

Co-authored-by: Clay Good <hi@claygood.com>
2026-08-05 00:18:37 +00:00
Clay Good 02b124e6b6 fix(security): patch fast-uri, postcss, and brace-expansion advisories (#1510)
* fix(security): patch fast-uri, postcss, and brace-expansion advisories

Resolve the two open Dependabot alerts plus a third high-severity advisory
the repo's own audit surfaces but Dependabot had not filed, all via
version-ranged pnpm overrides (they lapse once the upstream tree moves past
them):

- fast-uri 3.1.4 -> 3.1.5 (website): GHSA-7p8r-x3mc-p8w7, high. Host
  confusion via backslash authority introducer. Pulled in transitively by
  ajv@8.18.0; bounded to ^3.1.5 so it stays on the 3.x line ajv expects.
- postcss 8.5.22 -> 8.5.25 (root): GHSA-fxqj-rqcc-2cmp, moderate. Arbitrary
  .map file read via attacker-controlled sourceMappingURL. Pulled in by
  vite (dev/test tooling).
- brace-expansion 5.0.8 -> 5.0.9 (website): GHSA-rgw5-rvv9-x895, high. DoS
  via unbounded recursion. The existing override capped at >=5.0.8, and
  5.0.8 is itself vulnerable under this newer advisory; the root already
  resolved to 5.0.9.

Root and website audits are clean at --audit-level high (and any-severity
for the website). Full test suite: 3662 passing.

* harden(security): bound overrides, scope release perms, add website lockfile drift check, document archive TOCTOU intent

Hardening pass over the security fixes, from a parallel review of the
dependency, CI, archive, and adjacent-code surfaces. Each item is low-risk
and verified; resolved dependency versions are unchanged.

- deps: bound the three security overrides to their current major
  (brace-expansion ">=5.0.9 <6", postcss ">=8.5.23 <9"). A bare ">=X" pin
  would take a future major on the next lockfile regen without review; the
  website already models the caret-bounded idiom.
- ci: scope release-prepare.yml permissions per job. The top-level block
  dropped "pull-requests: write"; only the "prepare" job (which opens the
  Version Packages PR) now holds it. The "beta" job only tags/releases and
  publishes via OIDC, so it inherits the narrower default (least privilege).
- ci: add a "Website Lockfile Drift" job to security.yml. The website keeps
  its own lockfile and is never installed in CI, so a website override that
  stops resolving would go unnoticed and `pnpm audit` would scan a stale
  graph. A `pnpm install --frozen-lockfile --ignore-scripts --dir website`
  fails fast on that drift (root drift is already caught in ci.yml).
- archive: add intent comments at the 7 js/file-system-race sites in
  src/core/archive.ts. The stat->read->re-stat pattern is a deliberate
  concurrent-change detector; the comments record why, so no future refactor
  (human or scanner-driven) collapses it to fd I/O and blinds the guard.

Verified: 3662 tests pass, build clean, website build clean, root+website
audits clean at --audit-level high, and the new frozen-lockfile check passes
locally.

* chore(nix): refresh pnpmDeps hash for the lockfile change

The root pnpm-lock.yaml changed (postcss + brace-expansion overrides), which
stales the fixed-output pnpmDeps hash and fails Nix Flake Validation. Repin to
the value CI computed from the new lockfile.
2026-08-04 22:52:40 +00:00
Clay Good 4e4c9e1ffd docs(workflows): visualize the OpenSpec lifecycle (#1507)
* docs(workflows): add lifecycle diagrams

* docs(workflows): clarify optional archive paths

* docs(workflows): correct lifecycle diagrams

* docs(website): render Mermaid diagrams

* fix(website): preserve Mermaid label text
2026-08-04 18:09:08 +00:00
dependabot[bot] 80ad1fbaef chore(deps): bump the website-dependencies group (#1496)
Bumps the website-dependencies group in /website with 9 updates:

| Package | From | To |
| --- | --- | --- |
| [fumadocs-core](https://github.com/fuma-nama/fumadocs) | `16.11.5` | `16.12.1` |
| [fumadocs-mdx](https://github.com/fuma-nama/fumadocs) | `15.2.0` | `15.2.1` |
| [fumadocs-ui](https://github.com/fuma-nama/fumadocs) | `16.11.5` | `16.12.1` |
| [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) | `1.25.0` | `1.27.0` |
| [next](https://github.com/vercel/next.js) | `16.2.11` | `16.2.12` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `26.1.1` | `26.1.2` |
| [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) | `19.2.17` | `19.2.18` |
| [@types/react-dom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-dom) | `19.2.3` | `19.2.4` |
| [postcss](https://github.com/postcss/postcss) | `8.5.22` | `8.5.25` |


Updates `fumadocs-core` from 16.11.5 to 16.12.1
- [Release notes](https://github.com/fuma-nama/fumadocs/releases)
- [Commits](https://github.com/fuma-nama/fumadocs/compare/fumadocs@16.11.5...fumadocs@16.12.1)

Updates `fumadocs-mdx` from 15.2.0 to 15.2.1
- [Release notes](https://github.com/fuma-nama/fumadocs/releases)
- [Commits](https://github.com/fuma-nama/fumadocs/compare/fumadocs-mdx@15.2.0...fumadocs-mdx@15.2.1)

Updates `fumadocs-ui` from 16.11.5 to 16.12.1
- [Release notes](https://github.com/fuma-nama/fumadocs/releases)
- [Commits](https://github.com/fuma-nama/fumadocs/compare/fumadocs@16.11.5...fumadocs@16.12.1)

Updates `lucide-react` from 1.25.0 to 1.27.0
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/1.27.0/packages/lucide-react)

Updates `next` from 16.2.11 to 16.2.12
- [Release notes](https://github.com/vercel/next.js/releases)
- [Commits](https://github.com/vercel/next.js/compare/v16.2.11...v16.2.12)

Updates `@types/node` from 26.1.1 to 26.1.2
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@types/react` from 19.2.17 to 19.2.18
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

Updates `@types/react-dom` from 19.2.3 to 19.2.4
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react-dom)

Updates `postcss` from 8.5.22 to 8.5.25
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.5.22...8.5.25)

---
updated-dependencies:
- dependency-name: fumadocs-core
  dependency-version: 16.12.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: website-dependencies
- dependency-name: fumadocs-mdx
  dependency-version: 15.2.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: website-dependencies
- dependency-name: fumadocs-ui
  dependency-version: 16.12.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: website-dependencies
- dependency-name: lucide-react
  dependency-version: 1.27.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: website-dependencies
- dependency-name: next
  dependency-version: 16.2.12
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: website-dependencies
- dependency-name: "@types/node"
  dependency-version: 26.1.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: website-dependencies
- dependency-name: "@types/react"
  dependency-version: 19.2.18
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: website-dependencies
- dependency-name: "@types/react-dom"
  dependency-version: 19.2.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: website-dependencies
- dependency-name: postcss
  dependency-version: 8.5.25
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: website-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-04 17:39:57 +00:00
Mehdi Shahdoost 1637856c42 feat(adapters): follow the Windsurf rename to Devin Desktop (#1167)
* proposal: add devin desktop support

* feat(adapters): add devin desktop command adapter

- Create new Devin Desktop adapter for .devin/workflows/opsx-<id>.md
- Register adapter in CommandAdapterRegistry
- Export adapter from adapters index
- Update docs/supported-tools.md with Devin Desktop entry
- Add 'devin' to available tool IDs list

Devin Desktop uses the same Cascade workflow system as Windsurf,
making it a natural migration path for existing users.

* fix(config): add devin desktop to AI_TOOLS

Add Devin Desktop entry to AI_TOOLS configuration so that:
- getToolsWithSkillsDir() includes 'devin' as a valid tool ID
- getWorkspaceSkillToolIds() returns 'devin' in the list
- parseWorkspaceSkillToolsValue() accepts 'devin' as valid input
- openspec init --tools devin works correctly

This fixes validation failures where 'devin' was documented in
docs/supported-tools.md but not recognized by validation functions
that derive valid IDs from AI_TOOLS.

* fix(devin-adapter): escape implicit YAML scalars in frontmatter

Update escapeYamlValue to detect and quote implicit YAML scalars that
would be coerced by parsers:
- Booleans: true, false, yes, no, on, off
- Null variants: null, ~
- Numbers: integers, floats, exponentials, hex (0x), octal (0o)
- Edge cases: standalone dash (-) and dot (.)

This ensures values like 'true', '123', 'null' remain strings in YAML
frontmatter instead of being interpreted as booleans, numbers, or nulls.

Preserves existing escaping logic for special characters and newlines.

* test(devin-adapter): add comprehensive tests for Devin Desktop adapter

Add test coverage for the Devin Desktop adapter including:
- Command reference transformation from colon to hyphen syntax
- YAML frontmatter escaping for special characters and implicit scalars
- File path generation for workflows
- Integration with available tools detection
- Init and update command workflows

* Add cross-platform testcase.

* fix(devin): refresh deltas against canonical specs and point skills at skills

Addresses the two release blockers on this PR.

Archive: the change's MODIFIED blocks were written against an older
canonical `cli-init`, so `openspec archive add-devin-desktop-support`
aborted rather than merging. The deltas are regenerated from the current
canonical specs (cli-init `Skill Generation` + `Slash Command
Generation`, cli-update `Slash Command Updates`, and a new
`ai-tool-paths` delta for the `.devin` skillsDir), each restating every
existing scenario so archive is purely additive.

Invocation syntax: only Devin Desktop reads `.devin/workflows/`, so a
`/opsx-*` workflow reference is dead text on Devin Local, which supports
skills only. Devin now takes the skill-reference transformer, so skill
bodies and the getting-started hint say `/openspec-*`. Workflow bodies
keep hyphen references, applied by devinAdapter itself.

The adapter also drops its private copy of escapeYamlValue /
formatTagsArray in favor of the shared helpers main centralized in
#1447, which quote unconditionally and escape control characters.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(devin): correct commands-only hint, fill doc gaps, cover both surfaces

Follow-up from adversarial review of the previous commit.

The devin special case in getTransformerForTool was unconditional, so
under commands-only delivery — where `.devin/skills/` is deleted — the
getting-started hint named `/openspec-propose`, a skill that is not on
disk. Devin now takes the skill transformer only when skills are
generated, and the hyphen form otherwise. The cli-init delta records the
fallback, and a unit test pins all three delivery modes.

Docs: `devin` was missing from the `--tools` list in docs/cli.md (which
mirrors the list supported-tools.md already had) and from the
command-syntax tables in docs/commands.md and docs/how-commands-work.md.
The supported-tools row gains a footnote citing Cognition's docs for the
`.windsurf/` -> `.devin/` move and the Devin Local workflow gap.

Tests: init and update now assert both surfaces — workflows carry
`/opsx-*`, skills carry `/openspec-*`, neither carries `/opsx:` — and
update checks the seeded skill was actually refreshed. Adds the negative
detection case. Drops three devin-only YAML assertions that duplicated,
less rigorously, the registry-derived escaping matrix that now enrolls
devin automatically.

Also reverts an unrelated zcode export and lingma reorder that a merge
resolution had pulled into adapters/index.ts. zcodeAdapter is registered
but missing from that barrel on main; that is a pre-existing gap and
belongs in its own change.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(devin): name the right command in the profile migration notice

The profile-migration notice printed by both `init` and `update` hardcoded
`/opsx:propose` for every adapter-backed tool. Devin registers no such
command on any surface — its workflows answer to `/opsx-propose` and its
skills to `/openspec-propose` — so an upgrading Devin user was told to run
something that does not exist:

  Migrated: custom profile with 6 workflows
  New in this version: /opsx:propose.

The reference now goes through getTransformerForTool, the same call
init.ts already makes for the getting-started hint. Devin prints
`/openspec-propose`; opencode and the other filename-invoked tools are
corrected to `/opsx-propose` as a side effect; claude is unchanged.

Also corrects two inherited false claims in the cli-update delta — Devin
workflows carry no OpenSpec markers, and update writes every profile
workflow rather than only refreshing files that already exist, which the
PR's own test demonstrates. Qualifies the supported-tools footnote for
commands-only delivery, and strips trailing whitespace.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(devin): keep the cli-update delta in step with the canonical spec

The delta restates the whole 'Slash Command Updates' requirement, and its
copy of the OpenCode scenario predated #1471 — archiving it would have
quietly reverted the spec to calling the hyphen rewrite an OpenCode special
case, the hand-maintained framing #1471 removed. Archive on a scratch copy
is now purely additive.

Also point tasks.md at the generator rather than the deleted
transformToHyphenCommands, and enroll devin in the pure-formatter tripwire —
it is the one adapter whose private body transform was just removed, so it
is the likeliest to have it re-added.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* feat(adapters): follow the Windsurf rename to Devin Desktop, with migration

Windsurf was rebranded to Devin Desktop on 2026-06-02 and its config
directory moved: `.devin/` is the preferred read+write location, `.windsurf/`
a legacy read-only fallback. Devin Local does not read `.windsurf/` at all,
so an existing Windsurf user's OpenSpec files are invisible to it.

Carrying `devin` as a second tool id alongside `windsurf` would list one
product twice and leave upgraders with two parallel installs — `openspec
update` even told them to create the second one ("Detected new tool: Devin
Desktop"). This follows the rename instead, as the repo already did for
Kimi CLI -> Kimi Code:

- `windsurf` is retired as a tool id; `devin` takes its place, with
  `detectionPaths: ['.devin', '.windsurf']` so pre-rebrand projects are
  still recognized. The Windsurf adapter is replaced, not duplicated.
- `TOOL_ID_ALIASES` keeps `--tools windsurf` resolving, so existing setup
  scripts and CI keep working; they now configure `.devin/`.
- OpenSpec-managed skills (`openspec-*`) and command files (`opsx-*`) under
  `.windsurf/` move to `.devin/`. The kimi migration handled skills only;
  command files now move too, deriving the legacy path from the adapter's
  own getFilePath rather than hard-coding a layout.
- The move is offered, not taken: nothing on disk distinguishes a user who
  took the rebrand from one still on a pre-rebrand Windsurf build that reads
  only `.windsurf/`. `openspec update` explains the rename and asks; --force
  and non-interactive runs migrate; declining leaves every file untouched and
  says what that costs. Files the user wrote are never moved.

Also gives Devin its own row in the authoritative invocation table — the
catch-all row claimed `/opsx-<id>` for both agents, which is wrong for Devin
Local.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(devin): stop the migration from deleting anything it does not own

An adversarial pass found two ways the move destroyed files.

Symlinked roots wiped the install. `ln -s .devin .windsurf` is a realistic
way to straddle the rebrand, and it makes source and destination the same
file — so the "destination exists, drop the legacy copy" branch deleted the
only copy. Twelve generated files, gone, and not regenerated: the wipe
happens before tool detection, so update then reported no configured tools.
Both roots are now realpath'd and a self-move is skipped.

User content inside an OpenSpec-managed path was deleted. The same branch
rm -rf'd the whole legacy skill directory, taking a hand-written
reference.md beside SKILL.md with it, and deleted a legacy command file even
when the user had edited it. Now only SKILL.md is removed from a skill
directory, and a command file is removed only when byte-identical to the
one that survives — an edit is left where it is.

Also: declining the move stranded the user. `update` then printed "No
configured tools found. Run openspec init", which is wrong — the project is
configured, just in the directory OpenSpec no longer writes. It now says so
and how to resume. A closed stdin during the prompt aborted the whole
update; it is treated as a decline.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* docs(devin): add a changeset for the Windsurf rename and migration

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(devin): move only SKILL.md, never the skill directory around it

alfred caught a data-loss path the earlier fix missed. When the destination
did not yet exist, migration renamed the whole legacy skill directory into
`.devin/` — carrying any file the user kept beside `SKILL.md` with it. That
destination is a directory OpenSpec owns and removes on its own: under
commands-only delivery, or for a workflow outside the active profile. So the
move handed the user's file to a later rm and it vanished.

Reproduced on `d94af8b`: with `delivery: commands`, a `reference.md` beside a
legacy `SKILL.md` was gone after `openspec update`.

Only `SKILL.md` crosses now, in both branches; anything else stays under the
legacy root, and the legacy directory is still removed when the move leaves
it empty. Regression tests cover the commands-only and deselected-workflow
cases and both fail against the previous code.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(devin): treat an edited skill the way an edited command is already treated

A final adversarial pass found the two paths disagreeing. When both roots
held the same file with different content, the command path compared bytes
and kept the user's version; the skill path deleted it with no comparison —
so one `openspec update` destroyed an edited SKILL.md while preserving an
edited opsx-*.md in the same project.

Both now share one `classifyManagedFile` rule: move when the destination is
empty, drop the legacy copy only when byte-identical, otherwise leave it.
Anything left behind is reported, so a user who customized a file knows two
copies exist rather than discovering it later.

Note on the other finding from that pass: OpenSpec regenerating or pruning
the files it owns is long-standing behavior, not something this PR
introduces. Verified against main — an edited SKILL.md under a deselected
workflow, and an edited selected skill and command, are all destroyed by
`openspec update` on 9a937cb too. No regression, so left alone here.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(devin): report divergent legacy files even when nothing is movable

collectLegacyToolMigrations only returned a result when something moved, so
a project where EVERY legacy file differs from its counterpart produced no
output at all — two divergent copies and not a word about them. That is the
one case where the report matters most, since it is entirely made of files
the migration deliberately refused to touch.

Kept-only results are retained now. Callers gate on hasMovableContent(), so
a kept-only result reports what was left without offering to move nothing
and without claiming a migration that did not happen.

Also reworded the notice. A legacy file can differ because the user edited
it or simply because an older OpenSpec generated it, so it no longer asserts
an edit — it states that nothing was overwritten and leaves the user to
compare the two copies.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* test(devin): stop matching the unrelated profile-migration line

The kept-only regression asserted no line matched /Migrated\s*:/, which also
matches OpenSpec's profile migration message, "Migrated: custom profile with
N workflows". That line only prints when the global config has no profile
yet — true on a fresh CI runner, false on a developer machine that has run
OpenSpec before — so the test passed locally and failed on all three CI
platforms.

Now matched on the directory arrow, ".windsurf → .devin", which is specific
to a migration report and unaffected by config state.

Reproduced both ways with an empty XDG_CONFIG_HOME: the old assertion fails
there, the new one passes, and the full suite is green under CI's
XDG_CONFIG_HOME + VITEST_MAX_WORKERS=4.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Clay Good <hi@claygood.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-28 21:02:23 +00:00
Clay Good 9a61f3f30d docs(installation): add an AI-assistant setup prompt (#1466)
* docs(installation): add an AI-assistant setup prompt

Adds a provider-neutral "Install with your AI assistant" section to
docs/installation.md with one copyable prompt that detects the runtime and
package manager, installs the CLI, runs `openspec init --tools <id>`, and
verifies the result. Surfaced from the README Quick Start and the docs map.
The manual package-manager instructions stay the source of truth.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* docs(installation): harden the AI-assistant prompt and link it from the install paths

Adversarial review found the first draft's verify step false-failing on healthy
installs and its guardrails unenforceable. The prompt now reports what init
actually printed instead of asserting config.yaml and command files (config.yml
is equally valid; six tools and delivery=skills correctly generate zero
commands), warns that --tools auto-cleans legacy files including opsx-*.md
prompts under $HOME, picks the package manager by what's on PATH rather than by
lockfile, scopes yarn to 1.x, and stops cleanly on EACCES, a missing pnpm global
bin dir, or a version-manager shim.

Also links the flow from getting-started, the docs map, troubleshooting, and the
website CTA; notes Berry dropped `yarn global`; replaces `npm bin -g` (removed in
npm 9) with `npm prefix -g`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* docs(installation): close the gaps two trial runs found in the setup prompt

Two assistants (different models) ran the prompt end to end in sandboxes, one
on Cursor and one on Codex with deliberately messy legacy files. Both finished
with a working, verified setup. Their findings:

- Cursor's commands are `/opsx-propose`, not `/opsx:propose`. The prompt named
  the colon form and init's summary agrees with it, so the assistant would have
  handed back a command the tool doesn't match. It now takes the spelling from
  the files init created.
- "List whatever you find and wait for my go-ahead" was undefined when the list
  is empty, i.e. on every fresh project. It now says to carry on.
- `openspec --version` succeeding doesn't prove it's the copy just installed;
  an older one earlier on PATH shadows it. Step 3 now compares the two.
- The request asked for confirmation before privileged/global changes; the
  prompt only stopped reactively on failure. It now shows the global install
  command and waits.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* docs: correct the core profile to six workflows and the tool count to 30+

Two long-standing inaccuracies, found while verifying the install docs.

`CORE_WORKFLOWS` (src/core/profiles.ts:14) is six — propose, explore, apply,
update, sync, archive — and a real `openspec init` generates six skills and six
commands. Eleven pages listed five, omitting `update`; migration-guide listed
four and filed `sync` under the expanded set. supported-tools also dropped
`update` from the full workflow-ID list. docs/commands.md was already right and
is untouched, as are flow diagrams that show a typical path rather than a
profile roster.

The tool count was written as both "25+" and "30+" against 34 supported tools.
Now consistently "30+".

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* docs: address CodeRabbit review on the AI-assisted install flow

- Windows puts global npm binaries directly in the prefix directory, not in a
  `bin/` subdirectory; the troubleshooting fix I added said otherwise.
- Tell the assistant to stop rather than improvise when none of npm/pnpm/yarn/bun
  is available, and point Nix users at the Nix section.
- Drop the blockquote on the getting-started pointer so it isn't a second `>`
  block adjacent to the explore callout (markdownlint MD028).

Two other comments were already fixed in 1bf0706 (stop on a PATH problem; map
the user's answer to an exact tool id).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-28 00:39:47 +00:00
Clay Good 05c701970a chore(security): override brace-expansion to fix the failing audit (#1461)
* chore(security): override brace-expansion to fix the failing audit

A new advisory (GHSA-mh99-v99m-4gvg, high) flags brace-expansion <= 5.0.7
with the only patched release being 5.0.8. The scheduled Security workflow
has failed on every run since 2026-07-27.

pnpm audit --fix adds a scoped override in both the root and website
packages; the lockfile diffs touch only brace-expansion and its subtree.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* chore(nix): blank pnpmDeps hash to surface the new lockfile hash

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* chore(nix): pin pnpmDeps hash for the updated lockfile

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 21:15:19 +00:00
Clay Good b976fc0666 fix(website): show openspec init in the homepage getting-started box (#1434)
The final "Ship your first change in five minutes" call-to-action showed
only `npm install -g @fission-ai/openspec@latest`, which installs the CLI
but does nothing on its own. New users who copy that one line get no
scaffolding and nothing to run. Add the `cd your-project && openspec init`
step so the box matches the canonical README flow.

Closes #1282

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 19:22:06 +00:00
Clay Good a874d1d671 chore(security): create test temp dirs with mkdtemp and override two pinned CVEs (#1432)
* test: create temp dirs with fs.mkdtemp

Every one of these suites built its temp directory by hand:

    testDir = path.join(os.tmpdir(), `openspec-test-${randomUUID()}`);
    await fs.mkdir(testDir, { recursive: true });

That check-then-create is what CodeQL's js/insecure-temporary-file flags,
and it accounted for 452 of the repo's 467 dismissed code-scanning alerts.
Dismissing them one by one is a treadmill: every new suite that copies the
idiom mints fresh alerts, and a real finding is easy to lose in that volume.

fs.mkdtemp creates the directory atomically at mode 0700 with a random
suffix, so there is no window to pre-empt and no name to guess. The suites
that already used it are the evidence this silences the rule: 33 of the 34
files calling mkdtemp carry zero alerts. The lone exception, archive.test.ts,
was scanned one commit before its own mkdtemp fix landed and is left to that
change rather than conflicting with it.

The dirs named on Date.now() alone were genuinely predictable; the randomUUID
ones were not, but they trained the same copy-paste. Both are gone now.

Behavior is unchanged: mkdtemp creates the root the old mkdir created, and
no assertion depended on the root being absent. Verified with the full suite
(2196 tests, 111 files).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore(deps): override postcss and sharp in the website

Two advisories on the docs site have no Dependabot PR and never will:
Next pins postcss at 8.4.31 as a direct dependency and sharp at ^0.34.5 as
an optional one, so Dependabot cannot raise either without a Next release
that does it first. 16.2.11 does not — it still pins both. Left alone these
sit open indefinitely.

  postcss  8.4.31 -> 8.5.22   GHSA-qx2v-qp2m-jg93  (XSS via unescaped </style>)
  sharp    0.34.5 -> 0.35.3   GHSA-f88m-g3jw-g9cj  (4 libvips CVEs)

A version-ranged selector (`postcss@<8.5.10`) was the first instinct, since it
lapses on its own once Next moves past it. It is the wrong tool: it pins the
override to one advisory's floor, and silently stops applying when the next
advisory raises that floor. GHSA-6g55-p6wh-862q landed while this branch was
open and moved postcss's patched floor to 8.5.12 — under the ranged selector a
dependency pinning 8.5.11 would have resolved to 8.5.11 and stayed vulnerable.
A plain floor cannot under-match, so that is what this uses.

The floor also covers the new advisory: 8.5.22 is past 8.5.12. postcss dedupes
to the single copy the site already had for Tailwind.

These are the last two open Dependabot alerts on the repo. `pnpm audit` on
website/ goes from 2 advisories to "No known vulnerabilities found". The site
builds clean, OG image generation included, and the package set grows by
exactly two platform-gated wasm32 binaries that never install on CI.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* ci(security): audit the docs site too

Both `pnpm audit` steps run at the repo root. The docs site keeps its own
lockfile and is not a workspace member, so neither step could see it — the
root audit passed all the way through while postcss and sharp sat open in
website/. That blind spot is why they needed a manual override to find.

Blocking rule copied from the published-dependency audit: advisory on pull
requests, blocking on the weekly schedule and on pushes to main. An
always-advisory step would only relocate the blind spot — the sweep would stay
green with a live advisory and someone would have to read the log of a passing
run to notice.

`!cancelled()` because the two audits above can fail hard. Without it a root
advisory would skip this step entirely, in exactly the situation where the
site's own state matters most.

Verified against the pre-fix lockfile — the step reports the two advisories it
would have caught:

  2 vulnerabilities found
  Severity: 1 moderate | 1 high

and reports "No known vulnerabilities found" against the fixed one. Confirmed
it reads website/pnpm-lock.yaml and not the root: with a vulnerable website
lockfile and a clean root, it exits 1; a missing website lockfile is a hard
ERR_PNPM_AUDIT_NO_LOCKFILE rather than a false clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 16:17:26 +00:00
dependabot[bot] 2b503389f5 chore(deps): bump next from 16.2.10 to 16.2.11 in /website (#1429)
Bumps [next](https://github.com/vercel/next.js) from 16.2.10 to 16.2.11.
- [Release notes](https://github.com/vercel/next.js/releases)
- [Commits](https://github.com/vercel/next.js/compare/v16.2.10...v16.2.11)

---
updated-dependencies:
- dependency-name: next
  dependency-version: 16.2.11
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-23 14:39:38 +00:00
T 81d5109b86 docs: switch Roo Code references to Zoo Code (#1428)
* docs: switch Roo Code references to Zoo Code

* no-mistakes(review): Remove unrelated AGENTS.md changes

* no-mistakes(document): Update Roo Code references to Zoo Code; fix unused eslint directive

---------

Co-authored-by: Clay Good <hi@claygood.com>
2026-07-22 22:58:35 +00:00
dependabot[bot] 11a301d5fb chore(deps): bump next in /website in the website-dependencies group (#1420)
Bumps the website-dependencies group in /website with 1 update: [next](https://github.com/vercel/next.js).


Updates `next` from 16.2.9 to 16.2.10
- [Release notes](https://github.com/vercel/next.js/releases)
- [Commits](https://github.com/vercel/next.js/compare/v16.2.9...v16.2.10)

---
updated-dependencies:
- dependency-name: next
  dependency-version: 16.2.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: website-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-22 21:17:20 +00:00
Clay Good e2f748c64f chore(security): add security policy, dependabot config, and config key guards (#1415)
* chore(security): add security policy, dependabot config, and config key guards

Adds a SECURITY.md with a private disclosure path and an explicit threat
model, a Dependabot configuration covering the CLI package, the docs site,
and CI actions, and closes a prototype-pollution path in `config set`.

`--allow-unknown` was meant to relax the known-key check but skipped every
key check, so `openspec config set --allow-unknown __proto__.polluted x`
reported success and assigned onto Object.prototype for the process
lifetime. Unsafe segments are now rejected at the command layer regardless
of `--allow-unknown`, and setNestedValue/deleteNestedValue refuse them for
any caller.

Also bumps the bundled yaml dependency from 2.8.2 to 2.9.0, the only
advisory in this repo that affects code shipped in the npm package.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore(nix): update pnpmDeps hash for the yaml bump

fetchPnpmDeps pins a fixed-output hash over the whole dependency set, so
changing pnpm-lock.yaml invalidates it. Recovered the new value from a
hash-mismatch build.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore(security): clear dependency advisories and automate future checks

Refreshes both lockfiles so every open advisory in the CLI package is
resolved, replaces a quadratically-backtracking heading parser, and adds
the automation to catch the next one.

Dependency refresh (in-range, lockfile only): brace-expansion, flatted,
js-yaml, minimatch, postcss, rollup, and vite all move to patched versions
in the root lockfile; fast-uri and brace-expansion move in the website
lockfile. Only @changesets/cli needed a declared floor bump, to reach a
patched js-yaml. Production dependencies now report zero advisories.

extractFirstPurposeLine parsed ATX headings with /\s+#+\s*$/, which
backtracks quadratically on a whitespace-padded title. Replaced with a
linear hand-rolled scan, verified identical to the old implementation
across 303,000 generated inputs.

Automation: a Security workflow runs dependency review on pull requests,
blocks on advisories in published dependencies, and re-audits weekly; every
GitHub Action is pinned to a commit SHA so a moved tag cannot change what
CI executes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(ci): drop the pnpm cache from the audit job

Nothing is installed there, so setup-node's cache-save post step failed on
the missing store path even though both audit steps passed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore(nix): repin pnpmDeps hash after the dependency refresh

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore(security): apply opengrep findings and fix a dependency-review permission gap

Ran opengrep against the repository to check the claims in #1414. Of 208
findings, 201 are one path-traversal rule firing on joins built from module
constants, argv, or readdir entry names; 1 non-literal-regexp is fed only by
LEGACY_SLASH_COMMAND_PATHS. Neither is reachable from untrusted input. The
actionable results are applied here.

- dependabot: add a cooldown so a freshly published version is not adopted
  immediately. Security updates ignore the cooldown, so this delays only
  routine bumps, long enough for a compromised release to be yanked.
- getNestedValue now refuses prototype-reaching segments, matching the
  guards already on setNestedValue and deleteNestedValue.
- dependency-review no longer asks to comment on the pull request. That
  needs `pull-requests: write`, which the workflow does not grant and a
  fork's token never gets, so a real finding would have failed on the
  comment instead of reporting the vulnerable dependency.
- SECURITY.md: show the command that proves build tooling is absent from an
  installed copy, rather than asking readers to take it on trust.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(dependabot): drop semver cooldown keys unsupported by github-actions

Dependabot rejected the whole config file, which would have silently
disabled every version update.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore(security): make the audit advisory and document runtime behavior

The published-dependency audit no longer fails the job. A newly published
advisory should not block an unrelated pull request, and the step depends on
registry availability; Dependabot alerts and dependency review remain the
gates. SECURITY.md is corrected to match — it claimed the audit was blocking.

Also documents what the CLI does on your machine, all verified rather than
asserted: the install script prints one line and makes no network request or
file write; every shell-invoking call uses a fixed literal while anything
carrying user input uses an argument array with shell:false; telemetry sends
a command name, a version, and a local random UUID, with IP capture disabled.

Secret scanning is now listed, confirmed enabled by a repository admin.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(ci): keep the production audit blocking off pull requests

Making the step advisory on every event meant a newly published
high-severity advisory in a shipped dependency could not fail any run
unless a dependency changed. It stays advisory on pull requests, so an
unrelated change is never blocked by an advisory published that morning,
and blocks on the weekly schedule and on pushes to main, where a failure
is the signal rather than a tax on someone else's work.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 18:55:51 +00:00
Tabish Bidiwale 0a99f41045 Deploy docs through Cloudflare Pages (#1342)
* Deploy docs with Cloudflare Pages

* Harden docs routing worker
2026-07-10 15:46:44 +00:00
Clay Good 65a7233f36 docs: add cloudflare documentation deployment website (#1285)
* docs(website): add Fumadocs documentation site for Cloudflare Pages

Add a self-contained marketing + documentation site under website/, built
with Fumadocs (Next.js) and configured as a static export so it deploys
directly to Cloudflare Pages with no server runtime.

What's included:
- A marketing landing page (hero, the two-folder model, the four core
  ideas, the explore→propose→apply→archive loop, and the "why").
- 13 documentation pages rewritten for clarity and delight: introduction,
  installation, getting started, how commands work, core concepts, the
  workflow, explore first, existing projects, editing a change,
  customization, FAQ, and a reference section (slash commands, CLI,
  supported tools).
- Static client-side search (Orama), per-page Open Graph images, and
  llms.txt / llms-full.txt routes — fitting for an AI-native tool.
- website/README.md with one-table Cloudflare Pages deploy settings
  (root: website, build: npm run build, output: out).

Content is faithful to the docs/ overhaul from #1237, restated in a
simpler, friendlier voice. Verified with a clean `next build` (48 static
pages, no warnings).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(website): sharpen the sell, add a Stores guide

Completes the documentation work begun in #1237 by tightening the
Fumadocs site toward the quality bar of the stores user-guide:

- Intro now opens problem-first ("the requirements lived only in chat"),
  adds an honest "How it compares" table (Spec Kit / Kiro / nothing), and
  frames the tradeoff in a "When the ceremony isn't worth it" callout.
- New Stores guide (beta) distilled from docs/stores-beta/user-guide.md:
  the problem, the annotated shape, a five-minute walkthrough with real
  command output, a role-based story, the root-resolution order, and an
  honest-limitations section. Linked from Existing Projects.

Verified with a clean `next build` (51 static pages, no warnings).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(website): make the value tangible — landing sections + Examples page

Continue the #1237 docs completion with a stronger product story:

- Landing page now reads like a real product site:
  - "Works with the tools you already use" strip (15 named assistants + more)
  - "What a change actually looks like" — three real artifacts
    (proposal.md, a spec delta, tasks.md) so the workflow is concrete
  - "The honest middle" comparison block (Spec Kit / Kiro / no specs)
  - Robust hero gradient via color-mix instead of v3 theme() syntax
- New Examples & Recipes page: seven copy-pasteable, narrated walkthroughs
  (small feature, bug fix, explore-first, parallel changes, no-behavior
  refactor with --skip-specs, step-by-step, onboard). Linked from the intro
  and getting-started.

Verified: clean `next build` (54 static pages, no warnings); Tailwind
opacity/color-mix utilities confirmed in the generated CSS; all internal
links resolve.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(website): add favicon, sitemap, and robots for a complete public site

- Branded SVG favicon (app/icon.svg) in the OpenSpec indigo.
- Static sitemap.xml covering the home page and every doc, built from the
  content source and NEXT_PUBLIC_SITE_URL.
- robots.txt allowing all and pointing at the sitemap.

All three are emitted by the static export. Clean `next build`, 57 pages.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs: lead with stores as "why teams adopt OpenSpec"; complete docs coverage

Final pass completing the #1237 documentation work.

Reposition stores (beta) as the team adoption story, consistently:
- README.md gains a prominent "Why teams adopt OpenSpec" section right
  after the demo (cross-repo features, shared requirements, plan before
  code), leading with stores.
- Landing page gains a matching "Why teams adopt OpenSpec" section.
- Docs intro gains a teams card + callout pointing at stores.
- Stores page expanded with full References and Worksets technical
  examples (the cross-team requirements story, workset create/open).

Incorporate the remaining source-doc knowledge so the site is complete:
- New pages: Glossary, Troubleshooting, Multi-Language, and an
  Agents & Automation reference (the machine-readable --json surfaces and
  workflow primitives that make OpenSpec AI-native).
- The Workflow page now covers ff-vs-continue, a three-dimension verify
  example, and the update-vs-start-fresh decision guide.
- Nav restructured with a Help section; reference section gains Agents.

Build hardening: `build` now runs `fumadocs-mdx && next build` so the
content source is always regenerated. Clean build: 69 static pages, no
warnings; all internal links verified.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(website): fix docs GitHub source links + address review nits

- page.tsx: prefix ViewOptionsPopover githubUrl with website/ so the
  "view/edit source" links resolve to website/content/docs/... instead
  of 404-ing on every deployed docs page (Alfred blocker).
- installation.mdx: note that `yarn global add` is Classic Yarn only and
  point Yarn Berry users at `yarn dlx` / npm / pnpm.
- index.mdx: label the comparison table's first column ("Option").
- (home)/page.tsx: use the shared docsRoute constant for all /docs links
  instead of hardcoded paths.

Verified with `npm run build` in website/ — 69 static pages, and the
built getting-started page links to blob/main/website/content/docs/...

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(website): mirror docs/*.md into the site + auto-deploy on a cadence

Make the repository's docs/*.md the single source of truth for the docs
site instead of maintaining a parallel set of hand-written MDX pages that
silently drift.

- scripts/sync-docs.mjs mirrors ../docs into content/docs/ on every build:
  derives title/description, injects Fumadocs frontmatter (+ githubSource),
  rewrites internal *.md links to /docs routes, and emits meta.json. Pages
  are written as .md so <placeholders>/{braces} in the docs stay literal
  and never break the MDX build.
- docs.sync.config.mjs is the one manifest deciding which docs publish and
  their slug/section/icon. content/docs/ is now generated + git-ignored;
  the curated .mdx pages are removed. The marketing landing page stays
  hand-authored.
- build/dev/types:check run sync:docs first, so the site is always current.
- .github/workflows/deploy-docs.yml rebuilds and deploys to Cloudflare
  Pages via Wrangler on push to docs/**|website/**, daily on a schedule,
  on demand, and as a build-only check on PRs. Needs CLOUDFLARE_API_TOKEN
  + CLOUDFLARE_ACCOUNT_ID secrets and the DOCS_SITE_URL variable.
- source.config.ts carries githubSource so "edit this page" opens the real
  docs/*.md; website/README.md documents the pipeline.

Verified: clean build, 23 pages generated, 78 static pages, no warnings;
all internal doc links resolve; MDX-hazard docs (cli, customization) build.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(website): fall back to default site URL when NEXT_PUBLIC_SITE_URL is empty

The deploy workflow passes NEXT_PUBLIC_SITE_URL from the DOCS_SITE_URL repo
variable, which resolves to an empty string when unset. `?? fallback` does
not catch '' (only null/undefined), so `metadataBase: new URL('')` crashed
`next build` with ERR_INVALID_URL while collecting page data. Use `||` so an
empty value also falls back. Verified: `NEXT_PUBLIC_SITE_URL='' npm run build`
now generates all 78 static pages.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs: add reviewing, writing-specs, and team-workflow guides

Fill the biggest gaps a new user hits, in the plain-language voice of the
stores user guide:

- reviewing-changes.md: the two-minute human review of an AI-drafted plan
  before /opsx:apply — what to open, in what order, and the red flags per
  artifact — plus the /opsx:verify pass after code.
- writing-specs.md: what a strong requirement and scenario are made of,
  choosing ADDED/MODIFIED/REMOVED, and right-sizing a change.
- team-workflow.md: how a change maps onto a branch and a pull request,
  reviewing spec deltas in a PR, when to archive, and parallel changes —
  framed as convention, since OpenSpec never touches git.

Wire them into the docs map (README), the site nav (docs.sync.config.mjs),
and light "next steps" cross-links from getting-started, editing-changes,
and workflows. Verified: site builds clean, 26 pages, all internal links
resolve.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(website): add one-time deploy setup checklist + landing-page note

Spell out the three maintainer steps that activate auto-deploy (create the
openspec-docs Pages project, add CLOUDFLARE_API_TOKEN/ACCOUNT_ID secrets,
merge to main), and note that the pipeline mirrors docs on build regardless.
Also flag that openspec.dev is a separate Astro landing page and whether to
keep/port this Fumadocs landing page is a maintainer decision.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(website): address review feedback on docs-site PR

Maintainer review (TabishB) + Alfred blocker:

- deploy-docs.yml: guard the Cloudflare deploy on `github.ref ==
  refs/heads/main`. A `workflow_dispatch` on a feature branch previously
  passed the guard and, since wrangler hardcodes `--branch=main` (a
  production deploy), would overwrite the live docs site. Non-main
  dispatches are now build-only. Also resolves Alfred's deploy-path blocker.
- package.json: drop the direct `cnfast` dependency and delete the dead
  `lib/cn.ts` (nothing imports it; a class-merge helper isn't used).
- package.json: declare `zod` (^4.4.3) — it was a phantom dep only
  resolving via fumadocs-mdx's hoisted copy. Refresh the lockfile.
- docs page: omit the on-page <DocsDescription>. The frontmatter
  description is derived from the first body paragraph, so it rendered
  the intro twice on every page. Kept in generateMetadata for SEO/OG.
- team-workflow.md: `openspec store create` does an initial commit, so
  scope "never commits" to the user's project and reframe the store
  clause as "never clones or syncs on its own."
- README.md: bump stale "20+ AI assistants" to "30+" to match the site.

Verified: npm run types:check + npm run build pass, 26 docs synced,
intro paragraph now renders once per page.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore(website): use pnpm to match the rest of the repo

Per maintainer review (TabishB): the root repo is pnpm (ci.yml runs
`pnpm install --frozen-lockfile` against a v9 `pnpm-lock.yaml`), but
`website/` had introduced npm + a `package-lock.json`. Standardize on
one package manager:

- Replace website/package-lock.json with website/pnpm-lock.yaml
  (lockfileVersion 9.0, generated with pnpm v9 to match root).
- deploy-docs.yml: add pnpm/action-setup@v4 (version 9, before
  setup-node, as in ci.yml), switch setup-node to `cache: pnpm` /
  `cache-dependency-path: website/pnpm-lock.yaml`, and
  `npm ci` → `pnpm install --frozen-lockfile`, `npm run build` →
  `pnpm run build`.
- package.json scripts + README: `npm run ...` → `pnpm run ...`.

website/ stays a standalone package (no pnpm-workspace.yaml), as before.

Verified: `pnpm install --frozen-lockfile`, `pnpm run build`, and
`pnpm run types:check` all pass — 26 docs synced, 87/87 static pages.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore: temporarily disable docs deploy

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Tabish Bidiwale <30385142+TabishB@users.noreply.github.com>
Co-authored-by: TabishB <tabishbidiwale@gmail.com>
2026-07-03 14:21:42 +00:00