specrails-core 1.1.0 → 1.2.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 +42 -1
- package/package.json +1 -1
- package/templates/commands/sr/health-check.md +135 -4
package/README.md
CHANGED
|
@@ -74,7 +74,23 @@ Claude runs a 5-phase wizard that reads your actual codebase and generates every
|
|
|
74
74
|
|
|
75
75
|
---
|
|
76
76
|
|
|
77
|
-
##
|
|
77
|
+
## Why SpecRails
|
|
78
|
+
|
|
79
|
+
| | SpecRails | Plain Claude Code | Cursor / Copilot |
|
|
80
|
+
|---|---|---|---|
|
|
81
|
+
| Structured pipeline | ✅ Architect → Dev → Review → PR | ❌ Manual | ❌ Manual |
|
|
82
|
+
| Adapts to your codebase | ✅ Reads your actual stack/CI | ⚠️ Prompts only | ❌ |
|
|
83
|
+
| Product-driven backlog | ✅ VPC persona scoring | ❌ | ❌ |
|
|
84
|
+
| Parallel feature builds | ✅ Git worktrees | ❌ | ❌ |
|
|
85
|
+
| Dry-run / preview mode | ✅ Preview before committing | ❌ | ❌ |
|
|
86
|
+
| Institutional memory | ✅ Agents learn across sessions | ❌ | ❌ |
|
|
87
|
+
| Open source | ✅ MIT | N/A | ❌ |
|
|
88
|
+
|
|
89
|
+
SpecRails is not a chat interface. It's a **development pipeline** that coordinates multiple specialized agents through your existing tools (GitHub Issues, JIRA, git, CI).
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## The agents
|
|
78
94
|
|
|
79
95
|
| Agent | Model | Role |
|
|
80
96
|
|-------|-------|------|
|
|
@@ -110,6 +126,31 @@ Reads GitHub Issues labeled `product-driven-backlog`, scores them against your V
|
|
|
110
126
|
|
|
111
127
|
Analyzes your codebase against each persona's jobs/pains/gains, generates new feature ideas, and creates GitHub Issues for the best ones.
|
|
112
128
|
|
|
129
|
+
#### Dry-run / preview mode
|
|
130
|
+
|
|
131
|
+
Not ready to commit? Run the full pipeline without touching git or GitHub:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
/sr:implement "add dark mode" --dry-run
|
|
135
|
+
/sr:implement #85 --preview # --preview is an alias for --dry-run
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
All agents run normally (architect, developer, tests, docs, review). Generated files land in `.claude/.dry-run/<feature-name>/` instead of your working tree. No branches, commits, PRs, or issue updates are created.
|
|
139
|
+
|
|
140
|
+
When you're happy with the preview, apply the cached output:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
/sr:implement --apply add-dark-mode # copies files to real paths, then ships
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
To discard without applying:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
rm -rf .claude/.dry-run/add-dark-mode/
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### `/sr:product-backlog` — View prioritized backlog
|
|
153
|
+
|
|
113
154
|
```
|
|
114
155
|
/sr:update-product-driven-backlog # explore all areas
|
|
115
156
|
/sr:update-product-driven-backlog Analytics # focus on one area
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "specrails-core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.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"
|
|
@@ -9,7 +9,7 @@ Run a full health check for **{{PROJECT_NAME}}**: detect available tools, execut
|
|
|
9
9
|
|
|
10
10
|
**Input:** $ARGUMENTS — optional flags:
|
|
11
11
|
- `--since <date>` — use the report from this date (ISO format: YYYY-MM-DD) as the comparison baseline instead of the most recent
|
|
12
|
-
- `--only <checks>` — comma-separated subset to run. Valid values: `tests`, `coverage`, `lint`, `complexity`, `deps`, `perf`
|
|
12
|
+
- `--only <checks>` — comma-separated subset to run. Valid values: `tests`, `coverage`, `lint`, `complexity`, `deps`, `perf`, `static`
|
|
13
13
|
- `--save` — always save the snapshot even when `--only` is used (default: skip save for partial runs)
|
|
14
14
|
|
|
15
15
|
---
|
|
@@ -29,8 +29,8 @@ Parse `$ARGUMENTS` to set runtime variables.
|
|
|
29
29
|
1. Scan `$ARGUMENTS` for `--since <date>`. If found, set `COMPARE_DATE=<date>`. Strip from arguments.
|
|
30
30
|
2. Scan for `--only <checks>`. If found:
|
|
31
31
|
- Split `<checks>` on commas to produce an array.
|
|
32
|
-
- Validate each entry against the allowed set: `tests`, `coverage`, `lint`, `complexity`, `deps`, `perf`.
|
|
33
|
-
- If any unknown value is found: print `Error: unknown check "<value>". Valid checks: tests, coverage, lint, complexity, deps, perf` and stop.
|
|
32
|
+
- Validate each entry against the allowed set: `tests`, `coverage`, `lint`, `complexity`, `deps`, `perf`, `static`.
|
|
33
|
+
- If any unknown value is found: print `Error: unknown check "<value>". Valid checks: tests, coverage, lint, complexity, deps, perf, static` and stop.
|
|
34
34
|
- Set `CHECKS_FILTER=<validated-array>`.
|
|
35
35
|
- Set `SAVE_SNAPSHOT=false` (partial run — snapshot may be incomplete).
|
|
36
36
|
3. Scan for `--save`. If found, set `SAVE_SNAPSHOT=true` regardless of `CHECKS_FILTER`.
|
|
@@ -38,7 +38,7 @@ Parse `$ARGUMENTS` to set runtime variables.
|
|
|
38
38
|
**Print active configuration:**
|
|
39
39
|
|
|
40
40
|
```
|
|
41
|
-
Running checks: <all | comma-separated list> | Comparing to: <COMPARE_DATE or "latest">
|
|
41
|
+
Running checks: <all | comma-separated list> | Static analysis: <enabled|disabled> | Comparing to: <COMPARE_DATE or "latest">
|
|
42
42
|
```
|
|
43
43
|
|
|
44
44
|
---
|
|
@@ -79,8 +79,11 @@ For each category, set two variables:
|
|
|
79
79
|
| complexity | yes/no | <tool or N/A> |
|
|
80
80
|
| deps | yes/no | <tool or N/A> |
|
|
81
81
|
| perf | yes/no | <tool or N/A> |
|
|
82
|
+
| static | yes | ai-analysis |
|
|
82
83
|
```
|
|
83
84
|
|
|
85
|
+
The `static` check is always available (AI-assisted analysis requires no external tools).
|
|
86
|
+
|
|
84
87
|
---
|
|
85
88
|
|
|
86
89
|
## Phase 2: Load Previous Report
|
|
@@ -248,6 +251,99 @@ perf: <PASS|FAIL|SKIPPED> (<tool>)
|
|
|
248
251
|
|
|
249
252
|
---
|
|
250
253
|
|
|
254
|
+
## Phase 3.5: Static Code Analysis
|
|
255
|
+
|
|
256
|
+
Perform static code inspection to detect issues that tools cannot surface: missing documentation, broken imports, and unused exports. These checks are language-aware and use AI-assisted code reading rather than external tooling.
|
|
257
|
+
|
|
258
|
+
Always exclude the following directories from analysis:
|
|
259
|
+
- `node_modules/`, `.git/`, `dist/`, `build/`, `vendor/`, `.claude/`, `coverage/`
|
|
260
|
+
|
|
261
|
+
For each finding, record a structured object:
|
|
262
|
+
```
|
|
263
|
+
{ severity: "critical"|"warning"|"info", check: string, file: string, line: number, description: string, action: string }
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
Set `STATIC_FINDINGS = []` before starting. Append each finding to this list.
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
### Check: documentation
|
|
271
|
+
|
|
272
|
+
Scan public-facing code units (exported functions, classes, interfaces, modules) for missing documentation comments.
|
|
273
|
+
|
|
274
|
+
**Language-specific rules:**
|
|
275
|
+
|
|
276
|
+
- **TypeScript/JavaScript**: Identify functions/classes with `export` keyword. Check whether a JSDoc block (`/** ... */`) appears immediately above the declaration. Missing JSDoc on exported symbols = finding.
|
|
277
|
+
- **Python**: Identify top-level functions, classes, and methods. Check for a docstring (a string literal as the first statement in the body). Missing docstring on public (non-underscore-prefixed) symbols = finding.
|
|
278
|
+
- **Ruby**: Identify public methods and classes. Check for a YARD/RDoc comment (`# @param`, `##`, or any comment block) immediately above the definition. Missing comment on public methods in lib/ = finding.
|
|
279
|
+
- **Go**: Identify exported types and functions (capitalized names). Check for a doc comment (line starting with `// <ExportedName>`) immediately above. Missing comment on exported symbols = finding.
|
|
280
|
+
|
|
281
|
+
**Severity assignment:**
|
|
282
|
+
- `critical`: Main entry points (e.g., `index.ts`, `main.go`, `app.rb`) with no module-level documentation
|
|
283
|
+
- `warning`: Exported/public function or class with no documentation
|
|
284
|
+
- `info`: Non-exported function over 20 lines with no documentation
|
|
285
|
+
|
|
286
|
+
Scan all source files matching the detected language(s). Skip test files (`*.test.*`, `*.spec.*`, `_test.go`, `spec/**`).
|
|
287
|
+
|
|
288
|
+
Append each finding to `STATIC_FINDINGS`.
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
### Check: broken_imports
|
|
293
|
+
|
|
294
|
+
Detect import/require statements that reference non-existent paths. Focus on local relative imports (skip `node_modules`, stdlib, installed packages — these are validated by the runtime).
|
|
295
|
+
|
|
296
|
+
**Language-specific rules:**
|
|
297
|
+
|
|
298
|
+
- **TypeScript/JavaScript**: Scan all `import ... from '...'` and `require('...')` statements. For each import path starting with `.` or `/`:
|
|
299
|
+
1. Resolve the path relative to the source file.
|
|
300
|
+
2. Check whether the resolved file exists (try: exact path, `.ts`, `.tsx`, `.js`, `.jsx`, `/index.ts`, `/index.js`).
|
|
301
|
+
3. If no match found: add a `critical` finding.
|
|
302
|
+
- **Python**: Scan all `from . import`, `from .. import`, and `import X` with relative markers. Resolve relative paths from the package root. If the resolved module file does not exist: add a `critical` finding.
|
|
303
|
+
- **Ruby**: Scan `require_relative '...'` statements. Resolve paths from the source file's directory (try `.rb` extension if missing). If the resolved path does not exist: add a `critical` finding.
|
|
304
|
+
- **Go**: Skip — Go's compiler validates imports; broken imports would fail the build.
|
|
305
|
+
|
|
306
|
+
**Severity:** Always `critical` — a broken import is a runtime error.
|
|
307
|
+
|
|
308
|
+
Append each finding to `STATIC_FINDINGS`.
|
|
309
|
+
|
|
310
|
+
---
|
|
311
|
+
|
|
312
|
+
### Check: unused_exports
|
|
313
|
+
|
|
314
|
+
Detect exported symbols that are never imported anywhere else in the codebase. Limit to the project source — do not flag exports intended as a library's public API (i.e., symbols re-exported from a barrel file like `index.ts`).
|
|
315
|
+
|
|
316
|
+
**Language-specific rules:**
|
|
317
|
+
|
|
318
|
+
- **TypeScript/JavaScript**:
|
|
319
|
+
1. Build a list of all exported symbols: scan `export const`, `export function`, `export class`, `export type`, `export interface`, `export default` across all non-test `.ts`/`.tsx`/`.js` files.
|
|
320
|
+
2. For each exported symbol, search the rest of the codebase for imports of that symbol by name. Exclude the barrel/index file itself.
|
|
321
|
+
3. If no import found anywhere: add a finding with severity `warning` (may be an intentional API export) unless the file is not `index.ts` and not under `src/` root — in that case severity is `info`.
|
|
322
|
+
- **Python**:
|
|
323
|
+
1. Scan for symbols listed in `__all__` or public top-level definitions (non-underscore).
|
|
324
|
+
2. Search for usages across the codebase. If the symbol appears only in its definition file: add a `info` finding.
|
|
325
|
+
- **Ruby**:
|
|
326
|
+
1. Scan for public constants, classes, and modules defined in `lib/`. Search for `require` or direct references elsewhere. If a class/module in `lib/` is never referenced outside its own file: add a `warning` finding.
|
|
327
|
+
|
|
328
|
+
**Severity:** `warning` for clearly unexported contexts; `info` when the symbol could be part of a public API.
|
|
329
|
+
|
|
330
|
+
Append each finding to `STATIC_FINDINGS`.
|
|
331
|
+
|
|
332
|
+
---
|
|
333
|
+
|
|
334
|
+
### Phase 3.5 summary
|
|
335
|
+
|
|
336
|
+
After all three static checks complete, print:
|
|
337
|
+
|
|
338
|
+
```
|
|
339
|
+
documentation: <N findings> (<N critical, N warning, N info>)
|
|
340
|
+
broken_imports: <N findings> (<N critical>)
|
|
341
|
+
unused_exports: <N findings> (<N warning, N info>)
|
|
342
|
+
Static findings total: <N>
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
251
347
|
## Phase 4: Build Health Report
|
|
252
348
|
|
|
253
349
|
Using all `RESULT_<CHECK>` values and `PREV_REPORT` (if `IS_FIRST_RUN=false`), compute the final health report object.
|
|
@@ -315,6 +411,7 @@ HEALTH_REPORT = {
|
|
|
315
411
|
deps: { status, tool, metrics: { vuln_critical, vuln_high, vuln_moderate, vuln_low, vuln_total } },
|
|
316
412
|
perf: { status, tool, metrics: { perf_p50_ms, perf_p95_ms, perf_p99_ms, perf_custom } }
|
|
317
413
|
},
|
|
414
|
+
static_findings: <STATIC_FINDINGS array — each: { severity, check, file, line, description, action }>,
|
|
318
415
|
grade: <"A"|"B"|"C"|"D"|"F">,
|
|
319
416
|
regressions: <REGRESSIONS array>,
|
|
320
417
|
comparison_report: <PREV_REPORT_PATH basename or null>
|
|
@@ -364,6 +461,40 @@ Regressions detected: N
|
|
|
364
461
|
- <check>: <metric> changed from X to Y (<delta>)
|
|
365
462
|
<if N == 0:>
|
|
366
463
|
No regressions detected.
|
|
464
|
+
|
|
465
|
+
---
|
|
466
|
+
|
|
467
|
+
### Static Analysis Findings [<N total: N critical, N warning, N info>]
|
|
468
|
+
|
|
469
|
+
<if STATIC_FINDINGS is empty:>
|
|
470
|
+
No static findings detected.
|
|
471
|
+
|
|
472
|
+
<if STATIC_FINDINGS is non-empty:>
|
|
473
|
+
|
|
474
|
+
| Severity | Check | File | Line | Finding | Action |
|
|
475
|
+
|----------|-------|------|------|---------|--------|
|
|
476
|
+
<for each finding in STATIC_FINDINGS, sorted by severity (critical first, then warning, then info):>
|
|
477
|
+
| <CRITICAL|WARNING|INFO> | <check> | <file> | <line> | <description> | <action> |
|
|
478
|
+
|
|
479
|
+
<if any critical findings:>
|
|
480
|
+
#### Critical Findings (require immediate attention)
|
|
481
|
+
<for each critical finding:>
|
|
482
|
+
**[CRITICAL] <check>** — `<file>:<line>`
|
|
483
|
+
> <description>
|
|
484
|
+
> **Action:** <action>
|
|
485
|
+
|
|
486
|
+
<if any warning findings (limit to top 5 by file breadth — prefer findings spread across more files):>
|
|
487
|
+
#### Warnings (recommended fixes)
|
|
488
|
+
<for each warning finding, up to 5:>
|
|
489
|
+
**[WARNING] <check>** — `<file>:<line>`
|
|
490
|
+
> <description>
|
|
491
|
+
> **Action:** <action>
|
|
492
|
+
<if more than 5 warning findings:>
|
|
493
|
+
> ... and N more warnings. Run with `--only static` to see all.
|
|
494
|
+
|
|
495
|
+
<if any info findings:>
|
|
496
|
+
#### Info (low-priority improvements)
|
|
497
|
+
Summary: N info-level findings across N files. Run with `--only static` to see full list.
|
|
367
498
|
```
|
|
368
499
|
|
|
369
500
|
For delta display: wrap positive deltas on error/failure metrics in `(+N)` to indicate regression; wrap negative deltas on pass-rate/coverage in `(-N%)` styled as improvement. For terminal rendering, use plain notation — the sign alone conveys direction.
|