specrails-core 3.5.1 → 3.5.2

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/commands/setup.md CHANGED
@@ -59,7 +59,7 @@ Read the following files to understand the current installation state:
59
59
  Command template files include `implement.md`, `batch-implement.md`, `compat-check.md`, `refactor-recommender.md`, `why.md`, `get-backlog-specs.md`, `auto-propose-backlog-specs.md`.
60
60
  If this directory does not exist, skip command template checking for this update.
61
61
 
62
- 6. Read `$SPECRAILS_DIR/backlog-config.json` if it exists — contains stored provider configuration needed for command placeholder substitution.
62
+ 6. Read `.specrails/backlog-config.json` if it exists — contains stored provider configuration needed for command placeholder substitution.
63
63
 
64
64
  ### Phase U2: Quick Codebase Re-Analysis
65
65
 
@@ -178,7 +178,7 @@ For each command in the "changed commands" list from Phase U3:
178
178
  1. Read the NEW template:
179
179
  - If `cli_provider == "claude"`: from `$SPECRAILS_DIR/setup-templates/commands/specrails/<name>.md`
180
180
  - If `cli_provider == "codex"`: from `$SPECRAILS_DIR/setup-templates/skills/sr-<name>/SKILL.md`
181
- 2. Read stored backlog configuration from `$SPECRAILS_DIR/backlog-config.json` (if it exists) to resolve provider-specific placeholders:
181
+ 2. Read stored backlog configuration from `.specrails/backlog-config.json` (if it exists) to resolve provider-specific placeholders:
182
182
  - `BACKLOG_PROVIDER` → `provider` field (`github`, `jira`, or `none`)
183
183
  - `BACKLOG_WRITE` → `write_access` field
184
184
  - `JIRA_BASE_URL` → `jira_base_url` field
@@ -424,8 +424,8 @@ Core commands (always install if missing):
424
424
  - `auto-propose-backlog-specs.md`
425
425
 
426
426
  **Initialize local ticket storage** (backlog provider defaults to `local`):
427
- 1. Copy `templates/local-tickets-schema.json` to `$SPECRAILS_DIR/local-tickets.json` and set `last_updated` to the current ISO-8601 timestamp. Skip if the file already exists.
428
- 2. Write `$SPECRAILS_DIR/backlog-config.json` (skip if already exists):
427
+ 1. Copy `templates/local-tickets-schema.json` to `.specrails/local-tickets.json` and set `last_updated` to the current ISO-8601 timestamp. Skip if the file already exists.
428
+ 2. Write `.specrails/backlog-config.json` (skip if already exists):
429
429
  ```json
430
430
  {
431
431
  "provider": "local",
@@ -725,10 +725,10 @@ Wait for the user's choice. Set `BACKLOG_PROVIDER` to `local`, `github`, `jira`,
725
725
 
726
726
  No external tools or credentials required. Initialize the storage file:
727
727
 
728
- 1. Copy `templates/local-tickets-schema.json` to `$SPECRAILS_DIR/local-tickets.json`
728
+ 1. Copy `templates/local-tickets-schema.json` to `.specrails/local-tickets.json`
729
729
  2. Set `last_updated` to the current ISO-8601 timestamp
730
730
 
731
- Store configuration in `$SPECRAILS_DIR/backlog-config.json`:
731
+ Store configuration in `.specrails/backlog-config.json`:
732
732
  ```json
