specrails-core 3.1.0 → 3.3.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/README.md +35 -8
- package/commands/setup.md +138 -26
- package/docs/agents.md +43 -1
- package/docs/getting-started.md +14 -4
- package/docs/installation.md +44 -4
- package/docs/local-tickets.md +218 -0
- package/docs/migration-guide.md +141 -0
- package/docs/user-docs/faq.md +6 -3
- package/docs/user-docs/installation.md +3 -1
- package/docs/user-docs/quick-start.md +7 -5
- package/docs/workflows.md +2 -2
- package/integration-contract.json +7 -1
- package/package.json +1 -1
- package/templates/commands/sr/implement.md +72 -14
- package/templates/commands/sr/product-backlog.md +31 -0
- package/templates/commands/sr/propose-spec.md +56 -0
- package/templates/commands/sr/update-product-driven-backlog.md +41 -1
- package/templates/local-tickets-schema.json +7 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# Local Ticket Management
|
|
2
|
+
|
|
3
|
+
specrails-core ships with a built-in, file-based ticket management system. It is the **default backlog provider** — no GitHub account, CLI tool, or external service required.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
Tickets live in `.claude/local-tickets.json` at your project root. Because it's a plain JSON file, tickets are:
|
|
10
|
+
|
|
11
|
+
- **Version-controlled** — tracked by git, diffable in PRs
|
|
12
|
+
- **Offline-first** — no network calls, no rate limits
|
|
13
|
+
- **Tool-agnostic** — readable by any script or editor
|
|
14
|
+
|
|
15
|
+
The file is shared between specrails-core (which reads and writes tickets during command execution) and specrails-hub (which provides a visual ticket panel with real-time sync).
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Storage format
|
|
20
|
+
|
|
21
|
+
`.claude/local-tickets.json`:
|
|
22
|
+
|
|
23
|
+
```json
|
|
24
|
+
{
|
|
25
|
+
"schema_version": "1.0",
|
|
26
|
+
"revision": 7,
|
|
27
|
+
"last_updated": "2026-03-23T10:00:00.000Z",
|
|
28
|
+
"next_id": 8,
|
|
29
|
+
"tickets": {
|
|
30
|
+
"1": {
|
|
31
|
+
"id": 1,
|
|
32
|
+
"title": "Add dark mode",
|
|
33
|
+
"description": "Support system-level dark mode preference via CSS variables.",
|
|
34
|
+
"status": "todo",
|
|
35
|
+
"priority": "medium",
|
|
36
|
+
"labels": ["area:frontend", "effort:medium"],
|
|
37
|
+
"assignee": null,
|
|
38
|
+
"prerequisites": [],
|
|
39
|
+
"metadata": {
|
|
40
|
+
"vpc_scores": { "persona-a": 4, "persona-b": 3 },
|
|
41
|
+
"effort_level": "Medium",
|
|
42
|
+
"user_story": "As a user working at night, I want dark mode...",
|
|
43
|
+
"area": "frontend"
|
|
44
|
+
},
|
|
45
|
+
"comments": [],
|
|
46
|
+
"created_at": "2026-03-20T09:00:00.000Z",
|
|
47
|
+
"updated_at": "2026-03-20T09:00:00.000Z",
|
|
48
|
+
"created_by": "sr-product-manager",
|
|
49
|
+
"source": "product-backlog"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Field reference
|
|
56
|
+
|
|
57
|
+
**Root fields**
|
|
58
|
+
|
|
59
|
+
| Field | Type | Description |
|
|
60
|
+
|-------|------|-------------|
|
|
61
|
+
| `schema_version` | string | Always `"1.0"` for the current format |
|
|
62
|
+
| `revision` | number | Incremented on every write — used for optimistic concurrency control |
|
|
63
|
+
| `last_updated` | ISO-8601 | Timestamp of the most recent mutation |
|
|
64
|
+
| `next_id` | number | Auto-increment counter for new ticket IDs |
|
|
65
|
+
| `tickets` | object | Map of ticket ID (as string) → ticket object |
|
|
66
|
+
|
|
67
|
+
**Ticket fields**
|
|
68
|
+
|
|
69
|
+
| Field | Type | Values | Description |
|
|
70
|
+
|-------|------|--------|-------------|
|
|
71
|
+
| `id` | number | Auto-assigned | Numeric ID, referenced as `#<id>` |
|
|
72
|
+
| `title` | string | — | Short title |
|
|
73
|
+
| `description` | string | Markdown | Full description |
|
|
74
|
+
| `status` | string | `todo`, `in_progress`, `done`, `cancelled` | Current state |
|
|
75
|
+
| `priority` | string | `critical`, `high`, `medium`, `low` | Priority level |
|
|
76
|
+
| `labels` | string[] | Freeform | Tag strings; convention: `area:*`, `effort:*` |
|
|
77
|
+
| `assignee` | string\|null | — | Agent name or user, if assigned |
|
|
78
|
+
| `prerequisites` | number[] | — | IDs of tickets that must be done first |
|
|
79
|
+
| `metadata` | object | — | VPC scores, effort level, user story, area (set by agents) |
|
|
80
|
+
| `comments` | array | — | Progress notes appended during implementation |
|
|
81
|
+
| `created_at` | ISO-8601 | — | Creation timestamp |
|
|
82
|
+
| `updated_at` | ISO-8601 | — | Last mutation timestamp |
|
|
83
|
+
| `created_by` | string | — | Agent name or `"user"` |
|
|
84
|
+
| `source` | string | `manual`, `product-backlog`, `propose-spec` | How the ticket was created |
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Setup
|
|
89
|
+
|
|
90
|
+
Local tickets become the default during `/setup`. The wizard prompts:
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
## Backlog Provider
|
|
94
|
+
|
|
95
|
+
Use local ticket management or connect an external provider?
|
|
96
|
+
|
|
97
|
+
1. Local tickets (default, recommended) — lightweight JSON-based ticket management.
|
|
98
|
+
No external tools or accounts required.
|
|
99
|
+
2. External provider — connect GitHub Issues, JIRA, or disable backlog commands
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Pressing **Enter** or selecting **1** initializes `.claude/local-tickets.json` with an empty ticket store and writes `.claude/backlog-config.json`:
|
|
103
|
+
|
|
104
|
+
```json
|
|
105
|
+
{
|
|
106
|
+
"provider": "local",
|
|
107
|
+
"write_access": true,
|
|
108
|
+
"git_auto": true
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
To switch providers later, re-run the setup wizard:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
npx specrails-core@latest init --root-dir .
|
|
116
|
+
> /setup
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Concurrency model
|
|
122
|
+
|
|
123
|
+
Both CLI agents and specrails-hub can modify `local-tickets.json` simultaneously. The system uses two complementary mechanisms:
|
|
124
|
+
|
|
125
|
+
### Advisory file lock
|
|
126
|
+
|
|
127
|
+
Before every write, the agent creates `.claude/local-tickets.json.lock`:
|
|
128
|
+
|
|
129
|
+
```json
|
|
130
|
+
{
|
|
131
|
+
"agent": "sr-product-manager",
|
|
132
|
+
"timestamp": "2026-03-23T10:00:00.000Z"
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
If the lock file already exists:
|
|
137
|
+
- **Fresh lock** (< 30 seconds old): wait 500 ms and retry, up to 5 attempts
|
|
138
|
+
- **Stale lock** (≥ 30 seconds old): treat as orphaned, delete it, proceed
|
|
139
|
+
|
|
140
|
+
The lock is deleted immediately after the write completes. The window is minimal: read → modify in memory → write → release.
|
|
141
|
+
|
|
142
|
+
### Revision counter
|
|
143
|
+
|
|
144
|
+
Every write increments `revision`. Readers that want to detect external changes compare the `revision` they last saw against the current value. This is how specrails-hub avoids echoing its own writes back through the file watcher.
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## Command integration
|
|
149
|
+
|
|
150
|
+
### `/sr:implement`
|
|
151
|
+
|
|
152
|
+
Pass local ticket IDs the same way you would GitHub issue numbers:
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
/sr:implement #1, #4, #7
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
The command reads each ticket from `local-tickets.json`, extracts metadata (area, effort, description), and tracks the ticket through the pipeline — updating status to `in_progress` on start and `done` on successful completion.
|
|
159
|
+
|
|
160
|
+
### `/sr:product-backlog`
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
/sr:product-backlog # all areas
|
|
164
|
+
/sr:product-backlog UI, Backend # filter by area
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Reads all `todo` and `in_progress` tickets, scores them by VPC match, respects the `prerequisites` dependency graph, and recommends the top 3 for your next sprint.
|
|
168
|
+
|
|
169
|
+
### `/sr:update-product-driven-backlog`
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
/sr:update-product-driven-backlog # explore all areas
|
|
173
|
+
/sr:update-product-driven-backlog Analytics # focus on one area
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Runs product discovery using your VPC personas. Creates new local tickets for discovered feature ideas, tagged with `source: "product-backlog"` and `labels: ["product-driven-backlog", "area:<area>"]`. Existing tickets are checked for duplicates before creating new ones.
|
|
177
|
+
|
|
178
|
+
### `/sr:propose-spec`
|
|
179
|
+
|
|
180
|
+
When a proposal is finalized, a local ticket is created automatically:
|
|
181
|
+
|
|
182
|
+
```
|
|
183
|
+
Created local ticket #12: Add analytics export
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
The ticket captures the full proposal as its description and is tagged `source: "propose-spec"` with the label `spec-proposal`.
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## integration-contract.json
|
|
191
|
+
|
|
192
|
+
The `ticketProvider` section tells specrails-hub where to find and how to use the ticket store:
|
|
193
|
+
|
|
194
|
+
```json
|
|
195
|
+
{
|
|
196
|
+
"ticketProvider": {
|
|
197
|
+
"type": "local",
|
|
198
|
+
"storageFile": "local-tickets.json",
|
|
199
|
+
"lockFile": "local-tickets.json.lock",
|
|
200
|
+
"capabilities": ["crud", "labels", "status", "priorities", "dependencies", "comments"]
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
| Field | Description |
|
|
206
|
+
|-------|-------------|
|
|
207
|
+
| `type` | `"local"` — file-based storage (the only supported type currently) |
|
|
208
|
+
| `storageFile` | Filename relative to the project's specrails dir (`.claude/` or `.codex/`) |
|
|
209
|
+
| `lockFile` | Advisory lock filename, same directory |
|
|
210
|
+
| `capabilities` | Features the hub enables based on what the provider supports |
|
|
211
|
+
|
|
212
|
+
specrails-hub reads this file when it loads a project. If the file is missing or the `ticketProvider` key is absent, hub falls back to safe defaults (`type: "local"`, `storageFile: "local-tickets.json"`).
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## Migrating from GitHub Issues or JIRA
|
|
217
|
+
|
|
218
|
+
See the [Migration Guide](./migration-guide.md).
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# Migration Guide: Switching to Local Tickets
|
|
2
|
+
|
|
3
|
+
This guide is for teams currently using GitHub Issues or JIRA as their specrails backlog provider who want to switch to the built-in local ticket system.
|
|
4
|
+
|
|
5
|
+
Switching is optional. GitHub Issues and JIRA remain fully supported. Local tickets are the recommended default for new projects.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Should you switch?
|
|
10
|
+
|
|
11
|
+
**Switch to local tickets if:**
|
|
12
|
+
- Your team prefers a simple, zero-dependency setup
|
|
13
|
+
- You want tickets version-controlled alongside your code
|
|
14
|
+
- You use specrails-hub and want the visual ticket panel
|
|
15
|
+
- You don't need GitHub/JIRA for other workflows (project boards, external stakeholders)
|
|
16
|
+
|
|
17
|
+
**Stay on GitHub Issues / JIRA if:**
|
|
18
|
+
- Other teams or stakeholders manage tickets in those tools
|
|
19
|
+
- You rely on GitHub Projects, Milestones, or JIRA sprints
|
|
20
|
+
- You want PR auto-close on issue merge (requires GitHub Issues)
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Step 1: Switch the provider
|
|
25
|
+
|
|
26
|
+
Edit `.claude/backlog-config.json` in your project root:
|
|
27
|
+
|
|
28
|
+
```json
|
|
29
|
+
{
|
|
30
|
+
"provider": "local",
|
|
31
|
+
"write_access": true,
|
|
32
|
+
"git_auto": true
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Then initialize the ticket store if it doesn't exist yet:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# Inside Claude Code or Codex
|
|
40
|
+
/sr:implement --setup-local-tickets
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Or create the file manually:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
cat > .claude/local-tickets.json << 'EOF'
|
|
47
|
+
{
|
|
48
|
+
"schema_version": "1.0",
|
|
49
|
+
"revision": 0,
|
|
50
|
+
"last_updated": null,
|
|
51
|
+
"next_id": 1,
|
|
52
|
+
"tickets": {}
|
|
53
|
+
}
|
|
54
|
+
EOF
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Step 2: Import existing issues (one-time migration)
|
|
60
|
+
|
|
61
|
+
### From GitHub Issues
|
|
62
|
+
|
|
63
|
+
Use the `sr:migrate-from-github` command (requires `gh` CLI):
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# Inside Claude Code
|
|
67
|
+
/sr:migrate-from-github
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
This command:
|
|
71
|
+
1. Fetches all open issues labeled `product-driven-backlog` (the label specrails uses)
|
|
72
|
+
2. Maps GitHub issue fields to local ticket schema:
|
|
73
|
+
- `number` → `id` (uses next available local ID)
|
|
74
|
+
- `title` → `title`
|
|
75
|
+
- `body` → `description`
|
|
76
|
+
- `labels` → `labels`
|
|
77
|
+
- `state: open` → `status: todo`
|
|
78
|
+
3. Writes each ticket to `local-tickets.json`
|
|
79
|
+
4. Prints a summary: `Imported 14 tickets from GitHub Issues`
|
|
80
|
+
|
|
81
|
+
To import all open issues regardless of label:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
/sr:migrate-from-github --all
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
To do a dry run (preview without writing):
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
/sr:migrate-from-github --dry-run
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**After import:** Your GitHub Issues are unchanged. The migration is additive — it only creates local tickets. You can continue using GitHub Issues in parallel until you're ready to stop.
|
|
94
|
+
|
|
95
|
+
### From JIRA
|
|
96
|
+
|
|
97
|
+
Use the `sr:migrate-from-jira` command (requires `jira` CLI or REST API credentials in `.claude/backlog-config.json`):
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
# Inside Claude Code
|
|
101
|
+
/sr:migrate-from-jira
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
This command:
|
|
105
|
+
1. Fetches all open issues from the configured JIRA project
|
|
106
|
+
2. Maps JIRA fields to local ticket schema:
|
|
107
|
+
- Issue key (`PROJECT-123`) → stored in `metadata.jira_key`
|
|
108
|
+
- `summary` → `title`
|
|
109
|
+
- `description` → `description`
|
|
110
|
+
- `priority` → `priority` (Critical/High/Medium/Low mapped directly)
|
|
111
|
+
- `status: To Do / Backlog` → `status: todo`
|
|
112
|
+
- `status: In Progress` → `status: in_progress`
|
|
113
|
+
- `labels` → `labels`
|
|
114
|
+
3. Writes each ticket to `local-tickets.json`
|
|
115
|
+
|
|
116
|
+
The original JIRA key is preserved in `metadata.jira_key` so you can cross-reference during the transition.
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Step 3: Regenerate commands (optional but recommended)
|
|
121
|
+
|
|
122
|
+
Command templates are generated at `/setup` time with provider-specific instructions baked in. After switching providers, regenerate them so commands use the local file operations instead of GitHub/JIRA CLI calls:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
npx specrails-core@latest init --root-dir .
|
|
126
|
+
> /setup --update
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
The `--update` flag regenerates only the backlog commands (`product-backlog`, `update-product-driven-backlog`, `implement`) without re-running the full stack analysis.
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Rollback
|
|
134
|
+
|
|
135
|
+
To revert to GitHub Issues:
|
|
136
|
+
|
|
137
|
+
1. Edit `.claude/backlog-config.json` and set `"provider": "github"`
|
|
138
|
+
2. Re-run `/setup --update` to regenerate commands
|
|
139
|
+
3. Your `local-tickets.json` is preserved — switch back any time
|
|
140
|
+
|
|
141
|
+
Local tickets and external provider data are independent. Switching providers does not delete tickets from either system.
|
package/docs/user-docs/faq.md
CHANGED
|
@@ -14,17 +14,20 @@ It creates a `.claude/` directory with agent templates, commands, and configurat
|
|
|
14
14
|
|
|
15
15
|
Yes. Node 18+ is required to run `npx specrails-core@latest`. Once installed, SpecRails works with any language or framework — the agents adapt to whatever stack your project uses.
|
|
16
16
|
|
|
17
|
-
**
|
|
17
|
+
**Do I need GitHub Issues?**
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
No. SpecRails ships with a built-in local ticket system — no GitHub account required. Local tickets are the default. Commands like `/sr:implement` accept ticket IDs or plain text:
|
|
20
20
|
|
|
21
21
|
```
|
|
22
|
+
/sr:implement #1, #4
|
|
22
23
|
/sr:implement "add rate limiting to the API"
|
|
23
24
|
```
|
|
24
25
|
|
|
26
|
+
You can switch to GitHub Issues or JIRA during `/setup` (Phase 3) if you prefer.
|
|
27
|
+
|
|
25
28
|
**How long does /setup take?**
|
|
26
29
|
|
|
27
|
-
|
|
30
|
+
The full wizard takes about 5 minutes — most of the time is Phase 2 (persona research via web search). For a faster start, use `/setup --lite`: three questions, under a minute, no web research.
|
|
28
31
|
|
|
29
32
|
---
|
|
30
33
|
|
|
@@ -95,7 +95,7 @@ codex # Codex
|
|
|
95
95
|
/setup
|
|
96
96
|
```
|
|
97
97
|
|
|
98
|
-
|
|
98
|
+
By default, `/setup` runs the full 5-phase wizard:
|
|
99
99
|
|
|
100
100
|
| Phase | What happens |
|
|
101
101
|
|-------|-------------|
|
|
@@ -105,6 +105,8 @@ The wizard runs 5 phases:
|
|
|
105
105
|
| **4. Generate** | Fills all templates with your project-specific context |
|
|
106
106
|
| **5. Cleanup** | Removes setup files, leaving only your tailored workflow |
|
|
107
107
|
|
|
108
|
+
**In a hurry?** Run `/setup --lite` instead — three questions, sensible defaults, done in under a minute.
|
|
109
|
+
|
|
108
110
|
After setup, `.claude/` contains fully configured agents and commands ready to use. The `/setup` command removes itself — it only runs once.
|
|
109
111
|
|
|
110
112
|
## Verify
|
|
@@ -46,7 +46,7 @@ Then run:
|
|
|
46
46
|
/setup
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
-
The wizard runs
|
|
49
|
+
The wizard runs the full 5-phase setup (about 5 minutes). It analyzes your codebase and configures SpecRails for your specific project:
|
|
50
50
|
|
|
51
51
|
```
|
|
52
52
|
Phase 1/5 Analyzing codebase...
|
|
@@ -59,14 +59,14 @@ Phase 2/5 Generating user personas...
|
|
|
59
59
|
→ Created 3 VPC profiles
|
|
60
60
|
|
|
61
61
|
Phase 3/5 Configuration...
|
|
62
|
-
→ Backlog provider:
|
|
62
|
+
→ Backlog provider: local
|
|
63
63
|
→ Git workflow: trunk-based
|
|
64
64
|
|
|
65
65
|
Phase 4/5 Generating files...
|
|
66
66
|
→ sr-architect.md (adapted to your stack)
|
|
67
67
|
→ sr-developer.md (knows your CI commands)
|
|
68
68
|
→ sr-reviewer.md (runs your specific checks)
|
|
69
|
-
→
|
|
69
|
+
→ 11 more agents
|
|
70
70
|
|
|
71
71
|
Phase 5/5 Cleanup complete. /setup removed.
|
|
72
72
|
|
|
@@ -75,6 +75,8 @@ Phase 5/5 Cleanup complete. /setup removed.
|
|
|
75
75
|
|
|
76
76
|
After setup, the `/setup` command is gone — it's a one-time wizard.
|
|
77
77
|
|
|
78
|
+
**In a hurry?** Use `/setup --lite` for a 3-question quick setup (under a minute). You can always run the full wizard later.
|
|
79
|
+
|
|
78
80
|
## Step 3: Implement your first feature
|
|
79
81
|
|
|
80
82
|
Pick something small. Either reference a GitHub Issue or describe it in plain text:
|
|
@@ -129,7 +131,7 @@ One command. The PR is ready for human review.
|
|
|
129
131
|
/sr:product-backlog
|
|
130
132
|
```
|
|
131
133
|
|
|
132
|
-
See your
|
|
134
|
+
See your tickets ranked by persona fit and effort. The top 3 are safe to implement next. Uses local tickets by default.
|
|
133
135
|
|
|
134
136
|
**Generate new feature ideas:**
|
|
135
137
|
|
|
@@ -137,7 +139,7 @@ See your GitHub Issues ranked by persona fit and effort. The top 3 are safe to i
|
|
|
137
139
|
/sr:update-product-driven-backlog
|
|
138
140
|
```
|
|
139
141
|
|
|
140
|
-
The Product Manager researches your competitive landscape and creates
|
|
142
|
+
The Product Manager researches your competitive landscape and creates new tickets (local by default, or GitHub Issues if configured).
|
|
141
143
|
|
|
142
144
|
**Run multiple features in parallel:**
|
|
143
145
|
|
package/docs/workflows.md
CHANGED
|
@@ -126,7 +126,7 @@ View your prioritized product backlog, ranked by VPC fit and effort.
|
|
|
126
126
|
|
|
127
127
|
### What it shows
|
|
128
128
|
|
|
129
|
-
The Product Analyst reads your GitHub Issues
|
|
129
|
+
The Product Analyst reads your backlog (local tickets in `.claude/local-tickets.json` by default, or GitHub Issues labeled `product-driven-backlog` if configured) and produces:
|
|
130
130
|
|
|
131
131
|
- **Backlog table** per area — sorted by Total Persona Score
|
|
132
132
|
- **Top 3 recommendations** — ranked by VPC score / effort ratio, filtered to Wave 1 of the safe implementation order
|
|
@@ -166,7 +166,7 @@ Generate new feature ideas through product discovery. The Product Manager (Opus)
|
|
|
166
166
|
2. Researches competitors via web search
|
|
167
167
|
3. Generates 2–4 feature ideas per area
|
|
168
168
|
4. Scores each against every persona (0–5)
|
|
169
|
-
5. Creates GitHub Issues
|
|
169
|
+
5. Creates tickets in your active backlog provider (local tickets by default; GitHub Issues or JIRA if configured) or displays for manual creation
|
|
170
170
|
|
|
171
171
|
---
|
|
172
172
|
|
|
@@ -35,5 +35,11 @@
|
|
|
35
35
|
"refactor-recommender",
|
|
36
36
|
"health-check",
|
|
37
37
|
"compat-check"
|
|
38
|
-
]
|
|
38
|
+
],
|
|
39
|
+
"ticketProvider": {
|
|
40
|
+
"type": "local",
|
|
41
|
+
"storageFile": "local-tickets.json",
|
|
42
|
+
"lockFile": "local-tickets.json.lock",
|
|
43
|
+
"capabilities": ["crud", "labels", "status", "priorities", "dependencies", "comments"]
|
|
44
|
+
}
|
|
39
45
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "specrails-core",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.0",
|
|
4
4
|
"description": "AI agent workflow system for Claude Code — installs 12 specialized agents, orchestration commands, and persona-driven product discovery into any repository",
|
|
5
5
|
"bin": {
|
|
6
6
|
"specrails-core": "bin/specrails-core.js"
|
|
@@ -24,12 +24,22 @@ Check the environment variable `CLAUDE_CODE_ENTRYPOINT`. If it contains `remote_
|
|
|
24
24
|
|
|
25
25
|
### Checks to run (sequential, fail-fast)
|
|
26
26
|
|
|
27
|
-
#### 1.
|
|
27
|
+
#### 1. Backlog provider availability
|
|
28
28
|
|
|
29
|
+
Read `.claude/backlog-config.json` and extract `BACKLOG_PROVIDER`.
|
|
30
|
+
|
|
31
|
+
**If `BACKLOG_PROVIDER=local`:**
|
|
29
32
|
```bash
|
|
30
|
-
|
|
33
|
+
[[ -f "$SPECRAILS_DIR/local-tickets.json" ]] && echo "Local tickets storage: OK" || echo "WARNING: local-tickets.json not found"
|
|
31
34
|
```
|
|
35
|
+
- Set `LOCAL_TICKETS_AVAILABLE=true/false` based on file existence.
|
|
36
|
+
- Set `GH_AVAILABLE=false` (GitHub CLI not needed for local provider).
|
|
37
|
+
- Set `BACKLOG_AVAILABLE=true` if local-tickets.json exists.
|
|
32
38
|
|
|
39
|
+
**Otherwise:**
|
|
40
|
+
```bash
|
|
41
|
+
gh auth status 2>&1
|
|
42
|
+
```
|
|
33
43
|
- Set `GH_AVAILABLE=true/false` for later phases.
|
|
34
44
|
|
|
35
45
|
#### 2. OpenSpec CLI
|
|
@@ -107,7 +117,7 @@ Initialize conflict-tracking variables:
|
|
|
107
117
|
- Set `SINGLE_MODE = true`. No worktrees, no parallelism.
|
|
108
118
|
- **Skip Phase 1 and Phase 2** — go directly to Phase 3a.
|
|
109
119
|
|
|
110
|
-
**If the user passed issue/ticket references** (e.g. `#85, #71` for GitHub or `PROJ-85, PROJ-71` for JIRA):
|
|
120
|
+
**If the user passed issue/ticket references** (e.g. `#85, #71` for GitHub, `#1, #2` for local tickets, or `PROJ-85, PROJ-71` for JIRA):
|
|
111
121
|
- Fetch each issue/ticket:
|
|
112
122
|
```bash
|
|
113
123
|
{{BACKLOG_VIEW_CMD}}
|
|
@@ -120,7 +130,44 @@ Initialize conflict-tracking variables:
|
|
|
120
130
|
|
|
121
131
|
After fetching issue refs, capture a baseline snapshot for conflict detection.
|
|
122
132
|
|
|
123
|
-
|
|
133
|
+
##### If `BACKLOG_PROVIDER=local` and input mode was issue numbers:
|
|
134
|
+
|
|
135
|
+
For each resolved ticket ID, read `$SPECRAILS_DIR/local-tickets.json` and extract the ticket object at `tickets["{id}"]`.
|
|
136
|
+
|
|
137
|
+
Build a snapshot object for each ticket:
|
|
138
|
+
- `number`: ticket `id` (integer)
|
|
139
|
+
- `title`: ticket `title` string
|
|
140
|
+
- `state`: map ticket `status` — `"done"` or `"cancelled"` → `"closed"`, otherwise → `"open"`
|
|
141
|
+
- `assignees`: `[ticket.assignee]` if non-null, else `[]`
|
|
142
|
+
- `labels`: ticket `labels` array, sorted alphabetically
|
|
143
|
+
- `body_sha`: SHA-256 of the ticket `description` string — compute with:
|
|
144
|
+
```bash
|
|
145
|
+
echo -n "{description}" | sha256sum | cut -d' ' -f1
|
|
146
|
+
```
|
|
147
|
+
If `sha256sum` is not available, fall back to `openssl dgst -sha256 -r` or `shasum -a 256`.
|
|
148
|
+
- `updated_at`: ticket `updated_at` value
|
|
149
|
+
- `captured_at`: current local time in ISO 8601 format
|
|
150
|
+
|
|
151
|
+
Write the following JSON to `.claude/backlog-cache.json` (overwrite fully — this establishes a fresh baseline for this run):
|
|
152
|
+
|
|
153
|
+
```json
|
|
154
|
+
{
|
|
155
|
+
"schema_version": "1",
|
|
156
|
+
"provider": "local",
|
|
157
|
+
"last_updated": "<ISO 8601 timestamp>",
|
|
158
|
+
"written_by": "implement",
|
|
159
|
+
"issues": {
|
|
160
|
+
"<id>": { <snapshot object> },
|
|
161
|
+
...
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
If the write succeeds: set `SNAPSHOTS_CAPTURED=true`.
|
|
167
|
+
|
|
168
|
+
If the write fails: print `[backlog-cache] Warning: could not write cache. Conflict detection disabled for this run.` and set `SNAPSHOTS_CAPTURED=false`. Do NOT abort the pipeline.
|
|
169
|
+
|
|
170
|
+
##### If `GH_AVAILABLE=true` and input mode was issue numbers (GitHub/JIRA):
|
|
124
171
|
|
|
125
172
|
For each resolved issue number, run:
|
|
126
173
|
|
|
@@ -161,9 +208,9 @@ If the write succeeds: set `SNAPSHOTS_CAPTURED=true`.
|
|
|
161
208
|
|
|
162
209
|
If the write fails (e.g., `.claude/` directory does not exist): print `[backlog-cache] Warning: could not write cache. Conflict detection disabled for this run.` and set `SNAPSHOTS_CAPTURED=false`. Do NOT abort the pipeline.
|
|
163
210
|
|
|
164
|
-
|
|
211
|
+
##### Otherwise (no backlog available or non-issue input):
|
|
165
212
|
|
|
166
|
-
Set `SNAPSHOTS_CAPTURED=false`. Print: `[conflict-check] Snapshot skipped —
|
|
213
|
+
Set `SNAPSHOTS_CAPTURED=false`. Print: `[conflict-check] Snapshot skipped — backlog unavailable or non-issue input.`
|
|
167
214
|
|
|
168
215
|
#### Gitignore advisory
|
|
169
216
|
|
|
@@ -267,7 +314,9 @@ Pick the single idea with the best impact/effort ratio from each exploration. Pr
|
|
|
267
314
|
|
|
268
315
|
Otherwise, re-fetch each issue in scope and diff against the Phase 0 snapshot:
|
|
269
316
|
|
|
270
|
-
For each
|
|
317
|
+
**If `BACKLOG_PROVIDER=local`:** For each ticket ID in `ISSUE_REFS`, read `$SPECRAILS_DIR/local-tickets.json` and extract the ticket at `tickets["{id}"]`. If the ticket does not exist (deleted): treat as a CRITICAL conflict — field `"state"`, was `<cached state>`, now `"deleted"`. Otherwise, reconstruct a current snapshot using the same mapping as the Phase 0 local snapshot.
|
|
318
|
+
|
|
319
|
+
**If `BACKLOG_PROVIDER=github`:** For each issue number in `ISSUE_REFS`:
|
|
271
320
|
|
|
272
321
|
```bash
|
|
273
322
|
gh issue view {number} --json number,title,state,assignees,labels,body,updatedAt
|
|
@@ -275,7 +324,7 @@ gh issue view {number} --json number,title,state,assignees,labels,body,updatedAt
|
|
|
275
324
|
|
|
276
325
|
If the `gh` command returns non-zero (issue deleted or inaccessible): treat as a CRITICAL conflict — field `"state"`, was `<cached state>`, now `"deleted"`.
|
|
277
326
|
|
|
278
|
-
|
|
327
|
+
In both cases, reconstruct a current snapshot (same shape as Phase 0: sort `assignees` and `labels`, compute `body_sha`).
|
|
279
328
|
|
|
280
329
|
**Short-circuit:** If `current.updatedAt == cached.updated_at`, mark the issue as clean and skip field comparison.
|
|
281
330
|
|
|
@@ -848,6 +897,9 @@ This check is independent of Phase 3a.0. Even if the user chose to continue thro
|
|
|
848
897
|
|
|
849
898
|
Re-fetch each issue in `ISSUE_REFS` and diff against `.claude/backlog-cache.json` using the same algorithm as Phase 3a.0:
|
|
850
899
|
|
|
900
|
+
**If `BACKLOG_PROVIDER=local`:** Read `$SPECRAILS_DIR/local-tickets.json` and extract each ticket by ID.
|
|
901
|
+
|
|
902
|
+
**If `BACKLOG_PROVIDER=github`:**
|
|
851
903
|
```bash
|
|
852
904
|
gh issue view {number} --json number,title,state,assignees,labels,body,updatedAt
|
|
853
905
|
```
|
|
@@ -881,8 +933,12 @@ Record skipped operations to `.cache-manifest.json` under `skipped_operations`:
|
|
|
881
933
|
- `"git: commit"`
|
|
882
934
|
- `"git: push"`
|
|
883
935
|
- `"github: pr creation"` (if `GH_AVAILABLE=true`)
|
|
884
|
-
-
|
|
885
|
-
- `"
|
|
936
|
+
- If `BACKLOG_PROVIDER=local` and `BACKLOG_WRITE=true`:
|
|
937
|
+
- `"local: ticket comment #{id}"` for each ticket in scope
|
|
938
|
+
- `"local: ticket status update #{id}"` for each fully resolved ticket
|
|
939
|
+
- If `BACKLOG_PROVIDER=github` and `BACKLOG_WRITE=true`:
|
|
940
|
+
- `"github: issue comment #N"` for each issue in scope
|
|
941
|
+
- `"github: issue close #N (via PR merge)"` for each fully resolved issue
|
|
886
942
|
|
|
887
943
|
Then skip the rest of Phase 4c and proceed directly to Phase 4e.
|
|
888
944
|
|
|
@@ -934,17 +990,19 @@ All implementation is complete and CI checks pass.
|
|
|
934
990
|
#### Backlog updates (both modes)
|
|
935
991
|
|
|
936
992
|
**If `BACKLOG_WRITE=true`:**
|
|
937
|
-
- For fully resolved issues/tickets: add a comment noting completion and reference the PR
|
|
993
|
+
- For fully resolved issues/tickets: add a comment noting completion and reference the PR:
|
|
938
994
|
```bash
|
|
939
995
|
{{BACKLOG_COMMENT_CMD}}
|
|
940
996
|
```
|
|
941
|
-
-
|
|
942
|
-
-
|
|
943
|
-
-
|
|
997
|
+
- **Local:** Update the ticket status to `"done"` using `{{BACKLOG_UPDATE_CMD}}` and add a comment: `"Implemented in PR #XX. All acceptance criteria met."` via `{{BACKLOG_COMMENT_CMD}}`. Local tickets are closed directly — there is no auto-close-on-merge mechanism.
|
|
998
|
+
- **GitHub:** `gh issue comment {number} --body "Implemented in PR #XX. All acceptance criteria met."` — do NOT close the issue explicitly. Use `Closes #N` in the PR body so GitHub auto-closes on merge.
|
|
999
|
+
- **JIRA:** `jira issue comment {key} --message "Implemented in PR #XX. All acceptance criteria met."`
|
|
1000
|
+
- For GitHub/JIRA: ensure the PR body includes `Closes #N` for each fully resolved issue (auto-closes on merge)
|
|
944
1001
|
- For partially resolved issues/tickets: add a comment noting progress:
|
|
945
1002
|
```bash
|
|
946
1003
|
{{BACKLOG_PARTIAL_COMMENT_CMD}}
|
|
947
1004
|
```
|
|
1005
|
+
- **Local:** Additionally update the ticket status to `"in_progress"` via `{{BACKLOG_UPDATE_CMD}}` if it is still `"todo"`.
|
|
948
1006
|
|
|
949
1007
|
**If `BACKLOG_WRITE=false`:**
|
|
950
1008
|
- Do NOT create, modify, or comment on any issues/tickets.
|