Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions .github/workflows/architon-example.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
name: Architon Example

on:
pull_request:
push:
branches: [main]

jobs:
architon:
runs-on: ubuntu-latest
permissions:
contents: read

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: stable

- name: Install rv
run: go install ./cmd/rv

- name: Scan clean fixture
shell: bash
run: |
rv scan internal/importers/kicad/testdata/bom_minimal.csv \
--format json \
--out architon-clean-report.json \
| tee architon-clean-ci.json

grep -q '"report_version": "1"' architon-clean-ci.json
grep -q '"violations": 0' architon-clean-ci.json
grep -q '"warnings": 0' architon-clean-ci.json

- name: Scan expected violation fixture
shell: bash
run: |
set +e
rv scan testdata/esp32_overvoltage/netlist.net \
--meta testdata/esp32_overvoltage/meta.yaml \
--format github \
--out architon-violation-report.json \
| tee architon-violation-annotations.txt
scan_status=${PIPESTATUS[0]}
set -e

if [ "$scan_status" -ne 2 ]; then
echo "expected rv scan to exit 2 for the overvoltage fixture, got $scan_status"
exit 1
fi

grep -q '::error title=ARCHITON CONTRACT VIOLATION::' architon-violation-annotations.txt
grep -q 'contract_id=ESP32-WROOM-32' architon-violation-annotations.txt
grep -q 'component=U1' architon-violation-annotations.txt
grep -q 'net=/+5V' architon-violation-annotations.txt

- name: Upload Architon reports
if: always()
uses: actions/upload-artifact@v4
with:
name: architon-reports
path: |
architon-*-report.json
architon-*-ci.json
architon-*-annotations.txt
if-no-files-found: ignore
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ Detailed CLI examples, scan behavior, import modes, rail inference, and advanced

- [docs/cli.md](docs/cli.md)
- [docs/contracts.md](docs/contracts.md)
- [docs/ci.md](docs/ci.md)
- [docs/importers.md](docs/importers.md)
- [docs/rail-inference.md](docs/rail-inference.md)
- [docs/report-format.md](docs/report-format.md)
Expand Down Expand Up @@ -189,6 +190,7 @@ No probabilistic models or network calls are used. Validation operates only on t
Detailed technical documentation is available in `docs/`:

- [docs/architecture.md](docs/architecture.md) — engine architecture and system design
- [docs/ci.md](docs/ci.md) — GitHub Actions, PR comments, and scan artifacts
- [docs/contracts.md](docs/contracts.md) — built-in and user system contracts
- [docs/importers.md](docs/importers.md) — KiCad/BOM/netlist import behavior
- [docs/rail-inference.md](docs/rail-inference.md) — rail voltage inference and coverage
Expand Down
44 changes: 20 additions & 24 deletions cmd/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package cmd

import (
"encoding/csv"
"encoding/json"
"errors"
"fmt"
"io"
Expand Down Expand Up @@ -62,9 +61,11 @@ func init() {
// newScanCmd builds the rv scan command and wires all scan flags.
func newScanCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "scan <path>",
Args: cobra.ExactArgs(1),
Short: "Scan an electronics BOM and generate a deterministic verification report",
Use: "scan <path>",
Args: cobra.ExactArgs(1),
Short: "Scan an electronics BOM and generate a deterministic verification report",
SilenceUsage: true,
SilenceErrors: true,
Long: `Scan an electronics BOM and generate a deterministic verification report.

Current supported input:
Expand Down Expand Up @@ -97,10 +98,10 @@ Examples:
if outputFormat == "" {
outputFormat = "text"
}
if outputFormat != "text" && outputFormat != "json" {
if outputFormat != "text" && outputFormat != "json" && outputFormat != "markdown" && outputFormat != "github" {
return &ExitError{
Code: 3,
Err: fmt.Errorf("unsupported output format %q (allowed: text, json)", outputFormat),
Err: fmt.Errorf("unsupported output format %q (allowed: text, json, markdown, github)", outputFormat),
}
}

Expand Down Expand Up @@ -200,7 +201,7 @@ Examples:
}
metaObj = prepared
metaLoaded = true
} else {
} else if outputFormat == "text" {
fmt.Fprintf(cmd.OutOrStdout(), "Hint: edit .architon/meta.yaml (sources/components) to enable voltage rules\n")
}
}
Expand Down Expand Up @@ -329,25 +330,20 @@ Examples:
// 3 tool execution failure
// -------------------------
exitCode := scanExitCode(designReport)
if outputFormat == "json" {
jsonReport := report.CanonicalizeVerificationReport(designReport)
data, err := json.MarshalIndent(jsonReport, "", " ")
switch outputFormat {
case "json":
data, err := scanRenderCIJSON(designReport, args[0])
if err != nil {
return internalError(fmt.Errorf("marshal scan report JSON: %w", err))
return internalError(fmt.Errorf("marshal scan CI JSON: %w", err))
}
fmt.Fprintln(cmd.OutOrStdout(), string(data))
switch exitCode {
case 0:
return nil
case 1:
return &ExitError{Code: 1, Err: errors.New("scan completed with warnings")}
case 2:
return &ExitError{Code: 2, Err: errors.New("scan violations detected")}
case 3:
return &ExitError{Code: 3, Err: errors.New("scan failed")}
default:
return &ExitError{Code: 3, Err: fmt.Errorf("scan failed with unexpected exit code %d", exitCode)}
}
return scanReturnExit(exitCode)
case "markdown":
fmt.Fprint(cmd.OutOrStdout(), scanRenderMarkdown(designReport, args[0]))
return scanReturnExit(exitCode)
case "github":
fmt.Fprint(cmd.OutOrStdout(), scanRenderGitHub(designReport, args[0]))
return scanReturnExit(exitCode)
}

fmt.Fprintf(cmd.OutOrStdout(), "ARCHITON SCAN\n")
Expand Down Expand Up @@ -436,7 +432,7 @@ Examples:
cmd.Flags().String("netlist", "", "Override netlist file path when scanning a project directory")
cmd.Flags().String("meta", "", "Override meta file path (default: .architon/meta.yaml if present)")
cmd.Flags().String("contracts", "", "Override contracts file path (default: .architon/contracts.yaml if present)")
cmd.Flags().String("format", "text", "Output format: text or json")
cmd.Flags().String("format", "text", "Output format: text, json, markdown, or github")
cmd.Flags().Bool("verbose", false, "Show detailed scan diagnostics")
cmd.Flags().Bool("explain-rails", false, "Print rail voltage inference provenance and confidence")
cmd.Flags().Bool("rails", false, "Alias for --explain-rails")
Expand Down
Loading
Loading