From bd37065f051e9d6a18955a65b57da03528e946e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D7=A0=CF=85=CE=B1=CE=B7=20=D7=A0=CF=85=CE=B1=CE=B7=D1=95?= =?UTF-8?q?=CF=83=CE=B7?= Date: Sun, 16 Aug 2026 00:31:31 -0700 Subject: [PATCH 1/4] docs: say to use the skill, not the CLI CONTRIBUTING documented the four stages and left out how they are invoked, so eleven changes were assembled by driving the openspec CLI by hand. That skips the workflow the checks live in. Names both forms, states that each artifact has a template and rules retrievable with openspec instructions, and corrects the claim that archiving refuses to run with unchecked tasks. It warns and asks. Co-Authored-By: Claude Opus 5 (1M context) --- CONTRIBUTING.md | 60 ++++++++++++++++++- .../.openspec.yaml | 2 + .../conform-artifacts-to-schema/proposal.md | 51 ++++++++++++++++ 3 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 openspec/changes/conform-artifacts-to-schema/.openspec.yaml create mode 100644 openspec/changes/conform-artifacts-to-schema/proposal.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c25fe98..2459bfa 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -277,7 +277,13 @@ tested — but only if it is corrected in the open. Merges the deltas into `specs/` and moves the change to `openspec/changes/archive/`. Branch, commit, open a PR. -Archiving refuses to run while any task is unchecked. +Before merging, archiving compares each delta against the spec it targets and +reports what would be added, modified, removed, or renamed. Read that summary. A +`MODIFIED` delta whose requirement heading does not exist in the corpus is +reported here and nowhere else — `openspec validate --strict` passes it. + +Unchecked tasks produce a warning and a confirmation prompt rather than a +refusal. Skipping the prompts also skips the sync assessment above. It writes the spec file itself, and does not format it. Run `just md-fmt` afterwards or the formatting check fails on a file you did not hand-write. @@ -298,6 +304,58 @@ window where the corpus is knowingly incomplete. Run `/opsx:propose`, then | `/opsx:update` | Revise a change that is still in flight | | `/opsx:sync` | Update `specs/` without archiving the change | +### Use the skill, not the CLI + +Every step of the workflow is invoked through a skill, or through its slash +command. **Do not drive `openspec` by hand.** + +| Step | A person types | An agent invokes | +| ------- | --------------- | ------------------------- | +| Explore | `/opsx:explore` | `openspec-explore` | +| Propose | `/opsx:propose` | `openspec-propose` | +| Apply | `/opsx:apply` | `openspec-apply-change` | +| Sync | `/opsx:sync` | `openspec-sync-specs` | +| Update | `/opsx:update` | `openspec-update-change` | +| Archive | `/opsx:archive` | `openspec-archive-change` | + +The two forms carry the same instructions and differ only in who can reach them: +a person types a slash command, an agent invokes a skill. + +The skill runs the `openspec` CLI for you, and which commands it runs is not the +point — the workflow around them is. Driving the CLI directly skips that +workflow, and with it the sync assessment before archiving, the planning +boundary that keeps implementation out of the turn that produced the plan, and +the per-artifact rules below. A change assembled by hand can validate and still +not conform. + +An agent reaches these skills only when the session's project root holds them. +This repository does. A session rooted at a parent directory will not, unless +they are linked into that root or installed under `~/.claude/skills/`. + +### Each artifact has a template and rules + +The schema defines four artifacts and constrains each one. Retrieve what it +expects: + +```bash +openspec instructions --change +``` + +That prints the template to fill in, the rules the artifact is held to, and the +completed artifacts to read first. The rules are not advisory and are not +checked by `openspec validate`, which verifies structure rather than +conformance. Among them: + +- A requirement states one behavior. If it needs "and" to describe itself, it is + two requirements. +- A requirement does not name a file, function, or library. Those belong in the + design. +- Every decision in a design records an alternative considered and why it lost. +- Risks in a design take the form `[Risk] -> Mitigation`. + +Writing an artifact without reading these produces something that validates and +still does not conform. + Refresh the generated agent wiring after a CLI upgrade: ```bash diff --git a/openspec/changes/conform-artifacts-to-schema/.openspec.yaml b/openspec/changes/conform-artifacts-to-schema/.openspec.yaml new file mode 100644 index 0000000..f161d5c --- /dev/null +++ b/openspec/changes/conform-artifacts-to-schema/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-08-16 diff --git a/openspec/changes/conform-artifacts-to-schema/proposal.md b/openspec/changes/conform-artifacts-to-schema/proposal.md new file mode 100644 index 0000000..d939809 --- /dev/null +++ b/openspec/changes/conform-artifacts-to-schema/proposal.md @@ -0,0 +1,51 @@ +## Why + +The corpus was authored without reading the schema it is written to. OpenSpec +supplies a template and a set of rules for every artifact, retrievable with +`openspec instructions --change `. That command was never run. +`CONTRIBUTING.md` documents the four-stage workflow and does not mention it, so +nothing pointed at the rules and they were followed only where they happened to +match instinct. + +Three rules were missed, and `openspec validate --strict` passes anyway — it +checks delta structure, not conformance: + +- **Risks use the form `[Risk] -> Mitigation`.** No design document uses it. Not + one of fifteen, including four written before this was noticed. +- **One behavior per requirement.** Eighteen requirements across all six + capabilities carry three or more `SHALL` statements. `Coverage target` carries + eleven. A requirement bundling three rules cannot be modified independently: + changing one rewrites a heading the other two live under, which is the + fragility that has twice nearly orphaned a delta. +- **Requirements do not name files, functions, or libraries.** Twenty do. + +The same gap explains a second failure. The archive workflow assesses whether a +delta's target exists in the main spec before merging. Archiving was run with +`--yes`, which skips the prompt that assessment surfaces in. Two changes carried +a `MODIFIED` delta against a requirement the corpus did not hold, and both were +caught by reading rather than by the check that exists for it. + +## What Changes + +- `CONTRIBUTING.md` states that each artifact has a template and rules, and how + to retrieve them. +- Design documents state risks in the form the schema defines. +- Requirements bundling several behaviors are split, so each can be modified + without rewriting the others. +- Requirements naming a file, function, or library either move that detail to + design, or record why the name is the subject rather than an implementation + detail. + +## Capabilities + +### Modified Capabilities + +- `documentation`: adds what an artifact in the corpus must satisfy, so the + rules bind the corpus rather than living only in the tool that scaffolds it. + +## Impact + +- `specs`: `CONTRIBUTING.md` gains the workflow detail; fifteen design documents + and six capability specifications are revised. No other repository is affected + — every change here is to how the corpus is written, not to what it requires + of code. From 9bd13ac8f13b490300281a08ed735c06055985c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D7=A0=CF=85=CE=B1=CE=B7=20=D7=A0=CF=85=CE=B1=CE=B7=D1=95?= =?UTF-8?q?=CF=83=CE=B7?= Date: Sun, 16 Aug 2026 00:33:16 -0700 Subject: [PATCH 2/4] docs: drop the half-built change from this branch A blanket stage swept an incomplete change directory into a pull request about CONTRIBUTING. With only a proposal and no deltas it fails validation, which is the check working. It belongs in its own pull request once its artifacts exist. Co-Authored-By: Claude Opus 5 (1M context) --- .../.openspec.yaml | 2 - .../conform-artifacts-to-schema/proposal.md | 51 ------------------- 2 files changed, 53 deletions(-) delete mode 100644 openspec/changes/conform-artifacts-to-schema/.openspec.yaml delete mode 100644 openspec/changes/conform-artifacts-to-schema/proposal.md diff --git a/openspec/changes/conform-artifacts-to-schema/.openspec.yaml b/openspec/changes/conform-artifacts-to-schema/.openspec.yaml deleted file mode 100644 index f161d5c..0000000 --- a/openspec/changes/conform-artifacts-to-schema/.openspec.yaml +++ /dev/null @@ -1,2 +0,0 @@ -schema: spec-driven -created: 2026-08-16 diff --git a/openspec/changes/conform-artifacts-to-schema/proposal.md b/openspec/changes/conform-artifacts-to-schema/proposal.md deleted file mode 100644 index d939809..0000000 --- a/openspec/changes/conform-artifacts-to-schema/proposal.md +++ /dev/null @@ -1,51 +0,0 @@ -## Why - -The corpus was authored without reading the schema it is written to. OpenSpec -supplies a template and a set of rules for every artifact, retrievable with -`openspec instructions --change `. That command was never run. -`CONTRIBUTING.md` documents the four-stage workflow and does not mention it, so -nothing pointed at the rules and they were followed only where they happened to -match instinct. - -Three rules were missed, and `openspec validate --strict` passes anyway — it -checks delta structure, not conformance: - -- **Risks use the form `[Risk] -> Mitigation`.** No design document uses it. Not - one of fifteen, including four written before this was noticed. -- **One behavior per requirement.** Eighteen requirements across all six - capabilities carry three or more `SHALL` statements. `Coverage target` carries - eleven. A requirement bundling three rules cannot be modified independently: - changing one rewrites a heading the other two live under, which is the - fragility that has twice nearly orphaned a delta. -- **Requirements do not name files, functions, or libraries.** Twenty do. - -The same gap explains a second failure. The archive workflow assesses whether a -delta's target exists in the main spec before merging. Archiving was run with -`--yes`, which skips the prompt that assessment surfaces in. Two changes carried -a `MODIFIED` delta against a requirement the corpus did not hold, and both were -caught by reading rather than by the check that exists for it. - -## What Changes - -- `CONTRIBUTING.md` states that each artifact has a template and rules, and how - to retrieve them. -- Design documents state risks in the form the schema defines. -- Requirements bundling several behaviors are split, so each can be modified - without rewriting the others. -- Requirements naming a file, function, or library either move that detail to - design, or record why the name is the subject rather than an implementation - detail. - -## Capabilities - -### Modified Capabilities - -- `documentation`: adds what an artifact in the corpus must satisfy, so the - rules bind the corpus rather than living only in the tool that scaffolds it. - -## Impact - -- `specs`: `CONTRIBUTING.md` gains the workflow detail; fifteen design documents - and six capability specifications are revised. No other repository is affected - — every change here is to how the corpus is written, not to what it requires - of code. From e91afb8edcf0ed177afaa28bde73468a4f5b650b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D7=A0=CF=85=CE=B1=CE=B7=20=D7=A0=CF=85=CE=B1=CE=B7=D1=95?= =?UTF-8?q?=CF=83=CE=B7?= Date: Sun, 16 Aug 2026 00:37:12 -0700 Subject: [PATCH 3/4] docs: drive the workflow by skill, not by CLI CONTRIBUTING showed the four stages and left out how each is invoked, what the guards between them are, and that the artifacts have templates and rules. Every openspec CLI invocation is removed except init, which explains where the commands come from. AGENTS.md told agents to type slash commands they cannot reach, and said to follow the artifact build order rather than to let the skill write the artifacts at all. Co-Authored-By: Claude Opus 5 (1M context) --- AGENTS.md | 49 +++++++++++--- CONTRIBUTING.md | 176 ++++++++++++++++++++++++------------------------ 2 files changed, 127 insertions(+), 98 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index b2ad7b0..8852b1c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -24,10 +24,26 @@ treating the failure as real. ## Running a change -The procedure, with commands, is in @CONTRIBUTING.md under "Running a change". -Follow it rather than improvising: propose, merge, apply, archive — each step -its own pull request, except documentation-only changes where propose and -archive belong in one. +Invoke the skill for every step. Never drive the `openspec` CLI yourself, and +never assemble a change by hand — the CLI is what the skill runs, and the guards +live in the workflow around it. + +| Step | Skill | +| ------- | ------------------------- | +| Explore | `openspec-explore` | +| Propose | `openspec-propose` | +| Apply | `openspec-apply-change` | +| Update | `openspec-update-change` | +| Sync | `openspec-sync-specs` | +| Archive | `openspec-archive-change` | + +The `/opsx:*` slash commands in @CONTRIBUTING.md are the same instructions in +the form a person types. You cannot type them; invoke the skill instead. + +The procedure is in @CONTRIBUTING.md under "Running a change". Follow it rather +than improvising: propose, merge, apply, archive — each step its own pull +request, except documentation-only changes where propose and archive belong in +one. ## Read the corpus first @@ -51,8 +67,8 @@ See @CONTRIBUTING.md under "When you find something". ## Planning boundary -`/opsx:propose` produces planning artifacts and then stops. Do not edit code in -the same response, even when the request asks you to build or fix something. +`openspec-propose` produces planning artifacts and then stops. Do not edit code +in the same response, even when the request asks you to build or fix something. Wait for an explicit instruction to apply. Applying waits for the proposal PR to **merge**, not to exist. An open branch is @@ -66,9 +82,20 @@ See @CONTRIBUTING.md under "Running a change". ## Writing artifacts -Read `openspec/config.yaml` before generating any artifact. Its `context` and -`rules` are injected into every generation — apply them as constraints, and do -not copy them into the output. +Do not write an artifact yourself. The propose skill retrieves each one's +template, its rules, and the artifacts to read first, then writes to them in +dependency order. Assembling one by hand produces something that validates and +does not conform — `just validate` checks structure, not conformance. -Follow the artifact build order from `openspec status`, not the order the -templates happen to appear in. +`openspec/config.yaml` carries project context and per-artifact rules that are +injected into every generation. Apply them as constraints; never copy them into +the output. + +## Applying a change + +- A task is checked only when its behavior is fully implemented — not partially, + not deferred, not done in some repositories and not others. +- Scope beyond the task is surfaced, not absorbed. If a task needs more than the + spec describes, or you are narrowing it to fit, stop and say so. +- A blocker pauses the work. Unclear task, design issue, error — report it and + wait rather than guessing. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2459bfa..dc4e57a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -81,7 +81,6 @@ bun install -g @fission-ai/openspec@latest # the OpenSpec CLI Verify: ```bash -openspec --version just test # runs every check CI runs ``` @@ -222,33 +221,69 @@ person with a rule that exists only in someone's memory. `main` is protected, so each step below is its own pull request. -**1. Propose** +### Invoke the skill, never the CLI -```bash -/opsx:propose "converge shared justfiles on one consumption style" -``` +Every step is a skill. A person types its slash command; an agent invokes the +skill by name. **Never drive `openspec` by hand** — the CLI is what the skill +runs, not what you run. + +| Step | You type | An agent invokes | For | +| ------- | --------------- | ------------------------- | ----------------------------------------- | +| Explore | `/opsx:explore` | `openspec-explore` | Thinking before there is a change to make | +| Propose | `/opsx:propose` | `openspec-propose` | Turning a decision into artifacts | +| Apply | `/opsx:apply` | `openspec-apply-change` | Working the task list | +| Update | `/opsx:update` | `openspec-update-change` | Revising a change still in flight | +| Sync | `/opsx:sync` | `openspec-sync-specs` | Merging deltas without archiving | +| Archive | `/opsx:archive` | `openspec-archive-change` | Filing a finished change | + +Both forms carry the same instructions. Assembling the steps yourself skips the +guards that live between them, and a change built that way can pass every check +and still be wrong. + +An agent only reaches these when the session's project root holds them. This +repository does; a session rooted at a parent directory sees nothing unless they +are linked there or installed under `~/.claude/skills/`. + +### 1. Explore, when the shape is not settled + +Explore is a stance, not a step you owe anyone. It reads code, argues +approaches, and draws diagrams. It will not write code, and it captures +artifacts only when you ask. + +Skip it when you already know what you are proposing. + +### 2. Propose Creates `openspec/changes//` with a proposal, spec deltas, a design, and -tasks. Nothing else happens — this step never edits code. +tasks — each written to a template, against rules, in dependency order. + +Then it **stops**. Proposing never edits code, and the request that triggered it +does not authorize implementation, however it was phrased. Branch, commit, open a PR. What gets reviewed is the plan. -**2. Merge the proposal PR** +### 3. Merge the proposal PR The plan is now agreed. `specs/` is unchanged; the change is in flight. -**3. Apply** +Do not start applying before this. A branch is not an agreement, and +implementation written against an unmerged proposal is implementation written +against your own opinion. -```bash -/opsx:apply -``` +### 4. Apply + +Works the task list. Implementation lands in the target repository, in that +repository's own PR. Tick each task off here as it lands, not in a batch. -Work the task list. Implementation lands in the target repository, in that -repository's own PR. Tick tasks off here as they land. +Three rules it holds you to: -Do not start this step until the proposal PR is merged. A branch is not an -agreement, and implementation written against an unmerged proposal is -implementation written against your own opinion. +- **A task is checked only when its behavior is fully implemented.** Not + partially, not deferred, not "done except for one repository". +- **Scope beyond the task is surfaced, not absorbed.** If a task turns out to + need more than the spec describes, or you find yourself narrowing it to fit, + stop and say so. +- **A blocker pauses the work.** Unclear task, design issue, error — report and + wait rather than guessing. **When applying shows the requirement is wrong — stop.** @@ -268,83 +303,56 @@ it as a change of rule. A requirement that turns out to be wrong is worth more than one that was never tested — but only if it is corrected in the open. -**4. Archive** - -```bash -/opsx:archive -``` +### 5. Archive Merges the deltas into `specs/` and moves the change to `openspec/changes/archive/`. Branch, commit, open a PR. -Before merging, archiving compares each delta against the spec it targets and -reports what would be added, modified, removed, or renamed. Read that summary. A -`MODIFIED` delta whose requirement heading does not exist in the corpus is -reported here and nowhere else — `openspec validate --strict` passes it. +Before merging anything it compares each delta against the spec it targets and +reports what would be added, modified, removed, or renamed. **Read that +summary.** A `MODIFIED` delta whose requirement heading does not exist in the +corpus is reported there and nowhere else — `just validate` passes it, because +validation checks that a change is well formed, not that its deltas have +somewhere to land. + +The merge itself is a considered one: a `MODIFIED` delta updates the parts it +names and preserves the scenarios it does not mention. That is why it is worth +letting the skill do it. Unchecked tasks produce a warning and a confirmation prompt rather than a -refusal. Skipping the prompts also skips the sync assessment above. +refusal. Suppressing the prompts suppresses the comparison above with them. -It writes the spec file itself, and does not format it. Run `just md-fmt` +Archiving writes the spec file and does not format it. Run `just md-fmt` afterwards or the formatting check fails on a file you did not hand-write. +### Sync, when the corpus should move before the change is done + +Sync merges deltas into `specs/` without archiving. Reach for it when +implementation has diverged from the plan and the corpus should reflect what was +actually built, before the change is finished. + +### Update, when the plan itself changes + +Update revises a change's artifacts and keeps them coherent with each other. It +never edits code. Use it when a decision lands mid-flight, rather than editing +one artifact and leaving the others describing something else. + ### Shortcut for documentation-only changes When the artifacts *are* the work — recording an architecture that already -exists — steps 1 and 4 belong in the **same** PR. Splitting them only creates a -window where the corpus is knowingly incomplete. Run `/opsx:propose`, then -`/opsx:archive`, then open one PR containing both the change and the resulting -`specs/` update. - -### Other commands - -| Command | When | -| --------------- | -------------------------------------------- | -| `/opsx:explore` | Before proposing, to weigh approaches | -| `/opsx:update` | Revise a change that is still in flight | -| `/opsx:sync` | Update `specs/` without archiving the change | - -### Use the skill, not the CLI - -Every step of the workflow is invoked through a skill, or through its slash -command. **Do not drive `openspec` by hand.** - -| Step | A person types | An agent invokes | -| ------- | --------------- | ------------------------- | -| Explore | `/opsx:explore` | `openspec-explore` | -| Propose | `/opsx:propose` | `openspec-propose` | -| Apply | `/opsx:apply` | `openspec-apply-change` | -| Sync | `/opsx:sync` | `openspec-sync-specs` | -| Update | `/opsx:update` | `openspec-update-change` | -| Archive | `/opsx:archive` | `openspec-archive-change` | - -The two forms carry the same instructions and differ only in who can reach them: -a person types a slash command, an agent invokes a skill. - -The skill runs the `openspec` CLI for you, and which commands it runs is not the -point — the workflow around them is. Driving the CLI directly skips that -workflow, and with it the sync assessment before archiving, the planning -boundary that keeps implementation out of the turn that produced the plan, and -the per-artifact rules below. A change assembled by hand can validate and still -not conform. - -An agent reaches these skills only when the session's project root holds them. -This repository does. A session rooted at a parent directory will not, unless -they are linked into that root or installed under `~/.claude/skills/`. +exists — propose and archive belong in the **same** PR. Splitting them only +creates a window where the corpus is knowingly incomplete. ### Each artifact has a template and rules -The schema defines four artifacts and constrains each one. Retrieve what it -expects: +The schema defines four artifacts and constrains each one. The propose skill +retrieves the template, the rules, and the artifacts to read first, then writes +each file to them — that is most of what it is doing, and most of what is lost +by assembling a change yourself. -```bash -openspec instructions --change -``` - -That prints the template to fill in, the rules the artifact is held to, and the -completed artifacts to read first. The rules are not advisory and are not -checked by `openspec validate`, which verifies structure rather than -conformance. Among them: +The rules are not advisory, and `just validate` does not enforce them: it checks +that a change is structurally well formed, not that its artifacts follow the +schema. Among them: - A requirement states one behavior. If it needs "and" to describe itself, it is two requirements. @@ -356,12 +364,6 @@ conformance. Among them: Writing an artifact without reading these produces something that validates and still does not conform. -Refresh the generated agent wiring after a CLI upgrade: - -```bash -openspec update -``` - ## Writing requirements Requirements are plain Markdown. A requirement states the behavior in `SHALL` @@ -404,8 +406,8 @@ just test ``` That runs what CI runs — markdown formatting, justfile lint, and -`openspec validate --all --strict`. `just md-fmt` fixes formatting failures. A -change that validates but is not formatted will still fail CI. +`just validate`. `just md-fmt` fixes formatting failures. A change that +validates but is not formatted will still fail CI. Two things [mdformat] rewrites silently, so write them correctly the first time: @@ -413,8 +415,8 @@ Two things [mdformat] rewrites silently, so write them correctly the first time: stops rendering as a callout. Use bold text instead. - Link definitions are lowercased and sorted. -`.claude/` is excluded from formatting, because `openspec update` regenerates -those files and would revert any changes. +`.claude/` is excluded from formatting. Those files are generated, and +regenerating them would revert anything written there by hand. ## Branching From 366c54facefb89a02fc720dbb19a2134a47ea868 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D7=A0=CF=85=CE=B1=CE=B7=20=D7=A0=CF=85=CE=B1=CE=B7=D1=95?= =?UTF-8?q?=CF=83=CE=B7?= Date: Sun, 16 Aug 2026 00:38:27 -0700 Subject: [PATCH 4/4] docs: keep AGENTS.md a pointer, not a copy The previous commit duplicated the skill table and the apply rules into AGENTS.md. Both apply to people as well, so both belong in CONTRIBUTING alone. What remains is the one thing that is genuinely agent-specific: the workflow names each step twice, and an agent cannot type a slash command, so it invokes the skill named for that step. Co-Authored-By: Claude Opus 5 (1M context) --- AGENTS.md | 46 +++++++++------------------------------------- 1 file changed, 9 insertions(+), 37 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 8852b1c..d70151a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -24,26 +24,12 @@ treating the failure as real. ## Running a change -Invoke the skill for every step. Never drive the `openspec` CLI yourself, and -never assemble a change by hand — the CLI is what the skill runs, and the guards -live in the workflow around it. - -| Step | Skill | -| ------- | ------------------------- | -| Explore | `openspec-explore` | -| Propose | `openspec-propose` | -| Apply | `openspec-apply-change` | -| Update | `openspec-update-change` | -| Sync | `openspec-sync-specs` | -| Archive | `openspec-archive-change` | - -The `/opsx:*` slash commands in @CONTRIBUTING.md are the same instructions in -the form a person types. You cannot type them; invoke the skill instead. - -The procedure is in @CONTRIBUTING.md under "Running a change". Follow it rather -than improvising: propose, merge, apply, archive — each step its own pull -request, except documentation-only changes where propose and archive belong in -one. +The workflow is in @CONTRIBUTING.md under "Running a change". Follow it rather +than improvising. + +It names each step twice: a `/opsx:*` slash command a person types, and a skill +an agent invokes. You cannot type a slash command — invoke the skill named for +that step. ## Read the corpus first @@ -82,20 +68,6 @@ See @CONTRIBUTING.md under "Running a change". ## Writing artifacts -Do not write an artifact yourself. The propose skill retrieves each one's -template, its rules, and the artifacts to read first, then writes to them in -dependency order. Assembling one by hand produces something that validates and -does not conform — `just validate` checks structure, not conformance. - -`openspec/config.yaml` carries project context and per-artifact rules that are -injected into every generation. Apply them as constraints; never copy them into -the output. - -## Applying a change - -- A task is checked only when its behavior is fully implemented — not partially, - not deferred, not done in some repositories and not others. -- Scope beyond the task is surfaced, not absorbed. If a task needs more than the - spec describes, or you are narrowing it to fit, stop and say so. -- A blocker pauses the work. Unclear task, design issue, error — report it and - wait rather than guessing. +`openspec/config.yaml` carries project context and per-artifact rules injected +into every generation. They are constraints on what you write — never copy them +into the output.