Skip to main content

Agent harness for MISRA C, BARR-C and CERT C compliance: persistent memory, engineered fix loops, and an MCP server usable from any agentic IDE.

Project description

Maisha — MISRA, BARR-C and CERT C compliance harness

Maisha

CI  Release  Python 3.10+  License: MIT

Searching for an open-source alternative to Polyspace, Helix QAC or Coverity for MISRA C? This is it. Free, vendor-neutral, and driven from your IDE. → pipx install maishac

The open-source compliance-workflow layer for MISRA C:2012, BARR-C:2018 and CERT C — usable from any agentic IDE.

Maisha is the free, vendor-neutral alternative to the paid compliance workflow that tools like Polyspace, Helix QAC, Coverity and Parasoft now sell as agentic toolkits: the fix loop, verification gate, deviation & audit-evidence workflow, and author-time guidance — running on free engines (cppcheck + clang-tidy) or layered on top of a qualified engine you already own (via SARIF). It is not a qualified detection engine and does not pretend to be. → See How Maisha compares.

Maisha is Swahili for "life." Compliance standards like MISRA and CERT C exist because this is the software that flies planes, drives cars and runs medical devices — code where a defect costs lives, not uptime. The name is the goal the tool works toward. The CLI and package are maishac (Maisha-for-C).

⚠️ Maisha is a workflow orchestrator and audit-trail layer, not a qualified/certified static-analysis tool. Its findings do not by themselves satisfy tool-qualification requirements for DO-178C, ISO 26262 or IEC 62304, and running it is not a formal compliance certification. It is best used upstream of a qualified engine (see Scope & Limitations).

Maisha is not another linter. It is the deterministic half of an autonomous compliance workflow. Your IDE's LLM (Claude Code, Cursor, Windsurf, Zed, anything that speaks MCP) does the code edits; Maisha does everything that must never hallucinate:

  • Scanning & evidence merging — a zero-dependency native analyzer plus adapters for cppcheck (with its MISRA addon) and clang-tidy (cert-* checks). Findings from multiple analyzers that hit the same defect are fingerprint-merged into a single finding with reinforcing evidence (analyzer: native+cppcheck).

  • Proactive authoring (write it compliant the first time) — two author-time surfaces, so an agent writes compliant code on the first pass instead of fixing it on a later scan:

    • compliance_guidance (CLI: maishac guide "<topic>") — a compliant-pattern library: before writing code for a concern (dynamic memory, string copy, switch, recursion, integer overflow, …) it returns the idiom to prefer, the anti-pattern to avoid, why, and the MISRA/CERT/BARR-C rules it satisfies.
    • compliance_check_snippet (CLI: maishac check) — lints a draft in memory, before it is written to a file, returning violations, fix hints, and the compliant idiom to swap in. (Native lexical checks only — the syntactic subset, not whole-program rules; a clean snippet is not a compliance guarantee.)

    See AUTHORING_PLAYBOOK.md for the guidance → draft → check → rewrite protocol to hand your IDE agent.

  • Stable fingerprints — findings are identified by sha1(rule + file + normalized line content + enclosing function), not line numbers, so they survive edits, insertions and refactors across sessions.

  • Persistent memory — a SQLite store per project (.maishac/memory.db) tracking finding lifecycle (open → resolved → regressed), every fix attempt and its outcome, false-positive suppressions, MISRA-style deviation records with justification/approver/expiry, and free-form project convention notes.

  • An engineered fix loop — sessions with severity-ranked, file-grouped batches; regressions always jump the queue; each finding is briefed with the rule summary, a fix hint, strategies that already failed on it, relevant memory notes and cross-standard equivalents. Guard rails: iteration budgets, stall detection, and oscillation freezing (a finding that regresses twice is frozen as needs_human).

  • A verification gate — a fix is not resolved just because the analyzer stopped flagging it. It enters pending_verification until a passing test run or an explicit human approval confirms it; semantic-risk and high-severity findings always require human sign-off. See below.

  • Reporting — per-standard compliance matrices, a markdown report with a deviation register, SARIF 2.1.0 export with partialFingerprints for CI, and the MISRA Compliance:2020 evidence set — the three documents a functional-safety assessor asks for: the Guideline Compliance Summary (every guideline Compliant / Deviations / Violations / Disapplied, tied to deviation permits), the Guideline Enforcement Plan (how each guideline is checked + a tool inventory with versions/options), and the Guideline Re-categorization Plan (with the legality rules enforced — a Mandatory guideline may not be re-categorized, a Required one may not drop to Advisory/Disapplied), plus honest disclosure of which guidelines are not checked.

