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/CHANGELOG.md +39 -1
- package/dist/cli.js +543 -49
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +34 -5
- package/dist/index.js.map +1 -1
- package/docs/research/index.md +12 -0
- package/docs/research/security/auth-patterns.md +138 -0
- package/docs/research/security/data-exposure.md +185 -0
- package/docs/research/security/dependency-security.md +91 -0
- package/docs/research/security/injection-patterns.md +249 -0
- package/docs/research/security/overview.md +81 -0
- package/docs/research/security/secrets-checklist.md +92 -0
- package/docs/research/security/secure-coding-failure.md +297 -0
- package/package.json +3 -1
- package/scripts/postinstall.mjs +102 -0
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:
|
|
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
|
-
|
|
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
|
|
4882
|
-
2.
|
|
4883
|
-
|
|
4884
|
-
|
|
4885
|
-
|
|
4886
|
-
|
|
4887
|
-
|
|
4888
|
-
|
|
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/
|
|
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
|
|
4902
|
-
- **
|
|
4903
|
-
- **
|
|
4904
|
-
- **
|
|
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
|
-
|
|
7874
|
-
|
|
7875
|
-
|
|
7876
|
-
|
|
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.
|
|
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
|
|
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
|