* fix(validate): fail --strict on requirements over the length limit
A requirement description over 500 characters was an INFO finding, so
`openspec validate --all --strict` still exited 0 and CI could not hold
the limit. It is now a WARNING: normal validation and archive still pass,
while strict mode fails, the same split the SHALL/MUST keyword warning
already uses. The specs instruction and its docs page say so.
Closes#1976
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(validate): check ADDED requirement length and document splitting
With the length finding now failing --strict, a change could still add an
overlong requirement and pass `validate <change> --strict`; CI only went red
after archive merged it into the main spec. ADDED requirements now get the
same warning, using the shared body reader so the limit matches the main
spec exactly. MODIFIED is left alone, since its text is the existing
requirement the instruction says to keep whole.
The specs instruction (and its docs-lab page) now says how to split an
existing long requirement in a dedicated change: keep the MODIFIED header and
every scenario, cut the description to one behavior, and add each removed
behavior as its own ADDED requirement. Verified end to end: the split change
validates strict, archives, and the main spec then passes --strict.
Closes the rest of #1976.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* fix(archive): report retirement cleanup failures accurately
* test(archive): canonicalize recovery fixture paths
* test(archive): deny staged-root removal after main's verified-tree cleanup
Main now removes a fallback-copy staged source entry by entry and deletes
the staged root last, so the recovery-path test no longer reached its
fs.rm injection. Deny the final rmdir of the staged root instead, which
still leaves a staged source behind for the diagnostic to report.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Clay Good <hi@claygood.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* fix(tasks): separate completion from archive readiness
* fix(tasks): clarify optional workflow follow-up
* fix(tasks): keep profile-aware archive handoff and sync generated surfaces
Rebased onto main: the apply template now reports tracked completion
through the existing optional-workflow ARCHIVE_HANDOFF (#1775), so
profiles without the archive workflow still get the CLI fallback.
Regenerates the skills/ mirror and parity hashes, and syncs the
docs-lab spec-driven reference with the updated tasks instruction (#1952).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Clay Good <hi@claygood.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Security's docs-site audit went red on main after four advisories landed
in the site's dev-only serve dependency chain. Raise the site's existing
overrides so they resolve patched versions.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
removeZshrcConfig stripped every blank line at the top of .zshrc after
removing the OpenSpec block, so a file that started with blank lines
lost them in an install/uninstall round trip, even when the user had
moved the block further down. Drop only the separator line install
added, and only when the block sits at the top, as #1872 did for bash.
Closes#2015
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* fix(status): include the declaring repo in store-backed edit roots
For a store-selected root, actionContext.allowedEditRoots listed only the
store and claimed implementation edits were scoped to it, so the apply
skill reported a conflict and refused to implement tasks. The project whose
store: pointer names the store is now listed first; with no declaring
project, the constraint asks the agent to confirm the target repo instead.
Repo-local output is byte-identical.
Closes#2013
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(status): keep actionContext key order and scope the store wording
Adversarial review of the #2013 fix found:
- The editScope spread moved `constraints` ahead of
`requiresAffectedAreaSelection`, changing repo-local JSON key order.
toEqual could not see it; the byte-stable test now pins the serialized
form, and the keys are written out in contract order.
- "Implementation edits belong to <repo>" claimed task routing OpenSpec
does not do (a store change can span repos). It now names the current
declaring project and asks before editing any other repository.
- The no-declaring-project text was false when a pointer exists but is
ignored, and did not say the user's answer is where edits go.
New tests cover a subdirectory cwd, an ignored pointer on a real planning
root, and status --all.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test(status): pin the declaring repo's canonical path through an alias
test/AGENTS.md asks for an alias-path regression when touching path
identity logic (raised by CodeRabbit). The new case reaches the declaring
repo through a symlink (a junction on Windows) and asserts the canonical
path, both through the CLI and through a direct findDeclaringProjectRoot
call whose start path keeps the alias spelling on every platform.
The helper's own canonicalizeExistingPath call was redundant: the root
walk already returns canonical paths, and removing it changes no output.
The alias test fails only when that walk stops resolving aliases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* feat: add Grok Build skills-only support
* test(grok): cover skills-only installation and update lifecycle
---------
Co-authored-by: Clay Good <hi@claygood.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* feat: add Easy Code as a supported AI tool
- Register 'easycode' in AI_TOOLS (config.ts) with skillsDir '.easycode'
- Add EasycodeAdapter (easycode.ts): generates TOML commands at
.easycode/commands/opsx/<id>.toml, matching Easy Code's native format
- Export easycodeAdapter from adapters/index.ts
- Register easycodeAdapter in CommandAdapterRegistry
Easy Code (https://easycode.ai) is a terminal-based AI coding assistant.
Its commands use TOML with a description field and a prompt multiline
literal string, distinct from the Markdown/YAML frontmatter format used
by most other tools.
Tested locally: `openspec init --tools easycode` generates 5 SKILL.md
files and 5 .toml command files in the expected directory structure.
* fix: robust TOML serialization for Easy Code adapter
Per code review: the original formatFile had unsafe manual escaping
that would corrupt output for descriptions containing backslashes or
control characters, and prompt bodies containing triple-single-quotes.
Changes:
- Add src/core/command-generation/toml.ts with two helpers:
escapeTOMLBasicString — escapes \, ", \n, \r, \t for TOML
basic strings (double-quoted)
escapeTOMLMultilineString — escapes \ and \r, and breaks any
run of 3+ consecutive " (lookahead match)
for TOML basic multiline strings
- Switch prompt block from triple-single-quote literal string (''')
to triple-double-quote basic multiline string ("""), which allows
full escape sequence support and handles arbitrary body content
- Update easycode.ts to use both helpers
* fix: escape disallowed control characters in TOML helpers
Per code review: TOML basic strings forbid U+0000-U+0008, U+000B-U+000C,
U+000E-U+001F, and U+007F. Add escapeControlChars() helper that replaces
these with \uXXXX sequences, and apply it in both escapeTOMLBasicString
and escapeTOMLMultilineString after their named-escape passes.
* feat(easycode): harden project skills and command integration
---------
Co-authored-by: Trae <konghaifeng@cmcm.com>
Co-authored-by: Clay Good <hi@claygood.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* feat(nix): expose openspec as a consumable overlay
Refactor the flake so the package derivation is defined once, in
`overlays.default`, and every other output consumes it. Previously the
derivation lived inline in `packages.default`, so anyone who wanted
`openspec` in their own package set had to copy the derivation rather than
import it.
What changed:
- Add `overlays.default`, a standard `final: _prev:` overlay that exposes
`pkgs.openspec`. The derivation is written against `final`, so downstream
overlay composition and `overrideAttrs` behave as expected.
- Route `packages.{default,openspec}` through the overlay via a `pkgsFor`
helper (`import nixpkgs { overlays = [ self.overlays.default ]; }`), so the
flake's own package resolves exactly as a consumer's would. No more
duplicated build definition.
- Refresh the nixpkgs pin in `flake.lock`.
`apps` and `devShells` are unchanged in behaviour.
Usage — a downstream flake:
nixpkgs.overlays = [ openspec.overlays.default ];
# -> pkgs.openspec
or devenv, via `devenv.yaml`:
inputs:
openspec:
url: github:Fission-AI/OpenSpec
overlays:
- default
Assisted-by: Claude Opus 4.8 <noreply@anthropic.com>
* test(nix): cover downstream overlay composition and updater warnings
* fix(ci): compare Nix dependencies across multiple outputs
* chore: add Nix overlay changeset
---------
Co-authored-by: John Muchovej <jmuchovej@users.noreply.github.com>
Co-authored-by: Clay Good <hi@claygood.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* feat: show archived changes in list and view commands
Add --archived and --all flags to the list command to display archived changes.
The view dashboard now includes an "Archived Changes" section with a count in
the summary.
- list --archived: shows only archived changes
- list --all: shows both active and archived changes
- view: displays archived changes section in dashboard
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(list): reject malformed archive parents on Windows
* fix(list): preserve browsing of archived symbolic links
* fix(list,view): keep archived entries off nested findings and render past a file archive
An archived change that shares a name with an active namespace folder was
reported as nested. view now treats an archive path that is a file as no
archived changes, as it did before, instead of failing mid-dashboard.
The archive symlink test now uses a portable link and checks the link itself.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Clay Good <hi@claygood.com>
* fix(archive): stop sending the archive skill to an uninstalled sync skill
The archive skill always told the agent to run the `openspec-sync-specs`
skill, even when that skill was not installed, so an agent following it
stalled at the sync step. The archive command already chose between the
sync workflow and an inline merge based on what was installed; the skill
now does the same.
Closes#1975
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* docs(skills): document archive sync fallback
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* feat(github): add issue forms and a PR template
CONTRIBUTING asks every change to start with an issue or a discussion, but
the repository had no `.github/ISSUE_TEMPLATE/` and no PR template, so a
contributor who clones the repo and opens a PR meets a blank box and, later,
a review comment asking them to go file the issue they did not know they
needed.
- `ISSUE_TEMPLATE/bug_report.yml` asks for expected, actual, a minimal repro,
`openspec --version`, and the agent and model, and points users who already
have OpenSpec installed at `openspec feedback`.
- `ISSUE_TEMPLATE/feature_request.yml` asks for the problem, who it affects,
and what was tried, and routes core-design topics to Discussions.
- `ISSUE_TEMPLATE/config.yml` keeps blank issues enabled, so the pre-filled
URL that `openspec feedback` prints when `gh` is unavailable still works,
and links Discussions and Discord.
- `PULL_REQUEST_TEMPLATE.md` puts `Closes #` on the first line with the
"no issue yet?" path directly under it, catching the PR-first contributor
at the moment they need it — no bot and no CI gate.
Labels referenced by the forms (`bug`, `enhancement`, `needs-triage`) all
exist in this repository.
Part of #1834
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix(github): clarify issue submission and verification guidance
* fix(github): point agent disclosure to notes section
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
* docs(review): map requirements to verifiable evidence
Add an optional documentation recipe with fictional examples. Explain input and environment binding, evidence provenance, missing results, and reuse. No runtime changes. Related to #1652.
* docs(review): clarify evidence acceptance and reuse
* docs(review): simplify evidence guidance in docs-lab
* docs(review): make evidence checks easier to skim
---------
Co-authored-by: Clay Good <hi@claygood.com>
* feat: add AtomCode command adapter support
Add AtomCode as a supported tool with its own command adapter.
AtomCode is an open-source terminal AI coding assistant that uses
the same Agent Skills spec as Claude Code.
Changes:
- New adapter: src/core/command-generation/adapters/atomcode.ts
- File path: .atomcode/commands/opsx-<id>.md
- Frontmatter: description only
- Command references transformed from colon to hyphen format
- Register adapter in index.ts, registry.ts, and config.ts
- Update docs (supported-tools.md, cli.md) with AtomCode entry
- Add 6 test cases for atomcodeAdapter
- Add changeset for version tracking
Closes#1210
Co-Authored-By: hu-qi, AtomCode (GLM-5.1) <huqi1024@gmail.com>
* docs(atomcode): correct parser compatibility comments
* test(atomcode): cover detection and registry registration
The adapter shipped without the two per-tool checks its siblings carry:
a detection test asserting `.atomcode` surfaces the tool from
getAvailableTools, and registry assertions that the adapter is reachable
by id. Also adds the missing AtomCode row to the docs-lab support matrix.
Verified non-vacuous: removing the registry registration and the
AI_TOOLS entry fails all four new assertions.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* test(atomcode): lock the literal name/args invariant
AtomCode's custom-command loader scans for `key:` and takes the rest of
the line verbatim, with no YAML unquoting, then matches `args` against
the exact strings "required"/"optional". A quoted `args: "optional"`
falls through to ArgsRequirement::None and silently drops every
argument, so this adapter cannot use the shared escapeYamlValue helper
the way its siblings do.
That made the deviation look like an oversight inviting a "consistency"
refactor. Document why it exists and add a case proving a description
that needs quoting does not drag name/args into quotes.
Also drops the literal `description:` assertion. It passed only because
no current description needs quoting; the first one containing ": "
would have failed it, looking like an adapter bug rather than a
description edit. The parsed-frontmatter toEqual already covers it.
Verified non-vacuous: routing all three fields through a quoting helper
fails 13 tests, including the new one.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix(atomcode): declare args: none for workflows that take no input
Every generated command shipped `args: optional`, including `onboard`,
which reads no invocation input. AtomCode treats the two differently at
the slash menu: `none` executes the command immediately, while
`optional` completes to `/name ` and waits for a second Enter. Onboard
therefore cost every AtomCode user an extra keystroke to start, and its
body carried a `**Provided arguments**:` line that was always empty.
Gate both on the `**Input**:` contract the workflow bodies already
declare, matching how the Command Code adapter decides the same thing.
Output for the other 11 workflows is byte-identical; only `onboard`
changes. Adds the same tripwire assertion Command Code carries, so a
future workflow cannot silently lose its arguments.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* docs(atomcode): describe the args contract in the changeset
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* docs(atomcode): keep updates in docs-lab
---------
Co-authored-by: Clay Good <hi@claygood.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
* feat(view): display workflow status in active changes
Active changes now show workflow artifact status below each entry,
indicating schema name and completion state of each artifact (done✓,
ready→, blocked). Powered by loadChangeContext and formatChangeStatus.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* chore(release): track dashboard workflow status
* fix(view): neutralize controls in workflow output
* docs(view): move workflow status docs to docs-lab
* docs(view): preserve store in status guidance
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Clay Good <hi@claygood.com>
* proposal: add Amp skill support for OpenSpec workflows
Amp-Thread-ID: https://ampcode.com/threads/T-019b6a90-6107-755b-8087-942d9b5460ac
* feat(init): add Amp skills support for OpenSpec workflows
Add AmpSlashCommandConfigurator that generates Amp-native skill files
at .agents/skills/openspec-{proposal,apply,archive}/SKILL.md with YAML
frontmatter containing name and description fields.
- Register Amp in the native tool picker for init and update commands
- Include comprehensive test coverage for init and update scenarios
- Mark all add-amp-support tasks as complete
Amp-Thread-ID: https://ampcode.com/threads/T-019b6a90-6107-755b-8087-942d9b5460ac
* proposal: rename SlashCommandConfigurator to WorkflowConfigurator
Fix semantic mismatch with diverse tool terminology (skills, prompts,
commands). Old names kept as deprecated aliases for compatibility.
Amp-Thread-ID: https://ampcode.com/threads/T-019b6a90-6107-755b-8087-942d9b5460ac
* feat(init): add Amp skills support
---------
Co-authored-by: Jean du Plessis <jean@upbound.io>
Co-authored-by: Clay Good <hi@claygood.com>
* feat: add GigaCode as a supported --tools target
GigaCode is Sber's CLI coding agent, a fork of Qwen Code that reuses
its config directory shape (.gigacode/ vs .qwen/) and file formats.
Register a gigacodeAdapter mirroring the qwen adapter (Markdown
commands with a description frontmatter field at
.gigacode/commands/opsx-<id>.md), wire it into the config tool list
and command-adapter registry, and document it in
docs/supported-tools.md, docs/cli.md and docs-lab/reference/supported-tools.md.
Verified: GigaCode's fork relationship to Qwen Code and its .gigacode
config directory are confirmed by the task's own primary-source brief;
I could not independently find a GigaCode-authored doc page that
enumerates its custom-command file format (Markdown vs TOML), so this
mirrors Qwen Code's current (post-deprecation) Markdown spec on the
stated fork/format-compatibility basis. Flagging this assumption for
review.
Generated with Claude Code (claude-sonnet-5); tested with the full
vitest suite (5879 tests passing across 199 files), pnpm build,
tsc --noEmit, and eslint, all green.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* fix(gigacode): use current documentation sources
---------
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Clay Good <hi@claygood.com>
* chore(openspec): add change for IBM Bob rename and skills-only
* feat: rename Bob Shell to IBM Bob and make skills-only
- Rename AI_TOOLS entry from 'Bob Shell' to 'IBM Bob' (name + successLabel)
- Remove bobAdapter from CommandAdapterRegistry and adapters/index.ts
- Add 'bob' to skills-invocable capability path in command-surface.ts
- Add cleanupLegacyBobCommandFiles() to migration.ts for .bob/commands/ cleanup
- Call cleanup from init.ts and update.ts after skills are generated
- Update docs/supported-tools.md: IBM Bob, mark commands as not generated
- Remove bobAdapter tests; update flat-invocation and all-adapters lists
* chore: delete dead bob command adapter file
* fix: address CodeRabbit review comments on Bob command cleanup
- Guard bobCommandsDir and each commandFile against symlink escape
using areProjectArtifacts() before deletion
- Only remove files containing 'argument-hint:' frontmatter (OpenSpec
marker), leaving user-authored files with matching names intact
- Run cleanupLegacyBobCommandFiles on the up-to-date early-return
path in update.ts so stale .bob/commands/ files are cleaned even
when no tools need a version update
* fix: scope argument-hint check to YAML frontmatter block only
* fix(tools): identify Bob by product name
* chore(changeset): track IBM Bob naming fix
* docs(changeset): clarify IBM Bob user impact
---------
Co-authored-by: Clay Good <hi@claygood.com>
* fix(change-metadata): warn on unrecognized .openspec.yaml keys
Unknown keys such as skip_design were stripped with no signal, so status
still demanded design and validate --strict exited 0. Warn on the shared
status/validate/archive read path without rejecting the file.
Closes#1920
AI-assisted (Grok)
* fix(change-metadata): sanitize unknown keys before they are printed
A quoted YAML key can carry a terminal control sequence, and the warning
printed it as it was written. The listed keys now go through
sanitizeInline, which also flattens C1 controls from now on.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* test(change-metadata): cover sanitized archive warnings
* fix(change-metadata): keep warnings safe and structured
* fix(change-metadata): label key names as untrusted
* test(change-metadata): keep known keys in step with the schema
CHANGE_METADATA_KNOWN_KEYS is a hand-kept copy of ChangeMetadataSchema's
keys. A key added to the schema but not the list would warn on, and fail
validate --strict for, every change that uses it. Pin the two together.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Co-authored-by: Clay Good <hi@claygood.com>
* docs(openspec): correct 4 requirements that the code has outgrown
- cli-artifact-workflow/experimental-isolation#8: Updated the file path in the Single file implementation scenario to match the actual command location (src/commands/workflow/status.ts).
- cli-init/exit-codes#7: Updated the exit code for user-cancelled operations from 3 to 130 to match implementation.
- openspec-conventions/header-based-requirement-identification#6: Updated the normalization rule to remove a trailing run of '#' characters and surrounding spaces before trimming.
- cli-config/profile-configuration-flow#9: Changed the first action option label from 'Change delivery + workflows' to 'Delivery and workflows' to match the code.
None of these reduce what a requirement demands.
Scanned at bae58cf614 by openai/gpt-5-mini-2025-08-07.
* docs(openspec): harden drift corrections
* docs(openspec): clarify header normalization
---------
Co-authored-by: openspec-cloud[bot] <311461291+openspec-cloud[bot]@users.noreply.github.com>
Co-authored-by: Clay Good <hi@claygood.com>
show --json described each requirement as its SHALL sentence and each
scenario as its bullets. The parser read both headers and dropped them,
so a JSON reader could not name a requirement the way archive matches it.
Requirements and scenarios now carry a name, normalized by the same
helpers archive and the MODIFIED scenario loss check use. The field is
additive and optional in the schema.
Closes#1971
* fix(schemas): tell agents the requirement length limit
The validator flags requirement text over 500 characters, but the specs
instruction never mentioned the limit, so agents kept writing requirements
that tripped it. State the limit and how to split, and make the validator
message say how to fix it.
Part of #1976
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(schemas): match requirement length boundary
* test(validation): lock requirement length boundary
* fix(schemas): keep MODIFIED requirements whole under the length hint
The 500-character check is an INFO hint, not an error. Splitting or trimming
an existing requirement under MODIFIED drops scenarios the main spec still
has, which validate and archive reject. Say so, and scope the splitting
advice to new requirements.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* fix(config): name the offending rules item when a list is malformed
A rule item containing an unquoted ": " is valid-looking YAML but parses as
a mapping, so the artifact's whole rule set is dropped. The warning named only
the artifact, so the bad item had to be found by bisecting the list by hand.
Name every offending index with the shape YAML produced there, and point at the
quoting fix when a mapping is the cause. Parsing behavior is unchanged.
* test(config): cover remaining malformed rule shapes
---------
Co-authored-by: Yi-111-a <41823681+Yi-111-a@users.noreply.github.com>
Co-authored-by: Clay Good <hi@claygood.com>
* fix(view): align Active Changes progress bars for long names
* fix(view): cap the aligned name column at 48 characters
Pad names to the longest one only up to 48 characters, so rows with a
20-block bar and percentage still fit in 80 columns (#1986). Longer
names stay whole and start their own bar later.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(view): keep progress alignment scoped to changes
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Clay Good <hi@claygood.com>
* Updated Archive Skill
* Updated Testcase
* Updated Skill and Updated Unit Test
* Updated Archive and Bulk Archive Skill
* Updated Bulk Archive Skill
* fix(archive): keep existing main spec titles during sync verification
The post-sync structure check required every main spec to start with a
'# <capability> Specification' title. Neither sync-specs nor the validator
enforces that, and valid specs (including this repo's opsx-archive-skill)
use other titles, so an agent could stop the archive or rewrite a
user's title. Scope the title and heading rules to what the sync writes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* docs(specs): match opsx-archive-skill spec to the stricter sync check
The archive skill now treats a sync that reports a blocked retirement as a
failed sync, so the capability spec no longer calls that kept spec verified.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Clay Good <hi@claygood.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* test(flake): give the bash-spawning scope test a 60s timeout
The Windows runner took 13.1s to spawn bash three times on the Version
Packages push to main, tripping the 10s default. The same test ran in
0.3s and 4.2s on the two previous main runs; nothing in the code changed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test(e2e): give the git-clone init test a 60s timeout
Timed out at the 10s default on windows-pwsh three times (#1953 merge
queue, two changeset-release runs); it normally takes ~2.6s there.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* chore(changeset): track Kilo Code and Continue fixes for 1.13.2
#1938 and #1944 merged without changesets, so their user-visible
fixes would be missing from the 1.13.2 release notes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* chore(changeset): describe Kilo cleanup by file name
Cleanup deletes the known legacy file names without checking content, so
an edited copy is removed too; drop the claim that user files are kept.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* fix(verify): stop reporting removed requirements as missing
Verify walked every "### Requirement:" in the delta specs and looked for
an implementation of each one, whatever section it sat under. A REMOVED
requirement that the change had removed correctly came back as CRITICAL
"Requirement not found", with a recommendation to implement it. An agent
that follows the report puts back the behavior the change just deleted.
Verify now notes the delta section of each requirement first. ADDED and
MODIFIED keep the existing checks. REMOVED is checked the other way
round: finding nothing is the expected result, and it is only critical
while the behavior is still in the code. RENAMED only changes a name, so
the old name is not reported as missing. Scenario coverage skips removed
requirements, since there is nothing left to cover.
Archive and sync already handle each section on its own terms; verify
was the one step in the loop that did not.
Closes#1959
* docs(specs): scope the general verify scenarios to ADDED and MODIFIED
The Spec coverage, Requirement implementation mapping and Scenario
coverage scenarios still told the verifier to check every requirement
in the delta specs, which contradicts the Removed requirement scenario
added in the previous commit. A verifier following them would repeat
the #1959 failure.
* fix(verify): report a removal-only change as ready when nothing remains
With #1732 merged, a change whose delta specs only remove or rename
requirements left Requirement Implementation Mapping and Scenario
Coverage with nothing to check. The "no usable requirements" rule then
marked them not verified, so verify never reported the change ready,
the exact case #1959 describes. Those two checks are now not applicable
when the readable delta specs hold REMOVED or RENAMED requirements and
no ADDED or MODIFIED ones. An empty or unparseable delta still marks
them not verified.
Keyword matches in openspec/ artifacts, docs, or code that serves only
the Migration note or an ADDED requirement are no longer evidence by
themselves that a removed requirement is still implemented; a code path
that still delivers the removed behavior is reported even when shared.
The summary counts removals separately from covered requirements.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(verify): check a renamed requirement's behavior against its baseline
A RENAMED entry only told verify not to report the FROM name as
missing, and a rename-only change marked the correctness checks not
applicable. Nothing checked that the renamed requirement's behavior was
still implemented, so verify could report readiness unchecked.
Spec Coverage now reads the baseline requirement from the main spec
(under the FROM name, or the TO name once synced) and checks that its
behavior is still implemented, without requiring code symbols to be
renamed. A missing behavior is CRITICAL "Renamed requirement not
found"; an unreadable baseline marks the entry not verified. A TO name
that also appears under MODIFIED is still checked there.
Regression tests cover the skill template, the command template, and
the committed skills/ mirror.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Clay Good <hi@claygood.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* fix(verify): do not report unverified dimensions as passing
Step 5 gates task and spec coverage on `contextFiles.tasks` and
`contextFiles.specs`. `contextFiles` is an artifact-id map and artifact
ids come from the active schema, so on a schema that defines neither, both
branches are no-ops: nothing is checked, no issues are raised, and step 8
concludes "All checks passed. Ready for archive."
The Graceful Degradation guardrail already asks the agent to note skipped
checks, but nothing stopped the all-clear verdict. Mark an unchecked
dimension `Not verified` in the scorecard and require the final assessment
to name it.
* fix(verify): map skipped checks to report outcomes
* fix(verify): retain no-task and skipped-check context
* fix(verify): harden evidence gaps and final assessments
* fix(verify): preserve optional workflows and task artifact fallback
* fix(apply): resolve tracked task globs by schema path
* fix(verify): preserve unavailable task evidence
* fix(verify): distinguish untracked tasks from missing evidence
* docs(apply): document tracked globs and JSON evidence
* test(parity): regenerate hashes after merging #1940
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* test(parity): restore the #1837 regression tests dropped in the merge
The earlier conflict resolution took our whole side of the parity file,
which discarded the two threshold tests main gained in #1940. Take main's
file verbatim and regenerate the hashes instead.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* test(parity): regenerate hashes after merging #1955
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* test(parity): regenerate hashes after merging #1795 and #1926
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* test(parity): regenerate hashes after merging #1731
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
---------
Co-authored-by: Clay Good <hi@claygood.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>