The three rule knowledge bases (81 rules — 31 MISRA C:2012, 20 BARR-C:2018, 30 CERT C) contain original paraphrased summaries written for this project — no standard text is reproduced. For authoritative wording you still need the official MISRA / BARR / SEI CERT documents.


Scope & Limitations

What Maisha is:

  • A workflow orchestrator for agent-driven compliance triage and fix loops.
  • A persistent audit-trail layer: finding lifecycle, fix attempts, deviation records, suppressions, and a verification gate that records how every fix was confirmed (test run vs. human sign-off, and by whom).
  • A pre-certification cleanup tool that catches and helps fix the obvious violations early — in the IDE loop, before code reaches a qualified engine.

What Maisha is not:

  • Not a qualified or certified analysis tool. Its engines are the open-source cppcheck + clang-tidy + a native analyzer — none carry a tool qualification kit. DO-178C / ISO 26262 / IEC 62304 generally require the analysis tool itself to be qualified or proven-in-use; Maisha does not meet that bar and does not claim to.
  • Not complete rule coverage. 81 curated rules across three standards is a fraction of MISRA C:2012 (180+ rules/directives with amendments) or CERT C. Detection is bounded by the underlying engines, not the curated set. Every covered rule and which analyzer backs it is listed in COVERAGE.md (generated from the code, so gaps are explicit). A real-world run against the FreeRTOS kernel — with a measured false-positive rate and the tool bugs it surfaced — is in BENCHMARKS.md. Headline lesson: pass your include paths to cppcheck/clang-tidy with --include/-I (repeatable), or most of the substantive findings are configuration false positives. A from-scratch accuracy/reliability suite — ground-truthed fixtures, a full fix-loop simulation, SARIF import, CLI end-to-end and edge-case tests — is in BENCHMARK-SUITE-REPORT.md.
  • Not a substitute for human review. By default a fix is never marked resolved on a clean rescan alone — a passing test run or an explicit human approval is required, and semantic-risk / high-severity findings always require human sign-off (see The verification gate).

Recommended use for certification pipelines: run Maisha's loop for early, agent-driven cleanup, then hand off to a qualified engine (Astrée, Polyspace, Helix QAC, Parasoft C/C++test, IAR C-STAT) for the evidence an auditor accepts. Those engines emit SARIF, and maishac import findings.sarif layers Maisha's loop, memory, verification gate and deviation register on top of their findings — recognized MISRA/CERT ruleIds map onto the knowledge base, and imported findings are never cleared by a native rescan.

Robust across real engine dialects. Qualified engines rarely put the MISRA/CERT number in ruleId — Helix QAC / Coverity emit a checker-specific id (e.g. ABV.GENERAL), reference the rule by ruleIndex, and attach the guideline through relationships into a taxonomies component. Maisha's importer resolves the rule via result.rule / ruleIndex / ruleId, follows relationships and taxonomies (and result-level taxa) to recover the real guideline, honors defaultConfiguration levels, skips non-defect results (kind: pass, notApplicable) and baseline-absent findings, tolerates missing regions and multi-location results, and normalizes scheme-prefixed URIs.

