specrails-core 4.10.0 → 4.11.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 +6 -0
- package/package.json +1 -1
- package/templates/commands/specrails/implement.md +19 -91
package/README.md
CHANGED
|
@@ -134,6 +134,12 @@ specrails is not a chat interface. It's a **development pipeline** that coordina
|
|
|
134
134
|
|
|
135
135
|
Architect designs → developer builds → reviewer validates → PR created. Multiple features run in parallel with git worktrees.
|
|
136
136
|
|
|
137
|
+
#### Letting a host own version control (`SPECRAILS_GIT_AUTO`)
|
|
138
|
+
|
|
139
|
+
By default the pipeline ships automatically (`GIT_AUTO=true`): it creates a branch, commits, pushes, and opens a pull request. When specrails-core runs **inside a host that owns version control itself** — such as [specrails-desktop](https://github.com/fjpulidop/specrails-desktop), which runs each pipeline in an isolated git worktree and opens the pull request for you — that host sets the `SPECRAILS_GIT_AUTO` environment variable to `false`.
|
|
140
|
+
|
|
141
|
+
When `SPECRAILS_GIT_AUTO=false` (or `0`), the Ship phase is forced onto the **manual** path regardless of configuration: the pipeline stops at "code written and verified" and makes **no branch, commit, push, or PR** — the host does that. This prevents a second, uncoordinated pull request. Leave the variable unset for the normal standalone behaviour (automatic shipping, subject to your `GIT_AUTO` configuration). It composes with `--dry-run`, which independently skips all git/GitHub/backlog operations.
|
|
142
|
+
|
|
137
143
|
#### Dry-run / preview mode
|
|
138
144
|
|
|
139
145
|
Not ready to commit? Run the full pipeline without touching git or GitHub:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "specrails-core",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.11.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
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -6,9 +6,9 @@ Full OpenSpec lifecycle with specialized agents: architect designs, developer im
|
|
|
6
6
|
|
|
7
7
|
**Input:** $ARGUMENTS — accepts three modes:
|
|
8
8
|
|
|
9
|
-
1. **
|
|
9
|
+
1. **Ticket numbers** (recommended): `#85, #71, #63` — implement these specific tickets from the local backlog (`local-tickets.json`). Skips exploration and selection.
|
|
10
10
|
2. **Text description** (single feature): `"add price history chart"` — implement a single feature from a description. Skips exploration and selection.
|
|
11
|
-
3. **Area names** (fallback): `Analytics, UI, Testing` — explores areas and picks the best items. Only use if no backlog
|
|
11
|
+
3. **Area names** (fallback): `Analytics, UI, Testing` — explores areas and picks the best items. Only use if no backlog tickets exist.
|
|
12
12
|
|
|
13
13
|
**IMPORTANT:** Before running, ensure Read/Write/Bash/Glob/Grep permissions are set to "allow" — background agents cannot request permissions interactively.
|
|
14
14
|
|
|
@@ -21,7 +21,7 @@ Your working directory may NOT be the user's source repository. **Repo-resident*
|
|
|
21
21
|
Rules used throughout this pipeline:
|
|
22
22
|
- **openspec reads/writes** → `${SPECRAILS_REPO_DIR:-.}/openspec/...`
|
|
23
23
|
- **git commands** → `git -C "${SPECRAILS_REPO_DIR:-.}" ...`
|
|
24
|
-
- **`gh` commands** (
|
|
24
|
+
- **`gh` commands** (PR — they need the repo's remote) → run them from the repo: `(cd "${SPECRAILS_REPO_DIR:-.}" && gh ...)`
|
|
25
25
|
- **worktree merge-back** → the merge *target* side (the main working tree) is `${SPECRAILS_REPO_DIR:-.}/<file>`
|
|
26
26
|
|
|
27
27
|
**Run-state stays with the working directory** (NOT the repo): `.claude/pipeline-state/`, `.claude/agent-memory/`, `.claude/backlog-cache.json`, and the dry-run cache `.claude/.dry-run/` are all written relative to the current directory. **Profile/agent files** (`.claude/agents/sr-*.md`) are likewise resolved relative to the current directory — do NOT prefix them with `${SPECRAILS_REPO_DIR:-.}`.
|
|
@@ -40,22 +40,13 @@ Check the environment variable `CLAUDE_CODE_ENTRYPOINT`. If it contains `remote_
|
|
|
40
40
|
|
|
41
41
|
#### 1. Backlog provider availability
|
|
42
42
|
|
|
43
|
-
Read `.specrails/backlog-config.json` and extract `BACKLOG_PROVIDER`.
|
|
44
|
-
|
|
45
|
-
**If `BACKLOG_PROVIDER=local`:**
|
|
46
43
|
```bash
|
|
47
44
|
[[ -f ".specrails/local-tickets.json" ]] && echo "Local tickets storage: OK" || echo "WARNING: local-tickets.json not found"
|
|
48
45
|
```
|
|
49
46
|
- Set `LOCAL_TICKETS_AVAILABLE=true/false` based on file existence.
|
|
50
|
-
- Set `GH_AVAILABLE=false` (
|
|
47
|
+
- Set `GH_AVAILABLE=false` (backlog is always local).
|
|
51
48
|
- Set `BACKLOG_AVAILABLE=true` if local-tickets.json exists.
|
|
52
49
|
|
|
53
|
-
**Otherwise:**
|
|
54
|
-
```bash
|
|
55
|
-
gh auth status 2>&1
|
|
56
|
-
```
|
|
57
|
-
- Set `GH_AVAILABLE=true/false` for later phases.
|
|
58
|
-
|
|
59
50
|
#### 2. OpenSpec CLI
|
|
60
51
|
|
|
61
52
|
```bash
|
|
@@ -312,13 +303,10 @@ Initialize conflict-tracking variables:
|
|
|
312
303
|
- Set `SINGLE_MODE = true`. No worktrees, no parallelism.
|
|
313
304
|
- **Skip Phase 1 and Phase 2** — go directly to Phase 3a.
|
|
314
305
|
|
|
315
|
-
**If the user passed
|
|
316
|
-
- Fetch each
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
```
|
|
320
|
-
- Extract area, value, effort, and feature details from each issue body.
|
|
321
|
-
- If only 1 issue: set `SINGLE_MODE = true`.
|
|
306
|
+
**If the user passed ticket references** (e.g. `#85, #71` or `#1, #2`):
|
|
307
|
+
- Fetch each ticket from `.specrails/local-tickets.json` at `tickets["{id}"]`.
|
|
308
|
+
- Extract area, value, effort, and feature details from each ticket body.
|
|
309
|
+
- If only 1 ticket: set `SINGLE_MODE = true`.
|
|
322
310
|
- **Skip Phase 1 and Phase 2** — go directly to confirmation table.
|
|
323
311
|
|
|
324
312
|
#### Phase 0 snapshot capture
|
|
@@ -362,48 +350,7 @@ If the write succeeds: set `SNAPSHOTS_CAPTURED=true`.
|
|
|
362
350
|
|
|
363
351
|
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.
|
|
364
352
|
|
|
365
|
-
#####
|
|
366
|
-
|
|
367
|
-
For each resolved issue number, run:
|
|
368
|
-
|
|
369
|
-
```bash
|
|
370
|
-
(cd "${SPECRAILS_REPO_DIR:-.}" && gh issue view {number} --json number,title,state,assignees,labels,body,updatedAt)
|
|
371
|
-
```
|
|
372
|
-
|
|
373
|
-
Build a snapshot object for each issue:
|
|
374
|
-
- `number`: integer issue number
|
|
375
|
-
- `title`: issue title string
|
|
376
|
-
- `state`: `"open"` or `"closed"`
|
|
377
|
-
- `assignees`: array of assignee login names, sorted alphabetically
|
|
378
|
-
- `labels`: array of label names, sorted alphabetically
|
|
379
|
-
- `body_sha`: SHA-256 of the raw body string — compute with:
|
|
380
|
-
```bash
|
|
381
|
-
echo -n "{body}" | sha256sum | cut -d' ' -f1
|
|
382
|
-
```
|
|
383
|
-
If `sha256sum` is not available, fall back to `openssl dgst -sha256 -r` or `shasum -a 256`.
|
|
384
|
-
- `updated_at`: the `updatedAt` value from the GitHub API response
|
|
385
|
-
- `captured_at`: current local time in ISO 8601 format
|
|
386
|
-
|
|
387
|
-
Write the following JSON to `.claude/backlog-cache.json` (overwrite fully — this establishes a fresh baseline for this run):
|
|
388
|
-
|
|
389
|
-
```json
|
|
390
|
-
{
|
|
391
|
-
"schema_version": "1",
|
|
392
|
-
"provider": "github",
|
|
393
|
-
"last_updated": "<ISO 8601 timestamp>",
|
|
394
|
-
"written_by": "implement",
|
|
395
|
-
"issues": {
|
|
396
|
-
"<number>": { <snapshot object> },
|
|
397
|
-
...
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
```
|
|
401
|
-
|
|
402
|
-
If the write succeeds: set `SNAPSHOTS_CAPTURED=true`.
|
|
403
|
-
|
|
404
|
-
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.
|
|
405
|
-
|
|
406
|
-
##### Otherwise (no backlog available or non-issue input):
|
|
353
|
+
##### Otherwise (no backlog available or non-ticket input):
|
|
407
354
|
|
|
408
355
|
Set `SNAPSHOTS_CAPTURED=false`. Print: `[conflict-check] Snapshot skipped — backlog unavailable or non-issue input.`
|
|
409
356
|
|
|
@@ -509,19 +456,9 @@ Pick the single idea with the best impact/effort ratio from each exploration. Pr
|
|
|
509
456
|
|
|
510
457
|
**Guard:** If `SNAPSHOTS_CAPTURED=false` OR `DRY_RUN=true`, print `[conflict-check] Skipped — SNAPSHOTS_CAPTURED=false (or dry-run mode).` and proceed directly to Phase 3a.
|
|
511
458
|
|
|
512
|
-
Otherwise, re-fetch each
|
|
459
|
+
Otherwise, re-fetch each ticket in scope and diff against the Phase 0 snapshot:
|
|
513
460
|
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
**If `BACKLOG_PROVIDER=github`:** For each issue number in `ISSUE_REFS`:
|
|
517
|
-
|
|
518
|
-
```bash
|
|
519
|
-
(cd "${SPECRAILS_REPO_DIR:-.}" && gh issue view {number} --json number,title,state,assignees,labels,body,updatedAt)
|
|
520
|
-
```
|
|
521
|
-
|
|
522
|
-
If the `gh` command returns non-zero (issue deleted or inaccessible): treat as a CRITICAL conflict — field `"state"`, was `<cached state>`, now `"deleted"`.
|
|
523
|
-
|
|
524
|
-
In both cases, reconstruct a current snapshot (same shape as Phase 0: sort `assignees` and `labels`, compute `body_sha`).
|
|
461
|
+
For each ticket ID in `ISSUE_REFS`, read `.specrails/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 (sort `assignees` and `labels`, compute `body_sha`).
|
|
525
462
|
|
|
526
463
|
**Short-circuit:** If `current.updatedAt == cached.updated_at`, mark the issue as clean and skip field comparison.
|
|
527
464
|
|
|
@@ -1223,14 +1160,9 @@ When `DRY_RUN=true`, the reviewer still writes `confidence-score.json` (it is an
|
|
|
1223
1160
|
|
|
1224
1161
|
This check is independent of Phase 3a.0. Even if the user chose to continue through a conflict at Phase 3a.0, this gate re-checks all in-scope issues against the Phase 0 snapshot. It is the final gate before any code reaches git.
|
|
1225
1162
|
|
|
1226
|
-
Re-fetch each
|
|
1163
|
+
Re-fetch each ticket in `ISSUE_REFS` and diff against `.claude/backlog-cache.json` using the same algorithm as Phase 3a.0:
|
|
1227
1164
|
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
**If `BACKLOG_PROVIDER=github`:**
|
|
1231
|
-
```bash
|
|
1232
|
-
(cd "${SPECRAILS_REPO_DIR:-.}" && gh issue view {number} --json number,title,state,assignees,labels,body,updatedAt)
|
|
1233
|
-
```
|
|
1165
|
+
Read `.specrails/local-tickets.json` and extract each ticket by ID.
|
|
1234
1166
|
|
|
1235
1167
|
If the cache file is missing or malformed JSON at this point: log `[conflict-check] Warning: cache file missing or unreadable. Skipping diff for this run.` and proceed to Phase 4c (treat as clean).
|
|
1236
1168
|
|
|
@@ -1264,9 +1196,6 @@ Record skipped operations to `.cache-manifest.json` under `skipped_operations`:
|
|
|
1264
1196
|
- If `BACKLOG_PROVIDER=local` and `BACKLOG_WRITE=true`:
|
|
1265
1197
|
- `"local: ticket comment #{id}"` for each ticket in scope
|
|
1266
1198
|
- `"local: ticket status update #{id}"` for each fully resolved ticket
|
|
1267
|
-
- If `BACKLOG_PROVIDER=github` and `BACKLOG_WRITE=true`:
|
|
1268
|
-
- `"github: issue comment #N"` for each issue in scope
|
|
1269
|
-
- `"github: issue close #N (via PR merge)"` for each fully resolved issue
|
|
1270
1199
|
|
|
1271
1200
|
Then skip the rest of Phase 4c and proceed directly to Phase 4e.
|
|
1272
1201
|
|
|
@@ -1284,6 +1213,8 @@ Then skip the rest of Phase 4c and proceed directly to Phase 4e.
|
|
|
1284
1213
|
|
|
1285
1214
|
This phase respects the `GIT_AUTO` and `BACKLOG_WRITE` settings from configuration.
|
|
1286
1215
|
|
|
1216
|
+
**Environment override (host owns version control).** Before applying the `GIT_AUTO` logic below, check the `SPECRAILS_GIT_AUTO` environment variable. If it is set to `false` or `0`, treat `GIT_AUTO` as `false` for the rest of this phase (and Phase 4d) **regardless of configuration** — do not create a branch, commit, push, or open a PR; follow the `GIT_AUTO=false` (manual shipping) path instead. A host such as [specrails-desktop](https://github.com/fjpulidop/specrails-desktop) sets this when it owns version control (it runs the pipeline in an isolated worktree and opens the pull request itself), so honouring it prevents a second, uncoordinated PR. When `SPECRAILS_GIT_AUTO` is unset or any other value, resolve `GIT_AUTO` from configuration as normal.
|
|
1217
|
+
|
|
1287
1218
|
#### If `GIT_AUTO=true` (automatic shipping)
|
|
1288
1219
|
|
|
1289
1220
|
All git operations run against the repo via `git -C "${SPECRAILS_REPO_DIR:-.}"`, and `gh` runs from inside the repo so it can detect the remote.
|
|
@@ -1324,15 +1255,12 @@ All implementation is complete and CI checks pass.
|
|
|
1324
1255
|
```bash
|
|
1325
1256
|
{{BACKLOG_COMMENT_CMD}}
|
|
1326
1257
|
```
|
|
1327
|
-
-
|
|
1328
|
-
- **GitHub:** `(cd "${SPECRAILS_REPO_DIR:-.}" && 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.
|
|
1329
|
-
- **JIRA:** `jira issue comment {key} --message "Implemented in PR #XX. All acceptance criteria met."`
|
|
1330
|
-
- For GitHub/JIRA: ensure the PR body includes `Closes #N` for each fully resolved issue (auto-closes on merge)
|
|
1258
|
+
- 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}}`. Tickets are closed directly in `local-tickets.json`.
|
|
1331
1259
|
- For partially resolved issues/tickets: add a comment noting progress:
|
|
1332
1260
|
```bash
|
|
1333
1261
|
{{BACKLOG_PARTIAL_COMMENT_CMD}}
|
|
1334
1262
|
```
|
|
1335
|
-
-
|
|
1263
|
+
- Additionally update the ticket status to `"in_progress"` via `{{BACKLOG_UPDATE_CMD}}` if it is still `"todo"`.
|
|
1336
1264
|
|
|
1337
1265
|
**If `BACKLOG_WRITE=false`:**
|
|
1338
1266
|
- Do NOT create, modify, or comment on any issues/tickets.
|
|
@@ -1343,8 +1271,8 @@ All implementation is complete and CI checks pass.
|
|
|
1343
1271
|
The following tickets should be updated:
|
|
1344
1272
|
| Ticket | Status | Suggested Action |
|
|
1345
1273
|
|--------|--------|-----------------|
|
|
1346
|
-
| #85
|
|
1347
|
-
| #71
|
|
1274
|
+
| #85 | Fully implemented | Mark as Done in local-tickets.json |
|
|
1275
|
+
| #71 | Partial progress | Update to "in_progress": "X completed, Y remaining" |
|
|
1348
1276
|
```
|
|
1349
1277
|
|
|
1350
1278
|
**Pipeline state:** update `ship` → `done` if git operations and PR creation succeeded, or `failed` with error context describing which step failed (e.g. `"git push failed: <exit code>"`, `"gh pr create failed"`, `"security gate blocked ship"`). If `DRY_RUN=true`: update `ship` → `skipped`.
|