git:20260830.6188cc0 to git:20260831.a7a770d

21 added, 14 removed. Audit A to A.

# SecGuard AI Agent Extension — E2E Design
## Multi-Agent Architecture
SecGuard supports multiple AI Agent platforms through a shared-core + platform-specific design:
```
extension/
shared/ # Platform-agnostic content — SINGLE SOURCE OF TRUTH
skills/ # Agent Skills spec (agentskills.io) — same for all
null-deref/SKILL.md
buffer-overflow/SKILL.md
memory-leak/SKILL.md
injection/SKILL.md
agent-body.md # Shared agent prompt (role, workflow, rules, output format)
command-instructions.md # Shared command workflow instructions
opencode/ # OpenCode-specific (thin frontmatter wrappers)
opencode.json # Config: agent, permissions, plugin
commands/secguard.md # Frontmatter + {{include shared/command-instructions.md}}
agents/security-auditor.md # Frontmatter + {{include shared/agent-body.md}}
tools/secguard_scan.ts # TypeScript tool wrappers (Bun.$ → CLI)
tools/secguard_index.ts
tools/secguard_plan.ts
tools/secguard_report.ts
tools/secguard_status.ts
plugins/secguard-context.ts # Plugin: auto-db-discovery, stale hints
claude-code/ # Claude Code-specific (thin frontmatter wrappers)
.claude/
settings.json # Permissions: pre-approve Bash(secguard *)
commands/secguard.md # Frontmatter + {{include shared/command-instructions.md}}
agents/security-auditor.md # Frontmatter + {{include shared/agent-body.md}}
install.sh # Installer: expands {{include}} + copies skills
```
## What's Shared vs. Platform-Specific
| Component | Shared? | Why |
|-----------|---------|-----|
| **Skills** (SKILL.md) | **Shared** | Both follow Agent Skills spec (agentskills.io). Identical format. |
| **Agent body** (role, workflow, rules, output) | **Shared** | Platform-agnostic instructions. Extracted to `shared/agent-body.md`. |
| **Command instructions** (workflow steps) | **Shared** | Platform-agnostic steps. Extracted to `shared/command-instructions.md`. |
| **Design doc** | **Shared** | Architecture is platform-agnostic. |
| **Command frontmatter** | **Separate** | Different fields (`agent:` vs `allowed-tools:`). Thin wrapper. |
| **Agent frontmatter** | **Separate** | Different permission models. Thin wrapper. |
| **Tools** | **Separate** | OpenCode: TypeScript + Bun.$; Claude Code: Bash + permissions. |
| **Config** | **Separate** | OpenCode: opencode.json; Claude Code: settings.json. |
| **Plugin/Hooks** | **Separate** | OpenCode: TS plugins; Claude Code: JSON hooks. |
### Turn Budget — Single Source of Truth
The orchestrator's batch model (see `shared/command-instructions.md` → Batch
Capacity Configuration) sizes subagent batches from `MAXTURNS` (30). Every
platform's agent definition MUST declare the same cap in its native field:
| Platform | Field | File |
|----------|-------|------|
| Claude Code | `maxTurns` | `claude-code/.claude/agents/security-auditor.md` |
| Claude CAC | `maxTurns` | `claude-cac/.cac/agents/security-auditor.md` |
| OpenCode | `steps` | `opencode/agents/security-auditor.md` (frontmatter) |
| OpenCode-NGA | `steps` | `opencode-nga/opencode.json` |
The OpenCode plugin (`opencode/index.ts`) reads `mode` / `temperature` / `steps` /
`permission` from the agent frontmatter — it never hardcodes them, so the
frontmatter is that platform's single declaration (no dead values).
`release/check-extension-consistency.py` asserts all five declarations match `MAXTURNS`
and that `index.ts` has no hardcoded `steps`; it also asserts the 8 `secguard_*`
tool names agree across `index.ts` `SECGUARD_TOOLS`, `opencode/tools/*.ts`, and the
`opencode-nga` permission list. `build-packages.sh` runs it before packaging, so
any drift fails the release build.
Changing the turn budget means editing `MAXTURNS` in `shared/command-instructions.md`
and the four platform declarations together — the guard is the backstop, not a
substitute for doing so deliberately.
### Template Expansion
Platform-specific files use `{{include shared/...}}` directives. The `install.sh` script expands these at install time:
```
Source template: Installed file:
opencode/agents/security-auditor.md → .opencode/agents/security-auditor.md
--- ---
mode: subagent mode: subagent
--- ---
{{include shared/agent-body.md}} You are a security auditor...
## Your Role
## Workflow
## Classification Rules
## Output Format
```
**Benefit**: Changing a classification rule or workflow step requires editing **one file** (`shared/agent-body.md`), not two. No shotgun surgery.
## E2E Flow (Platform-Agnostic)
```
Developer types /secguard [path]
│
▼
Command expands (path, status check)
│
▼
security-auditor subagent activated
│
├─ 1. Invoke secguard CLI (scan/index/plan)
│ ├─ OpenCode: secguard_scan tool → Bun.$`secguard scan <path>`
│ └─ Claude Code: Bash(secguard scan <path>)
│
│ secguard CLI internally:
│ ├─ Index codebase (tree-sitter → SQLite sgre.db)
│ ├─ Build call graph + data flow graph
│ ├─ Run all detectors (null-source, deref, buffer-overflow, ...)
│ ├─ Run convergence pipeline for each vuln type
│ └─ Return JSON: { evidence_packages, index_summary }
│
├─ 2. Load skills (lazy, on-demand)
│ └─ skill("null-deref") → SKILL.md loaded into context
│
├─ 3. Reason over evidence packages
│ ├─ Classify: confirmed / suspected / false-positive
│ ├─ Cross-reference with source code (Read tool)
│ └─ Produce structured findings
│
└─ 4. Present findings to developer
├─ Summary table (severity, confidence, location)
├─ Detailed evidence for each finding
└─ Suggested fixes
```
## Platform Comparison
| Aspect | OpenCode | Claude Code |
|--------|----------|-------------|
| **Command trigger** | `/secguard` (commands/secguard.md) | `/secguard` (commands/secguard.md) |
| **Subagent** | `security-auditor.md` (mode: subagent) | `security-auditor.md` (Agent tool) |
| **CLI invocation** | Custom TypeScript tools (Bun.$) | Bash tool (pre-approved) |
| **Permissions** | `permission: { edit: deny, bash: deny }` | `permissions.allow: ["Bash(secguard *)"]` |
| **Skills** | `.opencode/skills/` (shared) | `.claude/skills/` (shared) |
| **Context** | `context.worktree` | `${CLAUDE_PROJECT_DIR}` |
| **Result format** | Tool returns JSON string | Bash stdout (JSON) |
| **Stale hint** | Plugin `event` hook | `PostToolUse` hook on Edit|Write |
## Installation
```bash
# Install for both platforms (build binary + install both)
./deploy.sh all
# Install for specific platform only
./deploy.sh opencode
./deploy.sh claude-code
# Build binary only (no install)
./build.sh
```
The installer copies shared skills into both `.opencode/skills/` and `.claude/skills/`, then copies platform-specific files into their respective directories.
## Data Flow Contract (Same for Both Platforms)
```json
{
"evidence_packages": [
{
"vulnerability_type": "null-deref",
"summary": { "seed_count": 42, "final_count": 3, "convergence_rate": "92.8%" },
"candidates": [
{
"type": "NULL_DEREFERENCE",
"target": { "function": "process_data", "line": 42, "variable": "ptr" },
"evidence": [
{ "type": "nullable_source", "detail": "variable ptr has NULL_VALUE source (malloc)" },
{ "type": "call_path", "detail": "function process_data is reachable from entry" },
{ "type": "data_flow", "detail": "NULL value propagates to dereference at line 42" }
]
}
]
}
],
"index_summary": { "files_indexed": 15, "functions_indexed": 87 }
}
```
## Permission Model
+ > 以 `extension/opencode/agents/security-auditor.md` 与
+ > `extension/claude-code/.claude/agents/security-auditor.md` 的 frontmatter 为准;
+ > 本节只是概述,配置如有出入以 frontmatter 为准。
+
### OpenCode
- ```json
- {
- "permission": {
- "edit": "deny", "bash": "deny",
- "secguard_scan": "allow", "secguard_index": "allow",
- "secguard_plan": "allow", "secguard_report": "allow",
- "secguard_status": "allow", "read": "allow", "skill": "allow"
- }
- }
+ ```yaml
+ permission:
+ edit: allow # worker 需要用 Write 写 <tmpdir>/<type>.json
+ bash:
+ "secguard*": allow # 只放行 secguard CLI
+ "echo*": allow # stale-hint hook 用 echo 提示
+ "*": deny # 其余 bash 全拒
+ read: allow
+ grep: allow
+ glob: allow
+ external_directory: allow
+ skill: allow
```
### Claude Code
```json
{
"permissions": {
"allow": [
- "Bash(secguard scan *)", "Bash(secguard index *)",
- "Bash(secguard plan *)", "Bash(secguard report *)",
- "Bash(secguard status *)", "Bash(secguard query *)"
+ "Bash(secguard *)", "Read", "Write", "Glob", "Grep", "Skill"
]
}
}
```
Both models ensure the security-auditor agent can only:
- - Call secguard CLI commands (safe, read-only on codebase)
+ - Call secguard CLI commands (the CLI enforces read-only `secguard db`, and
+ writes go through `secguard report --write-json` only)
- Read source files (for cross-referencing)
- Load skills (for vulnerability knowledge)
- - NOT edit code or run arbitrary commands
+ - Write its own `<tmpdir>/<type>.json` verdict files (not source code)
+ - NOT edit source code or run arbitrary commands