specrails-core 3.8.1 → 4.0.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/install.sh CHANGED
@@ -127,7 +127,8 @@ if [[ -n "$CUSTOM_ROOT_DIR" ]]; then
127
127
  fi
128
128
 
129
129
  # Detect if running from within the specrails source repo itself
130
- if [[ -z "$CUSTOM_ROOT_DIR" && -f "$SCRIPT_DIR/install.sh" && -d "$SCRIPT_DIR/templates" && "$SCRIPT_DIR" == "$REPO_ROOT"* ]]; then
130
+ # Note: REPO_ROOT must be non-empty for the glob match when empty, * matches everything.
131
+ if [[ -z "$CUSTOM_ROOT_DIR" && -n "$REPO_ROOT" && -f "$SCRIPT_DIR/install.sh" && -d "$SCRIPT_DIR/templates" && "$SCRIPT_DIR" == "$REPO_ROOT"* ]]; then
131
132
  # We're inside the specrails source — ask for target repo
132
133
  echo ""
133
134
  echo -e "${YELLOW}⚠${NC} You're running the installer from inside the specrails source repo."
@@ -144,11 +145,24 @@ if [[ -z "$CUSTOM_ROOT_DIR" && -f "$SCRIPT_DIR/install.sh" && -d "$SCRIPT_DIR/te
144
145
  echo "Error: path does not exist or is not accessible: $TARGET_PATH" >&2
145
146
  exit 1
146
147
  }
147
- if [[ ! -d "$REPO_ROOT/.git" ]]; then
148
- echo -e "${YELLOW}⚠${NC} Warning: $REPO_ROOT does not appear to be a git repository."
149
- if [ "$AUTO_YES" = true ]; then CONTINUE_NOGIT="y"; else read -p " Continue anyway? (y/n): " CONTINUE_NOGIT; fi
150
- if [[ "$CONTINUE_NOGIT" != "y" && "$CONTINUE_NOGIT" != "Y" ]]; then
151
- echo " Aborted. No changes made."
148
+ fi
149
+
150
+ # Auto-init git if the target directory is not a git repository
151
+ if [[ -z "$REPO_ROOT" || ! -d "$REPO_ROOT/.git" ]]; then
152
+ # Resolve REPO_ROOT to cwd if still empty (no git found anywhere)
153
+ if [[ -z "$REPO_ROOT" ]]; then
154
+ REPO_ROOT="$(pwd)"
155
+ fi
156
+ if [[ "$AUTO_YES" == true ]]; then
157
+ git -C "$REPO_ROOT" init -q 2>/dev/null
158
+ else
159
+ echo ""
160
+ echo -e "${YELLOW}⚠${NC} ${REPO_ROOT} is not a git repository."
161
+ read -p " Initialize git? (y/n): " INIT_GIT || INIT_GIT="n"
162
+ if [[ "$INIT_GIT" == "y" || "$INIT_GIT" == "Y" ]]; then
163
+ git -C "$REPO_ROOT" init -q 2>/dev/null
164
+ else
165
+ echo " Aborted. specrails requires a git repository."
152
166
  exit 0
153
167
  fi
154
168
  fi
@@ -229,9 +243,9 @@ print_header
229
243
 
230
244
  step "Phase 1: Checking prerequisites"
231
245
 
232
- # 1.1 Git repository
246
+ # 1.1 Git repository (should be resolved by now — early init or --root-dir)
233
247
  if [[ -z "$REPO_ROOT" ]]; then
234
- fail "Not inside a git repository and no --root-dir provided."
248
+ fail "Could not determine target directory."
235
249
  echo " Usage: install.sh [--root-dir <path>]"
236
250
  exit 1
237
251
  fi
@@ -502,6 +516,16 @@ else
502
516
  fi
503
517
 
504
518
  # 1.5 OpenSpec CLI
519
+ # Read pinned version from package.json (specrails.openspecVersion field)
520
+ _openspec_pkg_version=""
521
+ if [[ -f "$SCRIPT_DIR/package.json" ]]; then
522
+ _openspec_pkg_version=$(python3 -c "import json; d=json.load(open('$SCRIPT_DIR/package.json')); print(d.get('specrails',{}).get('openspecVersion',''))" 2>/dev/null || true)
523
+ fi
524
+ _openspec_install_spec="@openspec/cli"
525
+ if [[ -n "$_openspec_pkg_version" ]]; then
526
+ _openspec_install_spec="@openspec/cli@${_openspec_pkg_version}"
527
+ fi
528
+
505
529
  if command -v openspec &> /dev/null; then
506
530
  OPENSPEC_VERSION=$(openspec --version 2>/dev/null || echo "unknown")
507
531
  ok "OpenSpec CLI: $OPENSPEC_VERSION"
@@ -510,17 +534,21 @@ elif [ -f "$REPO_ROOT/node_modules/.bin/openspec" ]; then
510
534
  ok "OpenSpec CLI: found in node_modules"
511
535
  HAS_OPENSPEC=true
512
536
  else
513
- warn "OpenSpec CLI not found."
514
537
  if [ "$HAS_NPM" = true ]; then
515
- if [ "$AUTO_YES" = true ]; then INSTALL_OPENSPEC="y"; else read -p " Install OpenSpec CLI globally? (y/n): " INSTALL_OPENSPEC || INSTALL_OPENSPEC="n"; fi
538
+ # Auto-install in --yes mode; ask otherwise
539
+ if [ "$AUTO_YES" = true ]; then
540
+ INSTALL_OPENSPEC="y"
541
+ else
542
+ read -p " OpenSpec CLI not found. Install ${_openspec_install_spec}? (y/n): " INSTALL_OPENSPEC || INSTALL_OPENSPEC="n"
543
+ fi
516
544
  if [ "$INSTALL_OPENSPEC" = "y" ] || [ "$INSTALL_OPENSPEC" = "Y" ]; then
517
- info "Installing OpenSpec CLI..."
518
- npm install -g @openspec/cli 2>/dev/null && {
519
- ok "OpenSpec CLI installed"
545
+ info "Installing ${_openspec_install_spec}..."
546
+ npm install -g "${_openspec_install_spec}" 2>/dev/null && {
547
+ ok "OpenSpec CLI installed ($(openspec --version 2>/dev/null || echo "${_openspec_pkg_version}"))"
520
548
  HAS_OPENSPEC=true
521
549
  } || {
522
550
  warn "Global install failed. Trying local..."
523
- cd "$REPO_ROOT" && npm install @openspec/cli 2>/dev/null && {
551
+ cd "$REPO_ROOT" && npm install "${_openspec_install_spec}" 2>/dev/null && {
524
552
  ok "OpenSpec CLI installed locally"
525
553
  HAS_OPENSPEC=true
526
554
  } || {
@@ -633,7 +661,7 @@ fi
633
661
  step "Phase 3: Installing specrails artifacts"
634
662
 
635
663
  # Create directory structure
636
- mkdir -p "$REPO_ROOT/specrails"
664
+ mkdir -p "$REPO_ROOT/$SPECRAILS_DIR"
637
665
  if [[ "$CLI_PROVIDER" == "codex" ]]; then
638
666
  # Codex: install as Agent Skills (Codex doesn't support .codex/commands/)
639
667
  mkdir -p "$REPO_ROOT/.agents/skills/enrich"
@@ -648,8 +676,15 @@ mkdir -p "$REPO_ROOT/.specrails/setup-templates/rules"
648
676
  mkdir -p "$REPO_ROOT/.specrails/setup-templates/personas"
649
677
  mkdir -p "$REPO_ROOT/.specrails/setup-templates/claude-md"
650
678
  mkdir -p "$REPO_ROOT/.specrails/setup-templates/settings"
651
- mkdir -p "$REPO_ROOT/.specrails/setup-templates/prompts"
652
- mkdir -p "$REPO_ROOT/$SPECRAILS_DIR/agent-memory/explanations"
679
+
680
+ # Ensure .gitignore excludes local runtime artifacts
681
+ _gitignore="${REPO_ROOT}/.gitignore"
682
+ _gitignore_entries=(".claude/agent-memory/" ".specrails/")
683
+ for _entry in "${_gitignore_entries[@]}"; do
684
+ if ! grep -qF "$_entry" "$_gitignore" 2>/dev/null; then
685
+ echo "$_entry" >> "$_gitignore"
686
+ fi
687
+ done
653
688
 
654
689
  # Copy the /specrails:enrich and /specrails:doctor commands (or skills for Codex)
655
690
  if [[ "$CLI_PROVIDER" == "codex" ]]; then
@@ -722,9 +757,6 @@ models:
722
757
  preset: balanced
723
758
  defaults: { model: sonnet }
724
759
  overrides: {}
725
- quick_context:
726
- product_description: ""
727
- target_users: ""
728
760
  agent_teams: ${_ic_agent_teams}
729
761
  YAML
730
762
  ok "Written .specrails/install-config.yaml (defaults)"
@@ -744,11 +776,19 @@ if [[ "$FROM_CONFIG" == true ]]; then
744
776
  # Parse selected agents from inline YAML list: selected: [sr-architect, sr-developer, ...]
745
777
  _selected_raw=$(grep '^ selected:' "$_cfg_to_read" | sed 's/.*\[//;s/\].*//;s/,/ /g' || true)
746
778
  if [[ -n "$_selected_raw" ]]; then
779
+ # Core agents are always kept — the pipeline depends on them
780
+ _core_agents="sr-architect sr-developer sr-reviewer sr-merge-resolver"
747
781
  _agents_dir="${REPO_ROOT}/.specrails/setup-templates/agents"
748
782
  _removed=0
749
783
  for _agent_file in "$_agents_dir/"*.md; do
750
784
  [[ -f "$_agent_file" ]] || continue
751
785
  _agent_name="$(basename "$_agent_file" .md)"
786
+
787
+ # Never remove core agents
788
+ if echo " $_core_agents " | grep -q " ${_agent_name} "; then
789
+ continue
790
+ fi
791
+
752
792
  _in_selected=false
753
793
  for _sel in $_selected_raw; do
754
794
  # Strip whitespace/commas from parsed token
@@ -851,11 +891,6 @@ if [ ! -f "${REPO_ROOT}/$SPECRAILS_DIR/security-exemptions.yaml" ]; then
851
891
  ok "Created $SPECRAILS_DIR/security-exemptions.yaml"
852
892
  fi
853
893
 
854
- # Copy prompts
855
- if [ -d "$SCRIPT_DIR/prompts" ] && [ "$(ls -A "$SCRIPT_DIR/prompts" 2>/dev/null)" ]; then
856
- cp -r "$SCRIPT_DIR/prompts/"* "$REPO_ROOT/.specrails/setup-templates/prompts/"
857
- ok "Installed prompts"
858
- fi
859
894
 
860
895
  # ─────────────────────────────────────────────
861
896
  # Phase 3c: Quick-tier direct placement
@@ -869,15 +904,6 @@ if [[ "$TIER" == "quick" ]]; then
869
904
 
870
905
  _templates="${REPO_ROOT}/.specrails/setup-templates"
871
906
  _project_name="$(basename "$REPO_ROOT")"
872
- _quick_product_desc=""
873
- _quick_target_users=""
874
-
875
- # Read quick_context from install-config.yaml if available
876
- _qc_file="${CONFIG_PATH:-${REPO_ROOT}/.specrails/install-config.yaml}"
877
- if [[ -f "$_qc_file" ]]; then
878
- _quick_product_desc=$(grep '^\s*product_description:' "$_qc_file" 2>/dev/null | head -1 | sed 's/.*product_description:[[:space:]]*//' | sed 's/^"//;s/"$//' || true)
879
- _quick_target_users=$(grep '^\s*target_users:' "$_qc_file" 2>/dev/null | head -1 | sed 's/.*target_users:[[:space:]]*//' | sed 's/^"//;s/"$//' || true)
880
- fi
881
907
 
882
908
  # VPC/persona-dependent agents are excluded from Quick tier (require enrichment)
883
909
  _quick_excluded_agents="sr-product-manager sr-product-analyst"
@@ -903,8 +929,6 @@ if [[ "$TIER" == "quick" ]]; then
903
929
  # Substitute known placeholders
904
930
  sed -i.bak \
905
931
  -e "s|{{PROJECT_NAME}}|${_project_name}|g" \
906
- -e "s|{{PROJECT_DESCRIPTION}}|${_quick_product_desc}|g" \
907
- -e "s|{{TARGET_USERS}}|${_quick_target_users}|g" \
908
932
  -e "s|{{MEMORY_PATH}}|.claude/agent-memory/${_name}/|g" \
909
933
  -e "s|{{SECURITY_EXEMPTIONS_PATH}}|${SPECRAILS_DIR}/security-exemptions.yaml|g" \
910
934
  -e "s|{{PERSONA_DIR}}|${SPECRAILS_DIR}/agents/personas/|g" \
@@ -916,6 +940,11 @@ if [[ "$TIER" == "quick" ]]; then
916
940
  # Create agent memory directory
917
941
  mkdir -p "${REPO_ROOT}/.claude/agent-memory/${_name}"
918
942
 
943
+ # Agents that write explanation records need the shared explanations dir
944
+ if [[ "$_name" == "sr-architect" || "$_name" == "sr-reviewer" ]]; then
945
+ mkdir -p "${REPO_ROOT}/.claude/agent-memory/explanations"
946
+ fi
947
+
919
948
  (( _agent_count++ )) || true
920
949
  done
921
950
  if (( _agent_skipped > 0 )); then
@@ -925,8 +954,38 @@ if [[ "$TIER" == "quick" ]]; then
925
954
  fi
926
955
  fi
927
956
 
928
- # Persona-dependent commands excluded from Quick tier
929
- _quick_excluded_cmds="auto-propose-backlog-specs vpc-drift get-backlog-specs"
957
+ # Dynamic command exclusion based on installed agents.
958
+ # Each command maps to the agent(s) it depends on — if the agent
959
+ # wasn't installed, the command is excluded automatically.
960
+ #
961
+ # Dependency map (command → required agent):
962
+ # auto-propose-backlog-specs → sr-product-manager
963
+ # get-backlog-specs → sr-product-analyst
964
+ # vpc-drift → sr-product-manager, sr-product-analyst
965
+ # merge-resolve → sr-merge-resolver
966
+ # team-debug, team-review → AGENT_TEAMS flag
967
+ _quick_excluded_cmds=""
968
+ _installed_agents_dir="${REPO_ROOT}/${SPECRAILS_DIR}/agents"
969
+
970
+ # Agent-dependent commands
971
+ if ! ls "$_installed_agents_dir/sr-product-manager.md" &>/dev/null; then
972
+ _quick_excluded_cmds="$_quick_excluded_cmds auto-propose-backlog-specs vpc-drift"
973
+ fi
974
+ if ! ls "$_installed_agents_dir/sr-product-analyst.md" &>/dev/null; then
975
+ _quick_excluded_cmds="$_quick_excluded_cmds get-backlog-specs"
976
+ # vpc-drift needs both product agents
977
+ if ! echo " $_quick_excluded_cmds " | grep -q " vpc-drift "; then
978
+ _quick_excluded_cmds="$_quick_excluded_cmds vpc-drift"
979
+ fi
980
+ fi
981
+ if ! ls "$_installed_agents_dir/sr-merge-resolver.md" &>/dev/null; then
982
+ _quick_excluded_cmds="$_quick_excluded_cmds merge-resolve"
983
+ fi
984
+
985
+ # Agent Teams commands (flag-dependent, not agent-dependent)
986
+ if [[ "$AGENT_TEAMS" != "true" ]]; then
987
+ _quick_excluded_cmds="$_quick_excluded_cmds team-debug team-review"
988
+ fi
930
989
 
931
990
  # --- Commands ---
932
991
  if [[ -d "$_templates/commands/specrails" ]]; then
@@ -936,7 +995,7 @@ if [[ "$TIER" == "quick" ]]; then
936
995
  [[ -f "$_src" ]] || continue
937
996
  _cmd_name="$(basename "$_src" .md)"
938
997
 
939
- # Skip persona-dependent commands in Quick tier
998
+ # Skip commands whose required agents are not installed
940
999
  if echo " $_quick_excluded_cmds " | grep -q " ${_cmd_name} "; then
941
1000
  continue
942
1001
  fi
@@ -945,8 +1004,6 @@ if [[ "$TIER" == "quick" ]]; then
945
1004
  cp "$_src" "$_dest"
946
1005
  sed -i.bak \
947
1006
  -e "s|{{PROJECT_NAME}}|${_project_name}|g" \
948
- -e "s|{{PROJECT_DESCRIPTION}}|${_quick_product_desc}|g" \
949
- -e "s|{{TARGET_USERS}}|${_quick_target_users}|g" \
950
1007
  -e "s|{{MEMORY_PATH}}|.claude/agent-memory/|g" \
951
1008
  -e "s|{{PERSONA_DIR}}|${SPECRAILS_DIR}/agents/personas/|g" \
952
1009
  -e "s|{{SECURITY_EXEMPTIONS_PATH}}|${SPECRAILS_DIR}/security-exemptions.yaml|g" \
@@ -1010,10 +1067,30 @@ LTEOF
1010
1067
  fi
1011
1068
 
1012
1069
  # --- Skills (OpenSpec) ---
1070
+ # Dynamic skill exclusion based on installed agents (mirrors command logic).
1071
+ # Dependency map (skill → required agent):
1072
+ # sr-auto-propose-backlog-specs → sr-product-manager
1073
+ # sr-get-backlog-specs → sr-product-analyst
1074
+ _quick_excluded_skills=""
1075
+ if ! ls "$_installed_agents_dir/sr-product-manager.md" &>/dev/null; then
1076
+ _quick_excluded_skills="$_quick_excluded_skills sr-auto-propose-backlog-specs"
1077
+ fi
1078
+ if ! ls "$_installed_agents_dir/sr-product-analyst.md" &>/dev/null; then
1079
+ _quick_excluded_skills="$_quick_excluded_skills sr-get-backlog-specs"
1080
+ fi
1013
1081
  if [[ -d "$_templates/skills" ]]; then
1014
1082
  mkdir -p "${REPO_ROOT}/${SPECRAILS_DIR}/skills"
1015
- cp -r "$_templates/skills/"* "${REPO_ROOT}/${SPECRAILS_DIR}/skills/" 2>/dev/null || true
1016
- ok "Installed skills to ${SPECRAILS_DIR}/skills/"
1083
+ _skill_count=0
1084
+ for _skill_dir in "$_templates/skills/"*/; do
1085
+ [[ -d "$_skill_dir" ]] || continue
1086
+ _skill_name="$(basename "$_skill_dir")"
1087
+ if echo " $_quick_excluded_skills " | grep -q " ${_skill_name} "; then
1088
+ continue
1089
+ fi
1090
+ cp -r "$_skill_dir" "${REPO_ROOT}/${SPECRAILS_DIR}/skills/${_skill_name}"
1091
+ (( _skill_count++ )) || true
1092
+ done
1093
+ ok "Installed ${_skill_count} skill(s) to ${SPECRAILS_DIR}/skills/"
1017
1094
  fi
1018
1095
 
1019
1096
  if [[ "$HUB_JSON" == true ]]; then
@@ -1023,8 +1100,12 @@ fi
1023
1100
 
1024
1101
  # Initialize OpenSpec if available and not already initialized
1025
1102
  if [ "$HAS_OPENSPEC" = true ] && [ ! -d "$REPO_ROOT/openspec" ]; then
1026
- info "Initializing OpenSpec..."
1027
- cd "$REPO_ROOT" && openspec init 2>/dev/null && {
1103
+ # Map specrails provider to openspec tool name
1104
+ _openspec_tool="claude"
1105
+ [[ "$CLI_PROVIDER" == "codex" ]] && _openspec_tool="codex"
1106
+
1107
+ info "Initializing OpenSpec (--tools ${_openspec_tool} --force)..."
1108
+ cd "$REPO_ROOT" && openspec init --tools "${_openspec_tool}" --force 2>/dev/null && {
1028
1109
  ok "OpenSpec initialized"
1029
1110
  } || {
1030
1111
  warn "OpenSpec init failed — you can run 'openspec init' manually later"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "specrails-core",
3
- "version": "3.8.1",
3
+ "version": "4.0.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"
@@ -10,7 +10,6 @@
10
10
  "install.sh",
11
11
  "update.sh",
12
12
  "templates/",
13
- "prompts/",
14
13
  ".claude/skills/",
15
14
  "commands/",
16
15
  "docs/",
@@ -53,6 +52,9 @@
53
52
  "test": "bash tests/run-all.sh",
54
53
  "test:coverage": "bash tests/run-coverage.sh"
55
54
  },
55
+ "specrails": {
56
+ "openspecVersion": "1.2.0"
57
+ },
56
58
  "dependencies": {
57
59
  "@inquirer/prompts": "^7.0.0"
58
60
  },
@@ -49,7 +49,9 @@ When an OpenSpec change is being applied, you:
49
49
  4. **Implement the changes** with surgical precision across all affected layers
50
50
  5. **Ensure consistency** with the existing codebase style, patterns, and architecture
51
51
 
52
- ## Workflow Protocol
52
+ ## Workflow Protocol — Strict TDD
53
+
54
+ You MUST follow Test-Driven Development. This is non-negotiable. The cycle is: **Red → Green → Refactor**. Never write production code without a failing test first.
53
55
 
54
56
  ### Phase 1: Understand
55
57
  - Read the OpenSpec change spec thoroughly
@@ -65,9 +67,25 @@ When an OpenSpec change is being applied, you:
65
67
  - Plan the dependency graph — what depends on what
66
68
  - Determine the implementation order
67
69
  - Identify edge cases and error handling requirements
70
+ - **Plan the test strategy**: for each piece of functionality, decide what tests to write and at what level (unit, integration, E2E)
71
+
72
+ ### Phase 3: Implement (TDD cycle)
73
+
74
+ **For each unit of functionality, follow this exact cycle:**
75
+
76
+ 1. **RED** — Write a failing test that describes the expected behavior. Run the test. Confirm it fails for the right reason.
77
+ 2. **GREEN** — Write the minimum production code to make the test pass. Run the test. Confirm it passes.
78
+ 3. **REFACTOR** — Clean up the code while keeping all tests green. Run all tests after refactoring.
79
+
80
+ **TDD rules:**
81
+ - Never write production code without a corresponding test
82
+ - Write tests BEFORE the production code, not after
83
+ - Each test should test one specific behavior
84
+ - Tests must be deterministic and isolated
85
+ - Cover the happy path, edge cases, and error cases
86
+ - If the project has an existing test framework, use it. If not, set one up before writing any production code.
68
87
 
69
- ### Phase 3: Implement
70
- - Follow the project architecture strictly:
88
+ Follow the project architecture strictly:
71
89
  ```
72
90
  {{ARCHITECTURE_DIAGRAM}}
73
91
  ```
@@ -82,12 +100,17 @@ When an OpenSpec change is being applied, you:
82
100
  - Consistent formatting and style
83
101
 
84
102
  ### Phase 4: Verify
103
+
104
+ **All tests MUST pass before you hand off to the reviewer. This is a hard gate — do not proceed if any test fails.**
105
+
106
+ - Run the **full CI-equivalent verification suite** (see below)
107
+ - If any test fails, fix the issue and re-run ALL tests
108
+ - Repeat until all tests pass — there is no maximum number of attempts
85
109
  - Review each file for adherence to conventions
86
110
  - Ensure all imports are correct and no circular dependencies exist
87
111
  - Verify type annotations are complete
88
112
  - Check that error handling is comprehensive and consistent
89
113
  - Validate that the implementation matches the spec exactly
90
- - Run the **full CI-equivalent verification suite** (see below)
91
114
 
92
115
  ## CI-Equivalent Verification Suite
93
116
 
@@ -36,10 +36,12 @@ Leave empty to review all areas with equal weight.
36
36
  ## Your Mission
37
37
 
38
38
  You are the last line of defense between developer output and a PR. You:
39
- 1. Run every check that CI runs in the exact same way
40
- 2. Fix any failures you find (up to 3 attempts per issue)
41
- 3. Verify code quality and consistency across all changes
42
- 4. Report what you found and fixed
39
+ 1. **Verify TDD compliance** every piece of production code must have corresponding tests
40
+ 2. **Verify spec completeness** every requirement from the architect's spec must be implemented
41
+ 3. Run every check that CI runs in the exact same way
42
+ 4. Fix any failures you find (up to 3 attempts per issue)
43
+ 5. Verify code quality and consistency across all changes
44
+ 6. Report what you found and fixed
43
45
 
44
46
  ## CI/CD Pipeline Equivalence
45
47
 
@@ -74,6 +76,19 @@ SECURITY_REVIEW_REPORT:
74
76
 
75
77
  After running CI checks, also review for:
76
78
 
79
+ ### TDD Compliance (mandatory)
80
+ - **Every new function/method** has at least one test covering its primary behavior
81
+ - **Every bug fix** has a regression test that would fail without the fix
82
+ - **Edge cases and error paths** have dedicated tests, not just the happy path
83
+ - If any production code lacks tests, **this is a blocking issue** — either write the missing tests yourself or reject the review with clear instructions on what tests are needed
84
+ - Check test quality: tests should assert on behavior, not implementation details
85
+
86
+ ### Spec Completeness (mandatory)
87
+ - Read the OpenSpec change spec in `openspec/changes/<name>/`
88
+ - **Every requirement listed in the spec must have a corresponding implementation** — cross-reference each spec item against the code changes
89
+ - If any spec requirement is missing or only partially implemented, **this is a blocking issue** — flag exactly which requirements are not fulfilled
90
+ - If the developer made assumptions about ambiguous spec items, verify they are reasonable
91
+
77
92
  ### Code Quality
78
93
  {{CODE_QUALITY_CHECKLIST}}
79
94
 
@@ -1,9 +1,5 @@
1
1
  # {{PROJECT_NAME}}
2
2
 
3
- > {{PROJECT_DESCRIPTION}}
4
-
5
- **Target users:** {{TARGET_USERS}}
6
-
7
3
  ---
8
4
 
9
5
  ## Agent Team
@@ -52,8 +52,6 @@ Parse the YAML and extract:
52
52
  - `config.models.preset` — `balanced`, `budget`, or `max` (see Model Presets below)
53
53
  - `config.models.defaults.model` — default model override (overrides preset)
54
54
  - `config.models.overrides` — per-agent model overrides (highest priority)
55
- - `config.quick_context.product_description` — product description seed
56
- - `config.quick_context.target_users` — target users seed
57
55
  - `config.agent_teams` — boolean; whether to install team-review/team-debug commands
58
56
 
59
57
  Store all values in variables prefixed `FC_`.
@@ -78,21 +76,19 @@ Set `SPECRAILS_DIR` and `CLI_PROVIDER` from resolved provider.
78
76
  ### FC3: If tier is `quick` — run Quick Mode with config context
79
77
 
80
78
  If `FC_tier == "quick"`:
81
- - Set `QS_PROJECT_DESCRIPTION = FC_quick_context.product_description`
82
- - Set `QS_TARGET_USERS = FC_quick_context.target_users`
83
79
  - Set `FC_AGENTS_SELECTED` as the list of agents to generate (instead of defaults)
84
- - Execute Quick Mode (QS1–QS4) with these values injected, generating all `FC_AGENTS_SELECTED` agents (not just defaults)
80
+ - Execute Quick Mode (QS1–QS4), generating all `FC_AGENTS_SELECTED` agents (not just defaults)
85
81
  - Then stop.
86
82
 
87
83
  ### FC4: If tier is `full` — run automated full wizard
88
84
 
89
85
  **Phase 1 (Silent):** Run the full Phase 1 analysis (1.1–1.4) without any user prompts. Store all detected values internally.
90
86
 
91
- **Phase 2 (Seeded VPC Discovery):** Run VPC persona generation using `FC_quick_context` as seeds:
92
- - Treat `FC_quick_context.product_description` as the answer to "Describe your product"
93
- - Treat `FC_quick_context.target_users` as the answer to "Who are your users"
94
- - Use AI to expand these seeds into full VPC personas (3 primary, 3 secondary)
95
- - Do not ask the user any questions — infer all answers from seeds + codebase analysis
87
+ **Phase 2 (AI-Inferred VPC Discovery):** Run VPC persona generation from codebase analysis:
88
+ - Analyze the codebase (README, package.json, source code, configs) to infer what the product does and who it serves
89
+ - Generate `PROJECT_DESCRIPTION` (2–3 sentence summary) and `TARGET_USERS` from analysis
90
+ - Use these inferred values to generate full VPC personas (3 primary, 3 secondary)
91
+ - Do not ask the user any questions — infer everything from codebase analysis
96
92
 
97
93
  **Phase 3 (Silent):** Run Phase 3 normally without user prompts.
98
94
 
@@ -422,20 +418,26 @@ Update `.specrails/specrails-manifest.json` to reflect the new checksums for all
422
418
 
423
419
  When `--quick` or `--lite` is passed, run this streamlined 3-question setup. Do NOT run Phase 1–5. When QS4 is complete, stop.
424
420
 
425
- ### QS1: Ask the 3 questions
421
+ ### QS1: Infer context and ask git access
426
422
 
427
- Display the following prompt EXACTLY ONCE and then wait for the user's responses. Do NOT repeat the questions — output them a single time only.
423
+ **Step 1 AI inference (silent):** Analyze the codebase to infer:
424
+ - `QS_PROJECT_DESCRIPTION` — a 2–3 sentence summary of what this project does (from README, package.json, source code, configs)
425
+ - `QS_TARGET_USERS` — who the target users are (from docs, UI copy, API design, domain language)
428
426
 
429
- Welcome to specrails! Let's get your AI agent team set up in 3 quick questions.
427
+ **Step 2 Ask one question:**
430
428
 
431
- 1. What is this project? (one sentence)
432
- 2. Who are the target users?
433
- 3. Git access for agents read-only or read-write?
429
+ Display the following prompt EXACTLY ONCE:
430
+
431
+ Welcome to specrails! Let's get your AI agent team set up.
432
+
433
+ I've analyzed your codebase:
434
+ - **Project:** {QS_PROJECT_DESCRIPTION}
435
+ - **Target users:** {QS_TARGET_USERS}
436
+
437
+ 1. Git access for agents — read-only or read-write?
434
438
  (read-only = agents can read and suggest; read-write = agents can commit)
435
439
 
436
- Store the answers as:
437
- - `QS_PROJECT_DESCRIPTION` — answer to question 1
438
- - `QS_TARGET_USERS` — answer to question 2
440
+ Store the answer as:
439
441
  - `QS_GIT_ACCESS` — "read-only" or "read-write" (normalize if user types "ro", "rw", "readonly", etc.)
440
442
 
441
443
  ### QS2: Apply opinionated defaults
@@ -497,8 +499,6 @@ Read `.specrails/setup-templates/claude-md/CLAUDE-quickstart.md` (or fall back t
497
499
 
498
500
  Replace placeholders:
499
501
  - `{{PROJECT_NAME}}` → derive from directory name or README.md first heading
500
- - `{{PROJECT_DESCRIPTION}}` → `QS_PROJECT_DESCRIPTION`
501
- - `{{TARGET_USERS}}` → `QS_TARGET_USERS`
502
502
  - `{{GIT_ACCESS}}` → `QS_GIT_ACCESS`
503
503
 
504
504
  Write to `CLAUDE.md` in the repo root. If `CLAUDE.md` already exists, ask:
@@ -515,8 +515,6 @@ If `.specrails/agents.yaml` exists, read it and apply model resolution (per-agen
515
515
 
516
516
  Fill placeholders with best-effort values from the limited context available:
517
517
  - `{{PROJECT_NAME}}` → directory name or README first heading
518
- - `{{PROJECT_DESCRIPTION}}` → `QS_PROJECT_DESCRIPTION`
519
- - `{{TARGET_USERS}}` → `QS_TARGET_USERS`
520
518
  - `{{GIT_ACCESS}}` → `QS_GIT_ACCESS`
521
519
  - `{{ARCHITECTURE_DIAGRAM}}` → "(Quick Mode — run `/specrails:enrich` for full architecture analysis)"
522
520
  - `{{TECH_EXPERTISE}}` → "(Quick Mode — run `/specrails:enrich` for codebase-specific expertise)"