Author: Ahmed Gaper, a contributor to Google Summer of Code 2025
GSoC project link

Table of Contents

  • Project overview
  • Usage guide
  • Default ruleset
  • Contributions & Merged PRs, Challenges & how I solved them
  • Conclusion & future work
  • Acknowledgments

Project overview

The Accord Project uses concerto models as human-readable schemas that drive the logic in smart legal contracts. This project delivered a concerto Linter: a modular tool that statically analyzes .cto model files and reports issues (naming, structural problems, reserved keywords, etc.) so models are high-quality before they are consumed.

Solution. A configurable linter that: 1) provides a sensible default ruleset, 2) lets teams supply or extend rulesets, and 3) integrates via a straightforward API and a CLI command so checks can run locally or in CI.

Goals. Catch common model issues early, reduce human review overhead, and provide actionable guidance rather than opaque errors.

Quick highlights

  • ✅ Modular @accordproject/concerto-linter package
  • ✅ Portable default ruleset package @accordproject/concerto-linter-default-ruleset
  • ✅ Programmatic API (lintModel) and concerto lint CLI

Usage guide

Programmatic – lintModel API

Install

Basic usage (CTO string)

Parsed AST (ModelManager)

Options (most useful)

  • ruleset: path to a custom Spectral ruleset or 'default' to force the built-in ruleset.
  • excludeNamespaces: override default exclusions (e.g. concerto.*org.accordproject.*).

For comprehensive details, including additional examples and usage patterns, see the concerto-linter README

CLI – concerto lint

Syntax

Key options

  • --model <file> – path to .cto model(s)
  • --exclude <namespace> – exclude a namespace
  • --json – JSON output
  • --ruleset <file|'default'>

Examples

Default Ruleset

@accordproject/concerto-linter-default-ruleset provides a curated set of Spectral rules tuned to concerto ASTs. It ships as a separate npm package so teams can consume or extend it.

Available rule categories:

  • namespace-version – ensure namespace includes a version
  • no-reserved-keywords – prevent use of reserved identifiers
  • pascal-case-declarations – declaration names must be PascalCase
  • camel-case-properties – property names must be camelCase
  • upper-snake-case-enum-constants – enum constants in UPPER_SNAKE_CASE
  • pascal-case-decorators – decorator names in PascalCase
  • string-length-validator – string properties should have length validators
  • no-empty-declarations – disallow empty declarations
  • abstract-must-subclassed – require concrete subclasses for abstract types

How to customize (summary)

  • Extend the default ruleset with extends: '@accordproject/concerto-linter-default-ruleset'.
  • Disable specific rules by setting their ID to off.
  • Set severity levels (errorwarninfohint).
  • Create custom rules using Spectral’s given / then constructs or custom functions when needed.

For more configuration examples, and extension guidance are available in the default ruleset README

Contributions & Merged PRs – Challenges & how I solved them

Challenge 1 – Understanding the existing architecture, defining the linter shape with configurable behavior

Problem. The concerto repository is large and feature-rich; I needed to identify stable extension points and design a simple, maintainable configurable linter architecture that fits the existing ecosystem.

How I solved it. First, I defined a high-level architecture up front: a small, focused linter runtime, a separate default-ruleset package. I exposed a simple programmatic API (lintModel) with configuration and built-in support for loading rulesets. Through iterative development, we incrementally refined the solution until it reached the full set of required features.. Finally, I delivered thorough README usage examples, configuration guides, and a comprehensive unit/integration test suite so the linter is reliable, easy to extend, and simple for other contributors to use.

Merged PRs:

Challenge 2 – Designing a useful default ruleset grounded in real-world needs

Problem: A default ruleset must be practical and relevant; it cannot be a collection of arbitrary checks. Finding and implementing rules that actually improve model quality required research and careful design.

How I solved it: I reviewed common modeling mistakes from real-world examples, prioritized rules that give actionable fixes, and implemented them using Spectral constructs (and custom functions where needed).

Merged PRs:

Challenge 3 – Output shape, filtering, and CLI integration

Problem: Consumers (API users and CLI users) expect a predictable output shape and filtering options (namespaces, JSON output, severity levels). Designing the output and CLI UX required coordination between the linter library and the CLI tooling.

How I solved it: I refactored the linter output to a stable shape, added namespace filtering, and implemented the concerto lint command so both programmatic and CLI consumers get consistent results.

Merged PRs:

Conclusion & Future Work

The concerto Linter lays the foundation for improved model quality across the Accord ecosystem. It ships a default ruleset, a programmatic API, a CLI, and configuration discovery, enabling teams to adopt the tool in local development and CI.

Next steps / future work

  • Expand the ruleset with community-driven rules (advanced inheritance checks, template-specific hints).
  • Tune severity and default rule choices based on ecosystem feedback.
  • Integrate lint annotations into the Accord VSCode extension so .cto files show inline diagnostics.

Acknowledgments

One of the greatest benefits of this project was the weekly Working Group (WG) meetings. They showed me how a professional team and organizational workflow operate and elevated my software career to a new level of professionalism. The routine of proposing what I would do and receiving feedback from the entire WG helped me iterate toward the best and most useful solutions. The 1:1 sessions with Jamie were also incredibly valuable, Jamie provided a clear plan and guidance that I followed throughout the project, which made a big difference in both my progress and learning.

The development of the concerto Linter was guided by the Accord Project community. Special thanks to all my mentors for technical mentorship and advice on rules design and configuration. Thanks to contributors to Spectral and the open-source community for tools that made this possible. This work was completed as part of Google Summer of Code 2025 with the support of the Accord Project (a Linux Foundation initiative) and is released under the Apache 2.0 License.