Skip to content

Update dependency npm:@fission-ai/openspec to v1.13.2 - #56

Open
renovate[bot] wants to merge 1 commit into
mainfrom
renovate/npm-fission-ai-openspec-1.x
Open

renovate[bot] wants to merge 1 commit into
mainfrom
renovate/npm-fission-ai-openspec-1.x

Conversation

@renovate

@renovate renovate Bot commented Sep 23, 2026

Copy link
Copy Markdown
Contributor

ℹ️ Note

This PR body was truncated due to platform limits.

This PR contains the following updates:

Package Change Age Confidence
npm:@fission-ai/openspec 1.5.0 → 1.13.2 age confidence

Release Notes

Fission-AI/OpenSpec (npm:@​fission-ai/openspec)

v1.13.2

Compare Source

Patch Changes
  • #​1940 0b5ce44 Thanks @​clay-good! - Keep fast-forward clarification guidance and onboarding task approval consistent across generated skills and commands. Fast-forward now asks only when context is critically unclear, while onboarding asks users to approve the task breakdown before saving it and separately asks whether to begin implementation.

  • #​1926 f2812f6 Thanks @​kevin9327! - ### Bug Fixes

    • Archive — When Windows EPERM blocks renaming a change directory that still has children, copy from the original source instead of requiring a staging rename that fails the same way. That lets archive finish instead of rolling back the spec write and leaving an empty capability directory git cannot see. A staging failure that is not EPERM/EXDEV still leaves the source untouched.

      The source of that unstaged copy is still the live change directory, which the archive claim does not cover, so cleanup removes only the entries it copied and verified rather than whatever is present when it runs. A file written in that window is left alone and the complete destination is retained for recovery, instead of being deleted without ever reaching the archive.

      An edit to a file that was already verified is covered too. Cleanup claims each entry with an atomic rename before reading it, then compares what it claimed against the copy. A rewrite that lands first is caught by that comparison and the file is put back; one that lands after creates a new file at the original path, which is never deleted. Either way the newer bytes stay on disk and archive reports the move as incomplete rather than succeeding with the older copy.

      Rollback of a newly created spec now also prunes the capability directory it created — and only that one. An empty capability directory that was already there is left in place with its own permissions.

  • #​1795 fb1b876 Thanks @​runsonmypc! - Archive workflows now use schema-aware task progress from openspec list --json, so custom task files and globs still trigger incomplete-task warnings.

  • #​1885 fd56e12 Thanks @​philo-x! - Fix artifact output resolution to recognize brace expansion and extglob patterns while preserving literal output filenames and confining brace-expanded paths to the change directory.

  • #​1964 7ac58dc Thanks @​clay-good! - Continue commands now open with an instruction to follow the active OpenSpec workflow directly, so local models no longer try to call a tool named after it (#​1944).

  • #​1964 7ac58dc Thanks @​clay-good! - Generate Kilo Code commands in .kilo/command/, the directory Kilo Code reads, instead of .kilocode/workflows/ (#​1938). openspec init and legacy cleanup remove the workflow files OpenSpec generated there, matched by their known file names (including copies you edited), and leave files with other names in place.

  • #​1958 1d35e90 Thanks @​clay-good! - Preserve a file's existing line endings when rewriting it, so Windows users no longer get whole-file diffs. Applying a delta to a CRLF spec (the default on a Windows checkout with core.autocrlf=true) rewrote the file to LF, turning a one-requirement change into a diff that touched every line. openspec archive now writes the spec back with the convention it already used; a spec that does not exist yet is still written with LF.

    The same fix covers marker-managed files: installing or updating shell completions in a CRLF .bashrc or .zshrc no longer leaves the file with mixed endings, which bash reports as $'\r': command not found.

    Removing a managed block is fixed the same way: the blank-line collapse in removeMarkerBlock rebuilt its separator as a bare LF, so cleaning up legacy artifacts left a lone LF inside an otherwise-CRLF CLAUDE.md or rc file. Both write paths now read the file the same way, by dominant ending, so one stray CRLF in an otherwise-LF file no longer pulls the whole rewrite to CRLF.

    scripts/pack-version-check.mjs now spawns npm through cross-spawn, so the release guard can run on Windows, where npm is npm.cmd and cannot be resolved by execFile.

  • #​1912 8826c0c Thanks @​Tyagiquamar! - Fix validate --strict reporting PURPOSE_IS_PLACEHOLDER for a Purpose that opens with the ordinary word "Todo" followed by prose, as in Spanish ("Todo el…") and Portuguese ("Todo o…") specs (#​1897).

    • Case now separates the marker from the word. TBD/TODO in capitals is still a placeholder marker whatever follows it, so TODO write this later is still reported.
    • In any other case it counts as a marker only when followed by the end of the Purpose, a line break, or marker punctuation (todo -, tbd.), so an authored Spanish or Portuguese sentence is not reported.
  • #​1744 5b55263 Thanks @​javigomez! - Clarify the Codex setup hint for CLI, IDE, and desktop app users.

  • #​1809 a5ceea3 Thanks @​ryandemelo! - Say what a MODIFIED block adds when the scenario-loss guard fires (#​1809). openspec validate and openspec archive already named the scenarios a block omits. They now also print how many scenarios each side has and which ones the block introduces, capped at three names, so a rename and a truncation read differently without opening either file. The guard catches exactly what it did before, and no exit code changes.

  • #​1731 d6bdef6 Thanks @​runsonmypc! - Stop workflows from displaying schema names that openspec list --json does not return. Update and continue no longer fabricate a spec-driven picker label, while bulk archive and explore describe only the change fields the list command actually provides.

  • #​1955 ed5d386 Thanks @​clay-good! - Task guidance now requires each task group to land its own tests and documentation updates instead of deferring them to a trailing group. The onboarding walkthrough teaches the same rule, and the published schema reference no longer quotes stale instruction text.

  • #​1939 a64303f Thanks @​clay-good! - Return a nonzero exit status when openspec update --force cannot replace a legacy-only Codex installation.

  • #​1733 72fbe4c Thanks @​runsonmypc! - Let /opsx:update fill a missing file under an already-satisfied glob artifact. A glob artifact is complete once one file matches it, and /opsx:continue only picks up ready artifacts, so the previous "point the user to /opsx:continue" handoff was unreachable and the missing file could never be created through the documented flow.

  • #​1962 3364146 Thanks @​ryandemelo! - Stop /opsx:verify from reporting a correctly removed requirement as missing. Verify now reads which delta section each requirement sits under: ADDED and MODIFIED requirements are checked for an implementation as before, a REMOVED requirement passes once its behavior is gone and is flagged only while it is still present, and the old name of a RENAMED requirement is no longer reported as missing.

  • #​1732 072de6b Thanks @​runsonmypc! - Stop /opsx:verify from reporting skipped checks as passing. Task completion now uses the schema-aware tasks and progress fields returned by apply instructions, while absent spec or design inputs are mapped to every check they prevent. Apply instructions aggregate every file matched by the configured task path or glob, regardless of the tracked artifact ID. Verification stays advisory and does not require optional or intentionally omitted artifacts. The scorecard identifies each skipped check, and the final assessment does not claim archive readiness when any check did not run.

  • #​1769 d3d7707 Thanks @​kikeprzn! - Fix openspec archive leaving .openspec-archive.lock behind on Windows. Node can report dev: 0n from a path stat while the open file handle reports the real volume id, so the claim-ownership check never matched and the stale lock blocked every later archive. The check now treats an absent device id as unavailable while still requiring the inode and the claim's contents to match before unlinking.