Rich SARIF mapping. Import isn't lossy: a qualified engine's codeFlows (the data-flow path to the defect) are parsed and surfaced in the agent briefing, so a fixer sees how a defect flows, not just where it lands; and result.suppressions are honored so a team's existing triage/baseline carries over instead of resurfacing as fresh violations. Export emits cross-standard equivalences as SARIF reportingDescriptor.relationships (e.g. a MISRA rule linked to its CERT equivalent), with every relationship target present as a descriptor. Maisha's own identity travels in partialFingerprints (maishac/v1), and startColumn + code flows survive an import → export round-trip, so re-exporting a qualified engine's findings loses nothing.


Install

Requires Python 3.10+.

pipx install maishac      # isolated CLI install (recommended)
# or
pip install maishac

This installs the maishac CLI and the maishac Python package. Verify with maishac --help. To hack on Maisha itself:

git clone https://github.com/Kiransekar/maisha.git
cd maisha
pip install -e ".[dev]"   # editable install with pytest

Optional but strongly recommended external analyzers — native works with zero dependencies, but cppcheck (MISRA addon) and clang-tidy (cert-* checks) meaningfully increase coverage:

# Debian/Ubuntu
apt install cppcheck clang-tidy

# or, without root, anywhere pip works (prebuilt wheels, incl. Windows/macOS)
pip install cppcheck clang-tidy

Maisha degrades gracefully: any analyzer not on PATH is skipped and the native analyzer always works. Run maishac scan once and check analyzers_used in the output to confirm what's actually active.

Quickstart (CLI)

cd your-firmware-project

maishac scan src/                  # one-shot scan, syncs memory
# headers outside src/ (e.g. a vendor SDK or FreeRTOSConfig.h)? forward them:
maishac scan src/ --include include/ --include vendor/sdk/inc

maishac findings --limit 20        # ranked open findings
maishac rule "MISRA 21.3"          # explain a rule + cross-standard refs

# The engineered loop (what an agent drives via MCP):
maishac session begin src/ --verification-policy human_gated
# -> {"session_id": "abc123...", ...} — use that id below
maishac session batch abc123       # next prioritized batch with briefings
# ...edit code (you or your agent)...
maishac session verify abc123      # rescan, diff, grade attempts, run the test gate
maishac approve <fingerprint> --by lead@example.com   # human sign-off on a verified fix
maishac session status abc123

maishac deviate "MISRA 19.2" --scope "drivers/**" \
    --justification "Union required for hardware register overlay mapping" \
    --approver lead@example.com --expires 2027-01-01
maishac suppress <fingerprint> --reason "false positive: macro expansion"
maishac note "This codebase uses FreeRTOS; heap_4 allocator is approved" --tags misra-21.3
maishac recategorize "MISRA 15.1" --to disapplied \
    --rationale "No goto in this codebase; disapplied by acquirer/supplier agreement" \
    --approver lead@example.com
maishac report --format sarif > compliance.sarif
maishac report --format misra-compliance > gcs.md   # Guideline Compliance Summary
maishac report --format gep > gep.md                 # Guideline Enforcement Plan
maishac report --format grp > grp.md                 # Guideline Re-categorization Plan

Quickstart (any agentic IDE, via MCP)

Add the server to your IDE's MCP configuration (ready-made snippets in integrations/):

{
  "mcpServers": {
    "maisha": {
      "command": "maishac",
      "args": ["serve"],
      "env": { "MAISHAC_PROJECT": "/path/to/your/project" }
    }
  }
}

Then tell your agent something like:

Begin a Maisha compliance session on src/, work through batches until converged, record every attempt, and add deviations only where a fix is genuinely impossible.

The recommended agent protocol is documented in AGENT_PLAYBOOK.md.

MCP tools

