Logging System
Sequant provides structured JSON logging for workflow runs, enabling analysis, debugging, and integration with external tools.
Overview
Section titled “Overview”Every sequant run execution produces a JSON log file in .sequant/logs/. These logs capture:
- Run configuration (phases, settings)
- Issue execution details (timing, status)
- Phase-level metrics (duration, errors, git diff stats)
- Git commit SHAs (start/end of run, per-phase)
- Per-file diff statistics (additions, deletions, status)
- QA cache hit/miss metrics
- Summary statistics
Configuration
Section titled “Configuration”Logging is enabled by default. Configure via .sequant/settings.json:
{ "version": "1.0", "run": { "logJson": true, "logPath": ".sequant/logs", "rotation": { "enabled": true, "maxSizeMB": 10, "maxFiles": 100 } }}CLI Flags
Section titled “CLI Flags”| Flag | Description |
|---|---|
--log-json | Enable JSON logging (default: true) |
--no-log | Disable logging for this run |
--log-path <path> | Custom log directory |
Log Rotation
Section titled “Log Rotation”To prevent unbounded log growth, Sequant automatically rotates old logs when thresholds are exceeded.
Thresholds
Section titled “Thresholds”- Size: Rotate when total log size exceeds
maxSizeMB(default: 10MB) - Count: Rotate when file count exceeds
maxFiles(default: 100)
When rotation triggers, the oldest logs are deleted until the directory is at 90% of the threshold (a 10% buffer prevents immediate re-rotation).
Manual Rotation
Section titled “Manual Rotation”# Preview what would be deletedsequant logs --rotate --dry-run
# Actually rotate logssequant logs --rotateStatistics
Section titled “Statistics”Use sequant stats for aggregate analysis across all runs:
# Human-readable summarysequant stats
# CSV exportsequant stats --csv > runs.csv
# JSON outputsequant stats --jsonOutput Includes
Section titled “Output Includes”- Total runs and issues processed
- Success/failure rates
- Average phase durations
- Common failure points
JSON Schema Reference
Section titled “JSON Schema Reference”Run Log (version 1)
Section titled “Run Log (version 1)”interface RunLog { version: 1; runId: string; // UUID startTime: string; // ISO 8601 endTime: string; // ISO 8601 config: RunConfig; issues: IssueLog[]; summary: RunSummary; startCommit?: string; // Git SHA at run start endCommit?: string; // Git SHA at run end}
interface RunConfig { phases: Phase[]; // ["spec", "exec", "qa"] sequential: boolean; qualityLoop: boolean; maxIterations: number;}
interface IssueLog { issueNumber: number; title: string; labels: string[]; status: "success" | "failure" | "partial"; phases: PhaseLog[]; totalDurationSeconds: number;}
interface PhaseLog { phase: Phase; issueNumber: number; startTime: string; endTime: string; durationSeconds: number; status: "success" | "failure" | "timeout" | "skipped"; error?: string; iterations?: number; // For loop phase filesModified?: string[]; // Files changed (git diff --name-only) testsRun?: number; testsPassed?: number; commitHash?: string; // Git SHA after phase completes fileDiffStats?: FileDiffStat[]; // Per-file diff breakdown cacheMetrics?: CacheMetrics; // QA cache hit/miss (qa phase only)}
interface FileDiffStat { path: string; // File path relative to repo root additions: number; // Lines added deletions: number; // Lines deleted status: "added" | "modified" | "deleted" | "renamed";}
interface CacheMetrics { hits: number; // Cached checks reused misses: number; // Checks re-executed skipped: number; // Checks skipped (always fresh)}
interface RunSummary { totalIssues: number; passed: number; failed: number; totalDurationSeconds: number;}
type Phase = "spec" | "testgen" | "exec" | "test" | "qa" | "loop";Log File Naming
Section titled “Log File Naming”Files are named: run-<timestamp>-<uuid>.json
Example: run-2024-01-15T14-30-00-a1b2c3d4-e5f6-7890-abcd-ef1234567890.json
Parsing Logs with jq
Section titled “Parsing Logs with jq”jq is a powerful command-line JSON processor. Here are useful examples:
List Failed Runs
Section titled “List Failed Runs”jq 'select(.summary.failed > 0) | {runId, failed: .summary.failed}' .sequant/logs/*.jsonCalculate Average Run Duration
Section titled “Calculate Average Run Duration”jq -s 'map(.summary.totalDurationSeconds) | add / length' .sequant/logs/*.jsonFind Runs for Specific Issue
Section titled “Find Runs for Specific Issue”jq 'select(.issues[].issueNumber == 42)' .sequant/logs/*.jsonShow Phase Breakdown
Section titled “Show Phase Breakdown”jq '.issues[].phases[] | {phase, status, duration: .durationSeconds}' .sequant/logs/*.jsonShow Files Modified Per Phase
Section titled “Show Files Modified Per Phase”jq '.issues[].phases[] | select(.filesModified) | {phase, files: .filesModified | length}' .sequant/logs/*.jsonShow Per-File Diff Stats
Section titled “Show Per-File Diff Stats”jq '.issues[].phases[] | select(.fileDiffStats) | .fileDiffStats[] | {path, additions, deletions, status}' .sequant/logs/*.jsonFind Commit SHA for a Phase
Section titled “Find Commit SHA for a Phase”jq '.issues[].phases[] | select(.commitHash) | {phase, commit: .commitHash[:8]}' .sequant/logs/*.jsonShow QA Cache Metrics
Section titled “Show QA Cache Metrics”jq '.issues[].phases[] | select(.cacheMetrics) | {phase, cache: .cacheMetrics}' .sequant/logs/*.jsonCommon Errors by Phase
Section titled “Common Errors by Phase”jq '.issues[].phases[] | select(.error) | {phase, error}' .sequant/logs/*.json | sort | uniq -c | sort -rnGet Success Rate
Section titled “Get Success Rate”jq -s '[.[].issues[] | .status] | group_by(.) | map({status: .[0], count: length})' .sequant/logs/*.jsonTotal Time by Phase Type
Section titled “Total Time by Phase Type”jq -s '[.[].issues[].phases[] | {phase, duration: .durationSeconds}] | group_by(.phase) | map({phase: .[0].phase, total: (map(.duration) | add)})' .sequant/logs/*.jsonExport to CSV (Manual)
Section titled “Export to CSV (Manual)”jq -r '[.runId, .startTime, .summary.totalDurationSeconds, .summary.totalIssues, .summary.passed, .summary.failed] | @csv' .sequant/logs/*.jsonOr use the built-in CSV export:
sequant stats --csvIntegration Examples
Section titled “Integration Examples”GitHub Actions
Section titled “GitHub Actions”- name: Run Sequant run: npx sequant run 42
- name: Upload logs uses: actions/upload-artifact@v4 with: name: sequant-logs path: .sequant/logs/Slack Notification on Failure
Section titled “Slack Notification on Failure”#!/bin/bashFAILED=$(jq -s '[.[].summary.failed] | add' .sequant/logs/*.json)if [ "$FAILED" -gt 0 ]; then curl -X POST "$SLACK_WEBHOOK" \ -d "{\"text\": \"Sequant: $FAILED issues failed\"}"fiTroubleshooting
Section titled “Troubleshooting”Logs Not Generated
Section titled “Logs Not Generated”- Check
--no-logwasn’t passed - Verify
.sequant/settings.jsonhaslogJson: true - Ensure
.sequant/logs/is writable
Log Directory Growing
Section titled “Log Directory Growing”Configure rotation thresholds or run manual rotation:
sequant logs --rotateParsing Errors
Section titled “Parsing Errors”Log files use Zod validation. If a log is malformed:
# Validate a log filenpx zod-to-json-schema .sequant/logs/run-*.json