v1.13.1

Compare Source

Patch Changes
  • #​1864 767d63c Thanks @​dwin-gharibi! - Stop archive adding a second copy of an existing requirement under a name that differs only in case or spacing. ADDED and the RENAMED target compared requirement names exactly, while REMOVED and the RENAMED source already treated a case or whitespace variant as a mistyped header, so an ADDED late fees beside an existing Late Fees, or a rename to LATE FEES, archived cleanly and left two contradicting requirements in the main spec, which validate then accepted. Both now refuse with an error naming the existing requirement, in the same form REMOVED already used. The exact-duplicate error is unchanged, a case-only rename of a requirement to its own name still works, and a variant of a requirement the same delta removes or renames away is still allowed, because ADDED is checked against the spec as it stands after the earlier operations, as the exact check already was.

  • #​1872 72bf760 Thanks @​dwin-gharibi! - Make openspec completion uninstall bash hand .bashrc back exactly as completion install bash found it. Install adds the OpenSpec block at the top of the file followed by a blank separator line; uninstall removed the block but kept that blank line at the top, then stripped every trailing blank line and wrote the file back without its final newline. The byte count happened to come out unchanged, but the next tool to append to .bashrc with >> (the nvm, conda and rustup installers all do) merged its first line into the user's last line and broke both. Uninstall now also drops the separator line install added when the block sits at the top of the file, and leaves the rest untouched: the final newline, trailing blank lines and CRLF line endings all survive the round trip. A block the user moved elsewhere in the file is still removed, and the zsh, fish and PowerShell installers are unchanged.

  • #​1829 e67ac47 Thanks @​choi138! - Fix bulk archive nesting a change inside an existing archive target. The workflow now checks every archive target before it writes any main spec, the same order openspec archive uses. A change whose target already exists, or that shares a target with another selected change, is reported as failed and is never synced or moved, while the rest of the batch continues. The check runs again just before each move.

  • #​1878 2ef6fbd Thanks @​dwin-gharibi! - Let openspec config edit run an EDITOR or VISUAL that carries arguments. The whole value was passed to spawn as the program name, so common settings such as code --wait, subl -w or emacsclient -t failed with spawn code --wait ENOENT, and because that error was never caught the command died with a raw Node stack trace. The value is now split into a program and its arguments, honoring quoted paths with spaces, and the config path is appended as its own argument. No shell is involved, so shell metacharacters in the value are passed through literally. On Windows, .cmd shims such as code.cmd are found. A value that is itself the absolute path of an existing file is still run as-is, so an unquoted editor path containing spaces keeps working. An editor that cannot be started, exits non-zero or is killed is now reported as a one-line error naming the editor, with an install hint when the program was not found, and the command exits 1 instead of throwing. EDITOR still takes precedence over VISUAL, and the file is still validated after the editor closes.

  • #​1773 11a9691 Thanks @​clay-good! - Stop dropping checkbox lines whose marker the task parser does not recognise. A tasks.md whose remaining work used a marker other than [ ]/[x]/[X], for example - [~] 1.2 Deferred, reported ✓ Complete in openspec list/status and archived with no incomplete-task warning, because unmatched lines counted toward neither the numerator nor the denominator. An empty [] and a padded [ x] were lost the same way. Only a box holding x or X means done (spacing inside the brackets is ignored, so [ x] is done), and every other marker now reads as unfinished, across progress, the apply task list, archive's gate and validate's task-numbering check. The archive, bulk-archive and verify workflows now tell agents the same rule, so a hand-counted tally cannot disagree with the CLI, and the tasks instruction in the spec-driven schema states it where agents author the file. Markdown link bullets stay out of the count: - [Some doc](./doc.md) and the one-character - [A](https://example.com) are not tasks.

  • #​1701 92fb72d Thanks @​clay-good! - Agent-driven archive and sync workflows now create a missing main spec from ADDED requirements instead of treating it as already synced. They block sync rather than inventing MODIFIED or RENAMED requirements or writing an empty spec for a REMOVED-only delta, while preserving the user's explicit choice to archive without syncing. A REMOVED-only delta with retire_capabilities: true remains already synced when its main spec is gone. Fixes #​1222 and #​1264.

  • #​1804 a5bf5c6 Thanks @​dwin-gharibi! - Say so when a requirement in a delta sits outside every delta section. A well-formed ### Requirement: block written under ## Notes, under a misspelled header such as ## Add Requirements, or above the first ## header was dropped with no diagnostic: openspec validate reported the change valid and openspec archive exited 0 without applying it. openspec validate now reports each one as a WARNING naming the section and line, and archive prints the same warning. Nothing else changes: the block is still not applied, the verdict stays valid outside --strict, and requirements shown inside a code fence are not reported. Fixes #​1803.

  • #​1832 4c369e0 Thanks @​clay-good! - Resolve the contradiction that left explore mode's capture branch without a governing rule. Explore states twice that the agent must ask a direct yes/no question and wait for confirmation in a separate user message before its first write-capable action, naming openspec new change as an example, while the capture branch tells the agent to transition "seamlessly" into running openspec new change and creating artifacts with no confirmation step. Both readings were defensible from the text, so the same "capture this as a change" request either wrote .openspec.yaml plus several artifacts immediately or stopped and asked, depending on which passage the agent weighed, which made the #​1715 guarantee unenforceable in the one explore path that writes files. An explicit capture request is now stated to be that confirmation, covering the change and the artifacts the request names and nothing else. The guardrail keeps its teeth for the case #​1715 actually reported: when the agent is the one proposing the capture, or when the work would go beyond the requested scope, it still asks first, and answers to design or clarifying questions are still never consent to write. Both explore delivery surfaces and the committed skill carry the same wording. Fixes #​1828.

  • #​1788 62106f4 Thanks @​clay-good! - Name the workflow where explore hands off. Explore mode refuses to implement, but every place it said what to do instead described the next step as prose ("create a change proposal") without naming the workflow that does it: the refusal itself, the "flow into a proposal" ending, the closing summary, and the do-not-implement guardrail. Its seamless capture path was worse: it scaffolded a change, wrote artifacts, and then said nothing at all about what came next. With no named exit, agents finished the discovery questions and started writing code, which is the failure reported through GitHub Copilot in #​869, and which the docs already promised would not happen ("when the picture is clear, it hands off to /opsx:propose").

    The explore skill and command now name /opsx:propose at all four prose handoffs, and the capture path ends by naming /opsx:propose for the remaining planning artifacts and /opsx:apply for implementation, with an explicit note that capturing artifacts is not permission to implement them. The references are written in the canonical /opsx:<id> form so each tool renders the invocation it actually registers (/openspec-propose for skills-only delivery, /opsx-propose, /opsx:propose, or @opsx-propose for command surfaces). The handoffs follow the installed workflow set: a custom profile without propose or apply gets explore's own capture path and the openspec instructions apply CLI instead of a command it never installed. Fixes #​869.

  • #​1787 9827762 Thanks @​clay-good! - ### Bug Fixes

    • Generated skills and commands no longer adopt a project that never ran openspec init. Every workflow now checks root from openspec list --json before its first write, and "root": null means the project is not set up. What happens next depends on how the workflow was reached. A skill the agent picked on its own drops OpenSpec and answers the request normally, without asking about setup. A workflow the user asked for by name, or ran as a slash command, stops and asks whether to initialize the project, target a store, or handle the request without OpenSpec. A project whose openspec/config.yaml names a store this machine cannot resolve (not registered, or a malformed store: line) is not mistaken for an uninitialized one: the workflow stops and shows the store error. Neither path lets openspec new change create openspec/ in the current directory as a side effect. Skill descriptions now name OpenSpec so hosts stop offering these workflows in unrelated repositories. openspec new change also says when it had to create the root itself, so a directory that was never set up no longer picks up an openspec/ directory in silence (human output only; --json is unchanged).
  • #​1902 eb03b9e Thanks @​clay-good! - Harden the CLI against repositories you have cloned but not yet read (#​1835).

    • A config.yaml value can no longer close the project context block and inject its own directives into the instructions an agent receives.
    • A crafted delta or skill file no longer stalls openspec update or openspec archive with catastrophic regex backtracking.
    • A repository's .npmrc can no longer point the update check at a cleartext or attacker-controlled registry; a rejected registry now disables the check instead of falling back.
    • openspec update now notices a generated SKILL.md that was edited by hand and restores it, instead of reporting every tool as up to date.
    • DO_NOT_TRACK=true and other common spellings of an opt-out now turn telemetry off, and nothing is sent until the first-run notice has been shown.
    • Shell-completion installs quote directory paths safely, git probes run with bounded time and output, and dependencies are cleared of known advisories.
  • #​1874 388d344 Thanks @​dwin-gharibi! - Stop legacy cleanup deleting the user's own files. The six pre-skills tools that kept their commands in a <tool>/commands/openspec/ folder (Claude Code, CodeBuddy, Qoder, Lingma, Crush and Gemini CLI) had that whole folder removed recursively whenever it existed, so a command the user kept there, such as a team review checklist, was deleted along with OpenSpec's files, and the summary named only the folder. Because openspec init cleans up automatically when there is no TTY, an agent or CI running plain openspec init did this without --force and without a prompt, and openspec update --force did the same. Cleanup now deletes only the files OpenSpec wrote there: proposal, apply and archive files that still carry the OpenSpec markers every legacy command was generated with, so a same-named file the user wrote is kept. It never follows a symlinked command folder, removes the folder only once nothing else is left in it, and lists each thing it kept. A folder holding nothing OpenSpec wrote is no longer reported as legacy at all. A folder holding only OpenSpec's files, or nothing, is still removed exactly as before, with the same summary line.

  • #​1866 8146be5 Thanks @​dwin-gharibi! - Stop one unresolvable file from breaking openspec list. To sort changes by recency, list stats every file inside each change, and any entry it could not stat failed the whole command: a dangling symlink, such as the .#tasks.md lock Emacs keeps beside every file with unsaved edits, or a symlink loop made list exit 1 and list --json report "changes": [], so agents discovering work through it saw no changes at all. An entry that no longer resolves (removed mid-walk, a dangling symlink, or a loop) is now skipped when computing a change's last-modified time. Valid symlinks are dated as before, and any other error, such as a permission failure, still fails the listing.

  • #​1849 09a999b Thanks @​clay-good! - Report a change directory nested in a namespace folder instead of silently listing the folder around it as a change. Specs can be nested by domain (specs/mobile/tutorial-videos/spec.md), so it looks reasonable to lay changes out the same way, but a change is only ever a directory directly under changes/: changes/mobile/refresh-token/ left the real change invisible while mobile was reported as a task-less change everywhere. openspec archive mobile then moved the unfinished change into the archive under the namespace's name and applied none of its deltas. openspec list now marks the folder not a change and names the nested directories and a flat alternative, openspec show, openspec status --change and openspec status --all say the same instead of reporting a missing proposal or a full artifact plan, openspec validate reports it instead of "must have at least one delta", openspec list --json carries a warnings entry, and openspec archive refuses the folder outright. Detection looks up to three directory levels below changes/, which covers every namespace layout seen in practice; a change buried deeper than that behaves as it did before. Fixes #​1846.

  • #​1902 eb03b9e Thanks @​clay-good! - Install shell completions with the Nix flake package (#​1785). The package now ships bash, zsh and fish completions in their standard share/ locations, so Nix users get tab completion without running openspec completion install against their home directory.

  • #​1775 626269e Thanks @​clay-good! - Generated skills and commands no longer point at workflows the active profile does not install. On the default core profile, the update workflow told agents to hand off to /opsx:continue for missing artifacts and to /opsx:new for a change of intent, neither of which core generates. Every cross-workflow handoff is now decided at generation time against the installed workflow set, and renders a concrete CLI fallback (openspec status, openspec instructions, openspec archive) when the workflow it would name is absent, rather than relying on a runtime availability check the agent had to perform. The onboarding tutorial's command tables are likewise built from the workflows you actually have.

    Also folds in #​1735, which fixed the same issue (#​1734) by removing the optional handoffs outright. The CLI's own runtime instructions no longer name the openspec-continue-change skill either, since those strings are chosen at run time and cannot be resolved against a profile; and the blocked-state fallback now carries the full CLI recovery (select the next ready artifact from openspec status, read its rules with openspec instructions, keep the selected --store) rather than a one-line pointer.

  • #​1870 e01ed07 Thanks @​dwin-gharibi! - Stop archiving a change whose delta was written somewhere archive never reads. validate and archive read a change's deltas only from specs/<capability-path>/spec.md, but the spec-driven artifact graph counts any markdown file under specs/ as the specs being written, so a delta at specs/user-auth.md, or in a second file beside a capability's spec.md, was reported done by status and ready by instructions apply with no warning, rejected by validate only as "no deltas found", and then archived with exit 0 and nothing merged into openspec/specs/. A markdown file that carries delta sections but is not a capability's spec.md is now a validation error naming the file and the spec.md its requirements belong in; archive runs that validation and refuses the change instead of archiving it unmerged, and instructions apply lists each such file in its warnings. --no-validate still archives as before, a change with no spec files still archives, and notes without delta sections under specs/ are not affected.

  • #​1806 6e62b1d Thanks @​dwin-gharibi! - Refuse a ## RENAMED Requirements section whose FROM: and TO: lines do not pair up, instead of guessing. The reader kept one pending pair and dropped whatever did not fit: a TO: before its FROM:, a FROM: displaced by a second FROM:, or a trailing FROM: vanished with no diagnostic. Listing the old names and then the new ones paired the second FROM: with the first TO:, so openspec archive renamed a requirement the delta never named, under a name written for a different one, and exited 0. openspec validate now reports each unpaired line as an ERROR with its line number, and archive refuses the change until the pairing is fixed. Well-formed renames, including several consecutive pairs, are unchanged. A change that used to archive with a malformed RENAMED section is now rejected. Fixes #​1805.

  • #​1860 4b5c07a Thanks @​dwin-gharibi! - Read a requirement heading written with a CommonMark closing sequence, such as ### Requirement: Late Fees ###, as the requirement it renders as. The trailing # run stayed in the name, so a REMOVED written that way looked for "Late Fees ###", missed the requirement, and archive exited 0 with a false "treating it as already removed" warning while the requirement stayed in the spec; a closed MODIFIED or RENAMED heading failed as "not found", and a closed and an open heading of one requirement were not reported as duplicates. Requirement names now drop the closing run wherever they are read, exactly as scenario names already did: only a run preceded by a space or tab counts, so a name such as C# keeps its #. Headings without a closing run are unaffected.

  • #​1868 7090e16 Thanks @​dwin-gharibi! - Reject a schema whose apply.requires names an artifact that does not exist. parseSchema checked every artifact's requires but never apply.requires, so openspec schema validate passed a one-character typo there, and apply then skipped the unknown id: apply.requires: [desgin] turned the apply gate off and told the agent "Proceed with implementation" with only a proposal written. That is now a schema error, raised wherever the schema is loaded, exactly like an unknown artifact requires, and it names the bad id and the artifacts the schema declares. openspec schema validate also warns, without failing, when apply.tracks isn't exactly equal to some artifact's generates value, because OpenSpec finds the tracked artifact by comparing those two strings and can otherwise not tell which artifact's progress the file belongs to. That covers a typo such as task.md and also tracks: tasks/main.md against generates: tasks/*.md, where the glob does produce the file but the strings still differ. Apply reads that path as written either way, so schemas that track a hand-written file keep loading and working. Every built-in schema parses as before.

  • #​1856 46ff91f Thanks @​dwin-gharibi! - Make openspec show --json --deltas-only report the deltas archive applies. ChangeParser, which backs show --json, the change list delta counts and archive's proposal warnings, read delta specs with its own section lookup instead of parseDeltaSpec, the reader archive uses, and the two disagreed. A REMOVED written in the bullet form (- `### Requirement: X`) was invisible to it, so it fell back to the proposal's "What Changes" prose and reported an invented MODIFIED while archive deleted the requirement; a repeated section header was read only once; and a RENAMED line written with * or + was dropped. The inspection command OpenSpec's own error text recommends therefore misreported a deletion. ChangeParser now derives every operation from parseDeltaSpec, and a change whose delta spec files carry a delta section is described by them alone, so proposal prose is never reported in place of what archive applies. Requirement text and scenarios are read exactly as before, header-form deltas produce the same output, and a change with no delta spec files, or a legacy change whose spec files carry no delta section, still falls back to the "What Changes" bullets.

  • #​1786 8b99c07 Thanks @​clay-good! - openspec status now names the command that moves the change forward.

    The text output reported state and stopped there, so picking a change back up (after a lost session, or on a change you did not start) meant already knowing which command came next. The JSON surface had carried that command all along in nextSteps; the text surface never printed it.

    Status now ends with a Next: line: the next ready artifact's openspec instructions command while planning is unfinished, and openspec instructions apply once every planning artifact exists. It carries --store <id> when the resolved root is a store, and it is built from the same source as the JSON nextSteps sentence, so the two surfaces cannot name different commands.

  • #​1882 208b5b5 Thanks @​dwin-gharibi! - Stop a store named specs or changes from taking over root selection. Stores are placed at ~/openspec/<id>, so a store with one of those ids is itself ~/openspec/specs or ~/openspec/changes, and that made $HOME look like a planning root. Every command run anywhere under the home directory then resolved $HOME as the nearest root: the global defaultStore was never consulted, and new change wrote into ~/openspec/changes, outside any store. A specs/ or changes/ directory that carries store metadata no longer counts as planning content of the directory above it, so these stores resolve like any other. A real project's openspec/specs/ and openspec/changes/ are unaffected.

  • #​1880 9f8dec5 Thanks @​dwin-gharibi! - Stop openspec store remove deleting a store the user did not name. Remove deletes the target's folder recursively, but it checked only the target's own metadata, so any other registered store living inside that folder was deleted with it, uncommitted planning work included, while its registry entry was left pointing at a path that no longer existed. The natural way to get there is a shared store vendored into another as a git submodule, a layout store register accepts. Remove now refuses when another registration points inside the folder, checked under the same registry lock that commits the removal, and the error names each nested store with the openspec store unregister command to run first. Removing a store whose other registrations are siblings is unchanged, and store register still accepts nested checkouts.

  • #​1884 5d22145 Thanks @​dwin-gharibi! - Let openspec store setup --no-init-git create a store inside an existing Git repository. Setup refuses a path inside another repository because initializing the store there would nest one repository in another, but it ran that check even with --no-init-git, which creates no repository at all. Users who keep their home directory as a dotfiles repository therefore could not set up a store at the recommended ~/openspec/<id> path with any flag. With --no-init-git the check is now skipped, and the store never records the enclosing repository's remote. The default setup and an explicit --init-git still refuse a path inside another repository.

  • #​1862 8fc65b7 Thanks @​dwin-gharibi! - Count task checkboxes under every CommonMark list marker. The task counter shared by list, status, view, instructions apply, validate --archived and archive's incomplete-task check recognized only - and * bullets, so a task written as an ordered item (1. [ ], 1) [ ]) or under a + bullet was invisible to all of them: a change with unfinished ordered tasks reported "✓ Complete", and openspec archive archived it without its incomplete-task warning. Task lines under + and ordered markers (. or ), up to nine digits, as CommonMark allows) now count exactly like - and * ones, including nested sub-tasks, CRLF files and the existing tolerance of a missing space after the marker, and task-numbering checks now see them too. Ordered and + items without a checkbox are still ignored, and - and * tasks count as before.

  • #​1777 3312af4 Thanks @​clay-good! - Start generated proposal, spec, design, and tasks files with a top-level heading, so artifacts are complete markdown documents instead of files whose first line is a section header. Editors that run markdownlint no longer flag every OpenSpec artifact with MD041. openspec schema init scaffolds custom templates the same way.

    openspec show --json and openspec change list --json keep naming a change by its id when its proposal opens with the template's bare # Proposal title.

  • #​1778 7de2404 Thanks @​clay-good! - Make the vendor-neutral tool target findable when your assistant is not on the list. openspec init now shows it as "Other / Universal (shared .agents skills)"; the picker's search box matches it on universal, other, generic, custom, proprietary, unlisted, unsupported, vendor-neutral and agents.md; a search that matches nothing points at it instead of ending at "No matches"; and --tools <unknown> names it in the error. The search box also accepts punctuation, so .agents and amazon-q filter instead of silently dropping their . and -.

  • #​1876 605d9e7 Thanks @​dwin-gharibi! - Stop OpenSpec rewriting a global config file it cannot parse. After a hand edit left a typo such as a trailing comma in config.json, the next command of any kind, including read-only ones like openspec list, read the fallback defaults as telemetry consent, minted a new anonymous ID and wrote it back, replacing the whole file: a telemetry.enabled false opt-out, the chosen profile and the workflow list were all lost, and usage events were sent. A config file that exists but does not hold a JSON object, whether it failed to parse or its root is something else such as null, an array or a string, is now never written implicitly, and telemetry and the update check treat it as opted out. config set, config unset and config profile refuse with an error that names the file and points to openspec config edit, and openspec config reset --all still replaces it. The existing "Invalid JSON" warning is unchanged, and valid or missing config files behave exactly as before.

  • #​1840 fede536 Thanks @​clay-good! - Resolve the contradiction that left /opsx:update's only write path without a governing rule. Step 4 told the agent to "Apply the requested edit", while step 5 and the guardrails told it to write only after the user confirms each revision, so the same /opsx:update "the design now uses X" either wrote immediately or stopped and showed the proposed revision first, depending on which passage the agent weighed. Step 4 now drafts the edit in the conversation and step 5 owns every artifact write, matching the workflow's own specified behavior: propose each revision and apply it only after user confirmation. Fixes #​1836.

  • #​1858 db560ae Thanks @​dwin-gharibi! - Stop validate accepting a requirement whose only scenario is a bare header. The delta scenario counter counted every #### header, while the spec path that archive uses to validate the rebuilt spec keeps a scenario only when its body has content, so validate called such a change valid and archive then refused it with a generic "Requirement must have at least one scenario" that did not name the requirement. Both paths now share one rule, hasScenarioBody, and read a scenario's body up to the same boundary, so validate rejects exactly what archive rejects, naming the requirement and saying that a header with no body under it does not count. A scenario whose body is only a fenced block or a deeper header still counts, a requirement with one real scenario is still accepted even when another is empty, and main-spec validation is unchanged.

  • #​1774 09984b8 Thanks @​clay-good! - ### Bug Fixes

    • Task lists without checkboxes are now caught: a tasks.md written as plain bullets or a numbered list counts as zero tasks, so openspec list and openspec status reported "No tasks" and openspec archive had no unfinished work to warn about. openspec validate now warns when a change's tracked task files contain list items but no checkbox at all, and points at the first offending line.
  • #​1852 5f5914e Thanks @​clay-good! - Match the natural "openspec " phrasing to the workflow it names. Users and agents say "openspec propose" or "do an openspec apply", but no workflow skill's description contained that phrasing (and a skill's description is what an agent matches on), so the phrase read as an invitation to hand-build the artifacts with the CLI instead of running the workflow. Every workflow skill's description now names the phrasings a user actually types ("openspec propose", "opsx apply", and so on). Run openspec update to pick it up. openspec update itself is deliberately left unclaimed: it is a real CLI command that refreshes generated files, unrelated to the update-change workflow, which claims "openspec update change" instead. Commands-only installs write no skills and are unchanged. Fixes #​1221.

