compound-agent 1.4.2 → 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 +52 -1
- package/dist/cli.js +634 -46
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +38 -6
- 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';
|
|
@@ -33,7 +33,7 @@ function ensureSqliteAvailable() {
|
|
|
33
33
|
checked = true;
|
|
34
34
|
} catch (cause) {
|
|
35
35
|
throw new Error(
|
|
36
|
-
'better-sqlite3 failed to load.\
|
|
36
|
+
'better-sqlite3 failed to load.\nFor pnpm projects:\n 1. Ensure package.json has: "pnpm": { "onlyBuiltDependencies": ["better-sqlite3"] }\n 2. Run: pnpm install && pnpm rebuild better-sqlite3\nFor npm/yarn projects:\n Run: npm rebuild better-sqlite3\nIf the error persists, check that build tools (python3, make, g++) are installed.',
|
|
37
37
|
{ cause }
|
|
38
38
|
);
|
|
39
39
|
}
|
|
@@ -42,6 +42,10 @@ function getDatabaseConstructor() {
|
|
|
42
42
|
ensureSqliteAvailable();
|
|
43
43
|
return DatabaseConstructor;
|
|
44
44
|
}
|
|
45
|
+
function resetSqliteAvailability() {
|
|
46
|
+
checked = false;
|
|
47
|
+
DatabaseConstructor = null;
|
|
48
|
+
}
|
|
45
49
|
var require2, checked, DatabaseConstructor;
|
|
46
50
|
var init_availability = __esm({
|
|
47
51
|
"src/memory/storage/sqlite/availability.ts"() {
|
|
@@ -580,7 +584,15 @@ async function isModelUsable() {
|
|
|
580
584
|
let context = null;
|
|
581
585
|
try {
|
|
582
586
|
const modelPath = join(DEFAULT_MODEL_DIR, MODEL_FILENAME);
|
|
583
|
-
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
|
+
});
|
|
584
596
|
model = await llama.loadModel({ modelPath });
|
|
585
597
|
context = await model.createEmbeddingContext();
|
|
586
598
|
cachedUsability = { usable: true };
|
|
@@ -596,7 +608,19 @@ async function isModelUsable() {
|
|
|
596
608
|
} finally {
|
|
597
609
|
if (context) {
|
|
598
610
|
try {
|
|
599
|
-
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();
|
|
600
624
|
} catch {
|
|
601
625
|
}
|
|
602
626
|
}
|
|
@@ -618,7 +642,15 @@ async function getEmbedding() {
|
|
|
618
642
|
pendingInit = (async () => {
|
|
619
643
|
try {
|
|
620
644
|
const modelPath = await resolveModel({ cli: true });
|
|
621
|
-
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
|
+
});
|
|
622
654
|
modelInstance = await llamaInstance.loadModel({ modelPath });
|
|
623
655
|
embeddingContext = await modelInstance.createEmbeddingContext();
|
|
624
656
|
return embeddingContext;
|
|
@@ -1086,6 +1118,9 @@ async function syncIfNeeded(repoRoot, options = {}) {
|
|
|
1086
1118
|
return false;
|
|
1087
1119
|
}
|
|
1088
1120
|
|
|
1121
|
+
// src/memory/storage/sqlite/index.ts
|
|
1122
|
+
init_availability();
|
|
1123
|
+
|
|
1089
1124
|
// src/memory/search/hybrid.ts
|
|
1090
1125
|
var DEFAULT_VECTOR_WEIGHT = 0.7;
|
|
1091
1126
|
var DEFAULT_TEXT_WEIGHT = 0.3;
|
|
@@ -3617,6 +3652,19 @@ function printPnpmConfigStatus(result) {
|
|
|
3617
3652
|
console.log(` pnpm config: Added onlyBuiltDependencies [${result.added.join(", ")}]`);
|
|
3618
3653
|
}
|
|
3619
3654
|
}
|
|
3655
|
+
var SQLITE_STATUS_MSG = {
|
|
3656
|
+
already_ok: "OK",
|
|
3657
|
+
rebuilt: "OK (rebuilt native module)",
|
|
3658
|
+
installed_and_rebuilt: "OK (installed + rebuilt native module)",
|
|
3659
|
+
failed: "FAILED"
|
|
3660
|
+
};
|
|
3661
|
+
function printSqliteStatus(result) {
|
|
3662
|
+
const msg = SQLITE_STATUS_MSG[result.action];
|
|
3663
|
+
console.log(` SQLite: ${msg}`);
|
|
3664
|
+
if (result.error) {
|
|
3665
|
+
console.log(` ${result.error}`);
|
|
3666
|
+
}
|
|
3667
|
+
}
|
|
3620
3668
|
function printBeadsFullStatus(check) {
|
|
3621
3669
|
console.log(` Beads CLI: ${check.cliAvailable ? "OK" : "not found"}`);
|
|
3622
3670
|
if (check.cliAvailable) {
|
|
@@ -3651,6 +3699,13 @@ async function runStatus(repoRoot) {
|
|
|
3651
3699
|
} catch {
|
|
3652
3700
|
}
|
|
3653
3701
|
console.log(` Hooks: ${hooksInstalled ? "installed" : "not installed"}`);
|
|
3702
|
+
let sqliteOk = false;
|
|
3703
|
+
try {
|
|
3704
|
+
ensureSqliteAvailable();
|
|
3705
|
+
sqliteOk = true;
|
|
3706
|
+
} catch {
|
|
3707
|
+
}
|
|
3708
|
+
console.log(` SQLite: ${sqliteOk ? "OK" : "not available (run: pnpm rebuild better-sqlite3)"}`);
|
|
3654
3709
|
const fullBeads = runFullBeadsCheck(repoRoot);
|
|
3655
3710
|
printBeadsFullStatus(fullBeads);
|
|
3656
3711
|
const scope = checkUserScope(repoRoot);
|
|
@@ -4842,39 +4897,59 @@ Return a list of relevant memory items:
|
|
|
4842
4897
|
`,
|
|
4843
4898
|
"security-reviewer": `---
|
|
4844
4899
|
name: Security Reviewer
|
|
4845
|
-
description:
|
|
4900
|
+
description: Mandatory core-4 reviewer with P0-P3 severity classification and specialist escalation
|
|
4846
4901
|
---
|
|
4847
4902
|
|
|
4848
4903
|
# Security Reviewer
|
|
4849
4904
|
|
|
4850
4905
|
## Role
|
|
4851
|
-
|
|
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.
|
|
4852
4907
|
|
|
4853
4908
|
## Instructions
|
|
4854
|
-
1. Read
|
|
4855
|
-
2.
|
|
4856
|
-
|
|
4857
|
-
|
|
4858
|
-
|
|
4859
|
-
|
|
4860
|
-
|
|
4861
|
-
|
|
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.
|
|
4862
4928
|
|
|
4863
4929
|
## Literature
|
|
4864
|
-
- 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
|
|
4865
4937
|
- Run \`npx ca knowledge "security review OWASP"\` for indexed security knowledge
|
|
4866
4938
|
|
|
4867
4939
|
## Collaboration
|
|
4868
|
-
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.
|
|
4869
4941
|
|
|
4870
4942
|
## Deployment
|
|
4871
4943
|
AgentTeam member in the **review** phase. Spawned via TeamCreate. Communicate with teammates via SendMessage.
|
|
4872
4944
|
|
|
4873
4945
|
## Output Format
|
|
4874
|
-
Return findings
|
|
4875
|
-
- **
|
|
4876
|
-
- **
|
|
4877
|
-
- **
|
|
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."
|
|
4878
4953
|
`,
|
|
4879
4954
|
"architecture-reviewer": `---
|
|
4880
4955
|
name: Architecture Reviewer
|
|
@@ -5013,6 +5088,266 @@ AgentTeam member in the **review** phase. Spawned via TeamCreate. Communicate wi
|
|
|
5013
5088
|
- **OVER-ENGINEERED**: Simpler solution exists
|
|
5014
5089
|
- **YAGNI**: Feature not needed yet
|
|
5015
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."
|
|
5016
5351
|
`
|
|
5017
5352
|
};
|
|
5018
5353
|
|
|
@@ -5487,8 +5822,8 @@ Multi-agent code review with severity classification.
|
|
|
5487
5822
|
|
|
5488
5823
|
- Run quality gates: \`pnpm test && pnpm lint\`
|
|
5489
5824
|
- Spawn specialized reviewers (security, architecture, performance, etc.)
|
|
5490
|
-
- Classify findings as P1/P2/P3
|
|
5491
|
-
- Fix all P1 findings before proceeding
|
|
5825
|
+
- Classify findings as P0 (blocks merge) / P1/P2/P3
|
|
5826
|
+
- Fix all P0/P1 findings before proceeding
|
|
5492
5827
|
|
|
5493
5828
|
## Phase 5: Compound
|
|
5494
5829
|
|
|
@@ -6169,7 +6504,7 @@ description: Multi-agent review with parallel specialized reviewers and severity
|
|
|
6169
6504
|
# Review Skill
|
|
6170
6505
|
|
|
6171
6506
|
## Overview
|
|
6172
|
-
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.
|
|
6173
6508
|
|
|
6174
6509
|
## Methodology
|
|
6175
6510
|
1. Run quality gates first: \`pnpm test && pnpm lint\`
|
|
@@ -6180,10 +6515,11 @@ Perform thorough code review by spawning specialized reviewers in parallel, cons
|
|
|
6180
6515
|
- **Large** (500+): all 11 reviewers including docs, consistency, error-handling, pattern-matcher
|
|
6181
6516
|
4. Spawn reviewers in an **AgentTeam** (TeamCreate + Task with \`team_name\`):
|
|
6182
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\`
|
|
6183
6519
|
- For large diffs (500+), deploy MULTIPLE instances; split files across instances, coordinate via SendMessage
|
|
6184
6520
|
5. Reviewers communicate findings to each other via \`SendMessage\`
|
|
6185
6521
|
6. Collect, consolidate, and deduplicate all findings
|
|
6186
|
-
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)
|
|
6187
6523
|
8. Use \`AskUserQuestion\` when severity is ambiguous or fix has multiple valid options
|
|
6188
6524
|
9. Create beads issues for P1 findings: \`bd create --title="P1: ..."\`
|
|
6189
6525
|
10. Fix all P1 findings before proceeding
|
|
@@ -6212,10 +6548,12 @@ Perform thorough code review by spawning specialized reviewers in parallel, cons
|
|
|
6212
6548
|
## Quality Criteria
|
|
6213
6549
|
- All quality gates pass (\`pnpm test\`, lint)
|
|
6214
6550
|
- All 11 reviewer perspectives were applied in parallel
|
|
6215
|
-
- Findings are classified P1/P2/P3 and deduplicated
|
|
6551
|
+
- Findings are classified P0/P1/P2/P3 and deduplicated
|
|
6216
6552
|
- pattern-matcher checked memory and reinforced recurring issues
|
|
6217
6553
|
- cct-reviewer checked against known Claude failure patterns
|
|
6218
6554
|
- docs-reviewer confirmed docs/ADR alignment
|
|
6555
|
+
- security-reviewer P0 findings: none (blocks merge)
|
|
6556
|
+
- security-reviewer P1 findings: all acknowledged or resolved
|
|
6219
6557
|
- All P1 findings fixed before \`/implementation-reviewer\` approval
|
|
6220
6558
|
- \`/implementation-reviewer\` approved as mandatory gate
|
|
6221
6559
|
|
|
@@ -6802,6 +7140,60 @@ async function mergePnpmConfig(pkgPath, pkg) {
|
|
|
6802
7140
|
await writeFile(pkgPath, JSON.stringify(pkg, null, 2) + "\n", "utf-8");
|
|
6803
7141
|
return { isPnpm: true, alreadyConfigured: false, added };
|
|
6804
7142
|
}
|
|
7143
|
+
function trySqliteLoad() {
|
|
7144
|
+
try {
|
|
7145
|
+
ensureSqliteAvailable();
|
|
7146
|
+
return true;
|
|
7147
|
+
} catch {
|
|
7148
|
+
return false;
|
|
7149
|
+
}
|
|
7150
|
+
}
|
|
7151
|
+
function verifySqlite(repoRoot, pnpmConfig) {
|
|
7152
|
+
if (trySqliteLoad()) {
|
|
7153
|
+
return { available: true, action: "already_ok" };
|
|
7154
|
+
}
|
|
7155
|
+
if (!pnpmConfig.isPnpm) {
|
|
7156
|
+
return {
|
|
7157
|
+
available: false,
|
|
7158
|
+
action: "failed",
|
|
7159
|
+
error: "better-sqlite3 failed to load. Run: npm rebuild better-sqlite3"
|
|
7160
|
+
};
|
|
7161
|
+
}
|
|
7162
|
+
try {
|
|
7163
|
+
execFileSync("pnpm", ["rebuild", "better-sqlite3"], {
|
|
7164
|
+
cwd: repoRoot,
|
|
7165
|
+
stdio: "pipe",
|
|
7166
|
+
timeout: 6e4
|
|
7167
|
+
});
|
|
7168
|
+
} catch {
|
|
7169
|
+
}
|
|
7170
|
+
resetSqliteAvailability();
|
|
7171
|
+
if (trySqliteLoad()) {
|
|
7172
|
+
return { available: true, action: "rebuilt" };
|
|
7173
|
+
}
|
|
7174
|
+
try {
|
|
7175
|
+
execFileSync("pnpm", ["install"], {
|
|
7176
|
+
cwd: repoRoot,
|
|
7177
|
+
stdio: "pipe",
|
|
7178
|
+
timeout: 12e4
|
|
7179
|
+
});
|
|
7180
|
+
execFileSync("pnpm", ["rebuild", "better-sqlite3"], {
|
|
7181
|
+
cwd: repoRoot,
|
|
7182
|
+
stdio: "pipe",
|
|
7183
|
+
timeout: 6e4
|
|
7184
|
+
});
|
|
7185
|
+
} catch {
|
|
7186
|
+
}
|
|
7187
|
+
resetSqliteAvailability();
|
|
7188
|
+
if (trySqliteLoad()) {
|
|
7189
|
+
return { available: true, action: "installed_and_rebuilt" };
|
|
7190
|
+
}
|
|
7191
|
+
return {
|
|
7192
|
+
available: false,
|
|
7193
|
+
action: "failed",
|
|
7194
|
+
error: "Auto-rebuild failed. Run manually: pnpm install && pnpm rebuild better-sqlite3"
|
|
7195
|
+
};
|
|
7196
|
+
}
|
|
6805
7197
|
async function runUninstall(repoRoot, dryRun) {
|
|
6806
7198
|
const actions = [];
|
|
6807
7199
|
const dirsToRemove = [
|
|
@@ -6998,6 +7390,7 @@ async function runSetup(options) {
|
|
|
6998
7390
|
upgrade = await runUpgrade(repoRoot);
|
|
6999
7391
|
}
|
|
7000
7392
|
const pnpmConfig = await ensurePnpmBuildConfig(repoRoot);
|
|
7393
|
+
const sqlite = verifySqlite(repoRoot, pnpmConfig);
|
|
7001
7394
|
const lessonsDir = await ensureLessonsDirectory(repoRoot);
|
|
7002
7395
|
const agentsMdUpdated = await updateAgentsMd(repoRoot);
|
|
7003
7396
|
await ensureClaudeMdReference(repoRoot);
|
|
@@ -7040,6 +7433,7 @@ async function runSetup(options) {
|
|
|
7040
7433
|
postCommitHook,
|
|
7041
7434
|
model: modelStatus,
|
|
7042
7435
|
pnpmConfig,
|
|
7436
|
+
sqlite,
|
|
7043
7437
|
beads,
|
|
7044
7438
|
scope,
|
|
7045
7439
|
upgrade,
|
|
@@ -7141,6 +7535,7 @@ async function printSetupResult(result, quiet, repoRoot) {
|
|
|
7141
7535
|
printSetupGitHooksStatus(result.gitHooks);
|
|
7142
7536
|
printPostCommitHookStatus(result.postCommitHook);
|
|
7143
7537
|
printPnpmConfigStatus(result.pnpmConfig);
|
|
7538
|
+
printSqliteStatus(result.sqlite);
|
|
7144
7539
|
printGitignoreStatus(result.gitignore);
|
|
7145
7540
|
console.log(` Model: ${MODEL_STATUS_MSG[result.model]}`);
|
|
7146
7541
|
const fullBeads = runFullBeadsCheck(repoRoot);
|
|
@@ -7786,12 +8181,12 @@ async function runDoctor(repoRoot) {
|
|
|
7786
8181
|
} catch {
|
|
7787
8182
|
}
|
|
7788
8183
|
checks.push(hooksOk ? { name: "Claude hooks", status: "pass" } : { name: "Claude hooks", status: "fail", fix: "Run: npx ca setup" });
|
|
7789
|
-
|
|
7790
|
-
|
|
7791
|
-
|
|
7792
|
-
|
|
8184
|
+
checks.push(checkEmbeddingModel());
|
|
8185
|
+
checks.push(checkSqliteHealth());
|
|
8186
|
+
const pnpmCheck = checkPnpmBuildConfig(repoRoot);
|
|
8187
|
+
if (pnpmCheck !== null) {
|
|
8188
|
+
checks.push(pnpmCheck);
|
|
7793
8189
|
}
|
|
7794
|
-
checks.push(modelOk ? { name: "Embedding model", status: "pass" } : { name: "Embedding model", status: "warn", fix: "Run: npx ca download-model" });
|
|
7795
8190
|
const beadsResult = checkBeadsAvailable();
|
|
7796
8191
|
checks.push(beadsResult.available ? { name: "Beads CLI", status: "pass" } : { name: "Beads CLI", status: "warn", fix: "Install beads: https://github.com/Nathandela/beads" });
|
|
7797
8192
|
checks.push(checkGitignoreHealth(repoRoot) ? { name: ".gitignore health", status: "pass" } : { name: ".gitignore health", status: "warn", fix: "Run: npx ca setup --update" });
|
|
@@ -7811,6 +8206,46 @@ async function runDoctor(repoRoot) {
|
|
|
7811
8206
|
checks.push(!scope.isUserScope ? { name: "Codebase scope", status: "pass" } : { name: "Codebase scope", status: "warn", fix: "Install in a specific repository, not home directory" });
|
|
7812
8207
|
return checks;
|
|
7813
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
|
+
}
|
|
7814
8249
|
var STATUS_ICONS = {
|
|
7815
8250
|
pass: "OK",
|
|
7816
8251
|
fail: "FAIL",
|
|
@@ -8595,29 +9030,61 @@ function registerVerifyGatesCommand(program2) {
|
|
|
8595
9030
|
}
|
|
8596
9031
|
|
|
8597
9032
|
// src/changelog-data.ts
|
|
8598
|
-
var CHANGELOG_RECENT = `## [1.4.
|
|
9033
|
+
var CHANGELOG_RECENT = `## [1.4.4] - 2026-02-23
|
|
8599
9034
|
|
|
8600
|
-
###
|
|
9035
|
+
### Added
|
|
8601
9036
|
|
|
8602
|
-
- **
|
|
8603
|
-
- **
|
|
8604
|
-
- **
|
|
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
|
|
8605
9047
|
|
|
8606
|
-
|
|
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)
|
|
8607
9057
|
|
|
8608
9058
|
### Changed
|
|
8609
9059
|
|
|
8610
|
-
-
|
|
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
|
|
8611
9067
|
|
|
8612
|
-
## [1.4.
|
|
9068
|
+
## [1.4.3] - 2026-02-23
|
|
8613
9069
|
|
|
8614
9070
|
### Fixed
|
|
8615
9071
|
|
|
8616
|
-
- **
|
|
9072
|
+
- **Setup reports success when SQLite is broken**: \`npx ca setup\` now verifies that \`better-sqlite3\` actually loads after configuring \`pnpm.onlyBuiltDependencies\`, and auto-rebuilds if needed (escalates from \`pnpm rebuild\` to \`pnpm install + rebuild\`)
|
|
9073
|
+
- **Misleading error message**: \`ensureSqliteAvailable()\` no longer suggests "Run: npx ca setup" (which didn't fix the problem); now provides per-package-manager rebuild instructions and build tools hint
|
|
8617
9074
|
|
|
8618
|
-
###
|
|
9075
|
+
### Added
|
|
9076
|
+
|
|
9077
|
+
- **SQLite health check in \`ca doctor\`**: New check reports \`[FAIL]\` with fix hint when \`better-sqlite3\` cannot load
|
|
9078
|
+
- **SQLite status in \`ca setup --status\`**: Shows "OK" or "not available" alongside other status checks
|
|
9079
|
+
- **\`resetSqliteAvailability()\` export**: Allows re-probing SQLite after native module rebuild
|
|
8619
9080
|
|
|
8620
|
-
|
|
9081
|
+
## [1.4.2] - 2026-02-23
|
|
9082
|
+
|
|
9083
|
+
### Fixed
|
|
9084
|
+
|
|
9085
|
+
- **Banner audio crash on headless Linux**: Async \`ENOENT\` error from missing \`aplay\` no longer crashes \`ca setup --update\`
|
|
9086
|
+
- **PowerShell path injection on Windows**: Temp paths containing apostrophes no longer break or inject commands in \`banner-audio.ts\`
|
|
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`;
|
|
8621
9088
|
|
|
8622
9089
|
// src/commands/about.ts
|
|
8623
9090
|
function registerAboutCommand(program2) {
|
|
@@ -9256,6 +9723,7 @@ function registerCaptureCommands(program2) {
|
|
|
9256
9723
|
});
|
|
9257
9724
|
}
|
|
9258
9725
|
var EPIC_ID_PATTERN2 = /^[a-zA-Z0-9_.-]+$/;
|
|
9726
|
+
var MODEL_PATTERN = /^[a-zA-Z0-9_.:/-]+$/;
|
|
9259
9727
|
function buildScriptHeader(timestamp, maxRetries, model, epicIds) {
|
|
9260
9728
|
return `#!/usr/bin/env bash
|
|
9261
9729
|
# Infinity Loop - Generated by: ca loop
|
|
@@ -9456,18 +9924,18 @@ while true; do
|
|
|
9456
9924
|
-p "$PROMPT" \\
|
|
9457
9925
|
&> "$LOGFILE" || true
|
|
9458
9926
|
|
|
9459
|
-
if grep -q "EPIC_COMPLETE" "$LOGFILE"; then
|
|
9927
|
+
if grep -q "^EPIC_COMPLETE$" "$LOGFILE"; then
|
|
9460
9928
|
log "Epic $EPIC_ID completed successfully"
|
|
9461
9929
|
SUCCESS=true
|
|
9462
9930
|
break
|
|
9463
|
-
elif grep -q "HUMAN_REQUIRED" "$LOGFILE"; then
|
|
9464
|
-
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: *//')
|
|
9465
9933
|
log "Epic $EPIC_ID needs human action: $REASON"
|
|
9466
9934
|
bd update "$EPIC_ID" --notes "Human required: $REASON" 2>/dev/null || true
|
|
9467
9935
|
SKIPPED=$((SKIPPED + 1))
|
|
9468
9936
|
SUCCESS=skip
|
|
9469
9937
|
break
|
|
9470
|
-
elif grep -q "EPIC_FAILED" "$LOGFILE"; then
|
|
9938
|
+
elif grep -q "^EPIC_FAILED$" "$LOGFILE"; then
|
|
9471
9939
|
log "Epic $EPIC_ID reported failure (attempt $ATTEMPT)"
|
|
9472
9940
|
else
|
|
9473
9941
|
log "Epic $EPIC_ID session ended without marker (attempt $ATTEMPT)"
|
|
@@ -9501,6 +9969,9 @@ function validateOptions(options) {
|
|
|
9501
9969
|
if (!Number.isInteger(options.maxRetries) || options.maxRetries < 0) {
|
|
9502
9970
|
throw new Error(`Invalid maxRetries: must be a non-negative integer, got ${options.maxRetries}`);
|
|
9503
9971
|
}
|
|
9972
|
+
if (!MODEL_PATTERN.test(options.model)) {
|
|
9973
|
+
throw new Error(`Invalid model "${options.model}": must match ${MODEL_PATTERN}`);
|
|
9974
|
+
}
|
|
9504
9975
|
if (options.epics) {
|
|
9505
9976
|
for (const id of options.epics) {
|
|
9506
9977
|
if (!EPIC_ID_PATTERN2.test(id)) {
|
|
@@ -9848,6 +10319,109 @@ function registerManagementCommands(program2) {
|
|
|
9848
10319
|
registerWorktreeCommands(program2);
|
|
9849
10320
|
}
|
|
9850
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
|
+
|
|
9851
10425
|
// src/cli.ts
|
|
9852
10426
|
function cleanup() {
|
|
9853
10427
|
try {
|
|
@@ -9873,6 +10447,20 @@ registerSetupCommands(program);
|
|
|
9873
10447
|
registerCompoundCommands(program);
|
|
9874
10448
|
registerLoopCommands(program);
|
|
9875
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
|
+
});
|
|
9876
10464
|
program.parse();
|
|
9877
10465
|
//# sourceMappingURL=cli.js.map
|
|
9878
10466
|
//# sourceMappingURL=cli.js.map
|