diff --git a/.changeset/adapterless-skill-references.md b/.changeset/adapterless-skill-references.md deleted file mode 100644 index bffe78285f..0000000000 --- a/.changeset/adapterless-skill-references.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@fission-ai/openspec': patch ---- - -Generated skills for tools without a command adapter (Kimi Code, Mistral Vibe, Hermes, ForgeCode, CodeArts) no longer reference `/opsx:*` commands that were never generated: skill cross-references, the init getting-started hint, and the profile-migration message now use each tool's documented skill invocation (Kimi Code: `/skill:openspec-*`; others: `/openspec-*`), and Codex — skills-invocable with no slash surface — gets a syntax-neutral hint that names the skill. Selections that mix invocation syntaxes print one labeled hint per distinct form, so every advertised instruction is usable by the tool it names. When `delivery: commands` would generate nothing for a selected tool, init prints a configuration correction naming that tool, even when other tools did get commands or skills. The committed skills.sh distribution is regenerated with skill references (default `/openspec-*` form, as that channel installs skills only). diff --git a/.changeset/add-codearts-tool.md b/.changeset/add-codearts-tool.md deleted file mode 100644 index d18a465c28..0000000000 --- a/.changeset/add-codearts-tool.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": minor ---- - -Add CodeArts Agent skills support: `openspec init --tools codeartsagent` installs the workflow skills. diff --git a/.changeset/add-global-default-store.md b/.changeset/add-global-default-store.md deleted file mode 100644 index 95475d8341..0000000000 --- a/.changeset/add-global-default-store.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -### Features - -- **One default store for every repo on your machine** — `openspec config set defaultStore ` sets a machine-level fallback root: any command run outside a planning root, with no `--store` flag and no project `store:` pointer, resolves to that store. It sits at the bottom of the precedence list, so `--store`, a local root, and a project pointer all still win. The root banner and JSON `root` block report the distinct provenance `source: "global_default"`, so users and tooling can tell a machine-wide default from a repo's own pointer. A stale id degrades to the underlying store error with a fix that names `openspec config unset defaultStore`. diff --git a/.changeset/add-hermes-tool.md b/.changeset/add-hermes-tool.md deleted file mode 100644 index eed0b2213f..0000000000 --- a/.changeset/add-hermes-tool.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": minor ---- - -Add Hermes Agent as a supported AI tool: `openspec init --tools hermes` installs the workflow skills (Hermes is skills-only and invokes them directly). diff --git a/.changeset/add-zcode-tool.md b/.changeset/add-zcode-tool.md deleted file mode 100644 index 4a39b7703a..0000000000 --- a/.changeset/add-zcode-tool.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": minor ---- - -Add ZCode as a supported AI tool: `openspec init --tools zcode` generates its skills and `/opsx:*` commands. diff --git a/.changeset/allow-numeric-prefixed-change-names.md b/.changeset/allow-numeric-prefixed-change-names.md deleted file mode 100644 index 6c0a66d8af..0000000000 --- a/.changeset/allow-numeric-prefixed-change-names.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@fission-ai/openspec': patch ---- - -`openspec new change` now accepts numeric-prefixed names like `100-add-feature` or `00001-add-auth`, useful for ordering or tiering changes. Change names now use the same kebab-case grammar as store ids and change metadata (a leading digit is allowed); `archive` already treated date-prefixed names as a supported convention. Uppercase, spaces, underscores, and leading/trailing or consecutive hyphens are still rejected, and every previously valid name stays valid. diff --git a/.changeset/analyzer-visible-key-guards.md b/.changeset/analyzer-visible-key-guards.md deleted file mode 100644 index 6a9b37919f..0000000000 --- a/.changeset/analyzer-visible-key-guards.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -Compare config key guards literally instead of through a helper. - -`setNestedValue` and `deleteNestedValue` rejected prototype-reaching key segments through a helper that did a `Set` lookup. That is correct, but static analysis could not follow it, so CodeQL kept reporting prototype-pollution on the very assignments the guard protects. The segments are now compared literally in the same function, still checked across the whole path before anything is written. Behavior is unchanged for every input, verified against the previous implementation across 400,000 generated cases. diff --git a/.changeset/archive-carries-delta-purpose.md b/.changeset/archive-carries-delta-purpose.md deleted file mode 100644 index 0bd89ca20a..0000000000 --- a/.changeset/archive-carries-delta-purpose.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -A delta spec that introduces a brand-new capability can now open with a `## Purpose`, and `openspec archive` uses it as the Purpose of the main spec it creates instead of writing the `TBD - created by archiving change . Update Purpose after archive.` placeholder over it. The `specs` artifact instruction, its example, the delta template and the `openspec-sync-specs` skill all tell authors and agents to write one, so the CLI and agent-driven sync paths produce the same main spec. - -Archive keeps the placeholder when the delta has no usable `## Purpose`: - -- no `## Purpose` header outside a code fence or HTML comment, or a body that is only a code fence or only a comment -- a body that would leave a spec its own parser cannot read — a heading or requirement header that truncates a section, an unterminated fence, or any HTML comment -- in the second case archive also says why, and still completes rather than aborting - -A carried Purpose under 50 characters is kept but warned about, since `openspec validate --strict` reports it as too brief. The Purpose of an existing main spec is never touched; archive warns when it ignores a delta's Purpose there. diff --git a/.changeset/archive-early-synced-removed.md b/.changeset/archive-early-synced-removed.md deleted file mode 100644 index 25ed4dba06..0000000000 --- a/.changeset/archive-early-synced-removed.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@fission-ai/openspec': patch ---- - -`openspec archive` no longer aborts when a REMOVED delta's requirement is already gone from the main spec (the early-sync pattern the sync skill teaches): it warns, treats the removal as already applied, and reports applied-only totals. In `--json` mode those warnings are carried in a new optional `warnings` array on the archive result. When every operation for a spec was already synced, archive skips rewriting that file instead of churning normalization differences into it. A delta that both RENAMEs and REMOVEs the same requirement is now rejected explicitly, by both `validate` and `archive` — the two spellings are compared case- and whitespace-insensitively — and a REMOVED header that differs only in case or whitespace from an existing requirement still aborts (that is a typo, not an early sync). Also fixed: the archive delta gate matches section headers case-insensitively like the parser; symlinked `specs//spec.md` files are discovered instead of silently dropped; `openspec show ` no longer prints a spurious "scenarios" flag warning; files generated for qwen and bob reference commands by their real hyphenated names (`/opsx-`), and init's getting-started hint follows suit; apply/update/onboard guidance names the CLI fallback for profiles that don't install `/opsx:continue` or `/opsx:new`. diff --git a/.changeset/archive-phantom-proposal-warnings.md b/.changeset/archive-phantom-proposal-warnings.md deleted file mode 100644 index 1b232f3612..0000000000 --- a/.changeset/archive-phantom-proposal-warnings.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -Fix phantom requirements parsed from delta specs, which made `openspec archive` warn about problems `openspec validate` never reported. - -A header inside a delta section that is not a `### Requirement:` header — a divider such as `### Documentation Requirements` — was read as a requirement with no scenario. `openspec archive` warned that it was missing a scenario, and `openspec show --json` and `openspec change list` counted it as an extra delta. The change parser now ignores those headers, matching the delta reader, so the phantom is gone from the warnings and from the JSON. Main spec parsing is unchanged. - -`openspec archive` also no longer repeats requirement-level issues from the delta specs in its non-blocking "Proposal warnings in proposal.md" block. Each defect was printed twice there, and a `## REMOVED Requirements` entry — names-only by design — was reported as missing a scenario on every correct removal. Delta spec validation still reports and blocks on genuine defects, and proposal-level warnings are unchanged. diff --git a/.changeset/archive-waits-for-spec-sync.md b/.changeset/archive-waits-for-spec-sync.md deleted file mode 100644 index 21e6f663b2..0000000000 --- a/.changeset/archive-waits-for-spec-sync.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -### Bug Fixes - -- **Archive no longer races the spec sync, or reports a sync that never landed** — the generated `openspec-archive-change` skill (and the matching `opsx:archive` command) handed the spec sync to a background task and then moved the change folder immediately. The archive could move the delta specs out from under the running sync: the change ended up archived, `openspec/specs/` was never updated, and the summary still reported `Specs: ✓ Synced`. The sync now runs inline, and the archive only proceeds once every capability with a delta spec has been checked against it — ADDED present, MODIFIED changes applied, REMOVED gone, RENAMED under the new name and not the old. If the sync fails or a capability doesn't match, the archive stops and reports what differs instead of claiming success; nothing has moved, so you can fix it and retry. diff --git a/.changeset/avoid-npx-profile-changes.md b/.changeset/avoid-npx-profile-changes.md deleted file mode 100644 index 4e250e4bd6..0000000000 --- a/.changeset/avoid-npx-profile-changes.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -Apply profile changes with the installed CLI instead of shelling out to `npx`, which could run a different version. diff --git a/.changeset/bom-delta-parsing.md b/.changeset/bom-delta-parsing.md deleted file mode 100644 index ee6e7307a9..0000000000 --- a/.changeset/bom-delta-parsing.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -Delta and main-spec parsers strip a UTF-8 BOM, so files saved by Windows editors or PowerShell redirects no longer fail with "No delta sections found". diff --git a/.changeset/bulk-archive-honors-cancel.md b/.changeset/bulk-archive-honors-cancel.md deleted file mode 100644 index 0756501fdf..0000000000 --- a/.changeset/bulk-archive-honors-cancel.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -### Bug Fixes - -- **Bulk archive now stops when you pick "Cancel"** — the generated `openspec-bulk-archive-change` skill (and the matching `opsx:bulk-archive` command) offered a "Cancel" option at the confirmation prompt but never told the agent what to do with it, so the next step archived every selected change anyway. The prompt now routes each answer by intent: "Cancel" stops without archiving anything, the archive options proceed (the ready-only option archives just the changes the status table marks `Ready` or `Ready*`), and any other answer re-asks instead of archiving. The single-change archive skill already routes Cancel this way; this brings the bulk variant in line. diff --git a/.changeset/change-lookup-accepts-existing-names.md b/.changeset/change-lookup-accepts-existing-names.md deleted file mode 100644 index 3f110aee47..0000000000 --- a/.changeset/change-lookup-accepts-existing-names.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@fission-ai/openspec': patch ---- - -`--change` now accepts any change name that exists on disk (e.g. date-prefixed names like `2026-07-04-voice-copilot-v1`), matching what `list`, `validate`, and `archive` already resolve. Lookup still rejects unsafe names (path separators, `..`, hidden entries); the kebab-case naming rule still applies when creating a change. diff --git a/.changeset/change-name-length.md b/.changeset/change-name-length.md deleted file mode 100644 index cd053ba251..0000000000 --- a/.changeset/change-name-length.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -`openspec new change` rejects names over 200 characters with a validation message instead of surfacing a raw ENAMETOOLONG filesystem error. diff --git a/.changeset/codex-skills-only.md b/.changeset/codex-skills-only.md deleted file mode 100644 index 5866f48d40..0000000000 --- a/.changeset/codex-skills-only.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": minor ---- - -Codex is now skills-only: workflows install as `$openspec-*` skills and previously managed custom prompts are retired (existing ones are cleaned up on update). diff --git a/.changeset/command-adapter-yaml-escaping.md b/.changeset/command-adapter-yaml-escaping.md deleted file mode 100644 index b025426dab..0000000000 --- a/.changeset/command-adapter-yaml-escaping.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@fission-ai/openspec': patch ---- - -Generated tool command files now carry valid YAML frontmatter for every supported tool. Command names ship as `OPSX: Explore`, and the unquoted `name: OPSX: Explore` that adapters emitted is not parseable YAML — strict parsers rejected the whole file, so the command failed to load. Several adapters also re-implemented their own escaping, and a few interpolated descriptions in raw. - -Escaping now lives in one place (`escapeYamlValue` / `formatTagsArray`) and every adapter uses it. String frontmatter values are always double-quoted, which also keeps values like `true`, `null` and `123` from round-tripping as booleans, nulls and numbers. Non-string fields such as `allowed-tools` and `invokable` are unchanged. Expect the first `openspec update` after upgrading to rewrite the frontmatter lines of your generated command files. - -Archive workflow guidance also gets two corrections: bulk archive now carries its per-delta include/exclude decisions into execution, so a delta whose implementation was not found is reported as `sync skipped` instead of being synced anyway, and both archive workflows verify the main specs before moving the change directory. diff --git a/.changeset/command-invocation-parity.md b/.changeset/command-invocation-parity.md deleted file mode 100644 index 3e488e0de0..0000000000 --- a/.changeset/command-invocation-parity.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@fission-ai/openspec': patch ---- - -Reference slash commands by the name each tool actually registers. Command bodies, generated `SKILL.md` cross-references, and the `init`/`update`/migration hints all advertised `/opsx:`, but only 7 of the 28 tools with a command adapter register that name — the ones whose files sit in an `opsx/` directory. The other 21 write `.../opsx-.md`, where the filename is the command, so tools such as Cursor, GitHub Copilot, Windsurf and Kilo Code were told to type a command their palette never had; a single generated Cursor file named itself `/opsx-apply` in frontmatter and then told the reader to run `/opsx:apply`. The command *name* is now derived from the command file each adapter writes rather than a hand-maintained tool list, so a newly added adapter cannot drift, and the *wrapper* around it is adapter metadata: Amazon Q loads its files into a prompt library invoked with `@`, so it now gets `@opsx-` in command bodies, skills, and the onboarding hint instead of a slash command it never registers. Codex, which generates no command files at all, now gets `$openspec-` — the syntax its CLI actually accepts — everywhere it previously advertised `/opsx:*`, superseding the syntax-neutral hint described in the pending `adapterless-skill-references` note. Command filenames and paths are unchanged, and Claude Code output is byte-identical. diff --git a/.changeset/completion-detect-parent-shell.md b/.changeset/completion-detect-parent-shell.md deleted file mode 100644 index 255ce1c915..0000000000 --- a/.changeset/completion-detect-parent-shell.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -Fix `openspec completion install` detecting the wrong shell for fish (and other) -users whose interactive shell differs from their login shell. Detection now -consults the parent process before falling back to `$SHELL`, so running the -command from fish installs fish completions instead of defaulting to bash. diff --git a/.changeset/config-rules-cross-schema.md b/.changeset/config-rules-cross-schema.md deleted file mode 100644 index b37b44c819..0000000000 --- a/.changeset/config-rules-cross-schema.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -### Bug Fixes - -- Config `rules:` keys are no longer reported as `Unknown artifact ID` when they belong to a different schema. The global rules map is now validated against the union of artifact IDs across every available schema, so multi-schema projects stop seeing spurious warnings on every command (#1322). diff --git a/.changeset/design-proposal-boundary.md b/.changeset/design-proposal-boundary.md deleted file mode 100644 index ba25d51e08..0000000000 --- a/.changeset/design-proposal-boundary.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -Stop `design.md` from restating the proposal. In the default `spec-driven` schema, the design instruction asked for "Background, current state, constraints, stakeholders" and "What this design achieves and excludes" without saying that motivation and scope already live in `proposal.md`, so agents restated the proposal's Why and What Changes instead of adding the design's own value - approach, alternatives, and trade-offs. The instruction and the design template now state the boundary explicitly (the proposal covers why and what, design covers how) and tell the agent to reference those documents rather than repeat them (#1382). diff --git a/.changeset/devin-desktop-rename.md b/.changeset/devin-desktop-rename.md deleted file mode 100644 index f51bcf124b..0000000000 --- a/.changeset/devin-desktop-rename.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@fission-ai/openspec': patch ---- - -**Windsurf is now Devin Desktop.** Windsurf was rebranded on June 2, 2026 and its config directory moved: `.devin/` is the preferred read + write location, `.windsurf/` a legacy read-only fallback that the Devin Local agent does not read at all. OpenSpec follows the rename rather than carrying two ids for one product — the tool id is `devin`, writing `.devin/workflows/opsx-.md` and `.devin/skills/openspec-*/SKILL.md`, and it is detected from either directory. - -- `--tools windsurf` still resolves, so existing setup scripts keep working; it now configures `.devin/`. -- If your OpenSpec files are still in `.windsurf/`, `openspec update` explains the rebrand and offers to move them. `--force` and non-interactive runs take the move; declining leaves every file exactly where it is. Only the files OpenSpec generates move — each skill's `SKILL.md` and commands named `opsx-*`. A hand-written Cascade workflow, a reference file you keep beside a `SKILL.md`, a command file you edited, and `.devin/rules/` all stay exactly where they are. -- Devin skills and the getting-started hint reference `/openspec-*` skills rather than `/opsx-*` workflows, because only Devin Desktop reads workflows; the `/openspec-*` form works on both agents. Workflow bodies still use `/opsx-`, the name Devin registers for a workflow file. diff --git a/.changeset/doctor-store-drift.md b/.changeset/doctor-store-drift.md deleted file mode 100644 index d106b5d86e..0000000000 --- a/.changeset/doctor-store-drift.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -`openspec doctor` now notes when a store checkout is behind its upstream ref. diff --git a/.changeset/drift-check-multiplicity.md b/.changeset/drift-check-multiplicity.md deleted file mode 100644 index 5510ec28ec..0000000000 --- a/.changeset/drift-check-multiplicity.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -Make the archive scenario-drift check multiplicity-aware: a MODIFIED block that keeps only one of two same-named scenarios no longer silently drops the other. diff --git a/.changeset/explore-project-context.md b/.changeset/explore-project-context.md deleted file mode 100644 index 93ebb46dcf..0000000000 --- a/.changeset/explore-project-context.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -Explore now reads the project's context and rules from `openspec/config.yaml` (or `config.yml`) at the start of a session, so it reasons with the same tech stack and conventions the artifact-creating workflows already receive. diff --git a/.changeset/feedback-manual-fallback.md b/.changeset/feedback-manual-fallback.md deleted file mode 100644 index 1ef59f8004..0000000000 --- a/.changeset/feedback-manual-fallback.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -`openspec feedback` shows the formatted text and a pre-filled submission URL on any gh failure (issues disabled, network, rate limit), not only when gh is missing or unauthenticated. diff --git a/.changeset/feedback-missing-label-retry.md b/.changeset/feedback-missing-label-retry.md deleted file mode 100644 index 14354c30c7..0000000000 --- a/.changeset/feedback-missing-label-retry.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -Fix `openspec feedback` failing when the repository does not define the `feedback` label. The command now retries without the label and notes that it was not applied, instead of exiting with an error and discarding the feedback. diff --git a/.changeset/fence-aware-delta-parsing.md b/.changeset/fence-aware-delta-parsing.md deleted file mode 100644 index a9237952ff..0000000000 --- a/.changeset/fence-aware-delta-parsing.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -### Fixed - -- Ignore Markdown structure (requirement headers, delta sections, scenarios, REMOVED/RENAMED entries) that appears inside fenced code blocks when parsing delta specs. Previously a fenced `### Requirement:` example was parsed as a real (phantom) requirement, producing spurious `validate` errors and risking incorrect `archive` output. Fenced-code detection is now shared across the Markdown parsers so `validate` and `archive` behave consistently. diff --git a/.changeset/fence-aware-drift-check.md b/.changeset/fence-aware-drift-check.md deleted file mode 100644 index 5e85c7a6dd..0000000000 --- a/.changeset/fence-aware-drift-check.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -The archive scenario-drift check now ignores `#### Scenario:` lines inside fenced code blocks, matching validate: a fenced example no longer false-aborts an archive, and a fenced name no longer masks a genuinely dropped scenario. diff --git a/.changeset/fix-archive-date-prefix-dedup.md b/.changeset/fix-archive-date-prefix-dedup.md deleted file mode 100644 index de6a686e1f..0000000000 --- a/.changeset/fix-archive-date-prefix-dedup.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -### Bug Fixes - -- **`archive` no longer stacks a second date prefix** — archiving a change whose name already starts with a `YYYY-MM-DD-` prefix (a common authoring convention) keeps the name as-is instead of prepending today's date. Previously `openspec archive 2026-07-04-voice-copilot-v1 --yes` produced `2026-07-06-2026-07-04-voice-copilot-v1`, and when run on a later day the folder sorted under a day on which the change did not happen. Names without a full date prefix (including partial dates like `2026-07-feature`) are dated as before, and the naming is now idempotent. diff --git a/.changeset/fix-powershell-empty-switch.md b/.changeset/fix-powershell-empty-switch.md deleted file mode 100644 index 29aa72eecb..0000000000 --- a/.changeset/fix-powershell-empty-switch.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -fix(completion): make the PowerShell completion script parse and load again - -The generated `OpenSpecCompletion.ps1` contained 18 empty `switch ($positionalIndex) { }` blocks — emitted for commands whose positionals are all `path`-typed (PowerShell completes paths natively, so those cases produce no clauses). A switch with no clauses is a PowerShell parse error ("Missing condition in switch statement clause"), and PowerShell parses the whole file before running it, so the script never loaded and completions never registered. The generator now skips the positional-index block entirely when no positional produces completions, so the script parses clean (18 → 0 errors) and tab completion works. diff --git a/.changeset/fix-template-archive-date-dedup.md b/.changeset/fix-template-archive-date-dedup.md deleted file mode 100644 index 866661fd3b..0000000000 --- a/.changeset/fix-template-archive-date-dedup.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -### Bug Fixes - -- **Archive workflow templates no longer teach agents to stack a second date prefix** — the `openspec-archive-change` and `openspec-bulk-archive-change` skill/command templates (and the onboarding walkthrough's archived-path example) now mirror the `openspec archive` rule: a change whose name already starts with a `YYYY-MM-DD-` prefix is archived under its own name, while other names get the current date prepended as before. Previously an agent following the workflow instructions on a change named `2026-07-04-voice-copilot-v1` produced `archive/2026-07-07-2026-07-04-voice-copilot-v1`, whatever the CLI did. diff --git a/.changeset/gemini-toml-escaping.md b/.changeset/gemini-toml-escaping.md deleted file mode 100644 index 4df52a851a..0000000000 --- a/.changeset/gemini-toml-escaping.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -Gemini command files escape TOML-active characters (quotes, backslashes, control characters) in the description and prompt, so a template value containing them can no longer produce an invalid `.toml` file. diff --git a/.changeset/generic-ask-user-guidance.md b/.changeset/generic-ask-user-guidance.md deleted file mode 100644 index c38544f519..0000000000 --- a/.changeset/generic-ask-user-guidance.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@fission-ai/openspec': patch ---- - -Workflow skills and commands no longer tell agents to use the Claude Code-only AskUserQuestion tool. The same templates are generated for every supported tool, and agents without that tool (OpenCode, Factory Droid, Codex, and others) errored or stalled on the instruction. The guidance is now runtime-neutral: agents are simply told to ask the user. diff --git a/.changeset/generic-todo-tracking.md b/.changeset/generic-todo-tracking.md deleted file mode 100644 index 58916679f3..0000000000 --- a/.changeset/generic-todo-tracking.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -### Bug Fixes - -- **Propose and fast-forward skills no longer name the Claude-only TodoWrite tool** — the generated `openspec-propose` and `openspec-ff-change` skills (and their `/opsx:propose` / `/opsx:ff` commands) told every agent to "Use the **TodoWrite tool**", which only exists in Claude Code. Codex, Cursor, Gemini, Copilot, and the other supported tools have no such tool, so agents either errored or stalled looking for it. The instruction is now runtime-neutral ("Use a todo list to track progress"), which works everywhere — including Claude Code. diff --git a/.changeset/harden-config-key-paths.md b/.changeset/harden-config-key-paths.md deleted file mode 100644 index f3f29a0d5b..0000000000 --- a/.changeset/harden-config-key-paths.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -Reject config key paths that reach the prototype chain, and update the bundled `yaml` dependency. - -`openspec config set --allow-unknown __proto__.polluted ` reported success and assigned onto `Object.prototype` for the rest of the process. `--allow-unknown` was meant to relax the known-key check only, but it skipped every key check, so `__proto__`, `constructor`, and `prototype` segments reached the nested-write helper. Those segments are now rejected in `config set` whether or not `--allow-unknown` is passed, and `setNestedValue` / `deleteNestedValue` refuse them regardless of caller. Ordinary keys such as `featureFlags.myFlag` behave exactly as before. - -The `yaml` runtime dependency moves from 2.8.2 to 2.9.0, picking up the fix for a stack overflow on deeply nested input (GHSA / advisory patched in 2.8.3). diff --git a/.changeset/idempotent-added-archive.md b/.changeset/idempotent-added-archive.md deleted file mode 100644 index 63e38ba44d..0000000000 --- a/.changeset/idempotent-added-archive.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -### Bug Fixes - -- **Archive after early sync** — `openspec archive` no longer fails with `ADDED failed … already exists` when a change's specs were already synced to the main specs before archiving (the early-sync pattern from the `sync` workflow). If an ADDED requirement already exists in the target spec with identical content, applying it is treated as a no-op; a same-named requirement with different content still aborts the archive as a genuine conflict (#1332). diff --git a/.changeset/idempotent-renamed-archive.md b/.changeset/idempotent-renamed-archive.md deleted file mode 100644 index 6306dfe59e..0000000000 --- a/.changeset/idempotent-renamed-archive.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -### Bug Fixes - -- **Archive after early sync (RENAMED)** — `openspec archive` no longer fails with `RENAMED failed … source not found` when a change's renames were already synced to the main specs before archiving (the early-sync pattern from the `sync` workflow). If a RENAMED requirement's source header is gone but the target header exists in the spec, applying the rename is treated as a no-op; a rename whose source and target are both missing still aborts the archive as a genuine error, and reported counts reflect only renames actually applied. diff --git a/.changeset/init-no-animation.md b/.changeset/init-no-animation.md deleted file mode 100644 index 196838d2bd..0000000000 --- a/.changeset/init-no-animation.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@fission-ai/openspec': patch ---- - -Respect reduced-motion preferences in `openspec init`: the welcome animation is skipped when the OS reduced-motion setting is on (macOS Reduce Motion, GNOME animations disabled), when `OPENSPEC_NO_ANIMATION` is set, or when the new `--no-animation` flag is passed. The static welcome screen is shown instead. diff --git a/.changeset/instruction-field-authority.md b/.changeset/instruction-field-authority.md deleted file mode 100644 index 087413289b..0000000000 --- a/.changeset/instruction-field-authority.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -### Bug Fixes - -- **Custom schema instructions are no longer overridden by hard-coded spec-driven patterns** — the `openspec-continue-change` skill/command embedded one-line "common artifact patterns" for proposal.md, specs, design.md, and tasks.md, so agents followed those shortcuts instead of the schema's `instruction` field whenever a custom schema reused familiar artifact names. The templates now state that the `instruction` field is the authoritative guidance, and the `propose`, `continue`, and `ff` workflows direct the agent — both in the artifact-creation step and in the guidelines — to invoke a skill when the instruction delegates artifact creation to one, verifying the artifact exists afterward (fixes #777). diff --git a/.changeset/kimi-cli-to-kimi-code.md b/.changeset/kimi-cli-to-kimi-code.md deleted file mode 100644 index 8daaf5b268..0000000000 --- a/.changeset/kimi-cli-to-kimi-code.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -Follow the Kimi CLI rename to Kimi Code: new install paths with automatic migration of existing `.kimi` setups. diff --git a/.changeset/linear-heading-parse.md b/.changeset/linear-heading-parse.md deleted file mode 100644 index fdec93518e..0000000000 --- a/.changeset/linear-heading-parse.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -Parse spec headings in linear time when the title is padded with whitespace. - -Building the reference index read the first Purpose line with a regex that backtracked quadratically on a heading full of spaces: 10,000 characters of padding took 60ms, and 100,000 would have taken roughly six seconds. The heading scan is now hand-rolled and linear. Behavior is unchanged — the replacement was checked against the old implementation across 303,000 generated inputs, including CommonMark closing sequences (`## Purpose ##`), seven-hash lines, and headings with no space after the hashes. diff --git a/.changeset/local-dates-cli.md b/.changeset/local-dates-cli.md deleted file mode 100644 index b26946abef..0000000000 --- a/.changeset/local-dates-cli.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -Use local dates for CLI date-only values (archive names, timestamps) instead of UTC, so late-evening archives no longer get tomorrow's date. diff --git a/.changeset/missing-core-workflows-warning.md b/.changeset/missing-core-workflows-warning.md deleted file mode 100644 index 959c93269c..0000000000 --- a/.changeset/missing-core-workflows-warning.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -`openspec update` warns when a custom profile is missing core workflows instead of silently generating a partial install. diff --git a/.changeset/modern-tigers-laugh.md b/.changeset/modern-tigers-laugh.md deleted file mode 100644 index 573064c8ae..0000000000 --- a/.changeset/modern-tigers-laugh.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -Update current Roo Code product references to its community successor, Zoo Code. diff --git a/.changeset/modified-noop-counting.md b/.changeset/modified-noop-counting.md deleted file mode 100644 index 7072974d0e..0000000000 --- a/.changeset/modified-noop-counting.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -Archive treats a MODIFIED delta whose content already matches the main spec as a no-op: a fully early-synced change now reports "Specs already in sync" instead of rewriting the file and claiming modifications. diff --git a/.changeset/multiselect-checkbox-markers.md b/.changeset/multiselect-checkbox-markers.md deleted file mode 100644 index caada04e08..0000000000 --- a/.changeset/multiselect-checkbox-markers.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -Render multi-select prompts with `[x]`/`[ ]` checkbox markers instead of radio-button icons. diff --git a/.changeset/nested-spec-discovery.md b/.changeset/nested-spec-discovery.md deleted file mode 100644 index 7a6881a164..0000000000 --- a/.changeset/nested-spec-discovery.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -Discover nested spec paths like `specs///spec.md` recursively and consistently across parse, apply, and archive. diff --git a/.changeset/profile-aware-onboarding-commands.md b/.changeset/profile-aware-onboarding-commands.md deleted file mode 100644 index 03f2ef9a73..0000000000 --- a/.changeset/profile-aware-onboarding-commands.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -Only advertise onboarding commands that will actually exist. The `openspec init` welcome screen and the `openspec update` "Getting started" summary listed `/opsx:new` and `/opsx:continue`, which the default `core` profile never generates, so users were told to run commands that did not exist. Both surfaces now list the commands for the installed workflows. The `init` and `update` completion hints also name the skill (`/openspec-propose`) instead of a command for tools that receive no command files — Codex, and any tool under skills-only delivery. diff --git a/.changeset/propose-includes-specs.md b/.changeset/propose-includes-specs.md deleted file mode 100644 index 137c69fc98..0000000000 --- a/.changeset/propose-includes-specs.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -### Fixed - -- **`/opsx:propose` and `/opsx:ff` no longer finish a change with no spec written.** The workflows listed only `proposal`/`design`/`tasks` and treated the apply phase's `tasks` artifact as the stop condition — but `status` marks an artifact `done` as soon as a matching file exists, so writing `tasks.md` early satisfied the loop while `specs//spec.md` was never created (a spec-less change in a spec-driven tool). The loop now derives the full required set — every apply dependency plus everything it transitively `requires` — from a single `status` call, creates each missing artifact, and only skips one when its own `instruction` field marks it conditional. (#1260, #788) - -### Changed - -- **`openspec status --json` now reports each artifact's `requires` edges.** Every entry in the `artifacts` array carries a `requires` array of the ids it directly depends on, present for every status (including `done`) so agents can compute the transitive required set from `status` alone. Additive and backward-compatible — existing fields are unchanged. diff --git a/.changeset/qwen-markdown-commands.md b/.changeset/qwen-markdown-commands.md deleted file mode 100644 index 6f74472c9d..0000000000 --- a/.changeset/qwen-markdown-commands.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@fission-ai/openspec': patch ---- - -Generate Markdown commands for Qwen Code instead of deprecated TOML format. Qwen Code now recommends Markdown custom commands with YAML frontmatter; the old `.qwen/commands/opsx-*.toml` files are cleaned up as legacy artifacts on update. diff --git a/.changeset/renamed-near-miss-guard.md b/.changeset/renamed-near-miss-guard.md deleted file mode 100644 index b852a8ef15..0000000000 --- a/.changeset/renamed-near-miss-guard.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -An already-synced RENAMED delta aborts when a case/whitespace variant of the source requirement still exists — the same typo guard REMOVED deltas have. diff --git a/.changeset/reread-dependencies-before-regenerating.md b/.changeset/reread-dependencies-before-regenerating.md deleted file mode 100644 index 6fd81540f9..0000000000 --- a/.changeset/reread-dependencies-before-regenerating.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -### Fixes - -- **Regenerated artifacts now pick up your manual edits** — the continue, propose, and fast-forward workflows (and the `openspec instructions` dependency block) now tell the agent to re-read dependency artifacts from disk before creating the next one, instead of trusting whatever version it saw earlier in the conversation. Previously, editing `spec.md` and deleting `design.md`/`tasks.md` to regenerate them could silently produce artifacts based on the stale, pre-edit content. diff --git a/.changeset/resolve-open-questions.md b/.changeset/resolve-open-questions.md deleted file mode 100644 index 731e1bc285..0000000000 --- a/.changeset/resolve-open-questions.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -Proposal guidance now resolves blocking open questions with the user instead of deferring them to design.md. diff --git a/.changeset/root-level-delta-spec.md b/.changeset/root-level-delta-spec.md deleted file mode 100644 index bb5567f944..0000000000 --- a/.changeset/root-level-delta-spec.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -### Fixed - -- Stop a delta spec written directly at a change's `specs/` root from being silently dropped. `validate` accepted `specs/spec.md` and counted its deltas, but the apply/archive merge only reads capability folders (`specs//spec.md`), so the change could pass validation and be archived while its requirements never reached `openspec/specs/`. `validate` now uses the same discovery rules as the merge path and reports the misplaced file with a fix hint, and `archive` blocks instead of completing. diff --git a/.changeset/runtime-operation-guidance.md b/.changeset/runtime-operation-guidance.md deleted file mode 100644 index 2b85aef53d..0000000000 --- a/.changeset/runtime-operation-guidance.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@fission-ai/openspec": minor ---- - -Add current project context and per-operation guidance to apply and archive workflows. Projects can configure `operations.apply.guidance` and `operations.archive.guidance`; `openspec instructions apply` returns apply inputs, and the new read-only `openspec instructions archive` surface returns archive inputs for the selected root. - -Archive, bulk archive, and sync skills now load current archive inputs and `specs` artifact rules at execution time, fail before writes or moves when required instruction lookups fail, and reuse specs-rule snapshots during inline sync. diff --git a/.changeset/schema-declared-artifact-order.md b/.changeset/schema-declared-artifact-order.md deleted file mode 100644 index 73162ddeff..0000000000 --- a/.changeset/schema-declared-artifact-order.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@fission-ai/openspec': patch ---- - -Order artifacts by the schema's declaration order instead of alphabetically. - -`specs` and `design` both require only `proposal`, so both become ready at once - and the tie used to be broken alphabetically, which put `design` first. `openspec status` listed design above specs and `nextSteps` recommended writing `design.md` before any spec existed, contradicting the spec-driven schema's own documented `proposal → specs → design → tasks` sequence. - -Ties now follow the order the schema declares its artifacts, so `openspec status`, `status --json`, `nextSteps`, `blocked by:` lists, and an artifact's `unlocks` all agree. No dependency edges changed, so nothing newly blocks and `design.md` stays optional - only the order of equally-ready artifacts moved. Custom schemas get the same guarantee: dependency order still comes first, but wherever your schema leaves two artifacts equally ready, the order of its `artifacts:` list now decides which one the CLI recommends - so reorder that list if it was never deliberate. diff --git a/.changeset/schema-init-validates-before-force.md b/.changeset/schema-init-validates-before-force.md deleted file mode 100644 index c7b4f82865..0000000000 --- a/.changeset/schema-init-validates-before-force.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -### Bug Fixes - -- Preserve an existing project-local schema when `openspec schema init --force` rejects an unknown artifact ID. Forced replacement now begins only after artifact validation succeeds. diff --git a/.changeset/show-resolves-proposalless-changes.md b/.changeset/show-resolves-proposalless-changes.md deleted file mode 100644 index 918c07f242..0000000000 --- a/.changeset/show-resolves-proposalless-changes.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@fission-ai/openspec': patch ---- - -Change lookup no longer requires `proposal.md`. `openspec show`, `openspec change list/show/validate`, and shell completion now resolve a change by its directory, matching `openspec list`, `status`, `instructions`, and `validate`. - -Previously a change created by `openspec new change` — which scaffolds only `.openspec.yaml` — was reported as `Unknown item` by `openspec show` and was missing from completions and `openspec change list` until a proposal was written, and a change from a schema with no proposal artifact was never resolvable. `openspec change list` now reports the same set as `openspec list`, keeps task counts for a change that has no proposal yet, and labels it `(no proposal.md yet)` rather than `(unable to read)`. Showing such a change explains that the proposal is not written yet and points at `openspec status --change `. diff --git a/.changeset/single-change-autoselect.md b/.changeset/single-change-autoselect.md deleted file mode 100644 index 07356cc515..0000000000 --- a/.changeset/single-change-autoselect.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@fission-ai/openspec': patch ---- - -The continue, update, verify, sync, and archive workflow skills now select a change the same way apply does: use the provided name, infer it from conversation context, auto-select when exactly one active change exists, and only prompt when the choice is genuinely ambiguous. Previously these workflows were told to always prompt ("Do NOT guess or auto-select"), so invoking them with a single active change stalled on a question with only one possible answer. The selection is always announced ("Using change: ") with how to override, and bulk archive still always prompts. diff --git a/.changeset/skills-only-references.md b/.changeset/skills-only-references.md deleted file mode 100644 index bf0d25f16e..0000000000 --- a/.changeset/skills-only-references.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@fission-ai/openspec': patch ---- - -Fix skills-only delivery emitting `/opsx:*` command references. SKILL.md files generated by init, update, and workspace skill setup now reference the corresponding skills (e.g. `/openspec-apply-change`) when `delivery: 'skills'` is configured, instead of commands that were never generated. diff --git a/.changeset/skills-sh-distribution.md b/.changeset/skills-sh-distribution.md deleted file mode 100644 index 84ab95a6f9..0000000000 --- a/.changeset/skills-sh-distribution.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": minor ---- - -Publish the workflow skills as static `skills//SKILL.md` files so `npx skills add Fission-AI/OpenSpec` works. diff --git a/.changeset/skip-specs-explicit-zero-delta.md b/.changeset/skip-specs-explicit-zero-delta.md deleted file mode 100644 index edd0886c2d..0000000000 --- a/.changeset/skip-specs-explicit-zero-delta.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": minor ---- - -Add `skip_specs: true` change metadata for work with no spec-level behavior change (pure refactors, tooling, docs). `openspec validate` accepts a zero-delta change that declares the marker (honored only when the metadata parses under the shared change-metadata schema and names a schema that loads) and errors when the marker and delta specs are both present, the artifact graph no longer blocks `tasks` on spec files for such changes, `openspec status` renders the specs stage as explicitly skipped, and the propose/specs guidance points to the marker instead of contradicting the validator. diff --git a/.changeset/spec-content-guidance.md b/.changeset/spec-content-guidance.md deleted file mode 100644 index d5fca0ad94..0000000000 --- a/.changeset/spec-content-guidance.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -Specs instructions include the spec content guidance from the concepts docs, so generated specs follow the requirement/scenario format. diff --git a/.changeset/static-welcome-waits.md b/.changeset/static-welcome-waits.md deleted file mode 100644 index 25dfe55356..0000000000 --- a/.changeset/static-welcome-waits.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -The static welcome screen (reduced motion, `--no-animation`, narrow terminals) now waits for the Enter it asks for instead of letting the keystroke submit the tool picker unseen. diff --git a/.changeset/store-aware-main-specs.md b/.changeset/store-aware-main-specs.md deleted file mode 100644 index 4de9d453dd..0000000000 --- a/.changeset/store-aware-main-specs.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -Sync and archive workflows resolve main specs through the store-aware root instead of assuming `openspec/specs` in the repo. diff --git a/.changeset/symlinked-schema-dirs.md b/.changeset/symlinked-schema-dirs.md deleted file mode 100644 index 1b1c80bf6b..0000000000 --- a/.changeset/symlinked-schema-dirs.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": minor ---- - -Resolve symlinked schema directories so schemas shared via symlink (e.g. from a dotfiles repo) are discovered. diff --git a/.changeset/sync-specs-main-spec-format.md b/.changeset/sync-specs-main-spec-format.md deleted file mode 100644 index 411109f3ee..0000000000 --- a/.changeset/sync-specs-main-spec-format.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -Show the main spec format in the sync-specs skill so agents stop leaving delta operation headers (`## ADDED/MODIFIED Requirements`) in `openspec/specs/` — merged main specs with those headers parse as 0 requirements in `openspec view` (#1120). diff --git a/.changeset/telemetry-without-posthog-node.md b/.changeset/telemetry-without-posthog-node.md deleted file mode 100644 index b27975a767..0000000000 --- a/.changeset/telemetry-without-posthog-node.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -Telemetry no longer depends on `posthog-node`: the single usage event is sent with a plain fetch to the same endpoint. Installing OpenSpec no longer pulls the fast-publishing `posthog-node`/`@posthog/core`/`@posthog/types` tree, which broke downstream installs under supply-chain age policies like pnpm's `minimumReleaseAge` (#1390). diff --git a/.changeset/update-check-detection-hardening.md b/.changeset/update-check-detection-hardening.md deleted file mode 100644 index fa54f8cef0..0000000000 --- a/.changeset/update-check-detection-hardening.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -The stale-CLI check hardens its install detection: a directory merely named `volta` no longer changes the upgrade hint, the Windows npm-ownership check corroborates against the `openspec.cmd` shim npm actually writes, and a registry redirect from https to plain http is no longer followed. diff --git a/.changeset/update-check-redirect-teardown.md b/.changeset/update-check-redirect-teardown.md deleted file mode 100644 index 069f445f14..0000000000 --- a/.changeset/update-check-redirect-teardown.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -The stale-CLI check tears down a redirected registry connection when its time budget expires instead of leaving the socket open. diff --git a/.changeset/update-detects-command-only-tools.md b/.changeset/update-detects-command-only-tools.md deleted file mode 100644 index c65d98a112..0000000000 --- a/.changeset/update-detects-command-only-tools.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@fission-ai/openspec': patch ---- - -`openspec update` now refreshes tools that are configured with command files but no skills (delivery `commands`). Previously it read the generating version only from skill files, so such a tool was reported as "up to date" forever and its command files were never regenerated after a CLI upgrade. Command files carry no version stamp, so OpenSpec compares their contents against what it would generate now — including removing a command file left behind by a workflow you have since deselected. CRLF line endings and a UTF-8 BOM are treated as checkout artifacts rather than drift, so a Windows clone does not report a spurious update. diff --git a/.changeset/update-flags-stale-cli.md b/.changeset/update-flags-stale-cli.md deleted file mode 100644 index 418d6ee17f..0000000000 --- a/.changeset/update-flags-stale-cli.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -"@fission-ai/openspec": minor ---- - -`openspec update` now offers to upgrade the CLI when yours is behind the published one. Instruction files are generated by the installed CLI, so a stale install reported `✓ All 1 tool(s) up to date (v1.6.0)` while the workflows added in newer releases were never written: - -```text -A newer OpenSpec CLI is available (v1.6.0 → v1.7.0). - Running from: /usr/local/lib/node_modules/@fission-ai/openspec -? Upgrade to v1.7.0 now? (Y/n) -``` - -Say yes and it upgrades, confirms the new version is the one that answers, then re-runs the update so the new workflows arrive in the same command. Say no and it prints the command matching how you installed OpenSpec, and updates with what you have. Nothing happens to your machine that you did not agree to: the offer appears only in an interactive terminal and only where `npm install -g` would help, and the check is skipped in CI or when `OPENSPEC_NO_UPDATE_CHECK`, `DO_NOT_TRACK=1`, or `OPENSPEC_TELEMETRY=0` is set. - -See [CLI reference → `openspec update`](https://github.com/Fission-AI/OpenSpec/blob/main/docs/cli.md#openspec-update) for the per-install-method behavior and every opt-out. diff --git a/.changeset/update-zero-artifact-notice.md b/.changeset/update-zero-artifact-notice.md deleted file mode 100644 index e84c1a6bc5..0000000000 --- a/.changeset/update-zero-artifact-notice.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -`openspec update` with `delivery: commands` prints the same configuration correction as init when it removes the skills of a tool that supports only skills, instead of deleting them silently. diff --git a/.changeset/validator-unreadable-specs.md b/.changeset/validator-unreadable-specs.md deleted file mode 100644 index 0f584da9ce..0000000000 --- a/.changeset/validator-unreadable-specs.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -`openspec validate` reports an unreadable specs/ directory as the error it is instead of misdiagnosing it as "no deltas found". diff --git a/.changeset/view-resolves-store-pointer.md b/.changeset/view-resolves-store-pointer.md deleted file mode 100644 index 15f3f49c34..0000000000 --- a/.changeset/view-resolves-store-pointer.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@fission-ai/openspec': patch ---- - -`openspec view` now resolves the configured OpenSpec root instead of always reading the current directory, and accepts `--store ` like its sibling commands. Projects whose `openspec/config.yaml` points at an external store saw an empty dashboard — 0 specs, 0 requirements — while `openspec list` read the same store correctly. diff --git a/.changeset/windows-welcome-input.md b/.changeset/windows-welcome-input.md deleted file mode 100644 index 423362ed35..0000000000 --- a/.changeset/windows-welcome-input.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -Preserve keyboard input on Windows after the welcome screen instead of dropping the first keystrokes. diff --git a/.changeset/zsh-completions-custom-omz.md b/.changeset/zsh-completions-custom-omz.md deleted file mode 100644 index 12bcc08f11..0000000000 --- a/.changeset/zsh-completions-custom-omz.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fission-ai/openspec": patch ---- - -zsh completion install honors `$ZSH` and `$ZSH_CUSTOM`, so Oh My Zsh setups at custom locations get the completion where their shell actually loads it. diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d9d313cf3..86d97fb50e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,254 @@ # @fission-ai/openspec +## 1.7.0 + +### Minor Changes + +- [#1475](https://github.com/Fission-AI/OpenSpec/pull/1475) [`17af60c`](https://github.com/Fission-AI/OpenSpec/commit/17af60c66e4c049e3986fdbafcdc16b202cda59f) Thanks [@clay-good](https://github.com/clay-good)! - Add CodeArts Agent skills support: `openspec init --tools codeartsagent` installs the workflow skills. + +- [#1475](https://github.com/Fission-AI/OpenSpec/pull/1475) [`17af60c`](https://github.com/Fission-AI/OpenSpec/commit/17af60c66e4c049e3986fdbafcdc16b202cda59f) Thanks [@clay-good](https://github.com/clay-good)! - Add Hermes Agent as a supported AI tool: `openspec init --tools hermes` installs the workflow skills (Hermes is skills-only and invokes them directly). + +- [#1475](https://github.com/Fission-AI/OpenSpec/pull/1475) [`17af60c`](https://github.com/Fission-AI/OpenSpec/commit/17af60c66e4c049e3986fdbafcdc16b202cda59f) Thanks [@clay-good](https://github.com/clay-good)! - Add ZCode as a supported AI tool: `openspec init --tools zcode` generates its skills and `/opsx:*` commands. + +- [#1475](https://github.com/Fission-AI/OpenSpec/pull/1475) [`17af60c`](https://github.com/Fission-AI/OpenSpec/commit/17af60c66e4c049e3986fdbafcdc16b202cda59f) Thanks [@clay-good](https://github.com/clay-good)! - Codex is now skills-only: workflows install as `$openspec-*` skills and previously managed custom prompts are retired (existing ones are cleaned up on update). + +- [#1062](https://github.com/Fission-AI/OpenSpec/pull/1062) [`eac2973`](https://github.com/Fission-AI/OpenSpec/commit/eac2973819037727b10214f70db2f54d82f2d891) Thanks [@showms](https://github.com/showms)! - Add current project context and per-operation guidance to apply and archive workflows. Projects can configure `operations.apply.guidance` and `operations.archive.guidance`; `openspec instructions apply` returns apply inputs, and the new read-only `openspec instructions archive` surface returns archive inputs for the selected root. + + Archive, bulk archive, and sync skills now load current archive inputs and `specs` artifact rules at execution time, fail before writes or moves when required instruction lookups fail, and reuse specs-rule snapshots during inline sync. + +- [#1475](https://github.com/Fission-AI/OpenSpec/pull/1475) [`17af60c`](https://github.com/Fission-AI/OpenSpec/commit/17af60c66e4c049e3986fdbafcdc16b202cda59f) Thanks [@clay-good](https://github.com/clay-good)! - Publish the workflow skills as static `skills//SKILL.md` files so `npx skills add Fission-AI/OpenSpec` works. + +- [#1399](https://github.com/Fission-AI/OpenSpec/pull/1399) [`27b22ab`](https://github.com/Fission-AI/OpenSpec/commit/27b22ab4cbf530fa00e17f0f6b75a44d56777542) Thanks [@clay-good](https://github.com/clay-good)! - Add `skip_specs: true` change metadata for work with no spec-level behavior change (pure refactors, tooling, docs). `openspec validate` accepts a zero-delta change that declares the marker (honored only when the metadata parses under the shared change-metadata schema and names a schema that loads) and errors when the marker and delta specs are both present, the artifact graph no longer blocks `tasks` on spec files for such changes, `openspec status` renders the specs stage as explicitly skipped, and the propose/specs guidance points to the marker instead of contradicting the validator. + +- [#1475](https://github.com/Fission-AI/OpenSpec/pull/1475) [`17af60c`](https://github.com/Fission-AI/OpenSpec/commit/17af60c66e4c049e3986fdbafcdc16b202cda59f) Thanks [@clay-good](https://github.com/clay-good)! - Resolve symlinked schema directories so schemas shared via symlink (e.g. from a dotfiles repo) are discovered. + +- [#1470](https://github.com/Fission-AI/OpenSpec/pull/1470) [`6295515`](https://github.com/Fission-AI/OpenSpec/commit/6295515d4da4f7c76eaed00b7f1926771eae92de) Thanks [@clay-good](https://github.com/clay-good)! - `openspec update` now offers to upgrade the CLI when yours is behind the published one. Instruction files are generated by the installed CLI, so a stale install reported `✓ All 1 tool(s) up to date (v1.6.0)` while the workflows added in newer releases were never written: + + ```text + A newer OpenSpec CLI is available (v1.6.0 → v1.7.0). + Running from: /usr/local/lib/node_modules/@fission-ai/openspec + ? Upgrade to v1.7.0 now? (Y/n) + ``` + + Say yes and it upgrades, confirms the new version is the one that answers, then re-runs the update so the new workflows arrive in the same command. Say no and it prints the command matching how you installed OpenSpec, and updates with what you have. Nothing happens to your machine that you did not agree to: the offer appears only in an interactive terminal and only where `npm install -g` would help, and the check is skipped in CI or when `OPENSPEC_NO_UPDATE_CHECK`, `DO_NOT_TRACK=1`, or `OPENSPEC_TELEMETRY=0` is set. + + See [CLI reference → `openspec update`](https://github.com/Fission-AI/OpenSpec/blob/main/docs/cli.md#openspec-update) for the per-install-method behavior and every opt-out. + +### Patch Changes + +- [#1404](https://github.com/Fission-AI/OpenSpec/pull/1404) [`a84ae70`](https://github.com/Fission-AI/OpenSpec/commit/a84ae70e8c6ef6ffaab56599d6f91fa39873e63d) Thanks [@clay-good](https://github.com/clay-good)! - Generated skills for tools without a command adapter (Kimi Code, Mistral Vibe, Hermes, ForgeCode, CodeArts) no longer reference `/opsx:*` commands that were never generated: skill cross-references, the init getting-started hint, and the profile-migration message now use each tool's documented skill invocation (Kimi Code: `/skill:openspec-*`; others: `/openspec-*`), and Codex — skills-invocable with no slash surface — gets a syntax-neutral hint that names the skill. Selections that mix invocation syntaxes print one labeled hint per distinct form, so every advertised instruction is usable by the tool it names. When `delivery: commands` would generate nothing for a selected tool, init prints a configuration correction naming that tool, even when other tools did get commands or skills. The committed skills.sh distribution is regenerated with skill references (default `/openspec-*` form, as that channel installs skills only). + +- [#1363](https://github.com/Fission-AI/OpenSpec/pull/1363) [`5199f41`](https://github.com/Fission-AI/OpenSpec/commit/5199f41a5d523b9212dd2854ec5e505d2f80e2e7) Thanks [@clay-good](https://github.com/clay-good)! - ### Features + + - **One default store for every repo on your machine** — `openspec config set defaultStore ` sets a machine-level fallback root: any command run outside a planning root, with no `--store` flag and no project `store:` pointer, resolves to that store. It sits at the bottom of the precedence list, so `--store`, a local root, and a project pointer all still win. The root banner and JSON `root` block report the distinct provenance `source: "global_default"`, so users and tooling can tell a machine-wide default from a repo's own pointer. A stale id degrades to the underlying store error with a fix that names `openspec config unset defaultStore`. + +- [#1435](https://github.com/Fission-AI/OpenSpec/pull/1435) [`6a5171e`](https://github.com/Fission-AI/OpenSpec/commit/6a5171e18630db4ed8e78c9edfaae4be532e2af6) Thanks [@clay-good](https://github.com/clay-good)! - `openspec new change` now accepts numeric-prefixed names like `100-add-feature` or `00001-add-auth`, useful for ordering or tiering changes. Change names now use the same kebab-case grammar as store ids and change metadata (a leading digit is allowed); `archive` already treated date-prefixed names as a supported convention. Uppercase, spaces, underscores, and leading/trailing or consecutive hyphens are still rejected, and every previously valid name stays valid. + +- [#1425](https://github.com/Fission-AI/OpenSpec/pull/1425) [`040a869`](https://github.com/Fission-AI/OpenSpec/commit/040a86931f5398167137a483b2e8081aec13016e) Thanks [@clay-good](https://github.com/clay-good)! - Compare config key guards literally instead of through a helper. + + `setNestedValue` and `deleteNestedValue` rejected prototype-reaching key segments through a helper that did a `Set` lookup. That is correct, but static analysis could not follow it, so CodeQL kept reporting prototype-pollution on the very assignments the guard protects. The segments are now compared literally in the same function, still checked across the whole path before anything is written. Behavior is unchanged for every input, verified against the previous implementation across 400,000 generated cases. + +- [#1431](https://github.com/Fission-AI/OpenSpec/pull/1431) [`6a4f0d7`](https://github.com/Fission-AI/OpenSpec/commit/6a4f0d7f3384486132cb9c516b635c23cadc1fa2) Thanks [@clay-good](https://github.com/clay-good)! - A delta spec that introduces a brand-new capability can now open with a `## Purpose`, and `openspec archive` uses it as the Purpose of the main spec it creates instead of writing the `TBD - created by archiving change . Update Purpose after archive.` placeholder over it. The `specs` artifact instruction, its example, the delta template and the `openspec-sync-specs` skill all tell authors and agents to write one, so the CLI and agent-driven sync paths produce the same main spec. + + Archive keeps the placeholder when the delta has no usable `## Purpose`: + + - no `## Purpose` header outside a code fence or HTML comment, or a body that is only a code fence or only a comment + - a body that would leave a spec its own parser cannot read — a heading or requirement header that truncates a section, an unterminated fence, or any HTML comment + - in the second case archive also says why, and still completes rather than aborting + + A carried Purpose under 50 characters is kept but warned about, since `openspec validate --strict` reports it as too brief. The Purpose of an existing main spec is never touched; archive warns when it ignores a delta's Purpose there. + +- [#1437](https://github.com/Fission-AI/OpenSpec/pull/1437) [`19d4171`](https://github.com/Fission-AI/OpenSpec/commit/19d41714c8b790488732687443713e406ef5aeef) Thanks [@clay-good](https://github.com/clay-good)! - `openspec archive` no longer aborts when a REMOVED delta's requirement is already gone from the main spec (the early-sync pattern the sync skill teaches): it warns, treats the removal as already applied, and reports applied-only totals. In `--json` mode those warnings are carried in a new optional `warnings` array on the archive result. When every operation for a spec was already synced, archive skips rewriting that file instead of churning normalization differences into it. A delta that both RENAMEs and REMOVEs the same requirement is now rejected explicitly, by both `validate` and `archive` — the two spellings are compared case- and whitespace-insensitively — and a REMOVED header that differs only in case or whitespace from an existing requirement still aborts (that is a typo, not an early sync). Also fixed: the archive delta gate matches section headers case-insensitively like the parser; symlinked `specs//spec.md` files are discovered instead of silently dropped; `openspec show ` no longer prints a spurious "scenarios" flag warning; files generated for qwen and bob reference commands by their real hyphenated names (`/opsx-`), and init's getting-started hint follows suit; apply/update/onboard guidance names the CLI fallback for profiles that don't install `/opsx:continue` or `/opsx:new`. + +- [#1411](https://github.com/Fission-AI/OpenSpec/pull/1411) [`c439a4e`](https://github.com/Fission-AI/OpenSpec/commit/c439a4ee48ef02dcdae6ac8101b7d12924695e7e) Thanks [@clay-good](https://github.com/clay-good)! - Fix phantom requirements parsed from delta specs, which made `openspec archive` warn about problems `openspec validate` never reported. + + A header inside a delta section that is not a `### Requirement:` header — a divider such as `### Documentation Requirements` — was read as a requirement with no scenario. `openspec archive` warned that it was missing a scenario, and `openspec show --json` and `openspec change list` counted it as an extra delta. The change parser now ignores those headers, matching the delta reader, so the phantom is gone from the warnings and from the JSON. Main spec parsing is unchanged. + + `openspec archive` also no longer repeats requirement-level issues from the delta specs in its non-blocking "Proposal warnings in proposal.md" block. Each defect was printed twice there, and a `## REMOVED Requirements` entry — names-only by design — was reported as missing a scenario on every correct removal. Delta spec validation still reports and blocks on genuine defects, and proposal-level warnings are unchanged. + +- [#1394](https://github.com/Fission-AI/OpenSpec/pull/1394) [`b474f81`](https://github.com/Fission-AI/OpenSpec/commit/b474f81cb4bebbeff0e447fd78c34a613ebd02fa) Thanks [@clay-good](https://github.com/clay-good)! - ### Bug Fixes + + - **Archive no longer races the spec sync, or reports a sync that never landed** — the generated `openspec-archive-change` skill (and the matching `opsx:archive` command) handed the spec sync to a background task and then moved the change folder immediately. The archive could move the delta specs out from under the running sync: the change ended up archived, `openspec/specs/` was never updated, and the summary still reported `Specs: ✓ Synced`. The sync now runs inline, and the archive only proceeds once every capability with a delta spec has been checked against it — ADDED present, MODIFIED changes applied, REMOVED gone, RENAMED under the new name and not the old. If the sync fails or a capability doesn't match, the archive stops and reports what differs instead of claiming success; nothing has moved, so you can fix it and retry. + +- [#1475](https://github.com/Fission-AI/OpenSpec/pull/1475) [`17af60c`](https://github.com/Fission-AI/OpenSpec/commit/17af60c66e4c049e3986fdbafcdc16b202cda59f) Thanks [@clay-good](https://github.com/clay-good)! - Apply profile changes with the installed CLI instead of shelling out to `npx`, which could run a different version. + +- [#1475](https://github.com/Fission-AI/OpenSpec/pull/1475) [`17af60c`](https://github.com/Fission-AI/OpenSpec/commit/17af60c66e4c049e3986fdbafcdc16b202cda59f) Thanks [@clay-good](https://github.com/clay-good)! - Delta and main-spec parsers strip a UTF-8 BOM, so files saved by Windows editors or PowerShell redirects no longer fail with "No delta sections found". + +- [#1398](https://github.com/Fission-AI/OpenSpec/pull/1398) [`97d441a`](https://github.com/Fission-AI/OpenSpec/commit/97d441a8ee2738d3008709e61acfc91925c7ae3a) Thanks [@clay-good](https://github.com/clay-good)! - ### Bug Fixes + + - **Bulk archive now stops when you pick "Cancel"** — the generated `openspec-bulk-archive-change` skill (and the matching `opsx:bulk-archive` command) offered a "Cancel" option at the confirmation prompt but never told the agent what to do with it, so the next step archived every selected change anyway. The prompt now routes each answer by intent: "Cancel" stops without archiving anything, the archive options proceed (the ready-only option archives just the changes the status table marks `Ready` or `Ready*`), and any other answer re-asks instead of archiving. The single-change archive skill already routes Cancel this way; this brings the bulk variant in line. + +- [#1375](https://github.com/Fission-AI/OpenSpec/pull/1375) [`52a8bce`](https://github.com/Fission-AI/OpenSpec/commit/52a8bce1fd2bc98c51fa35cf0cfa05e799eb4404) Thanks [@clay-good](https://github.com/clay-good)! - `--change` now accepts any change name that exists on disk (e.g. date-prefixed names like `2026-07-04-voice-copilot-v1`), matching what `list`, `validate`, and `archive` already resolve. Lookup still rejects unsafe names (path separators, `..`, hidden entries); the kebab-case naming rule still applies when creating a change. + +- [#1475](https://github.com/Fission-AI/OpenSpec/pull/1475) [`17af60c`](https://github.com/Fission-AI/OpenSpec/commit/17af60c66e4c049e3986fdbafcdc16b202cda59f) Thanks [@clay-good](https://github.com/clay-good)! - `openspec new change` rejects names over 200 characters with a validation message instead of surfacing a raw ENAMETOOLONG filesystem error. + +- [#1447](https://github.com/Fission-AI/OpenSpec/pull/1447) [`fb19699`](https://github.com/Fission-AI/OpenSpec/commit/fb196995dad017074415a638824eb546f3321cbc) Thanks [@hsusul](https://github.com/hsusul)! - Generated tool command files now carry valid YAML frontmatter for every supported tool. Command names ship as `OPSX: Explore`, and the unquoted `name: OPSX: Explore` that adapters emitted is not parseable YAML — strict parsers rejected the whole file, so the command failed to load. Several adapters also re-implemented their own escaping, and a few interpolated descriptions in raw. + + Escaping now lives in one place (`escapeYamlValue` / `formatTagsArray`) and every adapter uses it. String frontmatter values are always double-quoted, which also keeps values like `true`, `null` and `123` from round-tripping as booleans, nulls and numbers. Non-string fields such as `allowed-tools` and `invokable` are unchanged. Expect the first `openspec update` after upgrading to rewrite the frontmatter lines of your generated command files. + + Archive workflow guidance also gets two corrections: bulk archive now carries its per-delta include/exclude decisions into execution, so a delta whose implementation was not found is reported as `sync skipped` instead of being synced anyway, and both archive workflows verify the main specs before moving the change directory. + +- [#1471](https://github.com/Fission-AI/OpenSpec/pull/1471) [`9a937cb`](https://github.com/Fission-AI/OpenSpec/commit/9a937cb9b36fb1040bdbde3bab3fa3903944ef10) Thanks [@clay-good](https://github.com/clay-good)! - Reference slash commands by the name each tool actually registers. Command bodies, generated `SKILL.md` cross-references, and the `init`/`update`/migration hints all advertised `/opsx:`, but only 7 of the 28 tools with a command adapter register that name — the ones whose files sit in an `opsx/` directory. The other 21 write `.../opsx-.md`, where the filename is the command, so tools such as Cursor, GitHub Copilot, Windsurf and Kilo Code were told to type a command their palette never had; a single generated Cursor file named itself `/opsx-apply` in frontmatter and then told the reader to run `/opsx:apply`. The command _name_ is now derived from the command file each adapter writes rather than a hand-maintained tool list, so a newly added adapter cannot drift, and the _wrapper_ around it is adapter metadata: Amazon Q loads its files into a prompt library invoked with `@`, so it now gets `@opsx-` in command bodies, skills, and the onboarding hint instead of a slash command it never registers. Codex, which generates no command files at all, now gets `$openspec-` — the syntax its CLI actually accepts — everywhere it previously advertised `/opsx:*`, superseding the syntax-neutral hint described in the pending `adapterless-skill-references` note. Command filenames and paths are unchanged, and Claude Code output is byte-identical. + +- [#1364](https://github.com/Fission-AI/OpenSpec/pull/1364) [`f58b445`](https://github.com/Fission-AI/OpenSpec/commit/f58b4456925b6331f3e5902a1c57905afe7edbf5) Thanks [@clay-good](https://github.com/clay-good)! - Fix `openspec completion install` detecting the wrong shell for fish (and other) + users whose interactive shell differs from their login shell. Detection now + consults the parent process before falling back to `$SHELL`, so running the + command from fish installs fish completions instead of defaulting to bash. + +- [#1377](https://github.com/Fission-AI/OpenSpec/pull/1377) [`285dfd7`](https://github.com/Fission-AI/OpenSpec/commit/285dfd7d764752b2a1e7e8cc843d613421e62652) Thanks [@clay-good](https://github.com/clay-good)! - ### Bug Fixes + + - Config `rules:` keys are no longer reported as `Unknown artifact ID` when they belong to a different schema. The global rules map is now validated against the union of artifact IDs across every available schema, so multi-schema projects stop seeing spurious warnings on every command ([#1322](https://github.com/Fission-AI/OpenSpec/issues/1322)). + +- [#1401](https://github.com/Fission-AI/OpenSpec/pull/1401) [`b33b15d`](https://github.com/Fission-AI/OpenSpec/commit/b33b15d98ae929624c991632c7382ebc234d4ca7) Thanks [@clay-good](https://github.com/clay-good)! - Stop `design.md` from restating the proposal. In the default `spec-driven` schema, the design instruction asked for "Background, current state, constraints, stakeholders" and "What this design achieves and excludes" without saying that motivation and scope already live in `proposal.md`, so agents restated the proposal's Why and What Changes instead of adding the design's own value - approach, alternatives, and trade-offs. The instruction and the design template now state the boundary explicitly (the proposal covers why and what, design covers how) and tell the agent to reference those documents rather than repeat them ([#1382](https://github.com/Fission-AI/OpenSpec/issues/1382)). + +- [#1167](https://github.com/Fission-AI/OpenSpec/pull/1167) [`1637856`](https://github.com/Fission-AI/OpenSpec/commit/1637856c423f2e84457652d1ab58885fe9744fb2) Thanks [@mehdishahdoost](https://github.com/mehdishahdoost)! - **Windsurf is now Devin Desktop.** Windsurf was rebranded on June 2, 2026 and its config directory moved: `.devin/` is the preferred read + write location, `.windsurf/` a legacy read-only fallback that the Devin Local agent does not read at all. OpenSpec follows the rename rather than carrying two ids for one product — the tool id is `devin`, writing `.devin/workflows/opsx-.md` and `.devin/skills/openspec-*/SKILL.md`, and it is detected from either directory. + + - `--tools windsurf` still resolves, so existing setup scripts keep working; it now configures `.devin/`. + - If your OpenSpec files are still in `.windsurf/`, `openspec update` explains the rebrand and offers to move them. `--force` and non-interactive runs take the move; declining leaves every file exactly where it is. Only the files OpenSpec generates move — each skill's `SKILL.md` and commands named `opsx-*`. A hand-written Cascade workflow, a reference file you keep beside a `SKILL.md`, a command file you edited, and `.devin/rules/` all stay exactly where they are. + - Devin skills and the getting-started hint reference `/openspec-*` skills rather than `/opsx-*` workflows, because only Devin Desktop reads workflows; the `/openspec-*` form works on both agents. Workflow bodies still use `/opsx-`, the name Devin registers for a workflow file. + +- [#1475](https://github.com/Fission-AI/OpenSpec/pull/1475) [`17af60c`](https://github.com/Fission-AI/OpenSpec/commit/17af60c66e4c049e3986fdbafcdc16b202cda59f) Thanks [@clay-good](https://github.com/clay-good)! - `openspec doctor` now notes when a store checkout is behind its upstream ref. + +- [#1475](https://github.com/Fission-AI/OpenSpec/pull/1475) [`17af60c`](https://github.com/Fission-AI/OpenSpec/commit/17af60c66e4c049e3986fdbafcdc16b202cda59f) Thanks [@clay-good](https://github.com/clay-good)! - Make the archive scenario-drift check multiplicity-aware: a MODIFIED block that keeps only one of two same-named scenarios no longer silently drops the other. + +- [#1408](https://github.com/Fission-AI/OpenSpec/pull/1408) [`378d468`](https://github.com/Fission-AI/OpenSpec/commit/378d468ad348dc1e973ed30c5cfa458fb77c9de3) Thanks [@clay-good](https://github.com/clay-good)! - Explore now reads the project's context and rules from `openspec/config.yaml` (or `config.yml`) at the start of a session, so it reasons with the same tech stack and conventions the artifact-creating workflows already receive. + +- [#1475](https://github.com/Fission-AI/OpenSpec/pull/1475) [`17af60c`](https://github.com/Fission-AI/OpenSpec/commit/17af60c66e4c049e3986fdbafcdc16b202cda59f) Thanks [@clay-good](https://github.com/clay-good)! - `openspec feedback` shows the formatted text and a pre-filled submission URL on any gh failure (issues disabled, network, rate limit), not only when gh is missing or unauthenticated. + +- [#1396](https://github.com/Fission-AI/OpenSpec/pull/1396) [`60f720c`](https://github.com/Fission-AI/OpenSpec/commit/60f720c43acd94de7645ac8629c614ede4682b6a) Thanks [@clay-good](https://github.com/clay-good)! - Fix `openspec feedback` failing when the repository does not define the `feedback` label. The command now retries without the label and notes that it was not applied, instead of exiting with an error and discarding the feedback. + +- [#1151](https://github.com/Fission-AI/OpenSpec/pull/1151) [`18cbf5d`](https://github.com/Fission-AI/OpenSpec/commit/18cbf5d32ffe1bff4fff692e24568c605cf1e0fa) Thanks [@javigomez](https://github.com/javigomez)! - ### Fixed + + - Ignore Markdown structure (requirement headers, delta sections, scenarios, REMOVED/RENAMED entries) that appears inside fenced code blocks when parsing delta specs. Previously a fenced `### Requirement:` example was parsed as a real (phantom) requirement, producing spurious `validate` errors and risking incorrect `archive` output. Fenced-code detection is now shared across the Markdown parsers so `validate` and `archive` behave consistently. + +- [#1475](https://github.com/Fission-AI/OpenSpec/pull/1475) [`17af60c`](https://github.com/Fission-AI/OpenSpec/commit/17af60c66e4c049e3986fdbafcdc16b202cda59f) Thanks [@clay-good](https://github.com/clay-good)! - The archive scenario-drift check now ignores `#### Scenario:` lines inside fenced code blocks, matching validate: a fenced example no longer false-aborts an archive, and a fenced name no longer masks a genuinely dropped scenario. + +- [#1316](https://github.com/Fission-AI/OpenSpec/pull/1316) [`9b70481`](https://github.com/Fission-AI/OpenSpec/commit/9b70481df727ab9f7a00dd0118e4e09373a36fb9) Thanks [@mc856](https://github.com/mc856)! - ### Bug Fixes + + - **`archive` no longer stacks a second date prefix** — archiving a change whose name already starts with a `YYYY-MM-DD-` prefix (a common authoring convention) keeps the name as-is instead of prepending today's date. Previously `openspec archive 2026-07-04-voice-copilot-v1 --yes` produced `2026-07-06-2026-07-04-voice-copilot-v1`, and when run on a later day the folder sorted under a day on which the change did not happen. Names without a full date prefix (including partial dates like `2026-07-feature`) are dated as before, and the naming is now idempotent. + +- [#1374](https://github.com/Fission-AI/OpenSpec/pull/1374) [`da3907b`](https://github.com/Fission-AI/OpenSpec/commit/da3907b8a9170711c8b7f63e18352e8577cf7df5) Thanks [@clay-good](https://github.com/clay-good)! - fix(completion): make the PowerShell completion script parse and load again + + The generated `OpenSpecCompletion.ps1` contained 18 empty `switch ($positionalIndex) { }` blocks — emitted for commands whose positionals are all `path`-typed (PowerShell completes paths natively, so those cases produce no clauses). A switch with no clauses is a PowerShell parse error ("Missing condition in switch statement clause"), and PowerShell parses the whole file before running it, so the script never loaded and completions never registered. The generator now skips the positional-index block entirely when no positional produces completions, so the script parses clean (18 → 0 errors) and tab completion works. + +- [#1388](https://github.com/Fission-AI/OpenSpec/pull/1388) [`9b5d2cd`](https://github.com/Fission-AI/OpenSpec/commit/9b5d2cdd0c1aa4b1b49da4f95c6cec8d7d38b155) Thanks [@mc856](https://github.com/mc856)! - ### Bug Fixes + + - **Archive workflow templates no longer teach agents to stack a second date prefix** — the `openspec-archive-change` and `openspec-bulk-archive-change` skill/command templates (and the onboarding walkthrough's archived-path example) now mirror the `openspec archive` rule: a change whose name already starts with a `YYYY-MM-DD-` prefix is archived under its own name, while other names get the current date prepended as before. Previously an agent following the workflow instructions on a change named `2026-07-04-voice-copilot-v1` produced `archive/2026-07-07-2026-07-04-voice-copilot-v1`, whatever the CLI did. + +- [#1475](https://github.com/Fission-AI/OpenSpec/pull/1475) [`17af60c`](https://github.com/Fission-AI/OpenSpec/commit/17af60c66e4c049e3986fdbafcdc16b202cda59f) Thanks [@clay-good](https://github.com/clay-good)! - Gemini command files escape TOML-active characters (quotes, backslashes, control characters) in the description and prompt, so a template value containing them can no longer produce an invalid `.toml` file. + +- [#1464](https://github.com/Fission-AI/OpenSpec/pull/1464) [`5bcf057`](https://github.com/Fission-AI/OpenSpec/commit/5bcf05766a70ec0163c3e700a3029b1c1da895d8) Thanks [@clay-good](https://github.com/clay-good)! - Workflow skills and commands no longer tell agents to use the Claude Code-only AskUserQuestion tool. The same templates are generated for every supported tool, and agents without that tool (OpenCode, Factory Droid, Codex, and others) errored or stalled on the instruction. The guidance is now runtime-neutral: agents are simply told to ask the user. + +- [#1403](https://github.com/Fission-AI/OpenSpec/pull/1403) [`2d6c447`](https://github.com/Fission-AI/OpenSpec/commit/2d6c447100c51fb1e5f65c6f6a35ce02a3196a10) Thanks [@clay-good](https://github.com/clay-good)! - ### Bug Fixes + + - **Propose and fast-forward skills no longer name the Claude-only TodoWrite tool** — the generated `openspec-propose` and `openspec-ff-change` skills (and their `/opsx:propose` / `/opsx:ff` commands) told every agent to "Use the **TodoWrite tool**", which only exists in Claude Code. Codex, Cursor, Gemini, Copilot, and the other supported tools have no such tool, so agents either errored or stalled looking for it. The instruction is now runtime-neutral ("Use a todo list to track progress"), which works everywhere — including Claude Code. + +- [#1415](https://github.com/Fission-AI/OpenSpec/pull/1415) [`e2f748c`](https://github.com/Fission-AI/OpenSpec/commit/e2f748c64f05efaeac720f83c71fb6f1b6f6e18d) Thanks [@clay-good](https://github.com/clay-good)! - Reject config key paths that reach the prototype chain, and update the bundled `yaml` dependency. + + `openspec config set --allow-unknown __proto__.polluted ` reported success and assigned onto `Object.prototype` for the rest of the process. `--allow-unknown` was meant to relax the known-key check only, but it skipped every key check, so `__proto__`, `constructor`, and `prototype` segments reached the nested-write helper. Those segments are now rejected in `config set` whether or not `--allow-unknown` is passed, and `setNestedValue` / `deleteNestedValue` refuse them regardless of caller. Ordinary keys such as `featureFlags.myFlag` behave exactly as before. + + The `yaml` runtime dependency moves from 2.8.2 to 2.9.0, picking up the fix for a stack overflow on deeply nested input (GHSA / advisory patched in 2.8.3). + +- [#1376](https://github.com/Fission-AI/OpenSpec/pull/1376) [`7958924`](https://github.com/Fission-AI/OpenSpec/commit/7958924e95654af981437951e967983385da8001) Thanks [@clay-good](https://github.com/clay-good)! - ### Bug Fixes + + - **Archive after early sync** — `openspec archive` no longer fails with `ADDED failed … already exists` when a change's specs were already synced to the main specs before archiving (the early-sync pattern from the `sync` workflow). If an ADDED requirement already exists in the target spec with identical content, applying it is treated as a no-op; a same-named requirement with different content still aborts the archive as a genuine conflict ([#1332](https://github.com/Fission-AI/OpenSpec/issues/1332)). + +- [#1386](https://github.com/Fission-AI/OpenSpec/pull/1386) [`b419e96`](https://github.com/Fission-AI/OpenSpec/commit/b419e965bbf413cc658bbac37325ebc147b1c869) Thanks [@mc856](https://github.com/mc856)! - ### Bug Fixes + + - **Archive after early sync (RENAMED)** — `openspec archive` no longer fails with `RENAMED failed … source not found` when a change's renames were already synced to the main specs before archiving (the early-sync pattern from the `sync` workflow). If a RENAMED requirement's source header is gone but the target header exists in the spec, applying the rename is treated as a no-op; a rename whose source and target are both missing still aborts the archive as a genuine error, and reported counts reflect only renames actually applied. + +- [#1462](https://github.com/Fission-AI/OpenSpec/pull/1462) [`ebf66c7`](https://github.com/Fission-AI/OpenSpec/commit/ebf66c7ee1df3f7465d7f480753f952483133a73) Thanks [@clay-good](https://github.com/clay-good)! - Respect reduced-motion preferences in `openspec init`: the welcome animation is skipped when the OS reduced-motion setting is on (macOS Reduce Motion, GNOME animations disabled), when `OPENSPEC_NO_ANIMATION` is set, or when the new `--no-animation` flag is passed. The static welcome screen is shown instead. + +- [#1405](https://github.com/Fission-AI/OpenSpec/pull/1405) [`5dfef4b`](https://github.com/Fission-AI/OpenSpec/commit/5dfef4b00c233fbe78f40488bd4ff98f4204684c) Thanks [@clay-good](https://github.com/clay-good)! - ### Bug Fixes + + - **Custom schema instructions are no longer overridden by hard-coded spec-driven patterns** — the `openspec-continue-change` skill/command embedded one-line "common artifact patterns" for proposal.md, specs, design.md, and tasks.md, so agents followed those shortcuts instead of the schema's `instruction` field whenever a custom schema reused familiar artifact names. The templates now state that the `instruction` field is the authoritative guidance, and the `propose`, `continue`, and `ff` workflows direct the agent — both in the artifact-creation step and in the guidelines — to invoke a skill when the instruction delegates artifact creation to one, verifying the artifact exists afterward (fixes [#777](https://github.com/Fission-AI/OpenSpec/issues/777)). + +- [#1475](https://github.com/Fission-AI/OpenSpec/pull/1475) [`17af60c`](https://github.com/Fission-AI/OpenSpec/commit/17af60c66e4c049e3986fdbafcdc16b202cda59f) Thanks [@clay-good](https://github.com/clay-good)! - Follow the Kimi CLI rename to Kimi Code: new install paths with automatic migration of existing `.kimi` setups. + +- [#1415](https://github.com/Fission-AI/OpenSpec/pull/1415) [`e2f748c`](https://github.com/Fission-AI/OpenSpec/commit/e2f748c64f05efaeac720f83c71fb6f1b6f6e18d) Thanks [@clay-good](https://github.com/clay-good)! - Parse spec headings in linear time when the title is padded with whitespace. + + Building the reference index read the first Purpose line with a regex that backtracked quadratically on a heading full of spaces: 10,000 characters of padding took 60ms, and 100,000 would have taken roughly six seconds. The heading scan is now hand-rolled and linear. Behavior is unchanged — the replacement was checked against the old implementation across 303,000 generated inputs, including CommonMark closing sequences (`## Purpose ##`), seven-hash lines, and headings with no space after the hashes. + +- [#1475](https://github.com/Fission-AI/OpenSpec/pull/1475) [`17af60c`](https://github.com/Fission-AI/OpenSpec/commit/17af60c66e4c049e3986fdbafcdc16b202cda59f) Thanks [@clay-good](https://github.com/clay-good)! - Use local dates for CLI date-only values (archive names, timestamps) instead of UTC, so late-evening archives no longer get tomorrow's date. + +- [#1475](https://github.com/Fission-AI/OpenSpec/pull/1475) [`17af60c`](https://github.com/Fission-AI/OpenSpec/commit/17af60c66e4c049e3986fdbafcdc16b202cda59f) Thanks [@clay-good](https://github.com/clay-good)! - `openspec update` warns when a custom profile is missing core workflows instead of silently generating a partial install. + +- [#1428](https://github.com/Fission-AI/OpenSpec/pull/1428) [`81d5109`](https://github.com/Fission-AI/OpenSpec/commit/81d5109b86f16537deb99f84a772a83235dc9e09) Thanks [@taltas](https://github.com/taltas)! - Update current Roo Code product references to its community successor, Zoo Code. + +- [#1475](https://github.com/Fission-AI/OpenSpec/pull/1475) [`17af60c`](https://github.com/Fission-AI/OpenSpec/commit/17af60c66e4c049e3986fdbafcdc16b202cda59f) Thanks [@clay-good](https://github.com/clay-good)! - Archive treats a MODIFIED delta whose content already matches the main spec as a no-op: a fully early-synced change now reports "Specs already in sync" instead of rewriting the file and claiming modifications. + +- [#1475](https://github.com/Fission-AI/OpenSpec/pull/1475) [`17af60c`](https://github.com/Fission-AI/OpenSpec/commit/17af60c66e4c049e3986fdbafcdc16b202cda59f) Thanks [@clay-good](https://github.com/clay-good)! - Render multi-select prompts with `[x]`/`[ ]` checkbox markers instead of radio-button icons. + +- [#1475](https://github.com/Fission-AI/OpenSpec/pull/1475) [`17af60c`](https://github.com/Fission-AI/OpenSpec/commit/17af60c66e4c049e3986fdbafcdc16b202cda59f) Thanks [@clay-good](https://github.com/clay-good)! - Discover nested spec paths like `specs///spec.md` recursively and consistently across parse, apply, and archive. + +- [#1410](https://github.com/Fission-AI/OpenSpec/pull/1410) [`b3b05e1`](https://github.com/Fission-AI/OpenSpec/commit/b3b05e1abeb312caefd57e60be799aeb466c1d0e) Thanks [@clay-good](https://github.com/clay-good)! - Only advertise onboarding commands that will actually exist. The `openspec init` welcome screen and the `openspec update` "Getting started" summary listed `/opsx:new` and `/opsx:continue`, which the default `core` profile never generates, so users were told to run commands that did not exist. Both surfaces now list the commands for the installed workflows. The `init` and `update` completion hints also name the skill (`/openspec-propose`) instead of a command for tools that receive no command files — Codex, and any tool under skills-only delivery. + +- [#1412](https://github.com/Fission-AI/OpenSpec/pull/1412) [`1dc670d`](https://github.com/Fission-AI/OpenSpec/commit/1dc670deea741b8313b8a22fb975741f84677b3f) Thanks [@clay-good](https://github.com/clay-good)! - ### Fixed + + - **`/opsx:propose` and `/opsx:ff` no longer finish a change with no spec written.** The workflows listed only `proposal`/`design`/`tasks` and treated the apply phase's `tasks` artifact as the stop condition — but `status` marks an artifact `done` as soon as a matching file exists, so writing `tasks.md` early satisfied the loop while `specs//spec.md` was never created (a spec-less change in a spec-driven tool). The loop now derives the full required set — every apply dependency plus everything it transitively `requires` — from a single `status` call, creates each missing artifact, and only skips one when its own `instruction` field marks it conditional. ([#1260](https://github.com/Fission-AI/OpenSpec/issues/1260), [#788](https://github.com/Fission-AI/OpenSpec/issues/788)) + + ### Changed + + - **`openspec status --json` now reports each artifact's `requires` edges.** Every entry in the `artifacts` array carries a `requires` array of the ids it directly depends on, present for every status (including `done`) so agents can compute the transitive required set from `status` alone. Additive and backward-compatible — existing fields are unchanged. + +- [#1191](https://github.com/Fission-AI/OpenSpec/pull/1191) [`7704702`](https://github.com/Fission-AI/OpenSpec/commit/7704702d61fa71e4f553c21a06bdf8e4ee803b4a) Thanks [@mc856](https://github.com/mc856)! - Generate Markdown commands for Qwen Code instead of deprecated TOML format. Qwen Code now recommends Markdown custom commands with YAML frontmatter; the old `.qwen/commands/opsx-*.toml` files are cleaned up as legacy artifacts on update. + +- [#1475](https://github.com/Fission-AI/OpenSpec/pull/1475) [`17af60c`](https://github.com/Fission-AI/OpenSpec/commit/17af60c66e4c049e3986fdbafcdc16b202cda59f) Thanks [@clay-good](https://github.com/clay-good)! - An already-synced RENAMED delta aborts when a case/whitespace variant of the source requirement still exists — the same typo guard REMOVED deltas have. + +- [#1368](https://github.com/Fission-AI/OpenSpec/pull/1368) [`de78c31`](https://github.com/Fission-AI/OpenSpec/commit/de78c31ffd885a0558ae55d332f74d5485dc01c0) Thanks [@clay-good](https://github.com/clay-good)! - ### Fixes + + - **Regenerated artifacts now pick up your manual edits** — the continue, propose, and fast-forward workflows (and the `openspec instructions` dependency block) now tell the agent to re-read dependency artifacts from disk before creating the next one, instead of trusting whatever version it saw earlier in the conversation. Previously, editing `spec.md` and deleting `design.md`/`tasks.md` to regenerate them could silently produce artifacts based on the stale, pre-edit content. + +- [#1475](https://github.com/Fission-AI/OpenSpec/pull/1475) [`17af60c`](https://github.com/Fission-AI/OpenSpec/commit/17af60c66e4c049e3986fdbafcdc16b202cda59f) Thanks [@clay-good](https://github.com/clay-good)! - Proposal guidance now resolves blocking open questions with the user instead of deferring them to design.md. + +- [#1392](https://github.com/Fission-AI/OpenSpec/pull/1392) [`a13abea`](https://github.com/Fission-AI/OpenSpec/commit/a13abeac47d419462b0193dbf9423dd466ffe6c7) Thanks [@clay-good](https://github.com/clay-good)! - ### Fixed + + - Stop a delta spec written directly at a change's `specs/` root from being silently dropped. `validate` accepted `specs/spec.md` and counted its deltas, but the apply/archive merge only reads capability folders (`specs//spec.md`), so the change could pass validation and be archived while its requirements never reached `openspec/specs/`. `validate` now uses the same discovery rules as the merge path and reports the misplaced file with a fix hint, and `archive` blocks instead of completing. + +- [#1465](https://github.com/Fission-AI/OpenSpec/pull/1465) [`f917b8b`](https://github.com/Fission-AI/OpenSpec/commit/f917b8be5e1100189ef62320ba9322763053640e) Thanks [@clay-good](https://github.com/clay-good)! - Order artifacts by the schema's declaration order instead of alphabetically. + + `specs` and `design` both require only `proposal`, so both become ready at once - and the tie used to be broken alphabetically, which put `design` first. `openspec status` listed design above specs and `nextSteps` recommended writing `design.md` before any spec existed, contradicting the spec-driven schema's own documented `proposal → specs → design → tasks` sequence. + + Ties now follow the order the schema declares its artifacts, so `openspec status`, `status --json`, `nextSteps`, `blocked by:` lists, and an artifact's `unlocks` all agree. No dependency edges changed, so nothing newly blocks and `design.md` stays optional - only the order of equally-ready artifacts moved. Custom schemas get the same guarantee: dependency order still comes first, but wherever your schema leaves two artifacts equally ready, the order of its `artifacts:` list now decides which one the CLI recommends - so reorder that list if it was never deliberate. + +- [#1446](https://github.com/Fission-AI/OpenSpec/pull/1446) [`5348da9`](https://github.com/Fission-AI/OpenSpec/commit/5348da930c4038ffd5b5a521702b71315dcd0019) Thanks [@showms](https://github.com/showms)! - ### Bug Fixes + + - Preserve an existing project-local schema when `openspec schema init --force` rejects an unknown artifact ID. Forced replacement now begins only after artifact validation succeeds. + +- [#1433](https://github.com/Fission-AI/OpenSpec/pull/1433) [`26f009d`](https://github.com/Fission-AI/OpenSpec/commit/26f009d940f311b99db7f310816bb166a99fb3ef) Thanks [@clay-good](https://github.com/clay-good)! - Change lookup no longer requires `proposal.md`. `openspec show`, `openspec change list/show/validate`, and shell completion now resolve a change by its directory, matching `openspec list`, `status`, `instructions`, and `validate`. + + Previously a change created by `openspec new change` — which scaffolds only `.openspec.yaml` — was reported as `Unknown item` by `openspec show` and was missing from completions and `openspec change list` until a proposal was written, and a change from a schema with no proposal artifact was never resolvable. `openspec change list` now reports the same set as `openspec list`, keeps task counts for a change that has no proposal yet, and labels it `(no proposal.md yet)` rather than `(unable to read)`. Showing such a change explains that the proposal is not written yet and points at `openspec status --change `. + +- [#1468](https://github.com/Fission-AI/OpenSpec/pull/1468) [`fc886af`](https://github.com/Fission-AI/OpenSpec/commit/fc886af7f93068482bbf2c66fd1eb76b40c6a22f) Thanks [@clay-good](https://github.com/clay-good)! - The continue, update, verify, sync, and archive workflow skills now select a change the same way apply does: use the provided name, infer it from conversation context, auto-select when exactly one active change exists, and only prompt when the choice is genuinely ambiguous. Previously these workflows were told to always prompt ("Do NOT guess or auto-select"), so invoking them with a single active change stalled on a question with only one possible answer. The selection is always announced ("Using change: ") with how to override, and bulk archive still always prompts. + +- [#1194](https://github.com/Fission-AI/OpenSpec/pull/1194) [`b7c85c7`](https://github.com/Fission-AI/OpenSpec/commit/b7c85c741ca56748a4ae095b573fe4550c5c977f) Thanks [@mc856](https://github.com/mc856)! - Fix skills-only delivery emitting `/opsx:*` command references. SKILL.md files generated by init, update, and workspace skill setup now reference the corresponding skills (e.g. `/openspec-apply-change`) when `delivery: 'skills'` is configured, instead of commands that were never generated. + +- [#1475](https://github.com/Fission-AI/OpenSpec/pull/1475) [`17af60c`](https://github.com/Fission-AI/OpenSpec/commit/17af60c66e4c049e3986fdbafcdc16b202cda59f) Thanks [@clay-good](https://github.com/clay-good)! - Specs instructions include the spec content guidance from the concepts docs, so generated specs follow the requirement/scenario format. + +- [#1475](https://github.com/Fission-AI/OpenSpec/pull/1475) [`17af60c`](https://github.com/Fission-AI/OpenSpec/commit/17af60c66e4c049e3986fdbafcdc16b202cda59f) Thanks [@clay-good](https://github.com/clay-good)! - The static welcome screen (reduced motion, `--no-animation`, narrow terminals) now waits for the Enter it asks for instead of letting the keystroke submit the tool picker unseen. + +- [#1475](https://github.com/Fission-AI/OpenSpec/pull/1475) [`17af60c`](https://github.com/Fission-AI/OpenSpec/commit/17af60c66e4c049e3986fdbafcdc16b202cda59f) Thanks [@clay-good](https://github.com/clay-good)! - Sync and archive workflows resolve main specs through the store-aware root instead of assuming `openspec/specs` in the repo. + +- [#1402](https://github.com/Fission-AI/OpenSpec/pull/1402) [`0da5f98`](https://github.com/Fission-AI/OpenSpec/commit/0da5f98e147543a44379e32295e2e9798d775d83) Thanks [@clay-good](https://github.com/clay-good)! - Show the main spec format in the sync-specs skill so agents stop leaving delta operation headers (`## ADDED/MODIFIED Requirements`) in `openspec/specs/` — merged main specs with those headers parse as 0 requirements in `openspec view` ([#1120](https://github.com/Fission-AI/OpenSpec/issues/1120)). + +- [#1476](https://github.com/Fission-AI/OpenSpec/pull/1476) [`8731290`](https://github.com/Fission-AI/OpenSpec/commit/87312900f532c6c13ea556d4badaff2efdfa9602) Thanks [@clay-good](https://github.com/clay-good)! - Telemetry no longer depends on `posthog-node`: the single usage event is sent with a plain fetch to the same endpoint. Installing OpenSpec no longer pulls the fast-publishing `posthog-node`/`@posthog/core`/`@posthog/types` tree, which broke downstream installs under supply-chain age policies like pnpm's `minimumReleaseAge` ([#1390](https://github.com/Fission-AI/OpenSpec/issues/1390)). + +- [#1475](https://github.com/Fission-AI/OpenSpec/pull/1475) [`17af60c`](https://github.com/Fission-AI/OpenSpec/commit/17af60c66e4c049e3986fdbafcdc16b202cda59f) Thanks [@clay-good](https://github.com/clay-good)! - The stale-CLI check hardens its install detection: a directory merely named `volta` no longer changes the upgrade hint, the Windows npm-ownership check corroborates against the `openspec.cmd` shim npm actually writes, and a registry redirect from https to plain http is no longer followed. + +- [#1475](https://github.com/Fission-AI/OpenSpec/pull/1475) [`17af60c`](https://github.com/Fission-AI/OpenSpec/commit/17af60c66e4c049e3986fdbafcdc16b202cda59f) Thanks [@clay-good](https://github.com/clay-good)! - The stale-CLI check tears down a redirected registry connection when its time budget expires instead of leaving the socket open. + +- [#1442](https://github.com/Fission-AI/OpenSpec/pull/1442) [`10fa39b`](https://github.com/Fission-AI/OpenSpec/commit/10fa39b1c3a3e88c02ae7d3053864c03a793ff47) Thanks [@hsusul](https://github.com/hsusul)! - `openspec update` now refreshes tools that are configured with command files but no skills (delivery `commands`). Previously it read the generating version only from skill files, so such a tool was reported as "up to date" forever and its command files were never regenerated after a CLI upgrade. Command files carry no version stamp, so OpenSpec compares their contents against what it would generate now — including removing a command file left behind by a workflow you have since deselected. CRLF line endings and a UTF-8 BOM are treated as checkout artifacts rather than drift, so a Windows clone does not report a spurious update. + +- [#1475](https://github.com/Fission-AI/OpenSpec/pull/1475) [`17af60c`](https://github.com/Fission-AI/OpenSpec/commit/17af60c66e4c049e3986fdbafcdc16b202cda59f) Thanks [@clay-good](https://github.com/clay-good)! - `openspec update` with `delivery: commands` prints the same configuration correction as init when it removes the skills of a tool that supports only skills, instead of deleting them silently. + +- [#1475](https://github.com/Fission-AI/OpenSpec/pull/1475) [`17af60c`](https://github.com/Fission-AI/OpenSpec/commit/17af60c66e4c049e3986fdbafcdc16b202cda59f) Thanks [@clay-good](https://github.com/clay-good)! - `openspec validate` reports an unreadable specs/ directory as the error it is instead of misdiagnosing it as "no deltas found". + +- [#1455](https://github.com/Fission-AI/OpenSpec/pull/1455) [`6b3623a`](https://github.com/Fission-AI/OpenSpec/commit/6b3623a39e96f49995d38d642738b31f68e92039) Thanks [@c4patino](https://github.com/c4patino)! - `openspec view` now resolves the configured OpenSpec root instead of always reading the current directory, and accepts `--store ` like its sibling commands. Projects whose `openspec/config.yaml` points at an external store saw an empty dashboard — 0 specs, 0 requirements — while `openspec list` read the same store correctly. + +- [#1475](https://github.com/Fission-AI/OpenSpec/pull/1475) [`17af60c`](https://github.com/Fission-AI/OpenSpec/commit/17af60c66e4c049e3986fdbafcdc16b202cda59f) Thanks [@clay-good](https://github.com/clay-good)! - Preserve keyboard input on Windows after the welcome screen instead of dropping the first keystrokes. + +- [#1475](https://github.com/Fission-AI/OpenSpec/pull/1475) [`17af60c`](https://github.com/Fission-AI/OpenSpec/commit/17af60c66e4c049e3986fdbafcdc16b202cda59f) Thanks [@clay-good](https://github.com/clay-good)! - zsh completion install honors `$ZSH` and `$ZSH_CUSTOM`, so Oh My Zsh setups at custom locations get the completion where their shell actually loads it. + ## 1.6.0 ### Minor Changes diff --git a/package.json b/package.json index 7e19dec560..d17dbd471f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@fission-ai/openspec", - "version": "1.6.0", + "version": "1.7.0", "description": "AI-native system for spec-driven development", "keywords": [ "openspec",