v1.13.0

Compare Source

Minor Changes
  • #​1783 8ba4ac1 Thanks @​clay-good! - Apply now says when a change has no delta specs. Apply gates on the schema's apply.requires alone, so a change whose tasks.md was written ahead of its specs read as ready to implement even though it had no spec deltas at all — the state openspec validate rejects. openspec instructions apply now reports that gap as a warning (text and --json), naming both ways out: write the specs, or declare skip_specs: true. Changes that have specs, declare skip_specs, or are still blocked on their own required artifacts are unaffected.

    A blocked apply also names the whole chain now, not just the first hop: a change holding only a proposal reported Missing artifacts: tasks while the specs that tasks depends on were missing too, which reads as an instruction to write the tracking file straight from the proposal. The full build order is reported as missingPrerequisites in --json. The remedies these messages give are CLI commands (openspec instructions <artifact> --change <name>) rather than the openspec-continue-change skill, which the core profile never installs.

Patch Changes
  • #​1798 aedf4d0 Thanks @​dwin-gharibi! - Stop archive rewriting the inside of fenced code blocks. The final assembly in buildUpdatedSpec collapsed runs of blank lines across the whole rebuilt document to tidy the seams between the slices it rejoins, but the pass was not fence-aware, so a requirement documenting a sample with two or more consecutive blank lines had that sample silently edited on archive, and edited again on every later archive. That matters wherever whitespace carries meaning: YAML block scalars, Python, expected-output fixtures, Markdown inside Markdown. Blank runs are now collapsed only outside fenced blocks, using the same buildCodeFenceMask every other structural pass in the module already used. Behavior outside fences is unchanged, including that only a truly empty line counts as blank, so a line of spaces is still never a collapse boundary. Fixes #​1797.

  • #​1800 fadac3e Thanks @​dwin-gharibi! - Read a removal or rename written with * or + as the operation it is. CommonMark opens a bullet list with -, * or +, but the bullet form of ## REMOVED Requirements and the FROM:/TO: lines of ## RENAMED Requirements both hardcoded -, so either other marker matched nothing at all. The operation then silently never happened: openspec validate reported the change valid, openspec archive exited 0 with "Specs updated successfully", and the requirement that was supposed to be deleted or renamed stayed exactly as it was. The change archived as complete, leaving the spec quietly disagreeing with the delta that was meant to update it. Both forms now accept [-*+], the FROM:/TO: bullet stays optional, and the plain ### Requirement: header form is unchanged. Fixes #​1799.

  • #​1802 8251763 Thanks @​dwin-gharibi! - Apply every delta section, not just one copy of each. A delta file that wrote the same header twice, two ## ADDED Requirements sections say, silently kept one of them: sections were collected into a record keyed by title, so a repeated title overwrote the earlier body, and the case-insensitive lookup returned only the first entry that folded to the target, so ## ADDED Requirements beside ## Added Requirements left the second unread. Every requirement under the discarded copy was gone before validation or the merge could see it, so openspec validate reported zero issues and openspec archive exited 0 having applied less than the author wrote, then moved the change to the archive with the live spec quietly diverging from what was reviewed. Sections are now kept as a list and every body whose title matches is read, each keeping its own line numbers so diagnostics still point at the right copy. Rename pairs are read per section, so a FROM: in one copy of the header can never pair with a TO: in another. An author does not have to repeat a header on purpose to hit this: a delta documenting OpenSpec's own syntax inside a fenced example produces the duplicate on its own. Fixes #​1801.

  • #​1657 6d2dbe6 Thanks @​clay-good! - Load project context before proposal planning, using the selected project or store root and honoring config precedence and validation limits. When no root exists, stop without writing files and offer initializatio

❗ Important

✂ PR body was truncated to here.


Configuration

📅 Schedule: (UTC)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@renovate renovate Bot added the 📦 dependencies Pull requests that update a dependency file label Sep 23, 2026
@github-actions github-actions Bot added this to the v2026.9.2 milestone Sep 23, 2026
@github-actions

Copy link
Copy Markdown

Test Results

0 tests  ±0   0 ✅ ±0   0s ⏱️ ±0s
0 suites ±0   0 💤 ±0 
0 files   ±0   0 ❌ ±0 

Results for commit 60a1866. ± Comparison against base commit 41d2c67.

@github-actions github-actions Bot modified the milestones: v2026.9.2, v2026.9.3 Sep 28, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

📦 dependencies Pull requests that update a dependency file

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants