- Add DI container (src/services/) with AgentExecutionService, ConfigLoaderService, and ExploitationCheckerService — pure domain logic with no Temporal dependencies
- Introduce Result<T, E> type and ErrorCode enum for code-based error classification in classifyErrorForTemporal, replacing scattered string matching
- Consolidate billing/spending cap detection into utils/billing-detection.ts with shared pattern lists across message-handlers, claude-executor, and error-handling
- Extract LogStream abstraction for append-only logging with backpressure, used by both AgentLogger and WorkflowLogger
- Simplify activities.ts from inline lifecycle logic to thin wrappers delegating to services, with heartbeat and error classification
- Expand config-parser with human-readable AJV errors, security validation, and rule type-specific checks
- Remove 4 duplicate file I/O functions from audit/utils.ts, re-export from utils/file-io.ts
- Consolidate AgentEndResult interface into new types/audit.ts
- Use exported AgentDefinition from types/agents.ts in session-manager.ts
- Rename AgentMetrics to AgentAuditMetrics to disambiguate from temporal/shared.ts
Query functionality is redundant with the Temporal Web UI
at http://localhost:8233. Removes query.ts, CLI handler,
npm script, and all documentation references.
- Early exit when all agents already completed instead of running empty workflow
- Descriptive error when deliverables missing from disk despite session.json success
- Quote $WORKSPACE in shannon CLI to prevent word splitting
- Prevent MSYS from converting Unix container paths on Windows
- Install @anthropic-ai/claude-code globally in the Docker image
- Add Windows platform instructions to README
- Swap commitGitSuccess/getGitCommitHash order so checkpoint in
session.json points to the success commit (which contains deliverables)
instead of the pre-agent marker commit
- Simplify restoreGitCheckpoint: git reset --hard now naturally preserves
completed agent deliverables, removing the in-memory backup/restore
- Show cumulative cost/duration in workflow.log from session.json
- Fill in per-agent metrics for skipped agents in workflow.log breakdown
- Display cumulative cost in client output for resume runs
Moves the copyDeliverablesToAudit call from runAgentActivity (called after
every agent) to logWorkflowComplete (called once at workflow end). This
prevents intermediate agent runs from copying incomplete or rogue deliverables
into the audit trail.
logWorkflowComplete wrote to workflow.log but never called
updateSessionStatus, leaving all workspaces stuck as "in-progress"
in session.json. Also derive audit path for model injection instead
of requiring explicit outputPath.
logPhaseTransition was the first activity to create session.json but
didn't pass workflowId, so originalWorkflowId was never set. This
caused terminateExistingWorkflows to look up the workspace name instead
of the actual workflow ID during resume.
Also remove path import from types/agents.ts to fix Temporal workflow
bundle determinism error.
Support WORKSPACE=<name> flag for friendly workspace names that
auto-resume if they exist or create a new named workspace otherwise.
Add ./shannon workspaces command to list all workspaces with status,
duration, and cost.
When a workflow is interrupted (VM crash, Ctrl+C, Docker restart), it can
now be resumed by passing the workspace name. The system reads session.json
to determine which agents completed, validates deliverables exist on disk,
restores the git checkpoint, and skips already-completed agents.
- Add --workspace CLI flag and auto-terminate conflicting workflows
- Add loadResumeState, restoreGitCheckpoint, recordResumeAttempt activities
- Add skip logic for all 5 pipeline phases including parallel execution
- Separate sessionId (persistent directory) from workflowId (execution ID)
- Track resume attempts in session.json for audit trail
- Derive AgentName type from ALL_AGENTS array to eliminate duplication
- Add getDeliverablePath mapping for deliverable validation
- Replace single-call "Write to deliverables/" pattern with multi-step
Write + Edit chunked writing across all 12 agent prompts
- Standardize section name to "CHUNKED WRITING (MANDATORY)" for
vuln, exploit, pre-recon, and recon agents
- Prevents agents from hitting 32K output token limit when generating
large analysis reports and exploitation evidence
* fix: add file_path parameter to save_deliverable for large reports
Large deliverable reports can exceed output token limits when passed as
inline content. This change allows agents to write reports to disk first
and pass a file_path instead.
Changes:
- Add file_path parameter to save_deliverable MCP tool with path
traversal protection
- Pass CLAUDE_CODE_MAX_OUTPUT_TOKENS env var to SDK subprocesses
- Fix false positive error detection by extracting only text content
(not tool_use JSON) when checking for API errors
- Update all prompts to instruct agents to use file_path for large
reports and stop immediately after completion
* docs: simplify and condense CLAUDE.md
Reduce verbosity while preserving all essential information for AI
assistance. Makes the documentation more scannable and focused.
* feat: add issue number detection to pr command
The /pr command now automatically detects issue numbers from:
1. Explicit arguments (e.g., /pr 123 or /pr 123,456)
2. Branch name patterns (e.g., fix/123-bug, issue-456-feature)
Adds "Closes #X" lines to PR body to auto-close issues on merge.
* chore: remove CLAUDE_CODE_MAX_OUTPUT_TOKENS env var handling
No longer needed with the new Claude Agent SDK version.
* fix: restore max_output_tokens error handling
Podman doesn't support the `host-gateway` special value in extra_hosts,
which causes container startup failures on macOS with Podman Desktop.
Changes:
- Add docker-compose.docker.yml with extra_hosts override for Docker
- Update shannon script to detect Podman via `command -v podman`
- Skip extra_hosts override when Podman is detected
This ensures:
- Docker users (Linux): Get host.docker.internal working automatically
- Podman users (macOS): Base config works without modification
Co-authored-by: ajmallesh <ajmallesh@gmail.com>
Deliverables saved by agents were never committed to git because
git identity was not configured in the Docker container. This left
them as untracked files, which git clean -fd destroyed whenever
another agent's retry triggered a workspace rollback. Moves git
config after ENV HOME=/tmp so the config is written to /tmp/.gitconfig
where git actually looks at runtime.
* feat: upgrade claude-agent-sdk to 0.2.38 and adapt to new SDK types
- Bump @anthropic-ai/claude-agent-sdk from 0.1.x to 0.2.38 (both root and mcp-server)
- Bump zod from 3.x to 4.x (SDK peer dependency)
- Add allowDangerouslySkipPermissions to query options (required for bypassPermissions)
- Suppress new SDK message types (tool_progress, tool_use_summary, auth_status)
- Use structured error field on assistant messages instead of text-sniffing
- Add stop_reason to result message handling for diagnostics
- Add SDKAssistantMessageError type matching SDK's string literal union
* chore: remove CLAUDE_CODE_MAX_OUTPUT_TOKENS from all config and docs
Pre-create the deliverables directory with proper permissions on the
host before starting containers, and surface permission errors instead
of silently swallowing them in save_deliverable.
* feat: use static repos/ folder mount instead of dynamic TARGET_REPO
Replace dynamic per-run TARGET_REPO bind mount with a static ./repos:/repos
mount. Users place target repositories under ./repos/ and reference them by
folder name. This fixes stale mounts when switching targets and enables
running multiple scans concurrently against different repos.
* feat: mount configs directory into worker container
* docs: add instructions for repos and configs directory setup
The container runs as non-root user 'pentest' (UID 1001), but bind-mounted
directories are owned by the host user. Added chmod 777 after mkdir to ensure
the container can write to these directories.
- Add HTTP 402 and 'insufficient credits' patterns to error classification
- Detect provider billing errors in both exception and message content paths
- Track actual model name from router through audit logs, session.json, and query output
- Add router-utils.ts to resolve model names from ROUTER_DEFAULT env var
- Inject model info into final report's Executive Summary section
- Update documentation with supported providers, pricing, and config examples
- Update router-config.json with latest model versions (GPT-5.2, Gemini 2.5, etc.)
- Add DeepSeek provider config with Together.ai and official API support
- Configure deepseek and enhancetool transformers for reliable tool calling
- Add DEEPSEEK_API_KEY and DEEPSEEK_API_BASE env vars to docker-compose
- Update shannon CLI to recognize DeepSeek as valid router provider
- Add ROUTER=true flag to route requests through claude-code-router
- Add router service to docker-compose with profile-based activation
- Support OpenAI (gpt-4o) and Google Gemini (gemini-2.5-pro) as alternatives
- Add router-config.json with provider configuration template
- Update .env.example with provider API key options
- Document router mode limitations (cost tracking shows $0)