@haystackeditor/cli 0.8.0 → 0.9.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.
Files changed (76) hide show
  1. package/README.md +105 -12
  2. package/dist/assets/hooks/agent-context/detect.ts +136 -0
  3. package/dist/assets/hooks/agent-context/format.ts +99 -0
  4. package/dist/assets/hooks/agent-context/index.ts +39 -0
  5. package/dist/assets/hooks/agent-context/parsers/claude.ts +253 -0
  6. package/dist/assets/hooks/agent-context/parsers/gemini.ts +155 -0
  7. package/dist/assets/hooks/agent-context/parsers/opencode.ts +174 -0
  8. package/dist/assets/hooks/agent-context/tsconfig.json +13 -0
  9. package/dist/assets/hooks/agent-context/types.ts +58 -0
  10. package/dist/assets/hooks/llm-rules-template.md +56 -0
  11. package/dist/assets/hooks/package.json +11 -0
  12. package/dist/assets/hooks/scripts/commit-msg.sh +4 -0
  13. package/dist/assets/hooks/scripts/post-commit.sh +4 -0
  14. package/dist/assets/hooks/scripts/pre-commit.sh +92 -0
  15. package/dist/assets/hooks/scripts/pre-push.sh +25 -0
  16. package/dist/assets/hooks/scripts/prepare-commit-msg.sh +3 -0
  17. package/dist/assets/hooks/truncation-checker/ast-analyzer.ts +528 -0
  18. package/dist/assets/hooks/truncation-checker/index.ts +595 -0
  19. package/dist/assets/hooks/truncation-checker/tsconfig.json +13 -0
  20. package/dist/assets/skills/prepare-haystack.md +323 -0
  21. package/dist/assets/skills/secrets.md +164 -0
  22. package/dist/assets/skills/setup-external-sandbox.md +243 -0
  23. package/dist/assets/skills/setup-haystack.md +639 -0
  24. package/dist/assets/skills/submit.md +154 -0
  25. package/dist/assets/templates/CLAUDE.md.snippet +42 -0
  26. package/dist/assets/templates/haystack.yml +193 -0
  27. package/dist/commands/check-pending.d.ts +19 -0
  28. package/dist/commands/check-pending.js +217 -0
  29. package/dist/commands/config.d.ts +18 -12
  30. package/dist/commands/config.js +327 -52
  31. package/dist/commands/hooks.d.ts +17 -0
  32. package/dist/commands/hooks.js +269 -0
  33. package/dist/commands/install-session-hooks.d.ts +16 -0
  34. package/dist/commands/install-session-hooks.js +302 -0
  35. package/dist/commands/login.js +1 -1
  36. package/dist/commands/policy.d.ts +31 -0
  37. package/dist/commands/policy.js +365 -0
  38. package/dist/commands/skills.d.ts +8 -0
  39. package/dist/commands/skills.js +80 -0
  40. package/dist/commands/submit.d.ts +22 -0
  41. package/dist/commands/submit.js +428 -0
  42. package/dist/commands/triage.d.ts +16 -0
  43. package/dist/commands/triage.js +354 -0
  44. package/dist/index.d.ts +3 -0
  45. package/dist/index.js +317 -2
  46. package/dist/tools/detect.d.ts +50 -0
  47. package/dist/tools/detect.js +853 -0
  48. package/dist/tools/fixtures.d.ts +38 -0
  49. package/dist/tools/fixtures.js +199 -0
  50. package/dist/tools/setup.d.ts +43 -0
  51. package/dist/tools/setup.js +597 -0
  52. package/dist/triage/prompts.d.ts +31 -0
  53. package/dist/triage/prompts.js +266 -0
  54. package/dist/triage/runner.d.ts +21 -0
  55. package/dist/triage/runner.js +325 -0
  56. package/dist/triage/traces.d.ts +20 -0
  57. package/dist/triage/traces.js +305 -0
  58. package/dist/triage/types.d.ts +47 -0
  59. package/dist/triage/types.js +7 -0
  60. package/dist/types.d.ts +1387 -191
  61. package/dist/types.js +254 -2
  62. package/dist/utils/analysis-api.d.ts +108 -0
  63. package/dist/utils/analysis-api.js +194 -0
  64. package/dist/utils/config.js +1 -1
  65. package/dist/utils/git.d.ts +80 -0
  66. package/dist/utils/git.js +302 -0
  67. package/dist/utils/github-api.d.ts +83 -0
  68. package/dist/utils/github-api.js +266 -0
  69. package/dist/utils/hooks.d.ts +26 -0
  70. package/dist/utils/hooks.js +226 -0
  71. package/dist/utils/pending-state.d.ts +38 -0
  72. package/dist/utils/pending-state.js +86 -0
  73. package/dist/utils/secrets.js +3 -3
  74. package/dist/utils/skill.d.ts +1 -1
  75. package/dist/utils/skill.js +658 -1
  76. package/package.json +5 -3