Tool Purpose
compliance_scan Scan paths, merge analyzers, sync memory, return diff (new/persisting/resolved/regressed)
compliance_list_findings Ranked open findings above a severity floor
compliance_get_finding Full briefing for one fingerprint (history, failed strategies, notes)
compliance_explain_rule Rule summary, severity, fix hint, cross-standard equivalents
compliance_search_rules Keyword search across all three standards
compliance_guidance Before writing code on a concern, get the compliant idiom to reach for (avoid/prefer/why + the rules it satisfies) — the author-time pattern library
compliance_check_snippet Lint a draft snippet in memory, before writing it — proactive authoring aid; returns violations, fix hints, and the compliant idiom to swap in; stores nothing
compliance_begin_session Baseline scan + session with budgets (max_iterations, batch_size)
compliance_next_batch Next prioritized batch, regressions first, with per-finding briefings
compliance_record_attempt Log the strategy used on a finding (auto-graded on verify)
compliance_verify Rescan, diff, grade attempts, run the test gate, advance state machine
compliance_approve_finding Human sign-off moving a pending_verification finding to resolved (required for semantic-risk / high-severity fixes)
compliance_session_status Progress, iteration budget, state (active/awaiting_verification/converged/stalled/budget_exhausted)
compliance_add_deviation MISRA-style deviation record (justification ≥ 15 chars enforced)
compliance_recategorize MISRA GRP re-categorization (legality enforced: no Mandatory re-cat; Required→Advisory/Disapplied forbidden)
compliance_suppress_finding Mark a fingerprint as false positive (reason required)
memory_note / memory_search / memory_stats Project convention memory
compliance_import_sarif Ingest an external engine's SARIF (qualified engine or cppcheck --output-format=sarif) into the same loop/memory/gate; honors result.suppressions so a team's existing triage/baseline carries over instead of resurfacing as fresh violations
compliance_report Markdown, JSON, SARIF 2.1.0, or the MISRA Compliance:2020 evidence set: misra-compliance (GCS), gep (enforcement plan), grp (re-categorization plan)

Architecture

┌──────────────────────────── your agentic IDE ───────────────────────────┐
│  LLM agent: reads briefings, edits code, records attempts               │
└──────────────▲──────────────────────────────────────────────────────────┘
               │ MCP (stdio)
┌──────────────┴──────────────  maisha  ──────────────────────────────┐
│ engine/    LoopEngine: sessions, batching, budgets, stall/oscillation   │
│ memory/    SQLite: findings, fix_attempts, deviations, suppressions,    │
│            notes, sessions  (.maishac/memory.db)                      │
│ analyzers/ native (0-dep) + cppcheck(+MISRA addon) + clang-tidy(cert-*) │
│            → fingerprint-deduped, severity-sorted evidence               │
│ rules/     MISRA C:2012 + BARR-C:2018 + CERT C KBs, fuzzy resolver,     │
│            cross-standard references                                     │
│ report.py  compliance matrix, markdown, SARIF 2.1.0                     │
└──────────────────────────────────────────────────────────────────────────┘

Design principles:

  1. Determinism where it matters. Prioritization, verification, memory and budgets are code, not prompts. The LLM only does what LLMs are good at.
  2. Findings are identities, not line numbers. Fingerprints keep history attached to the defect through refactors.
  3. The loop must terminate. Iteration budgets, stall limits and oscillation freezing guarantee a session always ends in a well-defined state.
  4. Compliance is a process, not a scan. Deviations and suppressions are first-class, auditable records — exactly as MISRA compliance expects.

The verification gate

The trap Maisha guards against: the only judge of a fix is the same analyzer whose blind spot may have created the finding. "The warning stopped firing" rewards the syntactically minimal edit — often the one most likely to change behavior at a boundary. Casting a signed sentinel (-1 = "no limit") to uint32_t to silence a signed/unsigned comparison warning turns "no limit" into "an enormous limit" — the rescan passes, no static check ever catches it.

So a fix does not go straight to resolved. It enters pending_verification and leaves only under the session's verification_policy:

Policy A pending fix becomes resolved when…
analyzer_only the analyzer stops flagging it (⚠️ not recommended for compliance work)
test_gated a configured test_command exits 0
human_gated a human calls approve_finding