733
733
  {
734
734
  "provider": "local",
@@ -774,13 +774,13 @@ Local tickets are always read-write — there is no "read only" mode since the f
774
774
 
775
775
  The `revision` counter in the JSON root enables optimistic concurrency — increment it on **every** write. The lock file prevents concurrent corruption:
776
776
 
777
- 1. **Acquire lock:** Check for `$SPECRAILS_DIR/local-tickets.json.lock`
777
+ 1. **Acquire lock:** Check for `.specrails/local-tickets.json.lock`
778
778
  - If the file exists and its `timestamp` is less than 30 seconds old: wait 500ms and retry (max 5 attempts before aborting with an error)
779
779
  - If the file exists and its `timestamp` is 30+ seconds old (stale): delete it and proceed
780
780
  - If no lock file exists: proceed immediately
781
- 2. **Create lock file:** Write `{"agent": "<agent-name-or-process>", "timestamp": "<ISO-8601>"}` to `$SPECRAILS_DIR/local-tickets.json.lock`
781
+ 2. **Create lock file:** Write `{"agent": "<agent-name-or-process>", "timestamp": "<ISO-8601>"}` to `.specrails/local-tickets.json.lock`
782
782
  3. **Minimal lock window:** Read the JSON → modify in memory → write back → release
783
- 4. **Release lock:** Delete `$SPECRAILS_DIR/local-tickets.json.lock`
783
+ 4. **Release lock:** Delete `.specrails/local-tickets.json.lock`
784
784
  5. **Always increment `revision`** by 1 and update `last_updated` on every successful write
785
785
 
786
786
  The hub server uses `proper-lockfile` (or equivalent) to honor the same protocol via the `.lock` file path.
@@ -1147,22 +1147,22 @@ When adapting `auto-propose-backlog-specs.md` and `get-backlog-specs.md`, substi
1147
1147
 
1148
1148
  #### Local Tickets (`BACKLOG_PROVIDER=local`)
1149
1149
 
1150
- For the local provider, backlog placeholders resolve to **inline file-operation instructions** embedded in the generated command markdown — not shell commands. Agents execute these by reading/writing `$SPECRAILS_DIR/local-tickets.json` directly using their file tools.
1150
+ For the local provider, backlog placeholders resolve to **inline file-operation instructions** embedded in the generated command markdown — not shell commands. Agents execute these by reading/writing `.specrails/local-tickets.json` directly using their file tools.
1151
1151
 
1152
1152
  All write operations must follow the **advisory file locking protocol** defined in Phase 3.2. Always increment `revision` and update `last_updated` on every write.
1153
1153
 
1154
1154
  | Placeholder | Substituted value |
1155
1155
  |-------------|-------------------|
1156
1156
  | `{{BACKLOG_PROVIDER_NAME}}` | `Local Tickets` |
1157
- | `{{BACKLOG_PREFLIGHT}}` | `[[ -f "$SPECRAILS_DIR/local-tickets.json" ]] && echo "Local tickets storage: OK" \|\| echo "WARNING: $SPECRAILS_DIR/local-tickets.json not found — run /specrails:setup to initialize"` |
1158
- | `{{BACKLOG_FETCH_CMD}}` | Read `$SPECRAILS_DIR/local-tickets.json`. Parse the `tickets` map and return all entries where `status` is `"todo"` or `"in_progress"`. |
1159
- | `{{BACKLOG_FETCH_ALL_CMD}}` | Read `$SPECRAILS_DIR/local-tickets.json`. Parse the `tickets` map and return all entries regardless of status. |
1160
- | `{{BACKLOG_FETCH_CLOSED_CMD}}` | Read `$SPECRAILS_DIR/local-tickets.json`. Parse the `tickets` map and return all entries where `status` is `"done"` or `"cancelled"`. |
1161
- | `{{BACKLOG_VIEW_CMD}}` | Read `$SPECRAILS_DIR/local-tickets.json`. Parse JSON and return the full ticket object at `tickets["{id}"]`, or an error if not found. |
1162
- | `{{BACKLOG_CREATE_CMD}}` | Write to `$SPECRAILS_DIR/local-tickets.json` using the advisory locking protocol: acquire lock → read file → set `id = next_id`, increment `next_id`, set all ticket fields, set `created_at` and `updated_at` to now, bump `revision`, update `last_updated` → write → release lock. |
1163
- | `{{BACKLOG_UPDATE_CMD}}` | Write to `$SPECRAILS_DIR/local-tickets.json` using the advisory locking protocol: acquire lock → read file → update fields in `tickets["{id}"]`, set `updated_at` to now, bump `revision`, update `last_updated` → write → release lock. |
1164
- | `{{BACKLOG_DELETE_CMD}}` | Write to `$SPECRAILS_DIR/local-tickets.json` using the advisory locking protocol: acquire lock → read file → delete `tickets["{id}"]`, bump `revision`, update `last_updated` → write → release lock. |
1165
- | `{{BACKLOG_COMMENT_CMD}}` | Write to `$SPECRAILS_DIR/local-tickets.json` using the advisory locking protocol: acquire lock → read file → append `{"author": "<agent-name>", "body": "<comment>", "created_at": "<ISO-8601>"}` to `tickets["{id}"].comments` (create the array if absent), set `updated_at` to now, bump `revision`, update `last_updated` → write → release lock. |
1157
+ | `{{BACKLOG_PREFLIGHT}}` | `[[ -f ".specrails/local-tickets.json" ]] && echo "Local tickets storage: OK" \|\| echo "WARNING: .specrails/local-tickets.json not found — run /specrails:setup to initialize"` |
1158
+ | `{{BACKLOG_FETCH_CMD}}` | Read `.specrails/local-tickets.json`. Parse the `tickets` map and return all entries where `status` is `"todo"` or `"in_progress"`. |
1159
+ | `{{BACKLOG_FETCH_ALL_CMD}}` | Read `.specrails/local-tickets.json`. Parse the `tickets` map and return all entries regardless of status. |
1160
+ | `{{BACKLOG_FETCH_CLOSED_CMD}}` | Read `.specrails/local-tickets.json`. Parse the `tickets` map and return all entries where `status` is `"done"` or `"cancelled"`. |
1161
+ | `{{BACKLOG_VIEW_CMD}}` | Read `.specrails/local-tickets.json`. Parse JSON and return the full ticket object at `tickets["{id}"]`, or an error if not found. |
1162
+ | `{{BACKLOG_CREATE_CMD}}` | Write to `.specrails/local-tickets.json` using the advisory locking protocol: acquire lock → read file → set `id = next_id`, increment `next_id`, set all ticket fields, set `created_at` and `updated_at` to now, bump `revision`, update `last_updated` → write → release lock. |
1163
+ | `{{BACKLOG_UPDATE_CMD}}` | Write to `.specrails/local-tickets.json` using the advisory locking protocol: acquire lock → read file → update fields in `tickets["{id}"]`, set `updated_at` to now, bump `revision`, update `last_updated` → write → release lock. |
1164
+ | `{{BACKLOG_DELETE_CMD}}` | Write to `.specrails/local-tickets.json` using the advisory locking protocol: acquire lock → read file → delete `tickets["{id}"]`, bump `revision`, update `last_updated` → write → release lock. |
1165
+ | `{{BACKLOG_COMMENT_CMD}}` | Write to `.specrails/local-tickets.json` using the advisory locking protocol: acquire lock → read file → append `{"author": "<agent-name>", "body": "<comment>", "created_at": "<ISO-8601>"}` to `tickets["{id}"].comments` (create the array if absent), set `updated_at` to now, bump `revision`, update `last_updated` → write → release lock. |
1166
1166
  | `{{BACKLOG_PARTIAL_COMMENT_CMD}}` | Same as `{{BACKLOG_COMMENT_CMD}}` but append `{"author": "<agent-name>", "body": "<comment>", "type": "progress", "created_at": "<ISO-8601>"}`. |
1167
1167
  | `{{BACKLOG_INIT_LABELS_CMD}}` | No label initialization required. Local tickets use freeform label strings. Standard label conventions: `area:frontend`, `area:backend`, `area:api`, `effort:low`, `effort:medium`, `effort:high`. |
1168
1168
 
@@ -1183,7 +1183,7 @@ All write operations must follow the **advisory file locking protocol** defined
1183
1183
  - Issue view: `jira issue view {key}` or REST API
1184
1184
  - VPC scores stored in the issue description body (same markdown format, parsed from description)
1185
1185
  - Pre-flight check: `jira me` or test API connectivity
1186
- - Store JIRA config in `$SPECRAILS_DIR/backlog-config.json`:
1186
+ - Store JIRA config in `.specrails/backlog-config.json`:
1187
1187
  ```json
1188
1188
  {
1189
1189
  "provider": "jira",
@@ -93,7 +93,7 @@ To do a dry run (preview without writing):
93
93
 
94
94
  ### From JIRA
95
95
 
96
- Use the `sr:migrate-from-jira` command (requires `jira` CLI or REST API credentials in `.claude/backlog-config.json`):
96
+ Use the `sr:migrate-from-jira` command (requires `jira` CLI or REST API credentials in `.specrails/backlog-config.json`):
97
97
 
98
98
  ```bash
99
99
  # Inside Claude Code
@@ -133,7 +133,7 @@ The `--update` flag regenerates only the backlog commands (`get-backlog-specs`,
133
133
 
134
134
  To revert to GitHub Issues:
135
135
 
136
- 1. Edit `.specrails/config.yaml` (or `.claude/backlog-config.json` for scaffold installs) and set `provider: github`
136
+ 1. Edit `.specrails/config.yaml` (or `.specrails/backlog-config.json` for scaffold installs) and set `provider: github`
137
137
  2. Re-run `/specrails:setup --update` to regenerate commands
138
138
  3. Your `local-tickets.json` is preserved — switch back any time
139
139
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "specrails-core",
3
- "version": "3.5.1",
3
+ "version": "3.5.2",
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"
@@ -67,7 +67,7 @@ After the Explore agent completes:
67
67
 
68
68
  1. **Display** results to the user.
69
69
 
70
- 2. Read `.claude/backlog-config.json` and extract:
70
+ 2. Read `.specrails/backlog-config.json` and extract:
71
71
  - `BACKLOG_PROVIDER` (`local`, `github`, `jira`, or `none`)
72
72
  - `BACKLOG_WRITE` (from `write_access`)
73
73
 
@@ -100,7 +100,7 @@ After the Explore agent completes:
100
100
 
101
101
  ### If provider=local — Sync to Local Tickets
102
102
 
103
- Local tickets are always read-write. Sync directly to `$SPECRAILS_DIR/local-tickets.json`.
103
+ Local tickets are always read-write. Sync directly to `.specrails/local-tickets.json`.
104
104
 
105
105
  3. **Fetch existing local tickets** to avoid duplicates:
106
106
  ```
@@ -196,7 +196,7 @@ Local tickets are always read-write. Sync directly to `$SPECRAILS_DIR/local-tick
196
196
 
197
197
  ### If provider=jira and BACKLOG_WRITE=true — Sync to JIRA
198
198
 
199
- Read from `.claude/backlog-config.json`:
199
+ Read from `.specrails/backlog-config.json`:
200
200
  - `JIRA_BASE_URL`, `JIRA_PROJECT_KEY`, `AUTH_METHOD`
201
201
  - `PROJECT_LABEL` (may be empty string)
202
202
  - `EPIC_MAPPING` (object mapping area name → JIRA epic key)
@@ -262,7 +262,7 @@ For each unique area:
262
262
  If `PROJECT_LABEL` is non-empty, add it to the `labels` array.
263
263
  Set `EPIC_MAPPING[area] = <returned key>`.
264
264
 
265
- After all areas are processed: write the updated `EPIC_MAPPING` back to `.claude/backlog-config.json`.
265
+ After all areas are processed: write the updated `EPIC_MAPPING` back to `.specrails/backlog-config.json`.
266
266
 
267
267
  #### Step E: Create Story tickets
268
268
 
@@ -163,7 +163,7 @@ The product-analyst receives this prompt:
163
163
 
164
164
  #### If provider=local — Cache from Local Tickets
165
165
 
166
- Read `$SPECRAILS_DIR/local-tickets.json` and parse the `tickets` map. For each ticket with `"product-driven-backlog"` in its `labels` array and `status` not `"cancelled"`, build a snapshot object:
166
+ Read `.specrails/local-tickets.json` and parse the `tickets` map. For each ticket with `"product-driven-backlog"` in its `labels` array and `status` not `"cancelled"`, build a snapshot object:
167
167
  - `number`: ticket `id` (integer)
168
168
  - `title`: ticket `title` string
169
169
  - `state`: map ticket `status` — `"done"` or `"cancelled"` → `"closed"`, otherwise → `"open"`
@@ -26,11 +26,11 @@ Check the environment variable `CLAUDE_CODE_ENTRYPOINT`. If it contains `remote_
26
26
 
27
27
  #### 1. Backlog provider availability
28
28
 
29
- Read `.claude/backlog-config.json` and extract `BACKLOG_PROVIDER`.
29
+ Read `.specrails/backlog-config.json` and extract `BACKLOG_PROVIDER`.
30
30
 
31
31
  **If `BACKLOG_PROVIDER=local`:**
32
32
  ```bash
33
- [[ -f "$SPECRAILS_DIR/local-tickets.json" ]] && echo "Local tickets storage: OK" || echo "WARNING: local-tickets.json not found"
33
+ [[ -f ".specrails/local-tickets.json" ]] && echo "Local tickets storage: OK" || echo "WARNING: local-tickets.json not found"
34
34
  ```
35
35
  - Set `LOCAL_TICKETS_AVAILABLE=true/false` based on file existence.
36
36
  - Set `GH_AVAILABLE=false` (GitHub CLI not needed for local provider).
@@ -132,7 +132,7 @@ After fetching issue refs, capture a baseline snapshot for conflict detection.
132
132
 
133
133
  ##### If `BACKLOG_PROVIDER=local` and input mode was issue numbers:
134
134
 
135
- For each resolved ticket ID, read `$SPECRAILS_DIR/local-tickets.json` and extract the ticket object at `tickets["{id}"]`.
135
+ For each resolved ticket ID, read `.specrails/local-tickets.json` and extract the ticket object at `tickets["{id}"]`.
136
136
 
137
137
  Build a snapshot object for each ticket:
138
138
  - `number`: ticket `id` (integer)
@@ -314,7 +314,7 @@ Pick the single idea with the best impact/effort ratio from each exploration. Pr
314
314
 
315
315
  Otherwise, re-fetch each issue in scope and diff against the Phase 0 snapshot:
316
316
 
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.
317
+ **If `BACKLOG_PROVIDER=local`:** 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.
318
318
 
319
319
  **If `BACKLOG_PROVIDER=github`:** For each issue number in `ISSUE_REFS`:
320
320
 
@@ -897,7 +897,7 @@ This check is independent of Phase 3a.0. Even if the user chose to continue thro
897
897
 
898
898
  Re-fetch each issue in `ISSUE_REFS` and diff against `.claude/backlog-cache.json` using the same algorithm as Phase 3a.0:
899
899
 
900
- **If `BACKLOG_PROVIDER=local`:** Read `$SPECRAILS_DIR/local-tickets.json` and extract each ticket by ID.
900
+ **If `BACKLOG_PROVIDER=local`:** Read `.specrails/local-tickets.json` and extract each ticket by ID.
901
901
 
902
902
  **If `BACKLOG_PROVIDER=github`:**
903
903
  ```bash
@@ -47,7 +47,7 @@ Output ONLY the following structured markdown. Do not add any preamble or explan
47
47
 
48
48
  ## Backlog Sync
49
49
 
50
- After generating the proposal, read `.claude/backlog-config.json` to determine `BACKLOG_PROVIDER` and `BACKLOG_WRITE`.
50
+ After generating the proposal, read `.specrails/backlog-config.json` to determine `BACKLOG_PROVIDER` and `BACKLOG_WRITE`.
51
51
 
52
52
  ### If provider=local — Create Local Ticket
53
53
 
@@ -59,7 +59,7 @@ Read the following files to understand the current installation state:
59
59
  Command template files include `implement.md`, `batch-implement.md`, `compat-check.md`, `refactor-recommender.md`, `why.md`, `get-backlog-specs.md`, `auto-propose-backlog-specs.md`.
60
60
  If this directory does not exist, skip command template checking for this update.
61
61
 
62
- 6. Read `$SPECRAILS_DIR/backlog-config.json` if it exists — contains stored provider configuration needed for command placeholder substitution.
62
+ 6. Read `.specrails/backlog-config.json` if it exists — contains stored provider configuration needed for command placeholder substitution.
63
63
 
64
64
  ### Phase U2: Quick Codebase Re-Analysis
65
65
 
@@ -178,7 +178,7 @@ For each command in the "changed commands" list from Phase U3:
178
178
  1. Read the NEW template:
179
179
  - If `cli_provider == "claude"`: from `$SPECRAILS_DIR/setup-templates/commands/specrails/<name>.md`
180
180
  - If `cli_provider == "codex"`: from `$SPECRAILS_DIR/setup-templates/skills/sr-<name>/SKILL.md`
181
- 2. Read stored backlog configuration from `$SPECRAILS_DIR/backlog-config.json` (if it exists) to resolve provider-specific placeholders:
181
+ 2. Read stored backlog configuration from `.specrails/backlog-config.json` (if it exists) to resolve provider-specific placeholders:
182
182
  - `BACKLOG_PROVIDER` → `provider` field (`github`, `jira`, or `none`)
183
183
  - `BACKLOG_WRITE` → `write_access` field
184
184
  - `JIRA_BASE_URL` → `jira_base_url` field
@@ -424,8 +424,8 @@ Core commands (always install if missing):
424
424
  - `auto-propose-backlog-specs.md`
425
425
 
426
426
  **Initialize local ticket storage** (backlog provider defaults to `local`):
427
- 1. Copy `templates/local-tickets-schema.json` to `$SPECRAILS_DIR/local-tickets.json` and set `last_updated` to the current ISO-8601 timestamp. Skip if the file already exists.
428
- 2. Write `$SPECRAILS_DIR/backlog-config.json` (skip if already exists):
427
+ 1. Copy `templates/local-tickets-schema.json` to `.specrails/local-tickets.json` and set `last_updated` to the current ISO-8601 timestamp. Skip if the file already exists.
428
+ 2. Write `.specrails/backlog-config.json` (skip if already exists):
429
429
  ```json
430
430
  {
431
431
  "provider": "local",
@@ -725,10 +725,10 @@ Wait for the user's choice. Set `BACKLOG_PROVIDER` to `local`, `github`, `jira`,
725
725
 
726
726
  No external tools or credentials required. Initialize the storage file:
727
727
 
728
- 1. Copy `templates/local-tickets-schema.json` to `$SPECRAILS_DIR/local-tickets.json`
728
+ 1. Copy `templates/local-tickets-schema.json` to `.specrails/local-tickets.json`
729
729
  2. Set `last_updated` to the current ISO-8601 timestamp
730
730
 
731
- Store configuration in `$SPECRAILS_DIR/backlog-config.json`:
731
+ Store configuration in `.specrails/backlog-config.json`:
732
732
  ```json
733
733
  {
734
734
  "provider": "local",
@@ -774,13 +774,13 @@ Local tickets are always read-write — there is no "read only" mode since the f
774
774
 
775
775
  The `revision` counter in the JSON root enables optimistic concurrency — increment it on **every** write. The lock file prevents concurrent corruption:
776
776
 
777
- 1. **Acquire lock:** Check for `$SPECRAILS_DIR/local-tickets.json.lock`
777
+ 1. **Acquire lock:** Check for `.specrails/local-tickets.json.lock`
778
778
  - If the file exists and its `timestamp` is less than 30 seconds old: wait 500ms and retry (max 5 attempts before aborting with an error)
779
779
  - If the file exists and its `timestamp` is 30+ seconds old (stale): delete it and proceed
780
780
  - If no lock file exists: proceed immediately
781
- 2. **Create lock file:** Write `{"agent": "<agent-name-or-process>", "timestamp": "<ISO-8601>"}` to `$SPECRAILS_DIR/local-tickets.json.lock`
781
+ 2. **Create lock file:** Write `{"agent": "<agent-name-or-process>", "timestamp": "<ISO-8601>"}` to `.specrails/local-tickets.json.lock`
782
782
  3. **Minimal lock window:** Read the JSON → modify in memory → write back → release
783
- 4. **Release lock:** Delete `$SPECRAILS_DIR/local-tickets.json.lock`
783
+ 4. **Release lock:** Delete `.specrails/local-tickets.json.lock`
784
784
  5. **Always increment `revision`** by 1 and update `last_updated` on every successful write
785
785
 
786
786
  The hub server uses `proper-lockfile` (or equivalent) to honor the same protocol via the `.lock` file path.
@@ -1147,22 +1147,22 @@ When adapting `auto-propose-backlog-specs.md` and `get-backlog-specs.md`, substi
1147
1147
 
1148
1148
  #### Local Tickets (`BACKLOG_PROVIDER=local`)
1149
1149
 
1150
- For the local provider, backlog placeholders resolve to **inline file-operation instructions** embedded in the generated command markdown — not shell commands. Agents execute these by reading/writing `$SPECRAILS_DIR/local-tickets.json` directly using their file tools.
1150
+ For the local provider, backlog placeholders resolve to **inline file-operation instructions** embedded in the generated command markdown — not shell commands. Agents execute these by reading/writing `.specrails/local-tickets.json` directly using their file tools.
1151
1151
 
1152
1152
  All write operations must follow the **advisory file locking protocol** defined in Phase 3.2. Always increment `revision` and update `last_updated` on every write.
1153
1153
 
1154
1154
  | Placeholder | Substituted value |
1155
1155
  |-------------|-------------------|
1156
1156
  | `{{BACKLOG_PROVIDER_NAME}}` | `Local Tickets` |
1157
- | `{{BACKLOG_PREFLIGHT}}` | `[[ -f "$SPECRAILS_DIR/local-tickets.json" ]] && echo "Local tickets storage: OK" \|\| echo "WARNING: $SPECRAILS_DIR/local-tickets.json not found — run /specrails:setup to initialize"` |
1158
- | `{{BACKLOG_FETCH_CMD}}` | Read `$SPECRAILS_DIR/local-tickets.json`. Parse the `tickets` map and return all entries where `status` is `"todo"` or `"in_progress"`. |
1159
- | `{{BACKLOG_FETCH_ALL_CMD}}` | Read `$SPECRAILS_DIR/local-tickets.json`. Parse the `tickets` map and return all entries regardless of status. |
1160
- | `{{BACKLOG_FETCH_CLOSED_CMD}}` | Read `$SPECRAILS_DIR/local-tickets.json`. Parse the `tickets` map and return all entries where `status` is `"done"` or `"cancelled"`. |
1161
- | `{{BACKLOG_VIEW_CMD}}` | Read `$SPECRAILS_DIR/local-tickets.json`. Parse JSON and return the full ticket object at `tickets["{id}"]`, or an error if not found. |
1162
- | `{{BACKLOG_CREATE_CMD}}` | Write to `$SPECRAILS_DIR/local-tickets.json` using the advisory locking protocol: acquire lock → read file → set `id = next_id`, increment `next_id`, set all ticket fields, set `created_at` and `updated_at` to now, bump `revision`, update `last_updated` → write → release lock. |
1163
- | `{{BACKLOG_UPDATE_CMD}}` | Write to `$SPECRAILS_DIR/local-tickets.json` using the advisory locking protocol: acquire lock → read file → update fields in `tickets["{id}"]`, set `updated_at` to now, bump `revision`, update `last_updated` → write → release lock. |
1164
- | `{{BACKLOG_DELETE_CMD}}` | Write to `$SPECRAILS_DIR/local-tickets.json` using the advisory locking protocol: acquire lock → read file → delete `tickets["{id}"]`, bump `revision`, update `last_updated` → write → release lock. |
1165
- | `{{BACKLOG_COMMENT_CMD}}` | Write to `$SPECRAILS_DIR/local-tickets.json` using the advisory locking protocol: acquire lock → read file → append `{"author": "<agent-name>", "body": "<comment>", "created_at": "<ISO-8601>"}` to `tickets["{id}"].comments` (create the array if absent), set `updated_at` to now, bump `revision`, update `last_updated` → write → release lock. |
1157
+ | `{{BACKLOG_PREFLIGHT}}` | `[[ -f ".specrails/local-tickets.json" ]] && echo "Local tickets storage: OK" \|\| echo "WARNING: .specrails/local-tickets.json not found — run /specrails:setup to initialize"` |
1158
+ | `{{BACKLOG_FETCH_CMD}}` | Read `.specrails/local-tickets.json`. Parse the `tickets` map and return all entries where `status` is `"todo"` or `"in_progress"`. |
1159
+ | `{{BACKLOG_FETCH_ALL_CMD}}` | Read `.specrails/local-tickets.json`. Parse the `tickets` map and return all entries regardless of status. |
1160
+ | `{{BACKLOG_FETCH_CLOSED_CMD}}` | Read `.specrails/local-tickets.json`. Parse the `tickets` map and return all entries where `status` is `"done"` or `"cancelled"`. |
1161
+ | `{{BACKLOG_VIEW_CMD}}` | Read `.specrails/local-tickets.json`. Parse JSON and return the full ticket object at `tickets["{id}"]`, or an error if not found. |
1162
+ | `{{BACKLOG_CREATE_CMD}}` | Write to `.specrails/local-tickets.json` using the advisory locking protocol: acquire lock → read file → set `id = next_id`, increment `next_id`, set all ticket fields, set `created_at` and `updated_at` to now, bump `revision`, update `last_updated` → write → release lock. |
1163
+ | `{{BACKLOG_UPDATE_CMD}}` | Write to `.specrails/local-tickets.json` using the advisory locking protocol: acquire lock → read file → update fields in `tickets["{id}"]`, set `updated_at` to now, bump `revision`, update `last_updated` → write → release lock. |
1164
+ | `{{BACKLOG_DELETE_CMD}}` | Write to `.specrails/local-tickets.json` using the advisory locking protocol: acquire lock → read file → delete `tickets["{id}"]`, bump `revision`, update `last_updated` → write → release lock. |
1165
+ | `{{BACKLOG_COMMENT_CMD}}` | Write to `.specrails/local-tickets.json` using the advisory locking protocol: acquire lock → read file → append `{"author": "<agent-name>", "body": "<comment>", "created_at": "<ISO-8601>"}` to `tickets["{id}"].comments` (create the array if absent), set `updated_at` to now, bump `revision`, update `last_updated` → write → release lock. |
1166
1166
  | `{{BACKLOG_PARTIAL_COMMENT_CMD}}` | Same as `{{BACKLOG_COMMENT_CMD}}` but append `{"author": "<agent-name>", "body": "<comment>", "type": "progress", "created_at": "<ISO-8601>"}`. |
1167
1167
  | `{{BACKLOG_INIT_LABELS_CMD}}` | No label initialization required. Local tickets use freeform label strings. Standard label conventions: `area:frontend`, `area:backend`, `area:api`, `effort:low`, `effort:medium`, `effort:high`. |
1168
1168
 
@@ -1183,7 +1183,7 @@ All write operations must follow the **advisory file locking protocol** defined
1183
1183
  - Issue view: `jira issue view {key}` or REST API
1184
1184
  - VPC scores stored in the issue description body (same markdown format, parsed from description)
1185
1185
  - Pre-flight check: `jira me` or test API connectivity
1186
- - Store JIRA config in `$SPECRAILS_DIR/backlog-config.json`:
1186
+ - Store JIRA config in `.specrails/backlog-config.json`:
1187
1187
  ```json
1188
1188
  {
1189
1189
  "provider": "jira",
@@ -70,7 +70,7 @@ After the Explore agent completes:
70
70
 
71
71
  1. **Display** results to the user.
72
72
 
73
- 2. Read `.claude/backlog-config.json` and extract:
73
+ 2. Read `.specrails/backlog-config.json` and extract:
74
74
  - `BACKLOG_PROVIDER` (`github`, `jira`, or `none`)
75
75
  - `BACKLOG_WRITE` (from `write_access`)
76
76
 
@@ -159,7 +159,7 @@ After the Explore agent completes:
159
159
 
160
160
  ### If provider=jira and BACKLOG_WRITE=true — Sync to JIRA
161
161
 
162
- Read from `.claude/backlog-config.json`:
162
+ Read from `.specrails/backlog-config.json`:
163
163
  - `JIRA_BASE_URL`, `JIRA_PROJECT_KEY`, `AUTH_METHOD`
164
164
  - `PROJECT_LABEL` (may be empty string)
165
165
  - `EPIC_MAPPING` (object mapping area name → JIRA epic key)
@@ -225,7 +225,7 @@ For each unique area:
225
225
  If `PROJECT_LABEL` is non-empty, add it to the `labels` array.
226
226
  Set `EPIC_MAPPING[area] = <returned key>`.
227
227
 
228
- After all areas are processed: write the updated `EPIC_MAPPING` back to `.claude/backlog-config.json`.
228
+ After all areas are processed: write the updated `EPIC_MAPPING` back to `.specrails/backlog-config.json`.
229
229
 
230
230
  #### Step E: Create Story tickets
231
231