mirror of
https://github.com/Fission-AI/OpenSpec.git
synced 2026-10-18 05:59:56 +08:00
* feat(metadata): x- extension keys in .openspec.yaml are not reported as unknown Teams that keep tool data beside a change (a tracker id, a goal id, an owner) had no place for it: since 1.14.0 every unrecognized top-level key is a validation warning, so validate --strict fails. Keys that start with x- are now extension metadata, as in OpenAPI: never read, never written, never reported. Every other unknown key is still reported, and the warning now names the x- prefix as the way to keep such data. Refs #657 * fix(metadata): accept any x- name, and say so when a key just misses The extension grammar was narrower than the contract above it. The doc comment said "the prefix is the whole contract, as in OpenAPI's x- extensions", but the pattern was `/^x-[a-z0-9][a-z0-9_-]*$/`, so the spellings teams actually write were still reported: x-jiraKey warned x-a- accepted x-trackerID warned x-foo_bar accepted x-Owner warned `x-jiraKey` is the obvious key for the tracker case in #657, and it failed `validate --strict` while a trailing-hyphen name passed. Worse, the new remediation sentence told that user to "prefix a key with x-" - which they had done - so the warning became a dead end with no way out from the message alone. That is a worse experience than the warning this PR removes. The name after the prefix is now the owner's business: `/^x-\S+$/`. Empty and whitespace-carrying names stay rejected, the latter because whitespace would let a key forge a second line in the warning output. The prefix itself stays lowercase, keeping this PR's deliberate `X-goal -> false`. That is the one near-miss a user cannot diagnose from the old message, so the message now names both conditions it does not cover, and only when a reported key actually starts with the prefix. Also pinned the round-trip, which was the risk worth checking: archive moves `.openspec.yaml` rather than rewriting it, and `writeChangeMetadata` only ever writes a new file, so extension keys survive today. But `ChangeMetadataSchema` is not passthrough and strips them, so the first read-modify-write caller would silently delete data a team put there. A test pins the stripping and the writer's doc comment now says to merge `x-` keys back from the raw YAML. Documented the namespace in docs/cli.md next to the other metadata keys, since `x-* (yours)` in a directory-tree comment could not carry the rule, and flipped the changeset to `patch` to match the `fix` retitle and the #2020/#2028 precedent. Verified end to end: a change with `x-jiraKey` and `x-Owner` passes `validate --strict`, while `X-Tracker` beside a `taskss` typo reports both and explains the prefix. 6413 tests pass; lint clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * refactor(metadata): merge the stacked writeChangeMetadata JSDoc and trim extension-key comments - writeChangeMetadata had two consecutive /** */ blocks, orphaning the first; merge them into one that keeps the params and the x- key stripping caveat. - Trim the EXTENSION_KEY_PATTERN comment to the contract, dropping the history of the earlier grammar and the inaccurate claim that whitespace could forge a warning line (reported keys are already sanitized). - Tighten the changeset to the user-facing behavior. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(archive): keep x- extension keys byte-for-byte through archive Archive is the only path that touches an existing .openspec.yaml; it moves the file rather than rewriting it. Pin that, and that archive --json emits no unknown-key warning for x- keys. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(metadata): document x- extension keys in the docs-lab reference The canonical change-metadata reference still said every unknown top-level key is reported and fails --strict. Add an Extension keys section (name rule, ignored value, top-level scope, strict result, archive) and point the Validation bullets at it. Pin each documented claim where it is enforced, not only in the helper: the validator passes --strict on x- keys with any YAML value, still fails on X-Tracker, a bare x- and "x- tracker", and loadChangeContext (status, instructions) returns no warning. All three tests fail on main's code. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: beast-infra <hi@fbeeg.io> Co-authored-by: Clay Good <hi@claygood.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>