opensdd 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/bin/opensdd.js +2 -0
- package/opensdd/cli.md +633 -0
- package/opensdd/sdd-generate.md +209 -0
- package/opensdd/sdd-manager.md +134 -0
- package/opensdd/spec-format.md +494 -0
- package/package.json +31 -0
- package/src/commands/init.js +184 -0
- package/src/commands/install.js +161 -0
- package/src/commands/list.js +40 -0
- package/src/commands/publish.js +235 -0
- package/src/commands/status.js +91 -0
- package/src/commands/update.js +227 -0
- package/src/commands/updateApply.js +149 -0
- package/src/commands/validate.js +95 -0
- package/src/index.js +126 -0
- package/src/lib/manifest.js +38 -0
- package/src/lib/registry.js +176 -0
- package/src/lib/skills.js +204 -0
- package/src/lib/validation.js +122 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 DeepAgents
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/bin/opensdd.js
ADDED
package/opensdd/cli.md
ADDED
|
@@ -0,0 +1,633 @@
|
|
|
1
|
+
# CLI
|
|
2
|
+
|
|
3
|
+
> A thin Node.js command-line tool that installs, updates, publishes, and manages OpenSDD specs.
|
|
4
|
+
|
|
5
|
+
## Version
|
|
6
|
+
|
|
7
|
+
0.1.0
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
The CLI is the distribution mechanism for OpenSDD specs. It handles initializing projects, fetching specs from a registry, managing `opensdd.json`, producing changesets for dependency updates, and publishing authored specs to the registry. It does not perform AI operations — all implementation, testing, and conformance checking is delegated to the consumer's coding agent via the sdd-manager skill.
|
|
12
|
+
|
|
13
|
+
The CLI is published to npm as `opensdd` and invoked as `opensdd`.
|
|
14
|
+
|
|
15
|
+
## Behavioral Contract
|
|
16
|
+
|
|
17
|
+
### `opensdd init`
|
|
18
|
+
|
|
19
|
+
Initializes the OpenSDD protocol in the current project.
|
|
20
|
+
|
|
21
|
+
#### Behavior
|
|
22
|
+
|
|
23
|
+
1. Verify the current directory is a project root (contains `package.json`, `pyproject.toml`, `Cargo.toml`, `go.mod`, `.git`, `opensdd.json`, or similar project markers). If no project marker is found, warn the user and ask for confirmation to proceed.
|
|
24
|
+
2. Install both skills (sdd-manager and sdd-generate) into all supported agent configuration directories. If already present, overwrite — skills are always spec-owned. The full installation mapping is defined in the **Skill Installation Mapping** section below.
|
|
25
|
+
3. If `opensdd.json` does not exist at the project root, create it with default contents: `{ "opensdd": "0.1.0", "specs_dir": "opensdd", "deps_dir": ".opensdd.deps" }`. The `registry`, `publish`, and `dependencies` fields are intentionally omitted from the default — they are optional. When `registry` is absent, the CLI defaults to `https://github.com/deepagents-ai/opensdd` per the registry source resolution logic. If `opensdd.json` already exists, leave it untouched.
|
|
26
|
+
4. Create the `opensdd/` directory (or the directory specified by `specs_dir` in an existing `opensdd.json`) if it does not exist.
|
|
27
|
+
5. If `<specs_dir>/spec.md` does not exist, create a skeleton `spec.md` with placeholder sections:
|
|
28
|
+
```markdown
|
|
29
|
+
# {project-name}
|
|
30
|
+
|
|
31
|
+
> TODO: One-line description of what this software does.
|
|
32
|
+
|
|
33
|
+
## Behavioral Contract
|
|
34
|
+
|
|
35
|
+
<!-- Define behaviors here. -->
|
|
36
|
+
|
|
37
|
+
## NOT Specified (Implementation Freedom)
|
|
38
|
+
|
|
39
|
+
<!-- List aspects left to the implementer's discretion. -->
|
|
40
|
+
|
|
41
|
+
## Invariants
|
|
42
|
+
|
|
43
|
+
<!-- List properties that must hold true across all inputs and states. -->
|
|
44
|
+
```
|
|
45
|
+
The `{project-name}` placeholder SHOULD be inferred from the nearest project manifest (e.g., `name` in `package.json`) or default to the directory name. If `spec.md` already exists, leave it untouched.
|
|
46
|
+
6. Create the `.opensdd.deps/` directory (or the directory specified by `deps_dir` in an existing `opensdd.json`) if it does not exist.
|
|
47
|
+
7. Print a success message.
|
|
48
|
+
|
|
49
|
+
- `opensdd init` in a fresh project MUST produce the output below
|
|
50
|
+
- `opensdd init` in a project that already has OpenSDD initialized MUST overwrite all skill installation files across all agent formats but MUST NOT overwrite `opensdd.json`
|
|
51
|
+
|
|
52
|
+
#### Output
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
Initialized OpenSDD:
|
|
56
|
+
Skills installed for: Claude Code, Codex CLI, Cursor, GitHub Copilot, Gemini CLI, Amp
|
|
57
|
+
sdd-manager installed (6 agent formats)
|
|
58
|
+
sdd-generate installed (6 agent formats)
|
|
59
|
+
opensdd.json created
|
|
60
|
+
opensdd/ created
|
|
61
|
+
opensdd/spec.md created (skeleton)
|
|
62
|
+
.opensdd.deps/ created
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
If already initialized:
|
|
66
|
+
```
|
|
67
|
+
Initialized OpenSDD:
|
|
68
|
+
Skills installed for: Claude Code, Codex CLI, Cursor, GitHub Copilot, Gemini CLI, Amp
|
|
69
|
+
sdd-manager updated (6 agent formats)
|
|
70
|
+
sdd-generate updated (6 agent formats)
|
|
71
|
+
opensdd.json already exists (preserved)
|
|
72
|
+
opensdd/ already exists
|
|
73
|
+
opensdd/spec.md already exists (preserved)
|
|
74
|
+
.opensdd.deps/ already exists
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
#### Errors
|
|
78
|
+
|
|
79
|
+
- If `.claude/` directory cannot be created (permissions error), print error and exit with code 1.
|
|
80
|
+
- If `opensdd.json` exists but is malformed JSON, print error and exit with code 1.
|
|
81
|
+
|
|
82
|
+
### Skill Installation Mapping
|
|
83
|
+
|
|
84
|
+
`opensdd init` installs both skills (sdd-manager and sdd-generate) into the native configuration format of each supported coding agent. The canonical skill content is authored as markdown source files (`sdd-manager.md`, `sdd-generate.md`, `spec-format.md`). The CLI transforms these into each agent's expected format during installation.
|
|
85
|
+
|
|
86
|
+
All installed skill files are **spec-owned** — they are overwritten on every `opensdd init` and MUST NOT be edited by the user.
|
|
87
|
+
|
|
88
|
+
#### Claude Code (Agent Skills standard)
|
|
89
|
+
|
|
90
|
+
Each skill is a directory with a `SKILL.md` and a `references/` subdirectory. Claude Code auto-discovers skills in `.claude/skills/`.
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
.claude/skills/
|
|
94
|
+
sdd-manager/
|
|
95
|
+
SKILL.md ← sdd-manager.md
|
|
96
|
+
references/
|
|
97
|
+
spec-format.md ← spec-format.md
|
|
98
|
+
sdd-generate/
|
|
99
|
+
SKILL.md ← sdd-generate.md
|
|
100
|
+
references/
|
|
101
|
+
spec-format.md ← spec-format.md
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
#### OpenAI Codex CLI (Agent Skills standard)
|
|
105
|
+
|
|
106
|
+
Codex CLI follows the same Agent Skills standard but discovers skills in `.agents/skills/`.
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
.agents/skills/
|
|
110
|
+
sdd-manager/
|
|
111
|
+
SKILL.md ← sdd-manager.md
|
|
112
|
+
references/
|
|
113
|
+
spec-format.md ← spec-format.md
|
|
114
|
+
sdd-generate/
|
|
115
|
+
SKILL.md ← sdd-generate.md
|
|
116
|
+
references/
|
|
117
|
+
spec-format.md ← spec-format.md
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
#### Cursor
|
|
121
|
+
|
|
122
|
+
Cursor discovers rules as `.md` or `.mdc` files in `.cursor/rules/`. Each skill becomes a single rule file with YAML frontmatter. The frontmatter uses `description` for intelligent matching (Cursor decides when to apply the rule based on relevance). The body contains the full skill content followed by a reference to `spec-format.md`.
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
.cursor/rules/
|
|
126
|
+
sdd-manager.md ← sdd-manager.md with frontmatter
|
|
127
|
+
sdd-generate.md ← sdd-generate.md with frontmatter
|
|
128
|
+
opensdd-spec-format.md ← spec-format.md with frontmatter
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Frontmatter for `sdd-manager.md`:
|
|
132
|
+
```yaml
|
|
133
|
+
---
|
|
134
|
+
description: "Implement, update, and verify installed OpenSDD dependency specs. Use when the user asks to implement a spec, process a spec update, check conformance, or create a deviation."
|
|
135
|
+
alwaysApply: false
|
|
136
|
+
---
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Frontmatter for `sdd-generate.md`:
|
|
140
|
+
```yaml
|
|
141
|
+
---
|
|
142
|
+
description: "Generate an OpenSDD behavioral spec from existing code. Use when the user asks to generate, create, or extract a spec from a repository or codebase."
|
|
143
|
+
alwaysApply: false
|
|
144
|
+
---
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Frontmatter for `opensdd-spec-format.md`:
|
|
148
|
+
```yaml
|
|
149
|
+
---
|
|
150
|
+
description: "OpenSDD spec format reference. Defines the structure and rules for behavioral specifications. Referenced by sdd-manager and sdd-generate skills."
|
|
151
|
+
alwaysApply: false
|
|
152
|
+
---
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
#### GitHub Copilot
|
|
156
|
+
|
|
157
|
+
Copilot discovers instructions as `.instructions.md` files in `.github/instructions/`. Each skill becomes an instruction file with YAML frontmatter. The `applyTo` field is set to `"**"` so the instructions are available across the project.
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
.github/instructions/
|
|
161
|
+
sdd-manager.instructions.md ← sdd-manager.md with frontmatter
|
|
162
|
+
sdd-generate.instructions.md ← sdd-generate.md with frontmatter
|
|
163
|
+
opensdd-spec-format.instructions.md ← spec-format.md with frontmatter
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Frontmatter for each file:
|
|
167
|
+
```yaml
|
|
168
|
+
---
|
|
169
|
+
applyTo: "**"
|
|
170
|
+
---
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
#### Gemini CLI
|
|
174
|
+
|
|
175
|
+
Gemini CLI discovers `GEMINI.md` files in the project directory and supports `@file.md` import syntax for referencing other files. Rather than duplicating skill content, the CLI appends import directives to `GEMINI.md` (creating it if it does not exist) that reference the canonical skill files from the Claude Code installation.
|
|
176
|
+
|
|
177
|
+
Appended to `GEMINI.md`:
|
|
178
|
+
```markdown
|
|
179
|
+
<!-- OpenSDD Skills (managed by opensdd init — do not edit this section) -->
|
|
180
|
+
@.claude/skills/sdd-manager/SKILL.md
|
|
181
|
+
@.claude/skills/sdd-manager/references/spec-format.md
|
|
182
|
+
@.claude/skills/sdd-generate/SKILL.md
|
|
183
|
+
@.claude/skills/sdd-generate/references/spec-format.md
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
The CLI MUST only modify the clearly delimited OpenSDD section. If a `GEMINI.md` already exists with an OpenSDD section, the CLI MUST replace that section. Content outside the section MUST NOT be modified.
|
|
187
|
+
|
|
188
|
+
#### Amp
|
|
189
|
+
|
|
190
|
+
Amp discovers `AGENTS.md` files in the project directory and supports `@` reference syntax for including other files. The CLI appends references to `AGENTS.md` (creating it if it does not exist) that point to the canonical skill files.
|
|
191
|
+
|
|
192
|
+
Appended to `AGENTS.md`:
|
|
193
|
+
```markdown
|
|
194
|
+
<!-- OpenSDD Skills (managed by opensdd init — do not edit this section) -->
|
|
195
|
+
@.claude/skills/sdd-manager/SKILL.md
|
|
196
|
+
@.claude/skills/sdd-manager/references/spec-format.md
|
|
197
|
+
@.claude/skills/sdd-generate/SKILL.md
|
|
198
|
+
@.claude/skills/sdd-generate/references/spec-format.md
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
The CLI MUST only modify the clearly delimited OpenSDD section. If an `AGENTS.md` already exists with an OpenSDD section, the CLI MUST replace that section. Content outside the section MUST NOT be modified.
|
|
202
|
+
|
|
203
|
+
#### Installation notes
|
|
204
|
+
|
|
205
|
+
- The Claude Code installation (`.claude/skills/`) serves as the canonical source that Gemini CLI and Amp reference via imports. It MUST always be installed, even if the user only uses Gemini or Amp.
|
|
206
|
+
- All installed files are overwritten on every `opensdd init`. The CLI MUST NOT prompt for confirmation before overwriting skill files.
|
|
207
|
+
- If a target directory cannot be created (e.g., permissions), the CLI SHOULD warn and continue installing to other agent directories rather than failing entirely.
|
|
208
|
+
- For Gemini CLI and Amp, the CLI MUST NOT overwrite user content in `GEMINI.md` or `AGENTS.md` — it MUST only manage the clearly delimited OpenSDD section.
|
|
209
|
+
|
|
210
|
+
### `opensdd list`
|
|
211
|
+
|
|
212
|
+
Lists specs available in the registry.
|
|
213
|
+
|
|
214
|
+
#### Behavior
|
|
215
|
+
|
|
216
|
+
1. Fetch the directory listing of the `registry/` folder from the configured registry source (default: the OpenSDD GitHub repository).
|
|
217
|
+
2. For each subdirectory in `registry/`, read `index.json` to extract `name`, `latest` version, `description`.
|
|
218
|
+
3. Print a formatted list showing each spec's name, latest version, and description.
|
|
219
|
+
|
|
220
|
+
- `opensdd list` MUST work from any directory (no project markers required)
|
|
221
|
+
|
|
222
|
+
#### Input
|
|
223
|
+
|
|
224
|
+
Optional flag: `--registry <url>` to specify an alternative registry source.
|
|
225
|
+
|
|
226
|
+
#### Output
|
|
227
|
+
|
|
228
|
+
```
|
|
229
|
+
Available specs:
|
|
230
|
+
|
|
231
|
+
slugify v2.2.0 String to URL-friendly slug
|
|
232
|
+
http-retry v1.0.0 HTTP request retry with backoff
|
|
233
|
+
payments v1.3.0 Payment provider integrations
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
#### Errors
|
|
237
|
+
|
|
238
|
+
- If the registry is unreachable, print error with the URL that failed and exit with code 1.
|
|
239
|
+
- If a spec's `index.json` is malformed or missing, skip it and print a warning.
|
|
240
|
+
|
|
241
|
+
### `opensdd install <name> [version]`
|
|
242
|
+
|
|
243
|
+
Fetches a spec from the registry and installs it as a dependency.
|
|
244
|
+
|
|
245
|
+
#### Behavior
|
|
246
|
+
|
|
247
|
+
1. Verify `opensdd.json` exists at the project root. If not, print a message suggesting `opensdd init` first and exit with code 1.
|
|
248
|
+
2. Check if the spec `<name>` already exists as a key in `opensdd.json`'s `dependencies` object. If it does AND the spec directory exists in `<deps_dir>`, print a message indicating the spec is already installed and suggest `opensdd update` instead. Exit with code 1. If the entry exists BUT the spec directory is missing, treat as a re-install: log a message noting the stale entry, then continue to step 4 using the version from the existing entry (unless `[version]` is explicitly provided, in which case use that).
|
|
249
|
+
3. Validate the spec name (lowercase alphanumeric and hyphens only).
|
|
250
|
+
4. Fetch `index.json` from `registry/<name>/` in the configured registry source. If `[version]` is provided, use that version; otherwise use `latest` from `index.json`.
|
|
251
|
+
5. Read `manifest.json` from `registry/<name>/<version>/` to get spec_format and dependencies.
|
|
252
|
+
6. Copy all files from `registry/<name>/<version>/` into `<deps_dir>/<name>/` (including `manifest.json`, `spec.md`, and any supplementary files).
|
|
253
|
+
7. Add an entry to `opensdd.json` under `dependencies.<name>` with fields from `manifest.json` (`version`, `spec_format`), the resolved registry URL as `source`, and consumer-managed fields initialized to defaults: `implementation: null`, `tests: null`, `has_deviations: false`.
|
|
254
|
+
8. If the spec has `dependencies`, check whether each dependency name exists as a key in `opensdd.json`'s `dependencies` object. If any are missing, print a warning listing the missing dependencies and suggesting `opensdd install` for each.
|
|
255
|
+
9. Print a success message.
|
|
256
|
+
|
|
257
|
+
- `opensdd install slugify` MUST create `.opensdd.deps/slugify/` with all spec files and add a `slugify` entry to `opensdd.json` `dependencies`
|
|
258
|
+
|
|
259
|
+
#### Input
|
|
260
|
+
|
|
261
|
+
- `<name>` (required): The spec name as it appears in the registry.
|
|
262
|
+
- `[version]` (optional): Specific semver version to install. Defaults to latest.
|
|
263
|
+
- `--registry <url>` (optional): Alternative registry source.
|
|
264
|
+
|
|
265
|
+
#### Output
|
|
266
|
+
|
|
267
|
+
```
|
|
268
|
+
Installed slugify v2.2.0 to .opensdd.deps/slugify/
|
|
269
|
+
|
|
270
|
+
Run "implement the slugify spec" in your agent to generate an implementation.
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
#### Errors
|
|
274
|
+
|
|
275
|
+
- Spec not found in registry: print error listing available specs and exit with code 1.
|
|
276
|
+
- Requested version not found: print error listing available versions and exit with code 1.
|
|
277
|
+
- Spec already installed (entry and directory both exist): print message suggesting `opensdd update` and exit with code 1.
|
|
278
|
+
- OpenSDD not initialized: print message suggesting `opensdd init` and exit with code 1.
|
|
279
|
+
|
|
280
|
+
### `opensdd update [name]`
|
|
281
|
+
|
|
282
|
+
Fetches the latest version of installed dependency specs from the registry, updates spec files in `.opensdd.deps/`, and stages the update for the agent to process. Does NOT modify `opensdd.json` — the dependency entry remains at the old version until `opensdd update apply` is called after the agent has confirmed the migration.
|
|
283
|
+
|
|
284
|
+
#### Behavior
|
|
285
|
+
|
|
286
|
+
1. If `<name>` is provided, update that single spec. If no name is provided, update all installed dependencies.
|
|
287
|
+
2. For each spec being updated:
|
|
288
|
+
a. Read the spec's entry in `opensdd.json` `dependencies` to get the installed version and `spec_format` version.
|
|
289
|
+
b. Fetch `index.json` from the registry to get the latest version. Read `manifest.json` from the latest version directory.
|
|
290
|
+
c. If the registry version matches the installed version, skip with a message "already up to date".
|
|
291
|
+
d. Before overwriting, compute unified diffs of all spec-owned files that will change.
|
|
292
|
+
e. Overwrite all spec-owned files in `<deps_dir>/<name>/` with the new version from the registry (`manifest.json`, `spec.md`, and any supplementary files).
|
|
293
|
+
f. MUST NOT overwrite or delete `deviations.md`. The CLI MUST NOT create, modify, or delete `deviations.md` under any circumstances.
|
|
294
|
+
g. Create the staging directory `.opensdd.deps/.updates/<name>/` and write two files. If a pending update already exists for this spec, overwrite it and note the replacement in the output.
|
|
295
|
+
- `changeset.md` — contains previous and new version, `spec_format` version change (if any), and unified diffs from step (d).
|
|
296
|
+
- `manifest.json` — contains the metadata needed to finalize the update in `opensdd.json`: `name`, `previous_version`, `version`, `source`, `spec_format`.
|
|
297
|
+
3. Print a summary of what was updated.
|
|
298
|
+
|
|
299
|
+
#### Input
|
|
300
|
+
|
|
301
|
+
- `[name]` (optional): Dependency spec to update. If omitted, update all installed dependencies.
|
|
302
|
+
- `--registry <url>` (optional): Alternative registry source.
|
|
303
|
+
|
|
304
|
+
#### Output
|
|
305
|
+
|
|
306
|
+
For a single spec:
|
|
307
|
+
```
|
|
308
|
+
Updated slugify: v2.1.0 -> v2.2.0
|
|
309
|
+
|
|
310
|
+
Changed files:
|
|
311
|
+
spec.md updated
|
|
312
|
+
|
|
313
|
+
Preserved:
|
|
314
|
+
deviations.md (consumer-owned, not modified)
|
|
315
|
+
|
|
316
|
+
Staged update:
|
|
317
|
+
.opensdd.deps/.updates/slugify/changeset.md
|
|
318
|
+
.opensdd.deps/.updates/slugify/manifest.json
|
|
319
|
+
|
|
320
|
+
Run "process the slugify spec update" in your agent.
|
|
321
|
+
After confirming, run: opensdd update apply slugify
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
For all specs:
|
|
325
|
+
```
|
|
326
|
+
Updated 2 of 3 installed specs:
|
|
327
|
+
|
|
328
|
+
slugify v2.1.0 -> v2.2.0 staged
|
|
329
|
+
payments v1.3.0 -> v1.4.0 staged
|
|
330
|
+
http-retry v1.0.0 already up to date
|
|
331
|
+
|
|
332
|
+
Run "process spec updates" in your agent.
|
|
333
|
+
After confirming each update, run:
|
|
334
|
+
opensdd update apply slugify
|
|
335
|
+
opensdd update apply payments
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
#### Errors
|
|
339
|
+
|
|
340
|
+
- Spec not installed: print error and exit with code 1.
|
|
341
|
+
- Registry unreachable: print error and exit with code 1.
|
|
342
|
+
|
|
343
|
+
### `opensdd update apply [name]`
|
|
344
|
+
|
|
345
|
+
Applies a staged update to `opensdd.json`, confirming that the migration is complete.
|
|
346
|
+
|
|
347
|
+
#### Behavior
|
|
348
|
+
|
|
349
|
+
1. If `<name>` is provided, apply that single update. If no name is provided, apply all pending updates.
|
|
350
|
+
2. Print a warning: "This will finalize the update in opensdd.json. Only proceed if you have confirmed that all spec changes have been implemented and tests pass."
|
|
351
|
+
3. Prompt the user for confirmation (y/n). If declined, exit with code 0.
|
|
352
|
+
4. For each pending update:
|
|
353
|
+
a. Read `.opensdd.deps/.updates/<name>/manifest.json` to get the update metadata.
|
|
354
|
+
b. Update the `opensdd.json` `dependencies.<name>` entry: set `version`, `source`, and `spec_format` from the manifest. Preserve all consumer-managed fields (`implementation`, `tests`, `has_deviations`).
|
|
355
|
+
c. Delete the `.opensdd.deps/.updates/<name>/` directory.
|
|
356
|
+
5. If `.opensdd.deps/.updates/` is now empty, delete it.
|
|
357
|
+
6. Print a summary.
|
|
358
|
+
|
|
359
|
+
#### Input
|
|
360
|
+
|
|
361
|
+
- `[name]` (optional): Dependency spec to apply. If omitted, apply all pending updates.
|
|
362
|
+
|
|
363
|
+
#### Output
|
|
364
|
+
|
|
365
|
+
For a single spec:
|
|
366
|
+
```
|
|
367
|
+
⚠ This will finalize the update in opensdd.json.
|
|
368
|
+
Only proceed if you have confirmed that all spec changes
|
|
369
|
+
have been implemented and tests pass.
|
|
370
|
+
|
|
371
|
+
Apply update for slugify v2.1.0 -> v2.2.0? (y/n) y
|
|
372
|
+
|
|
373
|
+
Applied update for slugify: v2.1.0 -> v2.2.0
|
|
374
|
+
|
|
375
|
+
opensdd.json updated
|
|
376
|
+
staged files cleaned up
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
For all pending:
|
|
380
|
+
```
|
|
381
|
+
⚠ This will finalize the update in opensdd.json.
|
|
382
|
+
Only proceed if you have confirmed that all spec changes
|
|
383
|
+
have been implemented and tests pass.
|
|
384
|
+
|
|
385
|
+
Apply 2 pending updates? (y/n) y
|
|
386
|
+
|
|
387
|
+
Applied 2 updates:
|
|
388
|
+
|
|
389
|
+
slugify v2.1.0 -> v2.2.0 applied
|
|
390
|
+
payments v1.3.0 -> v1.4.0 applied
|
|
391
|
+
|
|
392
|
+
opensdd.json updated.
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
#### Errors
|
|
396
|
+
|
|
397
|
+
- No pending update for the specified spec: print error and exit with code 1.
|
|
398
|
+
- No pending updates at all (when no name provided): print "No pending updates." and exit with code 0.
|
|
399
|
+
- `.opensdd.deps/.updates/<name>/manifest.json` is missing or malformed: print error and exit with code 1.
|
|
400
|
+
|
|
401
|
+
### `opensdd publish`
|
|
402
|
+
|
|
403
|
+
Publishes an authored spec to the registry.
|
|
404
|
+
|
|
405
|
+
#### Behavior
|
|
406
|
+
|
|
407
|
+
1. Verify `opensdd.json` exists at the project root. If not, print a message suggesting `opensdd init` first and exit with code 1.
|
|
408
|
+
2. Verify `opensdd.json` has a `publish` object. If not, print an error suggesting the user add a `publish` section and exit with code 1.
|
|
409
|
+
3. Read the `publish` object to get `name`, `version`, `description`, `spec_format`, `dependencies`.
|
|
410
|
+
4. Verify `<specs_dir>/spec.md` exists. If not, print error and exit with code 1.
|
|
411
|
+
5. Run validation on the `<specs_dir>/` directory (same logic as `opensdd validate`). If validation fails with errors, print them and exit with code 1.
|
|
412
|
+
6. Resolve the registry source. The registry MUST be a GitHub repository URL for publishing.
|
|
413
|
+
7. Fetch `index.json` from `registry/<name>/` if it exists. If the version being published already exists in `index.json`, print error suggesting a version bump and exit with code 1.
|
|
414
|
+
8. Construct the registry entry:
|
|
415
|
+
a. Build `manifest.json` from the `opensdd.json` `publish` fields (`name`, `version`, `description`, `spec_format`, `dependencies`).
|
|
416
|
+
b. Collect all files from `<specs_dir>/`.
|
|
417
|
+
9. If `--branch <name>` was provided, use that as the branch name. Otherwise, prompt the user for a branch name.
|
|
418
|
+
10. Clone the registry repo (shallow), create a new branch with the chosen name, and:
|
|
419
|
+
a. Create `registry/<name>/<version>/` with `manifest.json` and all spec files.
|
|
420
|
+
b. Update (or create) `registry/<name>/index.json` — set `latest` to the new version, add the version to `versions`.
|
|
421
|
+
11. Commit the changes, push the branch, and open a pull request using `gh pr create`.
|
|
422
|
+
12. Print a success message with the PR URL.
|
|
423
|
+
|
|
424
|
+
- `opensdd publish` MUST create a PR adding `registry/<name>/<version>/` with the spec files
|
|
425
|
+
- `opensdd publish` MUST NOT allow publishing a version that already exists in the registry
|
|
426
|
+
|
|
427
|
+
#### Input
|
|
428
|
+
|
|
429
|
+
- `--branch <name>` (optional): Branch name for the registry PR. If omitted, the CLI prompts the user.
|
|
430
|
+
- `--registry <url>` (optional): Alternative registry source (must be a GitHub URL).
|
|
431
|
+
|
|
432
|
+
#### Output
|
|
433
|
+
|
|
434
|
+
```
|
|
435
|
+
Publishing auth v1.0.0 to registry...
|
|
436
|
+
|
|
437
|
+
Validated spec ok
|
|
438
|
+
Created branch opensdd/auth-v1.0.0
|
|
439
|
+
Created registry entry registry/auth/1.0.0/
|
|
440
|
+
Updated index.json latest: 1.0.0
|
|
441
|
+
Opened pull request https://github.com/deepagents-ai/opensdd/pull/42
|
|
442
|
+
|
|
443
|
+
Published. Spec will be available after PR is merged.
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
#### Errors
|
|
447
|
+
|
|
448
|
+
- OpenSDD not initialized: print message suggesting `opensdd init` and exit with code 1.
|
|
449
|
+
- No `publish` section in `opensdd.json`: print error and exit with code 1.
|
|
450
|
+
- `<specs_dir>/spec.md` missing: print error and exit with code 1.
|
|
451
|
+
- Spec validation fails: print validation errors and exit with code 1.
|
|
452
|
+
- Version already exists in registry: print error suggesting version bump and exit with code 1.
|
|
453
|
+
- Registry is not a GitHub URL: print error (publishing requires a GitHub registry) and exit with code 1.
|
|
454
|
+
- Git or `gh` CLI not available: print error with installation guidance and exit with code 1.
|
|
455
|
+
- Git authentication fails: print error guiding the user to authenticate and exit with code 1.
|
|
456
|
+
|
|
457
|
+
### `opensdd status`
|
|
458
|
+
|
|
459
|
+
Shows the status of the authored spec and all installed dependency specs in the current project.
|
|
460
|
+
|
|
461
|
+
#### Behavior
|
|
462
|
+
|
|
463
|
+
1. Read `opensdd.json`.
|
|
464
|
+
2. If `publish` exists, print authored spec section showing the spec's name, version, and directory.
|
|
465
|
+
3. If `dependencies` exists and has entries, iterate the `dependencies` object. For each entry, read its consumer-managed fields and check for the presence of `deviations.md` in `<deps_dir>/<name>/`. Print a dependency status table.
|
|
466
|
+
4. Check for untracked directories: spec directories in `<deps_dir>` that have no corresponding `opensdd.json` dependency entry. Warn about any found.
|
|
467
|
+
|
|
468
|
+
#### Output
|
|
469
|
+
|
|
470
|
+
```
|
|
471
|
+
Authored spec:
|
|
472
|
+
|
|
473
|
+
auth v1.0.0 opensdd/
|
|
474
|
+
|
|
475
|
+
Installed dependencies:
|
|
476
|
+
|
|
477
|
+
slugify v2.1.0 implemented src/utils/slugify.ts
|
|
478
|
+
payments v1.3.0 implemented src/payments/index.ts 2 deviations
|
|
479
|
+
http-retry v1.0.0 not implemented
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
#### Errors
|
|
483
|
+
|
|
484
|
+
- If `opensdd.json` does not exist, print "OpenSDD not initialized. Run `opensdd init` to get started."
|
|
485
|
+
- If no specs are published or installed, print "No specs found. Run `opensdd install <name>` to install a dependency or add a `publish` entry to opensdd.json."
|
|
486
|
+
|
|
487
|
+
### `opensdd validate [path]`
|
|
488
|
+
|
|
489
|
+
Validates that a spec directory conforms to the OpenSDD spec-format.
|
|
490
|
+
|
|
491
|
+
#### Behavior
|
|
492
|
+
|
|
493
|
+
1. If `[path]` is provided, use it as the directory to validate. If omitted, look for the `opensdd/` directory in the current working directory and use that.
|
|
494
|
+
2. Read the directory.
|
|
495
|
+
3. Check for required files: `spec.md` MUST exist.
|
|
496
|
+
4. If `manifest.json` exists, validate it:
|
|
497
|
+
a. `name` MUST be present.
|
|
498
|
+
b. `spec_format` MUST be present and be a recognized version.
|
|
499
|
+
c. `version` MUST be present and be valid semver.
|
|
500
|
+
5. Validate `spec.md`:
|
|
501
|
+
a. MUST start with an H1 header followed by a blockquote summary.
|
|
502
|
+
b. MUST contain `## Behavioral Contract` section.
|
|
503
|
+
c. `## NOT Specified` section SHOULD be present (warn if missing).
|
|
504
|
+
d. `## Invariants` section SHOULD be present (warn if missing).
|
|
505
|
+
e. `## Edge Cases` SHOULD be present (warn if missing).
|
|
506
|
+
6. Verify no `deviations.md` exists (specs intended for the registry MUST NOT contain deviations).
|
|
507
|
+
7. Print a summary of validation results.
|
|
508
|
+
|
|
509
|
+
- `opensdd validate` MUST work on any local directory (no project markers required)
|
|
510
|
+
- `opensdd validate` MUST NOT require OpenSDD to be initialized
|
|
511
|
+
|
|
512
|
+
#### Input
|
|
513
|
+
|
|
514
|
+
- `[path]` (optional): Path to a spec directory to validate. If omitted, defaults to `opensdd/` in the current directory.
|
|
515
|
+
|
|
516
|
+
#### Output
|
|
517
|
+
|
|
518
|
+
For a valid spec:
|
|
519
|
+
```
|
|
520
|
+
Validated slugify v2.1.0
|
|
521
|
+
|
|
522
|
+
spec.md structure ok
|
|
523
|
+
manifest.json ok
|
|
524
|
+
no deviations.md ok
|
|
525
|
+
|
|
526
|
+
Valid. Ready for publishing to registry.
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
For a spec with issues:
|
|
530
|
+
```
|
|
531
|
+
Validated slugify v2.1.0
|
|
532
|
+
|
|
533
|
+
spec.md structure 2 warnings
|
|
534
|
+
- Missing ## NOT Specified section (recommended)
|
|
535
|
+
- Missing ## Edge Cases section (recommended)
|
|
536
|
+
manifest.json ok
|
|
537
|
+
no deviations.md ok
|
|
538
|
+
|
|
539
|
+
Valid with warnings. Review warnings before publishing.
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
For an invalid spec:
|
|
543
|
+
```
|
|
544
|
+
Validation failed for slugify
|
|
545
|
+
|
|
546
|
+
spec.md structure error
|
|
547
|
+
- Missing required: H1 header with blockquote summary
|
|
548
|
+
manifest.json error
|
|
549
|
+
- Missing required field: version
|
|
550
|
+
|
|
551
|
+
2 errors. Fix errors before publishing.
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
#### Errors
|
|
555
|
+
|
|
556
|
+
- Path does not exist or is not a directory: print error and exit with code 1.
|
|
557
|
+
- No `[path]` provided and the default `opensdd/` directory does not exist: print error ("No spec directory found. Provide a path or run from a directory containing `opensdd/`.") and exit with code 1.
|
|
558
|
+
- Missing required file (`spec.md`): report as validation error (do not exit early — continue checking what can be checked).
|
|
559
|
+
- `opensdd validate` MUST exit with code 0 if validation passes (including with warnings) and code 1 if any errors are found.
|
|
560
|
+
|
|
561
|
+
### Manifest Resolution
|
|
562
|
+
|
|
563
|
+
Commands that require `opensdd.json` (all commands except `opensdd list` and `opensdd validate`) MUST resolve it by searching upward from the current working directory, stopping at the first `opensdd.json` found. This supports monorepos where each sub-project has its own `opensdd.json`. If no `opensdd.json` is found in any ancestor directory, the command fails with the appropriate "not initialized" error.
|
|
564
|
+
|
|
565
|
+
`opensdd init` always creates `opensdd.json` in the current working directory.
|
|
566
|
+
|
|
567
|
+
### Registry Source Resolution
|
|
568
|
+
|
|
569
|
+
The CLI fetches specs from a registry source. The default source is the `registry/` directory in the OpenSDD GitHub repository.
|
|
570
|
+
|
|
571
|
+
The CLI MUST resolve the registry source in this order:
|
|
572
|
+
1. `--registry` flag on the command (if provided)
|
|
573
|
+
2. `registry` field in `opensdd.json` (if present)
|
|
574
|
+
3. Default: `https://github.com/deepagents-ai/opensdd` (the canonical registry)
|
|
575
|
+
|
|
576
|
+
For GitHub sources, the CLI MUST use the GitHub API to list directory contents and fetch raw file content. This avoids requiring a full git clone (except for `opensdd publish`, which requires a clone to create a branch and PR).
|
|
577
|
+
|
|
578
|
+
For local paths, the CLI MUST read directly from the filesystem. This supports development and testing of specs before publishing to a registry.
|
|
579
|
+
|
|
580
|
+
### Consumer-Managed Field Preservation
|
|
581
|
+
|
|
582
|
+
During `opensdd update apply`, the CLI MUST preserve these `opensdd.json` fields for each affected dependency entry:
|
|
583
|
+
- `implementation`
|
|
584
|
+
- `tests`
|
|
585
|
+
- `has_deviations`
|
|
586
|
+
|
|
587
|
+
The CLI reads the existing `opensdd.json` dependency entry, applies updated metadata from the staged manifest, then re-applies the consumer-managed field values. Note that `opensdd update` does NOT touch `opensdd.json` at all — it only stages the update. The `opensdd.json` entry continues to reflect the old version until `opensdd update apply` is called.
|
|
588
|
+
|
|
589
|
+
## Edge Cases
|
|
590
|
+
|
|
591
|
+
- Running `opensdd install` for a spec that was previously installed and then manually deleted (directory gone, `opensdd.json` entry gone): treat as a fresh install.
|
|
592
|
+
- Running `opensdd install` when the `opensdd.json` dependency entry exists but the directory is missing: treat as a re-install — re-fetch spec files for the version in the existing entry and recreate the directory.
|
|
593
|
+
- Spec directory exists in `.opensdd.deps/` but has no `opensdd.json` dependency entry: `opensdd status` MUST warn about untracked spec directories.
|
|
594
|
+
- Running `opensdd update` when a spec's registry entry has been removed: print a warning that the spec is no longer available in the registry but leave local files and `opensdd.json` entry untouched.
|
|
595
|
+
- Running `opensdd update` when a pending update already exists for the spec: overwrite the existing staged update with the new one.
|
|
596
|
+
- Running `opensdd update apply` when no pending updates exist: print "No pending updates." and exit with code 0 (not an error).
|
|
597
|
+
- Running `opensdd update apply <name>` when the agent hasn't finished processing the changeset: the CLI has no way to verify this — it's the user's responsibility to confirm the migration is complete before applying.
|
|
598
|
+
- Running `opensdd init` in a project that already has OpenSDD initialized: overwrite all skill installation files across all agent formats, leave `opensdd.json` untouched.
|
|
599
|
+
- Running any command outside a project directory (no project markers found): warn but allow with confirmation, except `opensdd list` and `opensdd validate` which work anywhere.
|
|
600
|
+
- Spec name contains characters invalid for directory names: reject with an error listing allowed characters (lowercase alphanumeric and hyphens).
|
|
601
|
+
- Publishing a version that already exists in the registry: reject with an error suggesting a version bump.
|
|
602
|
+
- Publishing when the registry is a local path (not GitHub): reject with an error (publishing requires a GitHub registry for PR workflow).
|
|
603
|
+
- Running `opensdd publish` when `gh` CLI is not installed: print error with installation guidance.
|
|
604
|
+
- Running `opensdd install` with a version that doesn't exist in the registry: print error listing available versions.
|
|
605
|
+
|
|
606
|
+
## NOT Specified (Implementation Freedom)
|
|
607
|
+
|
|
608
|
+
- HTTP client library choice for GitHub API requests
|
|
609
|
+
- Caching strategy for registry requests
|
|
610
|
+
- CLI framework (commander, yargs, or plain process.argv parsing)
|
|
611
|
+
- Output coloring/formatting approach
|
|
612
|
+
- Whether to use TypeScript or plain JavaScript internally
|
|
613
|
+
- Progress indicator style for network requests
|
|
614
|
+
- The exact format of the registry's internal files beyond the required fields
|
|
615
|
+
- The git branching strategy used during `opensdd publish` (branch name is user-provided)
|
|
616
|
+
- Whether `opensdd publish` does a shallow or full clone of the registry repo
|
|
617
|
+
|
|
618
|
+
## Invariants
|
|
619
|
+
|
|
620
|
+
- The CLI MUST NOT create, modify, or delete `deviations.md` under any circumstances
|
|
621
|
+
- `opensdd install` MUST NOT create a `deviations.md` file
|
|
622
|
+
- `opensdd update` MUST NOT modify `opensdd.json` — it only stages the update
|
|
623
|
+
- `opensdd update` MUST create a staging directory in `.opensdd.deps/.updates/<name>/` for every spec that was updated (not for specs already up to date)
|
|
624
|
+
- `opensdd update apply` MUST update `opensdd.json` and delete the staging directory
|
|
625
|
+
- All skill installation files across all agent formats MUST always be overwritten on `opensdd init` (they are fully spec-owned)
|
|
626
|
+
- The Claude Code skill installation (`.claude/skills/`) MUST always be present since Gemini CLI and Amp reference it
|
|
627
|
+
- `opensdd.json` MUST be created by `opensdd init` if it does not exist, and MUST NOT be overwritten if it already exists
|
|
628
|
+
- Consumer-managed `opensdd.json` fields MUST survive all update operations
|
|
629
|
+
- Every installed dependency MUST have both a directory in `deps_dir` and an entry in `opensdd.json` `dependencies`
|
|
630
|
+
- All commands MUST exit with code 0 on success and code 1 on error
|
|
631
|
+
- The CLI MUST NOT invoke an AI model or coding agent
|
|
632
|
+
- `opensdd publish` MUST NOT allow overwriting an existing version in the registry
|
|
633
|
+
- `.opensdd.deps/` MUST be committed to the repo (NOT gitignored)
|