openspecpm 0.1.0-alpha.0 → 1.0.1
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/CHANGELOG.md +148 -86
- package/README.md +388 -352
- package/cli/bin/openspecpm.js +218 -198
- package/cli/src/adapters/azure.js +21 -5
- package/cli/src/adapters/gitlab.js +10 -5
- package/cli/src/audit.js +39 -7
- package/cli/src/bdd/judge.js +216 -0
- package/cli/src/commands/bulk.js +10 -0
- package/cli/src/commands/doctor.js +11 -0
- package/cli/src/commands/propose.js +41 -6
- package/cli/src/commands/reconcile.js +17 -4
- package/cli/src/commands/sync.js +70 -5
- package/cli/src/commands/validate.js +32 -1
- package/cli/src/http.js +14 -2
- package/cli/src/notify.js +25 -2
- package/cli/src/openspec-bridge.js +31 -0
- package/cli/src/tracking.js +30 -5
- package/package.json +2 -1
- package/skill/openspecpm/SKILL.md +74 -74
- package/skill/openspecpm/references/conventions.md +106 -105
- package/skill/openspecpm/references/execute.md +4 -4
- package/skill/openspecpm/references/plan.md +2 -2
- package/skill/openspecpm/references/structure.md +52 -52
- package/skill/openspecpm/references/sync.md +56 -56
|
@@ -1,52 +1,52 @@
|
|
|
1
|
-
# Structure — Decomposing a proposal into tasks
|
|
2
|
-
|
|
3
|
-
**When to use this:** A proposal exists at `openspec/changes/<feature>/proposal.md` and the user wants to break it down into individual work items.
|
|
4
|
-
|
|
5
|
-
## Outcome
|
|
6
|
-
|
|
7
|
-
A populated `openspec/changes/<feature>/tasks.md` where the `items:` frontmatter array lists every task with: title, dependency edges, parallelizability, and a `sync_state: pending` marker.
|
|
8
|
-
|
|
9
|
-
## Flow
|
|
10
|
-
|
|
11
|
-
1. **Read the proposal and specs.** Open `proposal.md`, `design.md`, and every file in `specs/`. Build a mental model of what behavior must exist for the change to be complete.
|
|
12
|
-
|
|
13
|
-
2. **Group by stream.** Most features decompose into 2–5 independent streams. Common patterns:
|
|
14
|
-
- **Data:** schema, migrations, persistence layer
|
|
15
|
-
- **Service:** business logic, validation, domain rules
|
|
16
|
-
- **API:** HTTP/RPC/CLI surface
|
|
17
|
-
- **UI:** components, flows, accessibility
|
|
18
|
-
- **Tests:** end-to-end coverage of the new behavior
|
|
19
|
-
|
|
20
|
-
Streams that can be worked in parallel get `parallel: true`. Streams that must wait on another stream get `depends_on: ["<earlier-task-title>"]`.
|
|
21
|
-
|
|
22
|
-
3. **Right-size each task.** A task should be 2–8 hours of focused work for one engineer. If a task is bigger, split. If smaller, merge into the next one (overhead exceeds value).
|
|
23
|
-
|
|
24
|
-
4. **Write tasks.md.** Use the frontmatter schema from `conventions.md`. Every task gets:
|
|
25
|
-
```yaml
|
|
26
|
-
- title: "Add user_preferences.theme column"
|
|
27
|
-
sync_state: pending
|
|
28
|
-
depends_on: []
|
|
29
|
-
parallel: true
|
|
30
|
-
effort_hours: 3
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
5. **Cross-check against BDD scenarios.** Every scenario in `specs/*.md` should map to at least one task. If a scenario is unimplemented, add a task. If a task isn't traceable to any scenario, ask whether it's actually needed.
|
|
34
|
-
|
|
35
|
-
## Hierarchy and the target PM tool
|
|
36
|
-
|
|
37
|
-
The backend's `capabilities().hierarchyDepth` determines how the structure projects into work items:
|
|
38
|
-
|
|
39
|
-
| Backend | Depth | Mapping |
|
|
40
|
-
|---|---|---|
|
|
41
|
-
| GitHub | 2 | Epic issue → sub-issues (via `gh-sub-issue`) |
|
|
42
|
-
| Linear | 2 | Project → Issues |
|
|
43
|
-
| GitLab | 2 | Parent issue → linked child issues (`relates_to` / `blocks`) |
|
|
44
|
-
| Jira | 3 | Epic → Story → Sub-task |
|
|
45
|
-
| Azure DevOps | 4 | Epic → Feature → User Story → Task |
|
|
46
|
-
|
|
47
|
-
The sync layer will **collapse levels gracefully** when authoring depth exceeds backend depth — e.g. on GitHub, "Feature" and "Story" levels are flattened into siblings of the Epic with a label tag, and a warning is printed. You do not need to author differently for each backend; author the deepest sensible structure and let the adapter compress.
|
|
48
|
-
|
|
49
|
-
## After this phase
|
|
50
|
-
|
|
51
|
-
- Route to `references/sync.md` to push tasks to the PM tool.
|
|
52
|
-
- If decomposition surfaced unknowns, route back to `references/plan.md` to refine the proposal.
|
|
1
|
+
# Structure — Decomposing a proposal into tasks
|
|
2
|
+
|
|
3
|
+
**When to use this:** A proposal exists at `openspec/changes/<feature>/proposal.md` and the user wants to break it down into individual work items.
|
|
4
|
+
|
|
5
|
+
## Outcome
|
|
6
|
+
|
|
7
|
+
A populated `openspec/changes/<feature>/tasks.md` where the `items:` frontmatter array lists every task with: title, dependency edges, parallelizability, and a `sync_state: pending` marker.
|
|
8
|
+
|
|
9
|
+
## Flow
|
|
10
|
+
|
|
11
|
+
1. **Read the proposal and specs.** Open `proposal.md`, `design.md`, and every file in `specs/`. Build a mental model of what behavior must exist for the change to be complete.
|
|
12
|
+
|
|
13
|
+
2. **Group by stream.** Most features decompose into 2–5 independent streams. Common patterns:
|
|
14
|
+
- **Data:** schema, migrations, persistence layer
|
|
15
|
+
- **Service:** business logic, validation, domain rules
|
|
16
|
+
- **API:** HTTP/RPC/CLI surface
|
|
17
|
+
- **UI:** components, flows, accessibility
|
|
18
|
+
- **Tests:** end-to-end coverage of the new behavior
|
|
19
|
+
|
|
20
|
+
Streams that can be worked in parallel get `parallel: true`. Streams that must wait on another stream get `depends_on: ["<earlier-task-title>"]`.
|
|
21
|
+
|
|
22
|
+
3. **Right-size each task.** A task should be 2–8 hours of focused work for one engineer. If a task is bigger, split. If smaller, merge into the next one (overhead exceeds value).
|
|
23
|
+
|
|
24
|
+
4. **Write tasks.md.** Use the frontmatter schema from `conventions.md`. Every task gets:
|
|
25
|
+
```yaml
|
|
26
|
+
- title: "Add user_preferences.theme column"
|
|
27
|
+
sync_state: pending
|
|
28
|
+
depends_on: []
|
|
29
|
+
parallel: true
|
|
30
|
+
effort_hours: 3
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
5. **Cross-check against BDD scenarios.** Every scenario in `specs/*.md` should map to at least one task. If a scenario is unimplemented, add a task. If a task isn't traceable to any scenario, ask whether it's actually needed.
|
|
34
|
+
|
|
35
|
+
## Hierarchy and the target PM tool
|
|
36
|
+
|
|
37
|
+
The backend's `capabilities().hierarchyDepth` determines how the structure projects into work items:
|
|
38
|
+
|
|
39
|
+
| Backend | Depth | Mapping |
|
|
40
|
+
|---|---|---|
|
|
41
|
+
| GitHub | 2 | Epic issue → sub-issues (via `gh-sub-issue`) |
|
|
42
|
+
| Linear | 2 | Project → Issues |
|
|
43
|
+
| GitLab | 2 | Parent issue → linked child issues (`relates_to` / `blocks`) |
|
|
44
|
+
| Jira | 3 | Epic → Story → Sub-task |
|
|
45
|
+
| Azure DevOps | 4 | Epic → Feature → User Story → Task |
|
|
46
|
+
|
|
47
|
+
The sync layer will **collapse levels gracefully** when authoring depth exceeds backend depth — e.g. on GitHub, "Feature" and "Story" levels are flattened into siblings of the Epic with a label tag, and a warning is printed. You do not need to author differently for each backend; author the deepest sensible structure and let the adapter compress.
|
|
48
|
+
|
|
49
|
+
## After this phase
|
|
50
|
+
|
|
51
|
+
- Route to `references/sync.md` to push tasks to the PM tool.
|
|
52
|
+
- If decomposition surfaced unknowns, route back to `references/plan.md` to refine the proposal.
|
|
@@ -1,56 +1,56 @@
|
|
|
1
|
-
# Sync — Pushing an OpenSpec change to the PM tool
|
|
2
|
-
|
|
3
|
-
**When to use this:** The user has a proposal + tasks ready and wants them tracked in GitHub Issues / Azure DevOps Boards / Jira / Linear / GitLab
|
|
4
|
-
|
|
5
|
-
## Outcome
|
|
6
|
-
|
|
7
|
-
For the chosen adapter, the epic and every task are created as work items, linked into a hierarchy where the backend supports it, and recorded back into local frontmatter (`external:` on `proposal.md`, `external_id` + `external_url` on each task in `tasks.md`).
|
|
8
|
-
|
|
9
|
-
## The CLI does the work
|
|
10
|
-
|
|
11
|
-
```
|
|
12
|
-
openspecpm sync <feature> # create + update
|
|
13
|
-
openspecpm sync <feature> --dry-run # print the call plan, no remote writes
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
Do not script `gh issue create` or hand-craft REST calls in agent reasoning — let the adapter handle vocabulary differences across backends.
|
|
17
|
-
|
|
18
|
-
## Idempotency contract
|
|
19
|
-
|
|
20
|
-
Sync is safe to re-run. The rules:
|
|
21
|
-
|
|
22
|
-
1. **Epic:** if `proposal.md` frontmatter already carries `external.<adapter>` with an `id`, the existing epic is reused. No duplicate epics are ever created.
|
|
23
|
-
2. **Tasks:** each task carries `sync_state: pending | created | failed`. `sync` skips `created` items and retries `failed` ones.
|
|
24
|
-
3. **Comments:** progress comments stamped `<!-- SYNCED: <iso-timestamp> -->` are append-only. Re-running sync after a comment was posted does not repost.
|
|
25
|
-
|
|
26
|
-
This means: if the network fails halfway through a 30-task sync, fix the cause, re-run, and only the un-created items get created.
|
|
27
|
-
|
|
28
|
-
## Capabilities and hierarchy collapse
|
|
29
|
-
|
|
30
|
-
Each adapter reports `capabilities()`. The sync layer reads `hierarchyDepth`:
|
|
31
|
-
|
|
32
|
-
- **GitHub (depth 2):** Epic issue + flat task sub-issues. If the task tree authored depth >2, intermediate levels are flattened into siblings tagged `openspec:<feature>` and a one-line warning is printed.
|
|
33
|
-
- **Linear (depth 2):** Project as epic, issues as tasks under the project. `parent` relation when supported by the workspace.
|
|
34
|
-
- **GitLab (depth 2):** Parent issue + child issues linked via `relates_to` / `blocks`. Milestone serves as the epic container if `--milestone` is supplied.
|
|
35
|
-
- **Jira (depth 3):** Epic → Story → optional Sub-task. Stories without sub-tasks just sit under the Epic via `Relates` link.
|
|
36
|
-
- **Azure DevOps (depth 4):** Epic → Feature → User Story → Task with `System.LinkTypes.Hierarchy-Reverse` Parent links.
|
|
37
|
-
|
|
38
|
-
## Field mapping per adapter
|
|
39
|
-
|
|
40
|
-
| OpenSpec field | GitHub | Azure DevOps | Jira | Linear | GitLab |
|
|
41
|
-
|---|---|---|---|---|---|
|
|
42
|
-
| `task.title` | Issue title | `System.Title` | `summary` | `title` | `title` |
|
|
43
|
-
| `task.body` | Issue body (markdown) | `System.Description` (HTML) | `description` (ADF) | `description` (markdown) | `description` (markdown) |
|
|
44
|
-
| `feature.name` (tag) | label `openspec:<name>` | tag `openspec:<name>` | label `openspec-<name>` | label `openspec:<name>` | label `openspec:<name>` |
|
|
45
|
-
| `task.depends_on` | task-list reference in body | `System.LinkTypes.Dependency` link | `Blocks` issue link | issue relation `blocks` | issue link `blocks` |
|
|
46
|
-
| `task.iteration` | (ignored, depth=2) | `System.IterationPath` | sprint custom field | `cycleId` | `milestone` |
|
|
47
|
-
| `task.assignee` | `--add-assignee` | `System.AssignedTo` | `assignee.accountId` | `assigneeId` | `assignee_ids` |
|
|
48
|
-
| `task.effort_hours` | (ignored) | `Microsoft.VSTS.Scheduling.Effort` | story-points custom field | `estimate` | `weight` |
|
|
49
|
-
|
|
50
|
-
The CLI handles the translation. Author tasks in the OpenSpec/CCPM dialect described in `conventions.md`.
|
|
51
|
-
|
|
52
|
-
## After sync
|
|
53
|
-
|
|
54
|
-
- Each item is now visible in the PM tool. The user can route stakeholders to those URLs for sign-off.
|
|
55
|
-
- Progress narrative still lives locally in `openspec/changes/<feature>/updates/<task>/progress.md`. Use `openspecpm comment <task>`
|
|
56
|
-
- Route to `references/execute.md` when the user is ready to start building.
|
|
1
|
+
# Sync — Pushing an OpenSpec change to the PM tool
|
|
2
|
+
|
|
3
|
+
**When to use this:** The user has a proposal + tasks ready and wants them tracked in GitHub Issues / Azure DevOps Boards / Jira / Linear / GitLab.
|
|
4
|
+
|
|
5
|
+
## Outcome
|
|
6
|
+
|
|
7
|
+
For the chosen adapter, the epic and every task are created as work items, linked into a hierarchy where the backend supports it, and recorded back into local frontmatter (`external:` on `proposal.md`, `external_id` + `external_url` on each task in `tasks.md`).
|
|
8
|
+
|
|
9
|
+
## The CLI does the work
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
openspecpm sync <feature> # create + update
|
|
13
|
+
openspecpm sync <feature> --dry-run # print the call plan, no remote writes
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Do not script `gh issue create` or hand-craft REST calls in agent reasoning — let the adapter handle vocabulary differences across backends.
|
|
17
|
+
|
|
18
|
+
## Idempotency contract
|
|
19
|
+
|
|
20
|
+
Sync is safe to re-run. The rules:
|
|
21
|
+
|
|
22
|
+
1. **Epic:** if `proposal.md` frontmatter already carries `external.<adapter>` with an `id`, the existing epic is reused. No duplicate epics are ever created.
|
|
23
|
+
2. **Tasks:** each task carries `sync_state: pending | created | failed`. `sync` skips `created` items and retries `failed` ones.
|
|
24
|
+
3. **Comments:** progress comments stamped `<!-- SYNCED: <iso-timestamp> -->` are append-only. Re-running sync after a comment was posted does not repost.
|
|
25
|
+
|
|
26
|
+
This means: if the network fails halfway through a 30-task sync, fix the cause, re-run, and only the un-created items get created.
|
|
27
|
+
|
|
28
|
+
## Capabilities and hierarchy collapse
|
|
29
|
+
|
|
30
|
+
Each adapter reports `capabilities()`. The sync layer reads `hierarchyDepth`:
|
|
31
|
+
|
|
32
|
+
- **GitHub (depth 2):** Epic issue + flat task sub-issues. If the task tree authored depth >2, intermediate levels are flattened into siblings tagged `openspec:<feature>` and a one-line warning is printed.
|
|
33
|
+
- **Linear (depth 2):** Project as epic, issues as tasks under the project. `parent` relation when supported by the workspace.
|
|
34
|
+
- **GitLab (depth 2):** Parent issue + child issues linked via `relates_to` / `blocks`. Milestone serves as the epic container if `--milestone` is supplied.
|
|
35
|
+
- **Jira (depth 3):** Epic → Story → optional Sub-task. Stories without sub-tasks just sit under the Epic via `Relates` link.
|
|
36
|
+
- **Azure DevOps (depth 4):** Epic → Feature → User Story → Task with `System.LinkTypes.Hierarchy-Reverse` Parent links.
|
|
37
|
+
|
|
38
|
+
## Field mapping per adapter
|
|
39
|
+
|
|
40
|
+
| OpenSpec field | GitHub | Azure DevOps | Jira | Linear | GitLab |
|
|
41
|
+
|---|---|---|---|---|---|
|
|
42
|
+
| `task.title` | Issue title | `System.Title` | `summary` | `title` | `title` |
|
|
43
|
+
| `task.body` | Issue body (markdown) | `System.Description` (HTML) | `description` (ADF) | `description` (markdown) | `description` (markdown) |
|
|
44
|
+
| `feature.name` (tag) | label `openspec:<name>` | tag `openspec:<name>` | label `openspec-<name>` | label `openspec:<name>` | label `openspec:<name>` |
|
|
45
|
+
| `task.depends_on` | task-list reference in body | `System.LinkTypes.Dependency` link | `Blocks` issue link | issue relation `blocks` | issue link `blocks` |
|
|
46
|
+
| `task.iteration` | (ignored, depth=2) | `System.IterationPath` | sprint custom field | `cycleId` | `milestone` |
|
|
47
|
+
| `task.assignee` | `--add-assignee` | `System.AssignedTo` | `assignee.accountId` | `assigneeId` | `assignee_ids` |
|
|
48
|
+
| `task.effort_hours` | (ignored) | `Microsoft.VSTS.Scheduling.Effort` | story-points custom field | `estimate` | `weight` |
|
|
49
|
+
|
|
50
|
+
The CLI handles the translation. Author tasks in the OpenSpec/CCPM dialect described in `conventions.md`.
|
|
51
|
+
|
|
52
|
+
## After sync
|
|
53
|
+
|
|
54
|
+
- Each item is now visible in the PM tool. The user can route stakeholders to those URLs for sign-off.
|
|
55
|
+
- Progress narrative still lives locally in `openspec/changes/<feature>/updates/<task>/progress.md`. Use `openspecpm comment <task>` to broadcast a new update to the PM tool.
|
|
56
|
+
- Route to `references/execute.md` when the user is ready to start building.
|