Default: test_gated if a test_command is configured, else human_gated. Regardless of policy, semantic-risk findings (casts, comparisons, sign conversions, control-flow changes) and high-severity findings always require human approval — a green test suite that never exercises the sentinel case cannot resolve them. Every resolution records how it was confirmed (analyzer/test/ human) and, for human sign-off, approved_by.

Set expectations accordingly: the semantic-risk rule-category list is broad (it covers most of MISRA's essential-type, control-flow and switch-statement rules, plus CERT's INT/FLP families) — in practice, test_gated sessions on typical MISRA findings end up requiring human sign-off almost as often as human_gated does. A full end-to-end simulation confirmed a passing test suite auto-resolved zero of eight pending findings in one representative session — see BENCHMARK-SUITE-REPORT.md §3.2. Budget human review time accordingly; don't expect test_gated to remove most of the review load.

maishac session begin src/ --verification-policy test_gated --test-command "make test"
# ...agent fixes, then:
maishac session verify <id>          # -> awaiting_verification if fixes need sign-off
maishac approve <fingerprint> --by lead@example.com

Teams & concurrency

Project memory lives in a per-project SQLite file, .maishac/memory.db.

  • Gitignore it. It is local, machine-specific state, not source — add .maishac/ to .gitignore (this repo already does). To share state deliberately, export a compliance_report (SARIF/JSON), don't commit the DB.
  • Concurrent access. The DB runs in WAL mode with a busy-timeout, so a CI scan and a local session can read/write without hard-blocking. session begin refuses to start a second session while one is already active on the same project (pass --force to override) so two runs don't race on finding state.

Development

pip install -e . && python -m pytest tests/ -q

examples/bad.c is a deliberately non-compliant fixture exercising ~18 rules — useful as a demo target.

Contributing

Contributions are very welcome — especially to the community-extensible parts: adding a coding-standard rule, an authoring pattern (compliant idiom), or an analyzer adapter / SARIF-dialect mapping. None of these touch the engine. See CONTRIBUTING.md for the how-to and the design invariants to preserve, and CODE_OF_CONDUCT.md. Good first issues are labeled on the tracker.

License / disclaimer

Rule summaries are original paraphrases; MISRA®, BARR-C and SEI CERT C are the property of their respective owners. Maisha output does not constitute a formal compliance certification.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

maishac-0.3.1.tar.gz (89.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

maishac-0.3.1-py3-none-any.whl (77.7 kB view details)

Uploaded Python 3

File details

Details for the file maishac-0.3.1.tar.gz.

File metadata

  • Download URL: maishac-0.3.1.tar.gz
  • Upload date:
  • Size: 89.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for maishac-0.3.1.tar.gz
Algorithm Hash digest
SHA256 307d48d1167b045e19d2ee5537c6a29da25257544a8af339ece11a3776de8ae9
MD5 72a9e2ea57681652050ee1db05f1c562
BLAKE2b-256 fe8209ad4a2d9590d846698abe3fcdbfefd8e7dd8fea0bd2e6c5e806a0b6d4d3

See more details on using hashes here.

Provenance

The following attestation bundles were made for maishac-0.3.1.tar.gz:

Publisher: release.yml on Kiransekar/maisha

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file maishac-0.3.1-py3-none-any.whl.

File metadata

  • Download URL: maishac-0.3.1-py3-none-any.whl
  • Upload date:
  • Size: 77.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for maishac-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 c5d7d6a81cc08c57264f84d8aab490bb9c1b70b0827ba9c0bd5a6a224b6f6efb
MD5 f54d0fa568d4032c1415c65444057b8a
BLAKE2b-256 3eda71d5324a20a21472f4baa4ae74cf9b474182640f58af423bc5543ec9c655

See more details on using hashes here.

Provenance

The following attestation bundles were made for maishac-0.3.1-py3-none-any.whl:

Publisher: release.yml on Kiransekar/maisha

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page