compound-agent 1.4.3 → 1.4.4

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/dist/cli.js CHANGED
@@ -6,7 +6,7 @@ import { createHash } from 'crypto';
6
6
  import * as fs from 'fs/promises';
7
7
  import { readFile, mkdir, appendFile, writeFile, chmod, rm, rename, readdir } from 'fs/promises';
8
8
  import { Command } from 'commander';
9
- import { getLlama, resolveModelFile } from 'node-llama-cpp';
9
+ import { getLlama, LlamaLogLevel, resolveModelFile } from 'node-llama-cpp';
10
10
  import { homedir, tmpdir } from 'os';
11
11
  import { z } from 'zod';
12
12
  import { execSync, execFileSync, spawn } from 'child_process';
@@ -584,7 +584,15 @@ async function isModelUsable() {
584
584
  let context = null;
585
585
  try {
586
586
  const modelPath = join(DEFAULT_MODEL_DIR, MODEL_FILENAME);
587
- llama = await getLlama();
587
+ llama = await getLlama({
588
+ build: "never",
589
+ // Never compile from source in a deployed tool
590
+ progressLogs: false,
591
+ // Suppress prebuilt binary fallback warnings
592
+ logLevel: LlamaLogLevel.error
593
+ // Only surface real errors from C++ backend
594
+ // Set NODE_LLAMA_CPP_DEBUG=true to re-enable all output for troubleshooting
595
+ });
588
596
  model = await llama.loadModel({ modelPath });
589
597
  context = await model.createEmbeddingContext();
590
598
  cachedUsability = { usable: true };
@@ -600,7 +608,19 @@ async function isModelUsable() {
600
608
  } finally {
601
609
  if (context) {
602
610
  try {
603
- context.dispose();
611
+ await context.dispose();
612
+ } catch {
613
+ }
614
+ }
615
+ if (model) {
616
+ try {
617
+ await model.dispose();
618
+ } catch {
619
+ }
620
+ }
621
+ if (llama) {
622
+ try {
623
+ await llama.dispose();
604
624
  } catch {
605
625
  }
606
626
  }
@@ -622,7 +642,15 @@ async function getEmbedding() {
622
642
  pendingInit = (async () => {
623
643
  try {
624
644
  const modelPath = await resolveModel({ cli: true });
625
- llamaInstance = await getLlama();
645
+ llamaInstance = await getLlama({
646
+ build: "never",
647
+ // Never compile from source in a deployed tool
648
+ progressLogs: false,
649
+ // Suppress prebuilt binary fallback warnings
650
+ logLevel: LlamaLogLevel.error
651
+ // Only surface real errors from C++ backend
652
+ // Set NODE_LLAMA_CPP_DEBUG=true to re-enable all output for troubleshooting
653
+ });
626
654
  modelInstance = await llamaInstance.loadModel({ modelPath });
627
655
  embeddingContext = await modelInstance.createEmbeddingContext();
628
656
  return embeddingContext;
@@ -4869,39 +4897,59 @@ Return a list of relevant memory items:
4869
4897
  `,
4870
4898
  "security-reviewer": `---
4871
4899
  name: Security Reviewer
4872
- description: Reviews code for security vulnerabilities
4900
+ description: Mandatory core-4 reviewer with P0-P3 severity classification and specialist escalation
4873
4901
  ---
4874
4902
 
4875
4903
  # Security Reviewer
4876
4904
 
4877
4905
  ## Role
4878
- Review code changes for security vulnerabilities including OWASP top 10, injection attacks, authentication issues, and data exposure risks.
4906
+ Mandatory core-4 reviewer responsible for identifying security vulnerabilities using P0-P3 severity classification. Has authority to escalate findings to specialist security skills for deep analysis.
4879
4907
 
4880
4908
  ## Instructions
4881
- 1. Read the changed files completely
4882
- 2. Check for injection vulnerabilities (SQL, command, XSS)
4883
- 3. Verify input validation and sanitization
4884
- 4. Review authentication and authorization logic
4885
- 5. Check for hardcoded secrets or credentials
4886
- 6. Verify error messages do not leak sensitive info
4887
- 7. Check dependency versions for known CVEs
4888
- 8. For large diffs, spawn opus subagents to review different file groups in parallel (e.g., 1 per module). Merge findings and deduplicate.
4909
+ 1. Read \`docs/compound/research/security/overview.md\` for severity classification and escalation triggers
4910
+ 2. Read all changed files completely, focusing on:
4911
+ - Input handling and data flow to interpreters (SQL, shell, HTML, templates)
4912
+ - Secrets and credential management
4913
+ - Authentication and authorization enforcement
4914
+ - Logging and error handling for data exposure
4915
+ - Dependency changes in lockfiles or manifests
4916
+ 3. Classify each finding using P0-P3 severity:
4917
+ - **P0**: Unauthenticated RCE, credential compromise, unauth data access (blocks merge)
4918
+ - **P1**: Authenticated exploit, limited data breach, missing auth on sensitive routes (requires ack)
4919
+ - **P2**: Medium impact, harder to exploit, missing hardening (should fix)
4920
+ - **P3**: Best practice, defense in depth, code hygiene (nice to have)
4921
+ 4. Escalate to specialist skills when deep analysis needed:
4922
+ - SQL/command concat or template interpolation -> \`/security-injection\`
4923
+ - Hardcoded strings matching key patterns, committed .env files -> \`/security-secrets\`
4924
+ - Route handlers missing auth middleware, IDOR patterns -> \`/security-auth\`
4925
+ - Logging calls with request objects, verbose error responses -> \`/security-data\`
4926
+ - Lockfile changes, new dependencies, postinstall scripts -> \`/security-deps\`
4927
+ 5. For large diffs, spawn opus subagents to review different file groups in parallel. Merge findings and deduplicate.
4889
4928
 
4890
4929
  ## Literature
4891
- - Consult \`docs/compound/research/code-review/\` for systematic review methodology and severity classification
4930
+ - Consult \`docs/compound/research/security/overview.md\` for severity classification and OWASP mapping
4931
+ - Consult \`docs/compound/research/security/injection-patterns.md\` for injection detection heuristics
4932
+ - Consult \`docs/compound/research/security/secrets-checklist.md\` for secret format patterns
4933
+ - Consult \`docs/compound/research/security/auth-patterns.md\` for auth/authz audit methodology
4934
+ - Consult \`docs/compound/research/security/data-exposure.md\` for data leak detection
4935
+ - Consult \`docs/compound/research/security/dependency-security.md\` for dependency risk assessment
4936
+ - Consult \`docs/compound/research/security/secure-coding-failure.md\` for full theoretical foundation
4892
4937
  - Run \`npx ca knowledge "security review OWASP"\` for indexed security knowledge
4893
4938
 
4894
4939
  ## Collaboration
4895
- Share cross-cutting findings via SendMessage: security issues impacting architecture go to architecture-reviewer; secrets in test fixtures go to test-coverage-reviewer.
4940
+ Share cross-cutting findings via SendMessage: security issues impacting architecture go to architecture-reviewer; secrets in test fixtures go to test-coverage-reviewer. Escalate to specialist skills via SendMessage when deep analysis needed.
4896
4941
 
4897
4942
  ## Deployment
4898
4943
  AgentTeam member in the **review** phase. Spawned via TeamCreate. Communicate with teammates via SendMessage.
4899
4944
 
4900
4945
  ## Output Format
4901
- Return findings as:
4902
- - **CRITICAL**: Must fix before merge
4903
- - **WARNING**: Should fix, potential risk
4904
- - **INFO**: Best practice suggestion
4946
+ Return findings classified by severity:
4947
+ - **P0** (BLOCKS MERGE): Must fix before merge, no exceptions
4948
+ - **P1** (REQUIRES ACK): Must acknowledge or fix before merge
4949
+ - **P2** (SHOULD FIX): Should fix, create beads issue if deferred
4950
+ - **P3** (NICE TO HAVE): Best practice suggestion, non-blocking
4951
+
4952
+ If no findings at any severity: return "SECURITY REVIEW: CLEAR -- No findings at any severity level."
4905
4953
  `,
4906
4954
  "architecture-reviewer": `---
4907
4955
  name: Architecture Reviewer
@@ -5040,6 +5088,266 @@ AgentTeam member in the **review** phase. Spawned via TeamCreate. Communicate wi
5040
5088
  - **OVER-ENGINEERED**: Simpler solution exists
5041
5089
  - **YAGNI**: Feature not needed yet
5042
5090
  - **OK**: Appropriate complexity for the task
5091
+ `,
5092
+ "security-injection": `---
5093
+ name: Security Injection Specialist
5094
+ description: Deep trace analysis for SQL, command, XSS, SSRF, and SSTI injection vulnerabilities
5095
+ ---
5096
+
5097
+ # Security Injection Specialist
5098
+
5099
+ ## Role
5100
+ On-demand specialist for deep injection vulnerability analysis. Traces data flow from untrusted input sources to interpreter sinks (SQL engines, shells, browsers, template engines, HTTP clients).
5101
+
5102
+ ## Instructions
5103
+ 1. Read \`docs/compound/research/security/injection-patterns.md\` for detection heuristics and safe/unsafe patterns
5104
+ 2. For each changed file, identify:
5105
+ - **Input sources**: request params, body fields, headers, query strings, URL params, environment variables
5106
+ - **Interpreter sinks**: SQL queries, shell commands, HTML output, template rendering, outbound HTTP requests
5107
+ 3. Trace data flow from each source to each sink:
5108
+ - Direct concatenation or template interpolation into sink -> P0/P1
5109
+ - Flow through sanitization/validation before sink -> check if sanitization is adequate
5110
+ - Parameterized/prepared statement usage -> safe, note as OK
5111
+ 4. Classify by injection type:
5112
+ - **SQL** (survey 4.1): \`db.query\` with template literals, f-strings in queries, raw SQL with string concat
5113
+ - **Command** (survey 4.2): \`exec\`, \`system\`, \`popen\` with user input, \`shell=True\` with untrusted args
5114
+ - **XSS** (survey 4.3): \`innerHTML\`, \`dangerouslySetInnerHTML\`, \`v-html\`, \`| safe\` filter on user input
5115
+ - **SSRF** (survey 4.4): \`axios.get(userUrl)\`, \`requests.get(userUrl)\`, fetch with user-controlled URL
5116
+ - **SSTI** (survey 4.5): \`Template(userString)\`, \`render_template_string(userInput)\`
5117
+ 5. For large diffs, spawn opus subagents to trace different file groups in parallel. Merge findings.
5118
+
5119
+ ## Literature
5120
+ - Consult \`docs/compound/research/security/injection-patterns.md\` for unsafe/safe pattern pairs and detection heuristics
5121
+ - Consult \`docs/compound/research/security/secure-coding-failure.md\` sections 4.1-4.5 for theoretical foundation
5122
+ - Run \`npx ca knowledge "injection SQL command XSS SSRF SSTI"\` for indexed knowledge
5123
+
5124
+ ## Collaboration
5125
+ Report findings to security-reviewer via SendMessage with severity classification. Flag architecture-level injection risks (e.g., missing parameterization layer) to architecture-reviewer.
5126
+
5127
+ ## Deployment
5128
+ On-demand AgentTeam member in the **review** phase. Spawned by security-reviewer when injection patterns detected. Communicate with teammates via SendMessage.
5129
+
5130
+ ## Output Format
5131
+ Per finding:
5132
+ - **Type**: SQL / Command / XSS / SSRF / SSTI
5133
+ - **Severity**: P0-P3
5134
+ - **File:Line**: Location
5135
+ - **Source**: Where untrusted data enters
5136
+ - **Sink**: Where it reaches an interpreter
5137
+ - **Flow**: Brief trace description
5138
+ - **Fix**: Recommended safe pattern
5139
+
5140
+ If no findings: return "INJECTION REVIEW: CLEAR -- No injection patterns found."
5141
+ For large diffs (500+ lines): prioritize files with interpreter sinks over pure data/config files.
5142
+ `,
5143
+ "security-secrets": `---
5144
+ name: Security Secrets Specialist
5145
+ description: Credential and secrets scanning using pattern matching, entropy analysis, and git history checks
5146
+ ---
5147
+
5148
+ # Security Secrets Specialist
5149
+
5150
+ ## Role
5151
+ On-demand specialist for detecting hardcoded credentials, leaked secrets, and improper secret management in code and configuration.
5152
+
5153
+ ## Instructions
5154
+ 1. Read \`docs/compound/research/security/secrets-checklist.md\` for key format patterns and detection heuristics
5155
+ 2. Scan changed files for:
5156
+ - **Variable name patterns**: password, secret, token, apiKey, api_key, auth, credential, private_key, connection_string
5157
+ - **Known key formats**: AWS \`AKIA[0-9A-Z]{16}\`, GitHub \`ghp_[a-zA-Z0-9]{36}\`, Slack \`xoxb-\`/\`xoxp-\`, JWT signatures
5158
+ - **High-entropy strings**: 20+ character strings with mixed case, digits, and special chars in assignment context
5159
+ 3. Check for common hiding spots:
5160
+ - Committed \`.env\` files or \`.env.local\` without gitignore
5161
+ - Docker files with \`ENV SECRET=\` or \`ARG PASSWORD=\`
5162
+ - CI config files (\`.github/workflows/\`, \`.gitlab-ci.yml\`) with inline secrets
5163
+ - Test fixtures that use real-looking credentials instead of obvious fakes
5164
+ 4. Check git history for previously committed secrets:
5165
+ - \`git log --diff-filter=D -- '*.env'\` for deleted env files
5166
+ - \`git log -p -- <file>\` for files that changed secret-like values
5167
+ 5. Distinguish real secrets from safe patterns:
5168
+ - Test fixtures prefixed with \`test_\`, \`fake_\`, \`mock_\` -> OK
5169
+ - Placeholder values like \`YOUR_API_KEY_HERE\`, \`changeme\`, \`xxx\` -> OK
5170
+ - Public keys (not private) -> OK
5171
+ - Everything else -> flag for review
5172
+
5173
+ ## Literature
5174
+ - Consult \`docs/compound/research/security/secrets-checklist.md\` for format patterns and hiding spots
5175
+ - Consult \`docs/compound/research/security/secure-coding-failure.md\` section 4.6 for theoretical foundation
5176
+ - Run \`npx ca knowledge "secrets credentials hardcoded"\` for indexed knowledge
5177
+
5178
+ ## Collaboration
5179
+ Report findings to security-reviewer via SendMessage with severity classification. Flag secrets in test files to test-coverage-reviewer.
5180
+
5181
+ ## Deployment
5182
+ On-demand AgentTeam member in the **review** phase. Spawned by security-reviewer when secret patterns detected. Communicate with teammates via SendMessage.
5183
+
5184
+ ## Output Format
5185
+ Per finding:
5186
+ - **Severity**: P0 (real credential) / P1 (likely credential) / P2 (suspicious pattern) / P3 (missing .gitignore for secret files)
5187
+ - **File:Line**: Location
5188
+ - **Pattern**: What matched (variable name, key format, entropy)
5189
+ - **Value preview**: First/last 4 chars only (never full secret)
5190
+ - **Fix**: Use environment variable, secret manager, or .gitignore
5191
+
5192
+ If no findings: return "SECRETS REVIEW: CLEAR -- No hardcoded secrets or credential patterns found."
5193
+ `,
5194
+ "security-auth": `---
5195
+ name: Security Auth Specialist
5196
+ description: Route and endpoint audit for authentication, authorization, IDOR, JWT, and CORS vulnerabilities
5197
+ ---
5198
+
5199
+ # Security Auth Specialist
5200
+
5201
+ ## Role
5202
+ On-demand specialist for auditing authentication and authorization enforcement across routes, endpoints, and API handlers.
5203
+
5204
+ ## Instructions
5205
+ 1. Read \`docs/compound/research/security/auth-patterns.md\` for common broken patterns and framework-specific checks
5206
+ 2. Perform route audit:
5207
+ - List all route/endpoint definitions in changed files
5208
+ - For each route, verify auth middleware or guard is applied
5209
+ - Flag routes that modify data (POST/PUT/DELETE) without auth
5210
+ - Flag admin/privileged routes accessible without role checks
5211
+ 3. Check for IDOR (Insecure Direct Object Reference):
5212
+ - Find DB queries using user-supplied IDs from params/body
5213
+ - Verify ownership checks exist (e.g., \`WHERE id = ? AND user_id = ?\`)
5214
+ - Flag queries that fetch by ID alone without ownership verification
5215
+ 4. Check JWT handling:
5216
+ - Verify signature validation is not skipped
5217
+ - Check for algorithm confusion vulnerabilities (\`alg: none\`)
5218
+ - Verify expiry (\`exp\`) is checked
5219
+ - Flag tokens stored in localStorage (prefer httpOnly cookies)
5220
+ 5. Check CORS configuration:
5221
+ - Flag \`Access-Control-Allow-Origin: *\` with credentials
5222
+ - Flag overly permissive origin patterns
5223
+ - Verify CORS is intentional and scoped appropriately
5224
+ 6. Framework-specific checks:
5225
+ - **Express/NestJS**: missing \`authMiddleware\`, missing \`@UseGuards()\`, routes outside auth scope
5226
+ - **Django/FastAPI**: missing \`@login_required\`, missing \`Depends(get_current_user)\`, missing permission classes
5227
+ 7. For non-web projects (CLI tools, libraries): limit scope to file permissions, API key handling, and privilege escalation
5228
+
5229
+ ## Literature
5230
+ - Consult \`docs/compound/research/security/auth-patterns.md\` for broken auth patterns and detection methodology
5231
+ - Consult \`docs/compound/research/security/secure-coding-failure.md\` section 4.7 for theoretical foundation
5232
+ - Run \`npx ca knowledge "authentication authorization IDOR"\` for indexed knowledge
5233
+
5234
+ ## Collaboration
5235
+ Report findings to security-reviewer via SendMessage with severity classification. Flag missing middleware patterns to architecture-reviewer.
5236
+
5237
+ ## Deployment
5238
+ On-demand AgentTeam member in the **review** phase. Spawned by security-reviewer when auth patterns need deep analysis. Communicate with teammates via SendMessage.
5239
+
5240
+ ## Output Format
5241
+ Per finding:
5242
+ - **Type**: Missing Auth / IDOR / Role Escalation / JWT / CORS
5243
+ - **Severity**: P0-P3
5244
+ - **File:Line**: Location
5245
+ - **Route/Endpoint**: The affected route
5246
+ - **Issue**: What is missing or broken
5247
+ - **Fix**: Specific middleware, guard, or check to add
5248
+
5249
+ If no findings: return "AUTH REVIEW: CLEAR -- No authentication or authorization issues found."
5250
+ `,
5251
+ "security-data": `---
5252
+ name: Security Data Specialist
5253
+ description: Audit for PII in logs, verbose error responses, sensitive data in URLs, and overly broad API responses
5254
+ ---
5255
+
5256
+ # Security Data Specialist
5257
+
5258
+ ## Role
5259
+ On-demand specialist for detecting sensitive data exposure through logging, error handling, URLs, and API responses.
5260
+
5261
+ ## Instructions
5262
+ 1. Read \`docs/compound/research/security/data-exposure.md\` for exposure patterns and detection heuristics
5263
+ 2. Audit logging calls:
5264
+ - Flag \`console.log(req.body)\`, \`console.log(req.headers)\`, \`logger.info(user)\` -- unfiltered objects may contain passwords/tokens
5265
+ - Flag logging of \`Authorization\` header values
5266
+ - Flag logging of full error objects that may contain connection strings
5267
+ - Check structured loggers for field-level filtering
5268
+ 3. Audit error handlers:
5269
+ - Flag \`res.status(500).json({ error: err.message })\` or \`err.stack\` sent to clients
5270
+ - Flag DB connection strings, internal paths, or query details in error responses
5271
+ - Verify production error handlers return generic messages
5272
+ 4. Audit URLs and query parameters:
5273
+ - Flag tokens, keys, or auth values in query strings (leaks via referrer, logs, browser history)
5274
+ - Flag PII (email, name, SSN) in URL paths or query params
5275
+ - Check redirect URLs for open redirect patterns
5276
+ 5. Audit API responses:
5277
+ - Flag endpoints returning full DB records instead of selected fields
5278
+ - Flag responses containing \`password_hash\`, \`internal_id\`, \`secret\`, or similar internal fields
5279
+ - Verify response serialization uses explicit field selection or DTOs
5280
+
5281
+ ## Literature
5282
+ - Consult \`docs/compound/research/security/data-exposure.md\` for exposure patterns and detection heuristics
5283
+ - Consult \`docs/compound/research/security/secure-coding-failure.md\` section 4.8 for theoretical foundation
5284
+ - Run \`npx ca knowledge "data exposure PII logging"\` for indexed knowledge
5285
+
5286
+ ## Collaboration
5287
+ Report findings to security-reviewer via SendMessage with severity classification. Flag logging architecture issues to architecture-reviewer.
5288
+
5289
+ ## Deployment
5290
+ On-demand AgentTeam member in the **review** phase. Spawned by security-reviewer when data exposure patterns detected. Communicate with teammates via SendMessage.
5291
+
5292
+ ## Output Format
5293
+ Per finding:
5294
+ - **Type**: PII in Logs / Verbose Error / URL Exposure / Broad API Response
5295
+ - **Severity**: P0 (credentials in logs/responses) / P1 (PII exposure) / P2 (internal details) / P3 (hardening)
5296
+ - **File:Line**: Location
5297
+ - **Data at risk**: What sensitive data is exposed
5298
+ - **Channel**: Log / Error response / URL / API response
5299
+ - **Fix**: Specific filtering, redaction, or restructuring needed
5300
+
5301
+ If no findings: return "DATA EXPOSURE REVIEW: CLEAR -- No sensitive data exposure patterns found."
5302
+ `,
5303
+ "security-deps": `---
5304
+ name: Security Deps Specialist
5305
+ description: Dependency audit for vulnerable packages, lockfile changes, postinstall scripts, and supply chain risks
5306
+ ---
5307
+
5308
+ # Security Deps Specialist
5309
+
5310
+ ## Role
5311
+ On-demand specialist for auditing dependency security, lockfile changes, and supply chain risks.
5312
+
5313
+ ## Instructions
5314
+ 1. Read \`docs/compound/research/security/dependency-security.md\` for risk model and audit methodology
5315
+ 2. Run audit tools on changed dependency files:
5316
+ - **JS/TS**: \`pnpm audit\` or \`npm audit\` -- report critical and high vulnerabilities
5317
+ - **Python**: \`pip-audit\` or \`safety check\` -- report known CVEs
5318
+ - If audit tool is unavailable, note it and proceed with manual lockfile analysis
5319
+ 3. Check lockfile changes (pnpm-lock.yaml, package-lock.json, poetry.lock, requirements.txt):
5320
+ - **New direct deps**: Were they intentionally added? Check PR context
5321
+ - **Version downgrades**: Suspicious -- may reintroduce vulnerabilities
5322
+ - **New postinstall scripts**: Can execute arbitrary code during install
5323
+ - **Removed integrity hashes**: May indicate tampering
5324
+ 4. Evaluate new dependencies:
5325
+ - Check maintenance status (last commit, open issues, bus factor)
5326
+ - Flag packages with fewer than 100 weekly downloads (typosquat risk)
5327
+ - Flag packages pinned 3+ major versions behind latest
5328
+ - Check for known alternatives with better security track record
5329
+ 5. For large dependency changes, spawn opus subagents to audit different package groups in parallel.
5330
+
5331
+ ## Literature
5332
+ - Consult \`docs/compound/research/security/dependency-security.md\` for risk assessment methodology
5333
+ - Consult \`docs/compound/research/security/secure-coding-failure.md\` section 4.9 for theoretical foundation
5334
+ - Run \`npx ca knowledge "dependency vulnerability supply chain"\` for indexed knowledge
5335
+
5336
+ ## Collaboration
5337
+ Report findings to security-reviewer via SendMessage with severity classification. Flag architecture-level dependency concerns (e.g., replacing a core library) to architecture-reviewer.
5338
+
5339
+ ## Deployment
5340
+ On-demand AgentTeam member in the **review** phase. Spawned by security-reviewer when dependency changes detected. Communicate with teammates via SendMessage.
5341
+
5342
+ ## Output Format
5343
+ Per finding:
5344
+ - **Package**: name@version
5345
+ - **Severity**: P0 (actively exploited CVE) / P1 (critical CVE) / P2 (high CVE, outdated) / P3 (maintenance concern)
5346
+ - **CVE**: ID if applicable
5347
+ - **Issue**: What the vulnerability enables
5348
+ - **Fix**: Update to version X, replace with Y, or accept risk with justification
5349
+
5350
+ If no findings: return "DEPENDENCY REVIEW: CLEAR -- No vulnerable or suspicious dependencies found."
5043
5351
  `
5044
5352
  };
5045
5353
 
@@ -5514,8 +5822,8 @@ Multi-agent code review with severity classification.
5514
5822
 
5515
5823
  - Run quality gates: \`pnpm test && pnpm lint\`
5516
5824
  - Spawn specialized reviewers (security, architecture, performance, etc.)
5517
- - Classify findings as P1/P2/P3
5518
- - Fix all P1 findings before proceeding
5825
+ - Classify findings as P0 (blocks merge) / P1/P2/P3
5826
+ - Fix all P0/P1 findings before proceeding
5519
5827
 
5520
5828
  ## Phase 5: Compound
5521
5829
 
@@ -6196,7 +6504,7 @@ description: Multi-agent review with parallel specialized reviewers and severity
6196
6504
  # Review Skill
6197
6505
 
6198
6506
  ## Overview
6199
- Perform thorough code review by spawning specialized reviewers in parallel, consolidating findings with severity classification (P1/P2/P3), and gating completion on implementation-reviewer approval.
6507
+ Perform thorough code review by spawning specialized reviewers in parallel, consolidating findings with severity classification (P0/P1/P2/P3), and gating completion on implementation-reviewer approval.
6200
6508
 
6201
6509
  ## Methodology
6202
6510
  1. Run quality gates first: \`pnpm test && pnpm lint\`
@@ -6207,10 +6515,11 @@ Perform thorough code review by spawning specialized reviewers in parallel, cons
6207
6515
  - **Large** (500+): all 11 reviewers including docs, consistency, error-handling, pattern-matcher
6208
6516
  4. Spawn reviewers in an **AgentTeam** (TeamCreate + Task with \`team_name\`):
6209
6517
  - Role skills: \`.claude/skills/compound/agents/{security-reviewer,architecture-reviewer,performance-reviewer,test-coverage-reviewer,simplicity-reviewer}/SKILL.md\`
6518
+ - Security specialist skills (on-demand, spawned by security-reviewer): \`.claude/skills/compound/agents/{security-injection,security-secrets,security-auth,security-data,security-deps}/SKILL.md\`
6210
6519
  - For large diffs (500+), deploy MULTIPLE instances; split files across instances, coordinate via SendMessage
6211
6520
  5. Reviewers communicate findings to each other via \`SendMessage\`
6212
6521
  6. Collect, consolidate, and deduplicate all findings
6213
- 7. Classify by severity: P1 (critical/blocking), P2 (important), P3 (minor)
6522
+ 7. Classify by severity: P0 (blocks merge), P1 (critical/blocking), P2 (important), P3 (minor)
6214
6523
  8. Use \`AskUserQuestion\` when severity is ambiguous or fix has multiple valid options
6215
6524
  9. Create beads issues for P1 findings: \`bd create --title="P1: ..."\`
6216
6525
  10. Fix all P1 findings before proceeding
@@ -6239,10 +6548,12 @@ Perform thorough code review by spawning specialized reviewers in parallel, cons
6239
6548
  ## Quality Criteria
6240
6549
  - All quality gates pass (\`pnpm test\`, lint)
6241
6550
  - All 11 reviewer perspectives were applied in parallel
6242
- - Findings are classified P1/P2/P3 and deduplicated
6551
+ - Findings are classified P0/P1/P2/P3 and deduplicated
6243
6552
  - pattern-matcher checked memory and reinforced recurring issues
6244
6553
  - cct-reviewer checked against known Claude failure patterns
6245
6554
  - docs-reviewer confirmed docs/ADR alignment
6555
+ - security-reviewer P0 findings: none (blocks merge)
6556
+ - security-reviewer P1 findings: all acknowledged or resolved
6246
6557
  - All P1 findings fixed before \`/implementation-reviewer\` approval
6247
6558
  - \`/implementation-reviewer\` approved as mandatory gate
6248
6559
 
@@ -7870,19 +8181,12 @@ async function runDoctor(repoRoot) {
7870
8181
  } catch {
7871
8182
  }
7872
8183
  checks.push(hooksOk ? { name: "Claude hooks", status: "pass" } : { name: "Claude hooks", status: "fail", fix: "Run: npx ca setup" });
7873
- let modelOk = false;
7874
- try {
7875
- modelOk = isModelAvailable();
7876
- } catch {
8184
+ checks.push(checkEmbeddingModel());
8185
+ checks.push(checkSqliteHealth());
8186
+ const pnpmCheck = checkPnpmBuildConfig(repoRoot);
8187
+ if (pnpmCheck !== null) {
8188
+ checks.push(pnpmCheck);
7877
8189
  }
7878
- checks.push(modelOk ? { name: "Embedding model", status: "pass" } : { name: "Embedding model", status: "warn", fix: "Run: npx ca download-model" });
7879
- let sqliteOk = false;
7880
- try {
7881
- ensureSqliteAvailable();
7882
- sqliteOk = true;
7883
- } catch {
7884
- }
7885
- checks.push(sqliteOk ? { name: "SQLite (better-sqlite3)", status: "pass" } : { name: "SQLite (better-sqlite3)", status: "fail", fix: "Run: pnpm rebuild better-sqlite3 (or npm rebuild better-sqlite3)" });
7886
8190
  const beadsResult = checkBeadsAvailable();
7887
8191
  checks.push(beadsResult.available ? { name: "Beads CLI", status: "pass" } : { name: "Beads CLI", status: "warn", fix: "Install beads: https://github.com/Nathandela/beads" });
7888
8192
  checks.push(checkGitignoreHealth(repoRoot) ? { name: ".gitignore health", status: "pass" } : { name: ".gitignore health", status: "warn", fix: "Run: npx ca setup --update" });
@@ -7902,6 +8206,46 @@ async function runDoctor(repoRoot) {
7902
8206
  checks.push(!scope.isUserScope ? { name: "Codebase scope", status: "pass" } : { name: "Codebase scope", status: "warn", fix: "Install in a specific repository, not home directory" });
7903
8207
  return checks;
7904
8208
  }
8209
+ function checkEmbeddingModel() {
8210
+ try {
8211
+ return isModelAvailable() ? { name: "Embedding model", status: "pass" } : { name: "Embedding model", status: "warn", fix: "Run: npx ca download-model" };
8212
+ } catch {
8213
+ return { name: "Embedding model", status: "warn", fix: "Run: npx ca download-model" };
8214
+ }
8215
+ }
8216
+ function checkSqliteHealth() {
8217
+ try {
8218
+ ensureSqliteAvailable();
8219
+ return { name: "SQLite (better-sqlite3)", status: "pass" };
8220
+ } catch {
8221
+ return { name: "SQLite (better-sqlite3)", status: "fail", fix: "Run: pnpm rebuild better-sqlite3 (or npm rebuild better-sqlite3)" };
8222
+ }
8223
+ }
8224
+ function checkPnpmBuildConfig(repoRoot) {
8225
+ const lockPath = join(repoRoot, "pnpm-lock.yaml");
8226
+ const pkgPath = join(repoRoot, "package.json");
8227
+ let pkg;
8228
+ try {
8229
+ pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
8230
+ } catch {
8231
+ return null;
8232
+ }
8233
+ const hasLockfile = existsSync(lockPath);
8234
+ const hasPmField = typeof pkg.packageManager === "string" && pkg.packageManager.startsWith("pnpm");
8235
+ if (!hasLockfile && !hasPmField) return null;
8236
+ const pnpmConfig = pkg.pnpm;
8237
+ const deps = pnpmConfig?.onlyBuiltDependencies;
8238
+ if (!Array.isArray(deps)) {
8239
+ return { name: "pnpm build config", status: "fail", fix: 'Run: npx ca setup (or add "pnpm.onlyBuiltDependencies" to package.json)' };
8240
+ }
8241
+ if (deps.includes("*")) return { name: "pnpm build config", status: "pass" };
8242
+ const required = ["better-sqlite3", "node-llama-cpp"];
8243
+ const missing = required.filter((d) => !deps.includes(d));
8244
+ if (missing.length > 0) {
8245
+ return { name: "pnpm build config", status: "fail", fix: `Missing from onlyBuiltDependencies: [${missing.join(", ")}]. Run: npx ca setup` };
8246
+ }
8247
+ return { name: "pnpm build config", status: "pass" };
8248
+ }
7905
8249
  var STATUS_ICONS = {
7906
8250
  pass: "OK",
7907
8251
  fail: "FAIL",
@@ -8686,7 +9030,42 @@ function registerVerifyGatesCommand(program2) {
8686
9030
  }
8687
9031
 
8688
9032
  // src/changelog-data.ts
8689
- var CHANGELOG_RECENT = `## [1.4.3] - 2026-02-23
9033
+ var CHANGELOG_RECENT = `## [1.4.4] - 2026-02-23
9034
+
9035
+ ### Added
9036
+
9037
+ - **Security arc with P0-P3 severity model**: Security-reviewer promoted from generic OWASP checker to mandatory core-4 reviewer with P0 (blocks merge), P1 (requires ack), P2 (should fix), P3 (nice to have) classification
9038
+ - **5 on-demand security specialist skills**: \`/security-injection\`, \`/security-secrets\`, \`/security-auth\`, \`/security-data\`, \`/security-deps\` -- spawned by security-reviewer via SendMessage within the review AgentTeam for deep trace analysis
9039
+ - **6 security reference docs** (\`docs/research/security/\`): overview, injection-patterns, secrets-checklist, auth-patterns, data-exposure, dependency-security -- distilled from the secure-coding-failure PhD survey into actionable agent guides
9040
+ - **Native addon build injection** (\`scripts/postinstall.mjs\`): Postinstall script auto-patches consumer \`package.json\` with \`pnpm.onlyBuiltDependencies\` config for \`better-sqlite3\` and \`node-llama-cpp\`. Handles indent preservation, BOM stripping, atomic writes
9041
+ - **CLI preflight diagnostics** (\`src/cli-preflight.ts\`): Catches native module load failures before commands run, prints PM-specific fix instructions (pnpm: 3 options; npm/yarn: rebuild + build tool hints)
9042
+ - **\`ca doctor\` pnpm check**: Verifies \`onlyBuiltDependencies\` is configured correctly for pnpm projects, recognizes wildcard \`["*"]\` as valid
9043
+ - **Escalation-wiring tests**: 7 new tests verifying security-reviewer mentions all 5 specialists, each specialist declares "Spawned by security-reviewer", P0 documented as merge-blocking, each specialist has \`npx ca knowledge\` and references correct research doc
9044
+ - **better-sqlite3 injection patterns**: Added project-specific \`db.exec()\` vs \`db.prepare().run()\` examples to \`injection-patterns.md\`
9045
+
9046
+ ### Fixed
9047
+
9048
+ - **Noisy \`node-llama-cpp\` warnings on headless Linux**: Vulkan binary fallback and \`special_eos_id\` tokenizer warnings no longer print during \`ca search\` / \`ca knowledge\` -- GPU auto-detection preserved via \`progressLogs: false\` + \`logLevel: error\`
9049
+ - **Resource leak in \`isModelUsable()\`**: \`Llama\` and \`LlamaModel\` instances are now properly disposed after the preflight usability check
9050
+ - **Wildcard \`onlyBuiltDependencies\`**: Doctor and postinstall now recognize \`["*"]\` as fully configured (no false positive)
9051
+ - **Infinity loop marker injection**: \`--model\` validated against shell metacharacters; grep patterns anchored (\`^EPIC_COMPLETE\`, \`^EPIC_FAILED\`) to prevent false-positive matches from prompt echo in logs
9052
+ - **Template-to-deployed SKILL.md drift**: Backported all deployed specialist improvements (output fields, collaboration notes, \`npx ca knowledge\` lines) into source templates so \`ca setup --update\` no longer regresses
9053
+ - **SSRF citations**: 3 OWASP references in \`secure-coding-failure.md\` corrected from A01 (Broken Access Control) to A10 (SSRF)
9054
+ - **Stale verification docs**: Exit criteria updated from 6 to 8 categories (added Security Clear + Workflow Gates); closed-loop review process updated with security check in Stage 4 flowchart
9055
+ - **Broken dual-path reference** in \`subagent-pipeline.md\`: Now documents both \`docs/research/security/\` (source repo) and \`docs/compound/research/security/\` (consumer repos)
9056
+ - **Incomplete OWASP mapping** in \`overview.md\`: Completed from 5/10 to 10/10 (added A04, A05, A07, A08, A09)
9057
+
9058
+ ### Changed
9059
+
9060
+ - **\`getLlama()\` initialization hardened**: Both call sites (\`nomic.ts\`, \`model.ts\`) now pass \`build: 'never'\` to prevent silent compilation from source on exotic platforms; set \`NODE_LLAMA_CPP_DEBUG=true\` to re-enable verbose output
9061
+ - **Review skill wired to security arc**: P0 added to severity overview, security specialist skills listed as on-demand members, quality criteria include P0/P1 checks
9062
+ - **WORKFLOW template**: Severity classification updated from P1/P2/P3 to P0-P3 with "Fix all P0/P1 findings"
9063
+ - **Zero-findings instruction**: All 6 security templates (reviewer + 5 specialists) now include "return CLEAR" instruction when no findings detected
9064
+ - **Scope-limiting instruction**: \`security-injection\` prioritizes files with interpreter sinks over pure data/config for large diffs (500+ lines)
9065
+ - **Non-web context**: \`security-auth\` includes step for CLI/API-only projects without web routes
9066
+ - **Graceful audit skip**: \`security-deps\` handles missing \`pnpm audit\` / \`pip-audit\` gracefully instead of failing
9067
+
9068
+ ## [1.4.3] - 2026-02-23
8690
9069
 
8691
9070
  ### Fixed
8692
9071
 
@@ -8705,13 +9084,7 @@ var CHANGELOG_RECENT = `## [1.4.3] - 2026-02-23
8705
9084
 
8706
9085
  - **Banner audio crash on headless Linux**: Async \`ENOENT\` error from missing \`aplay\` no longer crashes \`ca setup --update\`
8707
9086
  - **PowerShell path injection on Windows**: Temp paths containing apostrophes no longer break or inject commands in \`banner-audio.ts\`
8708
- - **Banner audio test coverage**: Rewrote tests with proper mock isolation (\`vi.spyOn\` + file-scope \`vi.mock\`), covering async ENOENT, sync throw, stop() idempotency, and normal exit cleanup
8709
-
8710
- ## [1.4.1] - 2026-02-22
8711
-
8712
- ### Changed
8713
-
8714
- - **Broader retrieval messaging**: \`ca search\` and \`ca knowledge\` descriptions in prime output and AGENTS.md now encourage general-purpose use beyond mandatory architectural triggers`;
9087
+ - **Banner audio test coverage**: Rewrote tests with proper mock isolation (\`vi.spyOn\` + file-scope \`vi.mock\`), covering async ENOENT, sync throw, stop() idempotency, and normal exit cleanup`;
8715
9088
 
8716
9089
  // src/commands/about.ts
8717
9090
  function registerAboutCommand(program2) {
@@ -9350,6 +9723,7 @@ function registerCaptureCommands(program2) {
9350
9723
  });
9351
9724
  }
9352
9725
  var EPIC_ID_PATTERN2 = /^[a-zA-Z0-9_.-]+$/;
9726
+ var MODEL_PATTERN = /^[a-zA-Z0-9_.:/-]+$/;
9353
9727
  function buildScriptHeader(timestamp, maxRetries, model, epicIds) {
9354
9728
  return `#!/usr/bin/env bash
9355
9729
  # Infinity Loop - Generated by: ca loop
@@ -9550,18 +9924,18 @@ while true; do
9550
9924
  -p "$PROMPT" \\
9551
9925
  &> "$LOGFILE" || true
9552
9926
 
9553
- if grep -q "EPIC_COMPLETE" "$LOGFILE"; then
9927
+ if grep -q "^EPIC_COMPLETE$" "$LOGFILE"; then
9554
9928
  log "Epic $EPIC_ID completed successfully"
9555
9929
  SUCCESS=true
9556
9930
  break
9557
- elif grep -q "HUMAN_REQUIRED" "$LOGFILE"; then
9558
- REASON=$(grep "HUMAN_REQUIRED:" "$LOGFILE" | head -1 | sed 's/.*HUMAN_REQUIRED: *//')
9931
+ elif grep -q "^HUMAN_REQUIRED:" "$LOGFILE"; then
9932
+ REASON=$(grep "^HUMAN_REQUIRED:" "$LOGFILE" | head -1 | sed 's/^HUMAN_REQUIRED: *//')
9559
9933
  log "Epic $EPIC_ID needs human action: $REASON"
9560
9934
  bd update "$EPIC_ID" --notes "Human required: $REASON" 2>/dev/null || true
9561
9935
  SKIPPED=$((SKIPPED + 1))
9562
9936
  SUCCESS=skip
9563
9937
  break
9564
- elif grep -q "EPIC_FAILED" "$LOGFILE"; then
9938
+ elif grep -q "^EPIC_FAILED$" "$LOGFILE"; then
9565
9939
  log "Epic $EPIC_ID reported failure (attempt $ATTEMPT)"
9566
9940
  else
9567
9941
  log "Epic $EPIC_ID session ended without marker (attempt $ATTEMPT)"
@@ -9595,6 +9969,9 @@ function validateOptions(options) {
9595
9969
  if (!Number.isInteger(options.maxRetries) || options.maxRetries < 0) {
9596
9970
  throw new Error(`Invalid maxRetries: must be a non-negative integer, got ${options.maxRetries}`);
9597
9971
  }
9972
+ if (!MODEL_PATTERN.test(options.model)) {
9973
+ throw new Error(`Invalid model "${options.model}": must match ${MODEL_PATTERN}`);
9974
+ }
9598
9975
  if (options.epics) {
9599
9976
  for (const id of options.epics) {
9600
9977
  if (!EPIC_ID_PATTERN2.test(id)) {
@@ -9942,6 +10319,109 @@ function registerManagementCommands(program2) {
9942
10319
  registerWorktreeCommands(program2);
9943
10320
  }
9944
10321
 
10322
+ // src/cli-preflight.ts
10323
+ var NEEDS_SQLITE = /* @__PURE__ */ new Set([
10324
+ // Capture
10325
+ "learn",
10326
+ "capture",
10327
+ "detect",
10328
+ // Retrieval
10329
+ "search",
10330
+ "list",
10331
+ "load-session",
10332
+ "check-plan",
10333
+ // Knowledge
10334
+ "knowledge",
10335
+ "index-docs",
10336
+ // Management - CRUD
10337
+ "show",
10338
+ "update",
10339
+ "delete",
10340
+ // Management - invalidation
10341
+ "wrong",
10342
+ "validate",
10343
+ // Management - maintenance
10344
+ "compact",
10345
+ "rebuild",
10346
+ "stats",
10347
+ "prime",
10348
+ // Management - IO
10349
+ "export",
10350
+ "import",
10351
+ // Audit & compound
10352
+ "audit",
10353
+ "compound"
10354
+ ]);
10355
+ function commandNeedsSqlite(cmd) {
10356
+ let current = cmd;
10357
+ while (current) {
10358
+ if (NEEDS_SQLITE.has(current.name())) return true;
10359
+ current = current.parent;
10360
+ }
10361
+ return false;
10362
+ }
10363
+ function detectPackageManager(cwd) {
10364
+ if (existsSync(join(cwd, "pnpm-lock.yaml"))) return "pnpm";
10365
+ try {
10366
+ const raw = readFileSync(join(cwd, "package.json"), "utf-8");
10367
+ const pkg = JSON.parse(raw);
10368
+ if (typeof pkg.packageManager === "string") {
10369
+ if (pkg.packageManager.startsWith("pnpm")) return "pnpm";
10370
+ if (pkg.packageManager.startsWith("yarn")) return "yarn";
10371
+ }
10372
+ } catch {
10373
+ }
10374
+ if (existsSync(join(cwd, "yarn.lock"))) return "yarn";
10375
+ if (existsSync(join(cwd, "package-lock.json"))) return "npm";
10376
+ return "unknown";
10377
+ }
10378
+ function printNativeBuildDiagnostic(err, cwd = process.cwd()) {
10379
+ const pm = detectPackageManager(cwd);
10380
+ console.error("");
10381
+ console.error('ERROR: Native module "better-sqlite3" failed to load.');
10382
+ console.error("");
10383
+ if (pm === "pnpm") {
10384
+ console.error(" pnpm v10+ blocks native addon builds by default.");
10385
+ console.error("");
10386
+ console.error(" Fix (choose one):");
10387
+ console.error("");
10388
+ console.error(" Option A -- Run setup (recommended):");
10389
+ console.error(" npx ca setup");
10390
+ console.error("");
10391
+ console.error(" Option B -- Manual patch:");
10392
+ console.error(" 1. Add to package.json:");
10393
+ console.error(' "pnpm": { "onlyBuiltDependencies": ["better-sqlite3", "node-llama-cpp"] }');
10394
+ console.error(" 2. Run: pnpm install && pnpm rebuild better-sqlite3");
10395
+ console.error("");
10396
+ console.error(" Option C -- Approve build scripts interactively:");
10397
+ console.error(" pnpm approve-builds");
10398
+ console.error("");
10399
+ } else {
10400
+ console.error(" Fix: npm rebuild better-sqlite3");
10401
+ console.error("");
10402
+ console.error(" If the error persists, ensure build tools are installed:");
10403
+ printBuildToolsHint();
10404
+ console.error("");
10405
+ }
10406
+ if (err instanceof Error && err.cause) {
10407
+ const causeMsg = err.cause instanceof Error ? err.cause.message : String(err.cause);
10408
+ console.error(" Underlying error:", causeMsg);
10409
+ console.error("");
10410
+ }
10411
+ }
10412
+ function printBuildToolsHint() {
10413
+ const platform = process.platform;
10414
+ if (platform === "darwin") {
10415
+ console.error(" macOS: xcode-select --install");
10416
+ } else if (platform === "linux") {
10417
+ console.error(" Linux: sudo apt install build-essential python3 (Debian/Ubuntu)");
10418
+ console.error(' sudo dnf groupinstall "Development Tools" (Fedora)');
10419
+ } else if (platform === "win32") {
10420
+ console.error(" Windows: Install Visual Studio Build Tools");
10421
+ console.error(" https://visualstudio.microsoft.com/visual-cpp-build-tools/");
10422
+ }
10423
+ }
10424
+
9945
10425
  // src/cli.ts
9946
10426
  function cleanup() {
9947
10427
  try {
@@ -9967,6 +10447,20 @@ registerSetupCommands(program);
9967
10447
  registerCompoundCommands(program);
9968
10448
  registerLoopCommands(program);
9969
10449
  registerPhaseCheckCommand(program);
10450
+ program.hook("preAction", (_thisCommand, actionCommand) => {
10451
+ if (!commandNeedsSqlite(actionCommand)) return;
10452
+ try {
10453
+ ensureSqliteAvailable();
10454
+ } catch (err) {
10455
+ let root;
10456
+ try {
10457
+ root = getRepoRoot();
10458
+ } catch {
10459
+ }
10460
+ printNativeBuildDiagnostic(err, root);
10461
+ process.exit(1);
10462
+ }
10463
+ });
9970
10464
  program.parse();
9971
10465
  //# sourceMappingURL=cli.js.map
9972
10466
  //# sourceMappingURL=cli.js.map