@@ -168,6 +168,92 @@ grep -r "https://" src/ --include="*.ts" --include="*.tsx" | grep -v node_module
168
168
 
169
169
  ---
170
170
 
171
+ ## STOP - Confirm Frontend Golden URLs
172
+
173
+ **Goldens are URLs with real staging data** - they let verification test pages that need actual content to render properly. You need MULTIPLE goldens to cover different scenarios.
174
+
175
+ **Before writing flows for dynamic routes, explore the codebase to find example data:**
176
+
177
+ 1. Check test files (\`*.test.ts\`, \`cypress/\`, \`playwright/\`) for example IDs/URLs
178
+ 2. Check README/docs for demo links or example usage
179
+ 3. Check seed data, fixtures, or mock files
180
+ 4. Check \`.env.example\` or config for staging URLs
181
+ 5. Check existing routes to understand the URL format
182
+
183
+ **Then propose MULTIPLE golden URLs (aim for 3-5) covering different scenarios:**
184
+
185
+ > I found these dynamic routes that need staging data to render:
186
+ >
187
+ > **[Route Name]** (\`/path/:param1/:param2\`)
188
+ >
189
+ > | Golden | URL | Why |
190
+ > |--------|-----|-----|
191
+ > | Large dataset | \`/path/example/large-123\` | Tests performance with many items |
192
+ > | Typical case | \`/path/example/medium-456\` | Common user scenario |
193
+ > | Edge case | \`/path/example/empty-789\` | Tests empty/minimal state |
194
+ > | Error state | \`/path/example/error-000\` | Tests error handling UI |
195
+ >
196
+ > **Evidence:**
197
+ > - Found \`large-123\` in \`cypress/fixtures/test-data.json\`
198
+ > - Found \`medium-456\` in README as demo example
199
+ > - Found \`empty-789\` in \`src/tests/edge-cases.test.ts\`
200
+ >
201
+ > Does this look right?
202
+ > 1. ✅ Yes, use these goldens
203
+ > 2. 🔄 Use different URLs (I'll provide them)
204
+
205
+ **Add goldens to \`verification.goldens\` in \`.haystack.json\` using this EXACT format:**
206
+
207
+ \`\`\`json
208
+ {
209
+ "verification": {
210
+ "goldens": {
211
+ "frontend": [
212
+ {
213
+ "id": "large-dataset",
214
+ "description": "100+ items - tests rendering performance",
215
+ "route": "/the/actual/url/with/data"
216
+ },
217
+ {
218
+ "id": "typical-case",
219
+ "description": "Standard 10-20 items",
220
+ "route": "/another/url/with/typical/data"
221
+ },
222
+ {
223
+ "id": "empty-state",
224
+ "description": "No items - tests empty state UI",
225
+ "route": "/url/that/shows/empty/state"
226
+ }
227
+ ],
228
+ "backend": [
229
+ {
230
+ "id": "golden-input-1",
231
+ "description": "Known-good input for pipeline testing",
232
+ "input": { "type": "github_pr", "value": "owner/repo#123" }
233
+ }
234
+ ]
235
+ },
236
+ "commands": [...]
237
+ }
238
+ }
239
+ \`\`\`
240
+
241
+ **DO NOT:**
242
+ - Ask the user what format to use - USE THIS FORMAT
243
+ - Put goldens at the top level - they go inside \`verification.goldens\`
244
+ - Use a flat object like \`{ "goldens": { "name": "url" } }\` - use the array format above
245
+ - Embed golden URLs only in flow steps - also add them to the goldens section for discoverability
246
+
247
+ **CRITICAL**:
248
+ - Propose MULTIPLE goldens (3-5), not just one
249
+ - Cover different scenarios: large, typical, empty, error states
250
+ - Always propose SPECIFIC URLs, never ask the user to freestyle
251
+ - Show WHERE you found the example data (file path, line if possible)
252
+ - Make sure URLs match the app's actual route format (check \`<Route path=\`)
253
+ - Wait for confirmation before writing flows with these URLs
254
+
255
+ ---
256
+
171
257
  ## Step 5: Write Flows
172
258
 
173
259
  Flows tell the Planner about your app's routes, UI elements, and user journeys.
@@ -984,31 +1070,602 @@ Follow .agents/skills/prepare-haystack.md to add accessibility attributes that m
984
1070
 
985
1071
  Run this BEFORE /setup-haystack to ensure your codebase has good selectors.
986
1072
  `;
1073
+ const SECRETS_COMMAND_CONTENT = `# Set Up Haystack Secrets
1074
+
1075
+ Follow .agents/skills/setup-haystack-secrets.md to configure secrets (API keys, credentials) for Haystack verification.
1076
+ `;
1077
+ const SECRETS_SKILL_CONTENT = `# Set Up Haystack Secrets
1078
+
1079
+ **Your job**: Help the user configure secrets needed for Haystack verification, especially LLM API keys for backend services.
1080
+
1081
+ ---
1082
+
1083
+ ## Step 1: Detect Services That Need Secrets
1084
+
1085
+ Scan the codebase to identify services that might need API keys or credentials:
1086
+
1087
+ \`\`\`bash
1088
+ # Find LLM/AI SDK usage
1089
+ grep -rn "openai\\|anthropic\\|bedrock\\|OPENAI_API_KEY\\|ANTHROPIC_API_KEY" --include="*.ts" --include="*.py" --include="*.js" | grep -v node_modules | head -20
1090
+
1091
+ # Find environment variable references
1092
+ grep -rn "process.env\\.\\|os.environ\\|env\\." --include="*.ts" --include="*.py" --include="*.js" | grep -v node_modules | grep -iE "key|secret|token|api" | head -20
1093
+
1094
+ # Check for .env.example or similar
1095
+ cat .env.example .env.sample 2>/dev/null || echo "No .env example found"
1096
+
1097
+ # Check existing secrets in .haystack.json
1098
+ grep -A10 '"secrets"' .haystack.json 2>/dev/null || echo "No secrets configured yet"
1099
+ \`\`\`
1100
+
1101
+ ---
1102
+
1103
+ ## Step 2: Categorize the Secrets Found
1104
+
1105
+ Group secrets by type and service:
1106
+
1107
+ | Category | Examples | Storage Recommendation |
1108
+ |----------|----------|------------------------|
1109
+ | **LLM API Keys** | \`OPENAI_API_KEY\`, \`ANTHROPIC_API_KEY\` | Haystack Secrets (encrypted) |
1110
+ | **Cloud Credentials** | \`AWS_ACCESS_KEY_ID\`, \`GCP_SERVICE_ACCOUNT\` | Use OIDC in CI, not static keys |
1111
+ | **Database** | \`DATABASE_URL\`, \`REDIS_URL\` | Haystack Secrets or passthrough |
1112
+ | **Third-party APIs** | \`STRIPE_KEY\`, \`SENDGRID_KEY\` | Haystack Secrets |
1113
+ | **Internal Services** | \`API_TOKEN\`, \`WEBHOOK_SECRET\` | Haystack Secrets |
1114
+
1115
+ ---
1116
+
1117
+ ## STOP - Present Findings and Ask User
1118
+
1119
+ **You MUST present what you found and ask the user before proceeding:**
1120
+
1121
+ > I scanned the codebase and found these services that may need secrets for verification:
1122
+ >
1123
+ > **Services detected:**
1124
+ > - [Service 1]: Uses \`OPENAI_API_KEY\` for [purpose]
1125
+ > - [Service 2]: Uses \`DATABASE_URL\` for [purpose]
1126
+ > - ...
1127
+ >
1128
+ > **Questions:**
1129
+ >
1130
+ > 1. **LLM API Keys**: Which provider do you use?
1131
+ > - OpenAI (\`OPENAI_API_KEY\`)
1132
+ > - Anthropic (\`ANTHROPIC_API_KEY\`)
1133
+ > - AWS Bedrock (use OIDC, no static keys needed)
1134
+ > - Other: ___
1135
+ >
1136
+ > 2. **For each secret**, should verification use:
1137
+ > - **Real credentials** (stored securely in Haystack Secrets)
1138
+ > - **Test/sandbox credentials** (separate keys for verification only)
1139
+ > - **Mock/skip** (service not needed for visual verification)
1140
+ >
1141
+ > 3. **Do you have separate test credentials?**
1142
+ > - Yes, I have sandbox/test API keys
1143
+ > - No, I'll use production keys (with usage limits)
1144
+ > - I need to create test credentials first
1145
+
1146
+ **Wait for the user's response before continuing.**
1147
+
1148
+ ---
1149
+
1150
+ ## Step 3: Configure Secrets in .haystack.json
1151
+
1152
+ Based on user's answers, add secrets to the config:
1153
+
1154
+ \`\`\`json
1155
+ {
1156
+ "secrets": {
1157
+ "OPENAI_API_KEY": {
1158
+ "description": "OpenAI API key for analysis service",
1159
+ "required": true,
1160
+ "services": ["analysis"]
1161
+ },
1162
+ "DATABASE_URL": {
1163
+ "description": "PostgreSQL connection string",
1164
+ "required": false,
1165
+ "services": ["api"]
1166
+ }
1167
+ }
1168
+ }
1169
+ \`\`\`
1170
+
1171
+ ### Secret Properties
1172
+
1173
+ | Property | Description |
1174
+ |----------|-------------|
1175
+ | \`description\` | What this secret is for (shown to user) |
1176
+ | \`required\` | If \`true\`, verification fails without it |
1177
+ | \`services\` | Which services need this secret (for scoping) |
1178
+
1179
+ ---
1180
+
1181
+ ## Step 4: Guide User to Store Secrets
1182
+
1183
+ ### Option A: Haystack CLI (Recommended)
1184
+
1185
+ \`\`\`bash
1186
+ # Store secrets securely (encrypted at rest)
1187
+ npx @haystackeditor/cli secrets set OPENAI_API_KEY
1188
+ # Prompts for value, never shown in terminal history
1189
+
1190
+ # Verify it's stored
1191
+ npx @haystackeditor/cli secrets list
1192
+ \`\`\`
1193
+
1194
+ ### Option B: Environment Variables (Local Development)
1195
+
1196
+ \`\`\`bash
1197
+ # Add to .env.local (gitignored)
1198
+ echo 'OPENAI_API_KEY=sk-...' >> .env.local
1199
+
1200
+ # Make sure .env.local is in .gitignore
1201
+ grep -q '.env.local' .gitignore || echo '.env.local' >> .gitignore
1202
+ \`\`\`
1203
+
1204
+ ### Option C: CI/CD Secrets (GitHub Actions)
1205
+
1206
+ \`\`\`yaml
1207
+ # .github/workflows/haystack.yml
1208
+ env:
1209
+ OPENAI_API_KEY: \${{ secrets.OPENAI_API_KEY }}
1210
+ \`\`\`
1211
+
1212
+ ---
1213
+
1214
+ ## Step 5: Handle Cloud Provider Credentials
1215
+
1216
+ **Never store long-lived cloud credentials.** Use OIDC instead:
1217
+
1218
+ ### AWS (Bedrock, S3, etc.)
1219
+
1220
+ \`\`\`yaml
1221
+ # GitHub Actions with OIDC - no secrets needed!
1222
+ jobs:
1223
+ verify:
1224
+ permissions:
1225
+ id-token: write
1226
+ contents: read
1227
+ steps:
1228
+ - uses: aws-actions/configure-aws-credentials@v4
1229
+ with:
1230
+ role-to-assume: arn:aws:iam::123456789:role/haystack-verify
1231
+ aws-region: us-west-2
1232
+ \`\`\`
1233
+
1234
+ ### GCP (Vertex AI, Cloud Storage, etc.)
1235
+
1236
+ \`\`\`yaml
1237
+ jobs:
1238
+ verify:
1239
+ permissions:
1240
+ id-token: write
1241
+ steps:
1242
+ - uses: google-github-actions/auth@v2
1243
+ with:
1244
+ workload_identity_provider: projects/123/locations/global/...
1245
+ service_account: haystack-verify@project.iam.gserviceaccount.com
1246
+ \`\`\`
1247
+
1248
+ ---
1249
+
1250
+ ## Step 6: Test Secret Access
1251
+
1252
+ After storing secrets, verify they're accessible:
1253
+
1254
+ \`\`\`bash
1255
+ # Test locally
1256
+ npx @haystackeditor/cli secrets test
1257
+
1258
+ # Or check manually
1259
+ npx @haystackeditor/cli secrets get OPENAI_API_KEY --masked
1260
+ # Shows: sk-...xxxx (last 4 chars only)
1261
+ \`\`\`
1262
+
1263
+ ---
1264
+
1265
+ ## Step 7: Update .haystack.json
1266
+
1267
+ Add the secrets configuration:
1268
+
1269
+ \`\`\`bash
1270
+ # Show what to add
1271
+ cat << 'EOF'
1272
+ Add this to your .haystack.json:
1273
+
1274
+ {
1275
+ "secrets": {
1276
+ "OPENAI_API_KEY": {
1277
+ "description": "OpenAI API key for LLM analysis",
1278
+ "required": true
1279
+ }
1280
+ }
1281
+ }
1282
+ EOF
1283
+ \`\`\`
1284
+
1285
+ ---
1286
+
1287
+ ## Common Patterns
1288
+
1289
+ ### Analysis Pipeline with LLM
1290
+
1291
+ \`\`\`json
1292
+ {
1293
+ "services": {
1294
+ "analysis": {
1295
+ "root": "packages/analysis",
1296
+ "command": "pnpm start",
1297
+ "env": {
1298
+ "PR_IDENTIFIER": "$PR_IDENTIFIER"
1299
+ }
1300
+ }
1301
+ },
1302
+ "secrets": {
1303
+ "OPENAI_API_KEY": {
1304
+ "description": "OpenAI API for code analysis",
1305
+ "required": true,
1306
+ "services": ["analysis"]
1307
+ }
1308
+ }
1309
+ }
1310
+ \`\`\`
1311
+
1312
+ ### Multiple LLM Providers
1313
+
1314
+ \`\`\`json
1315
+ {
1316
+ "secrets": {
1317
+ "OPENAI_API_KEY": {
1318
+ "description": "OpenAI for embeddings",
1319
+ "services": ["search"]
1320
+ },
1321
+ "ANTHROPIC_API_KEY": {
1322
+ "description": "Claude for code review",
1323
+ "services": ["review"]
1324
+ }
1325
+ }
1326
+ }
1327
+ \`\`\`
1328
+
1329
+ ### Database + API Keys
1330
+
1331
+ \`\`\`json
1332
+ {
1333
+ "secrets": {
1334
+ "DATABASE_URL": {
1335
+ "description": "PostgreSQL for test database",
1336
+ "required": true
1337
+ },
1338
+ "STRIPE_TEST_KEY": {
1339
+ "description": "Stripe test mode key",
1340
+ "required": false
1341
+ }
1342
+ }
1343
+ }
1344
+ \`\`\`
1345
+
1346
+ ---
1347
+
1348
+ ## Security Best Practices
1349
+
1350
+ 1. **Use test/sandbox credentials** when available (OpenAI, Stripe, etc. offer these)
1351
+ 2. **Set usage limits** on API keys used for verification
1352
+ 3. **Never commit secrets** - use \`.gitignore\` for \`.env.local\`
1353
+ 4. **Rotate regularly** - especially if verification runs on external PRs
1354
+ 5. **Scope narrowly** - use \`services\` array to limit which services see which secrets
1355
+ 6. **Prefer OIDC** for cloud providers instead of static credentials
1356
+
1357
+ ---
1358
+
1359
+ ## Troubleshooting
1360
+
1361
+ ### "Secret not found" errors
1362
+
1363
+ \`\`\`bash
1364
+ # Check if secret is stored
1365
+ npx @haystackeditor/cli secrets list
1366
+
1367
+ # Check if it's in the right scope
1368
+ npx @haystackeditor/cli secrets get SECRET_NAME --show-metadata
1369
+ \`\`\`
1370
+
1371
+ ### "Permission denied" for cloud resources
1372
+
1373
+ - Verify OIDC trust policy includes your repo
1374
+ - Check IAM role has required permissions
1375
+ - Ensure GitHub Actions has \`id-token: write\` permission
1376
+
1377
+ ### Secrets work locally but not in CI
1378
+
1379
+ - Secrets stored via CLI are user-scoped by default
1380
+ - For CI, use GitHub Secrets or organization-level Haystack secrets
1381
+ - Check \`npx @haystackeditor/cli secrets list --scope=org\`
1382
+ `;
1383
+ const SETUP_RULES_CONTENT = `# Set Up Review Policies & Rules
1384
+
1385
+ **Your job**: Help the user configure two systems that control how Haystack evaluates their PRs:
1386
+
1387
+ 1. **Review Policies** — deterministic, path-based triggers that **always** require human review
1388
+ 2. **PR Rules** — LLM-evaluated code invariants that **flag violations** in the diff
1389
+
1390
+ These are distinct systems. Make sure the user understands the difference before proceeding.
1391
+
1392
+ ---
1393
+
1394
+ ## The Two Systems
1395
+
1396
+ ### Review Policies (\`.haystack/review-policy.md\`)
1397
+
1398
+ **"If a PR touches X → human review needed, period."**
1399
+
1400
+ Policies are simple glob patterns. When a PR changes files matching a policy's paths, Haystack will always recommend human review for that PR, regardless of what the code changes look like.
1401
+
1402
+ **Good candidates for policies:**
1403
+ - Infrastructure (Terraform, Kubernetes, CI/CD pipelines)
1404
+ - Authentication and authorization code
1405
+ - Database migrations and schemas
1406
+ - API contracts (OpenAPI specs, GraphQL schemas, protobuf)
1407
+ - Security-sensitive code (crypto, secrets handling)
1408
+ - Billing/payment logic
1409
+ - Code that bypasses feature flags or launches directly to production
1410
+
1411
+ **Format:**
1412
+ \`\`\`markdown
1413
+ ## Policy name
1414
+ - **Paths**: \\\`glob/pattern/**\\\`, \\\`other/pattern/*.ts\\\`
1415
+ - **Severity**: critical | high | medium | low
1416
+ - **Reason**: Why this always needs human eyes
1417
+ \`\`\`
1418
+
1419
+ ### PR Rules (\`.haystack/pr-rules.yml\`)
1420
+
1421
+ **"If this invariant is violated in the diff → flag it."**
1422
+
1423
+ Rules are checked by an LLM that reads the PR diff and looks for violations. They catch patterns that shouldn't appear in new code, regardless of which files are touched.
1424
+
1425
+ **Good candidates for rules:**
1426
+ - Error handling conventions (no silent catches, no swallowed errors)
1427
+ - Logging requirements (all API calls must be logged)
1428
+ - Security patterns (no hardcoded secrets, no SQL string concatenation)
1429
+ - Code style invariants (no TODOs without issue refs, no console.log in production)
1430
+ - Architecture boundaries (service A must not import from service B)
1431
+ - Naming conventions specific to your team
1432
+
1433
+ **Format:**
1434
+ \`\`\`yaml
1435
+ - id: PR001
1436
+ name: Short rule name
1437
+ type: llm
1438
+ severity: warning | error
1439
+ message: Human-readable description of the violation
1440
+ llm:
1441
+ prompt: >
1442
+ Detailed instructions for the LLM about what to look for
1443
+ in the PR diff. Be specific about what counts as a violation
1444
+ and what doesn't.
1445
+ files: "optional/glob/pattern/**/*.ts" # optional file scope
1446
+ \`\`\`
1447
+
1448
+ ---
1449
+
1450
+ ## Step 1: Explore the Codebase
1451
+
1452
+ Before suggesting anything, understand the repo structure:
1453
+
1454
+ \`\`\`bash
1455
+ # Understand repo layout
1456
+ ls -la
1457
+ find . -maxdepth 2 -type d -not -path '*/node_modules/*' -not -path '*/.git/*' | head -40
1458
+
1459
+ # Find infrastructure files
1460
+ find . -name "*.tf" -o -name "Dockerfile*" -o -name "docker-compose*" -o -name "*.yml" -path "*/.github/*" | head -20
1461
+
1462
+ # Find auth-related code
1463
+ grep -rl "auth\\|login\\|session\\|token\\|credential" --include="*.ts" --include="*.py" --include="*.go" --include="*.js" -l | grep -v node_modules | head -20
1464
+
1465
+ # Find database/migration files
1466
+ find . -path "*/migration*" -o -path "*/schema*" -o -name "*.sql" | grep -v node_modules | head -20
1467
+
1468
+ # Find API contract files
1469
+ find . -name "*.proto" -o -name "openapi*" -o -name "swagger*" -o -name "*.graphql" | head -20
1470
+
1471
+ # Find feature flag patterns
1472
+ grep -rl "feature.?flag\\|feature.?toggle\\|isEnabled\\|FEATURE_" --include="*.ts" --include="*.py" --include="*.go" --include="*.js" -l | grep -v node_modules | head -20
1473
+
1474
+ # Check for existing config
1475
+ cat .haystack/review-policy.md 2>/dev/null || echo "No review-policy.md yet"
1476
+ cat .haystack/pr-rules.yml 2>/dev/null || echo "No pr-rules.yml yet"
1477
+ \`\`\`
1478
+
1479
+ Also look for:
1480
+ - CI/CD pipeline files
1481
+ - Payment or billing directories
1482
+ - Secrets or credential management code
1483
+ - Environment configuration patterns
1484
+ - Key shared libraries or core utilities that many things depend on
1485
+
1486
+ ---
1487
+
1488
+ ## STOP — Propose Review Policies
1489
+
1490
+ Present your findings to the user. Be specific about what you found and why each area warrants a policy.
1491
+
1492
+ **Format your proposal like this:**
1493
+
1494
+ > Based on the codebase, here are the areas I'd recommend always requiring human review:
1495
+ >
1496
+ > | # | Policy | Paths | Severity | Why |
1497
+ > |---|--------|-------|----------|-----|
1498
+ > | 1 | Infrastructure | \\\`terraform/**\\\`, \\\`*.tf\\\` | high | Cost and security implications |
1499
+ > | 2 | Auth & secrets | \\\`src/auth/**\\\`, \\\`**/*.secret*\\\` | critical | Security-sensitive |
1500
+ > | 3 | ... | ... | ... | ... |
1501
+ >
1502
+ > **Notes:**
1503
+ > - I didn't find any database migrations in this repo, so I'm not including that
1504
+ > - The \`src/core/\` directory is imported by everything — should changes there always need review?
1505
+ >
1506
+ > Which of these should I include? Any to add, remove, or modify?
1507
+
1508
+ **Wait for the user to confirm before writing anything.**
1509
+
1510
+ ---
1511
+
1512
+ ## Step 2: Write review-policy.md
1513
+
1514
+ Once the user confirms, write the policies to \`.haystack/review-policy.md\`:
1515
+
1516
+ \`\`\`markdown
1517
+ # Review Policies
1518
+
1519
+ Review policies define file patterns that always require human attention. When a PR touches files matching these patterns, Haystack will flag it for human review.
1520
+
1521
+ ## [Policy name]
1522
+ - **Paths**: \\\`pattern/**\\\`
1523
+ - **Severity**: [level]
1524
+ - **Reason**: [why]
1525
+ \`\`\`
1526
+
1527
+ Create the \`.haystack/\` directory if it doesn't exist.
1528
+
1529
+ ---
1530
+
1531
+ ## Step 3: Understand Team Conventions
1532
+
1533
+ Now shift to rules. Ask the user about their code quality invariants:
1534
+
1535
+ > Now let's set up **PR rules** — these are code invariants that Haystack checks in every diff.
1536
+ >
1537
+ > Unlike policies (which trigger on file paths), rules look at *what the code does*. For example:
1538
+ > - "Don't add empty catch blocks"
1539
+ > - "Don't add TODOs without issue references"
1540
+ > - "Don't hardcode API URLs"
1541
+ >
1542
+ > **What conventions does your team care about?** Some common categories:
1543
+ >
1544
+ > 1. **Error handling** — e.g., no swallowed errors, no silent fallbacks
1545
+ > 2. **Security** — e.g., no hardcoded secrets, no raw SQL strings
1546
+ > 3. **Logging** — e.g., all API calls must have logging
1547
+ > 4. **Code hygiene** — e.g., no TODOs without issues, no console.log in production
1548
+ > 5. **Architecture** — e.g., no cross-service imports, no direct DB access from UI layer
1549
+ > 6. **Testing** — e.g., no skipped tests without reason, no snapshot-only tests
1550
+ >
1551
+ > Tell me which categories matter to your team, or describe your own conventions.
1552
+
1553
+ Also explore the codebase for clues:
1554
+
1555
+ \`\`\`bash
1556
+ # Check for linter configs (reveals team conventions)
1557
+ cat .eslintrc* .eslintrc.json .eslintrc.js eslint.config.* 2>/dev/null | head -50
1558
+
1559
+ # Check for existing code review guidelines
1560
+ find . -name "CONTRIBUTING*" -o -name "REVIEW*" -o -name "STYLE*" | head -5
1561
+
1562
+ # Look for common anti-patterns
1563
+ grep -rn "catch.*{\\s*}" --include="*.ts" --include="*.js" | head -5
1564
+ grep -rn "console\\.log" --include="*.ts" --include="*.tsx" | grep -v test | head -5
1565
+ grep -rn "TODO\\|FIXME\\|HACK\\|XXX" --include="*.ts" --include="*.tsx" | head -10
1566
+ \`\`\`
1567
+
1568
+ ---
1569
+
1570
+ ## STOP — Propose PR Rules
1571
+
1572
+ Based on the user's input and your codebase exploration, propose 2-5 custom rules.
1573
+
1574
+ **Format your proposal like this:**
1575
+
1576
+ > Here are the PR rules I'd suggest:
1577
+ >
1578
+ > **1. PR001 — No silent error handling** (warning)
1579
+ > > Flag: Adding catch blocks that swallow errors without logging or re-throwing
1580
+ >
1581
+ > **2. PR002 — No TODOs without tracking issues** (warning)
1582
+ > > Flag: Adding TODO/FIXME comments without referencing an issue number
1583
+ >
1584
+ > **3. PR003 — No hardcoded API endpoints** (warning)
1585
+ > > Flag: Adding hardcoded URLs or API endpoints instead of using config/env vars
1586
+ >
1587
+ > Should I add, remove, or modify any of these?
1588
+
1589
+ **Wait for the user to confirm before writing.**
1590
+
1591
+ ---
1592
+
1593
+ ## Step 4: Write pr-rules.yml
1594
+
1595
+ Once confirmed, write to \`.haystack/pr-rules.yml\`:
1596
+
1597
+ \`\`\`yaml
1598
+ version: 1
1599
+
1600
+ rules:
1601
+ - id: PR001
1602
+ name: [Short name]
1603
+ type: llm
1604
+ severity: warning
1605
+ message: [Human-readable description]
1606
+ llm:
1607
+ prompt: >
1608
+ [Detailed LLM instructions — be specific about what counts as
1609
+ a violation and what doesn't. Include examples of violations
1610
+ and non-violations when helpful.]
1611
+ \`\`\`
1612
+
1613
+ **Tips for writing good rule prompts:**
1614
+ - Be specific about what counts as a violation
1615
+ - Mention common false positives to ignore (e.g., "test files are exempt")
1616
+ - Use the \`files\` field to scope rules to relevant file types
1617
+ - \`severity: error\` caps the Haystack rating at 3 (needs review); \`warning\` is advisory
1618
+
1619
+ ---
1620
+
1621
+ ## Step 5: Commit
1622
+
1623
+ \`\`\`bash
1624
+ git add .haystack/review-policy.md .haystack/pr-rules.yml
1625
+ git commit -m "Add Haystack review policies and PR rules"
1626
+ \`\`\`
1627
+
1628
+ Done! Haystack will now:
1629
+ - Flag PRs touching policy-matched files for human review
1630
+ - Check every PR diff against your custom rules and report violations
1631
+ `;
1632
+ const SETUP_RULES_COMMAND = `# Set Up Rules
1633
+
1634
+ Follow .agents/skills/setup-haystack-rules.md to configure review policies (what always needs human review) and PR rules (what code invariants to enforce).
1635
+ `;
987
1636
  export async function createSkillFile() {
988
1637
  const skillDir = path.join(process.cwd(), '.agents', 'skills');
989
1638
  const setupPath = path.join(skillDir, 'setup-haystack.md');
990
1639
  const refPath = path.join(skillDir, 'haystack-reference.md');
991
1640
  const prepPath = path.join(skillDir, 'prepare-haystack.md');
1641
+ const secretsPath = path.join(skillDir, 'setup-haystack-secrets.md');
1642
+ const rulesPath = path.join(skillDir, 'setup-haystack-rules.md');
992
1643
  // Create directory if needed
993
1644
  await fs.mkdir(skillDir, { recursive: true });
994
1645
  // Write all skill files
995
1646
  await fs.writeFile(setupPath, SKILL_CONTENT, 'utf-8');
996
1647
  await fs.writeFile(refPath, REFERENCE_CONTENT, 'utf-8');
997
1648
  await fs.writeFile(prepPath, PREPARE_VERIFICATION_CONTENT, 'utf-8');
1649
+ await fs.writeFile(secretsPath, SECRETS_SKILL_CONTENT, 'utf-8');
1650
+ await fs.writeFile(rulesPath, SETUP_RULES_CONTENT, 'utf-8');
998
1651
  return setupPath;
999
1652
  }
1000
1653
  /**
1001
1654
  * Create the .claude/commands/ files for Claude Code slash commands
1002
- * Users can invoke with /setup-haystack or /prepare-haystack
1655
+ * Users can invoke with /setup-haystack, /prepare-haystack, or /setup-haystack-secrets
1003
1656
  */
1004
1657
  export async function createClaudeCommand() {
1005
1658
  const commandDir = path.join(process.cwd(), '.claude', 'commands');
1006
1659
  const setupPath = path.join(commandDir, 'setup-haystack.md');
1007
1660
  const prepPath = path.join(commandDir, 'prepare-haystack.md');
1661
+ const secretsPath = path.join(commandDir, 'setup-haystack-secrets.md');
1662
+ const rulesPath = path.join(commandDir, 'setup-haystack-rules.md');
1008
1663
  // Create directory if needed
1009
1664
  await fs.mkdir(commandDir, { recursive: true });
1010
1665
  // Write command files
1011
1666
  await fs.writeFile(setupPath, CLAUDE_COMMAND_CONTENT, 'utf-8');
1012
1667
  await fs.writeFile(prepPath, PREPARE_HAYSTACK_COMMAND, 'utf-8');
1668
+ await fs.writeFile(secretsPath, SECRETS_COMMAND_CONTENT, 'utf-8');
1669
+ await fs.writeFile(rulesPath, SETUP_RULES_COMMAND, 'utf-8');
1013
1670
  return setupPath;
1014
1671
  }