Receber por email
← Voltar para o catálogo

specification-generator

Generate formal specifications including preconditions, postconditions, invariants, and contracts from code or requirements. Use this skill when documenting APIs, creating formal verification annotations, defining function contracts, specifying class invariants, writing design-by-contract code, or preparing code for formal verification. Supports multiple specification languages including JML, ACSL

105estrelas
Atualizado há 8 meses

Ver no GitHub ↗ Licença: Apache-2.0

Como adicionar

/plugin marketplace add ArabelaTso/Skills-4-SE

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/specification-generator/svg)](https://www.skillteca.com.br/skills/specification-generator)

Alerta por categoria

Receba novas skills de Design e Frontend toda segunda

1 email curto, só com as skills novas de Design e Frontend. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

Specification Generator

Systematically generate formal specifications from code and requirements. Produces preconditions, postconditions, invariants, and behavioral contracts that enable verification, documentation, and design-by-contract programming.

Core Capabilities

1. Precondition Generation

Define required conditions before execution:

  • Parameter validation - Valid ranges, types, states
  • Object state requirements - Required object states
  • Resource availability - Files exist, connections open
  • Authorization checks - Permission requirements
  • Null safety - Non-null parameter requirements
  • Invariant satisfaction - Class invariants must hold

2. Postcondition Generation

Specify guaranteed outcomes after execution:

  • Return value constraints - Valid return ranges and properties
  • State modifications - How object state changes
  • Side effects - File writes, database updates
  • Exception conditions - When exceptions are thrown
  • Resource management - Resources properly released
  • Invariant preservation - Invariants still hold

3. Invariant Generation

Identify properties that always hold:

  • Class invariants - Properties true for all instances
  • Loop invariants - Properties preserved by iterations
  • Data structure invariants - Consistency conditions
  • Representation invariants - Internal consistency
  • Temporal invariants - Time-based properties

4. Contract Generation

Create complete behavioral specifications:

  • Method contracts - Full pre/post conditions
  • Interface contracts - API behavioral guarantees
  • Type contracts - Type-level properties
  • Protocol contracts - Valid call sequences
  • Frame conditions - What doesn't change

Specification Generation Workflow

Step 1: Analyze Code or Requirements

Understand what needs to be specified:

For existing code:

  • Read function/method implementation
  • Identify parameters and return type
  • Find state modifications
  • Detect resource usage
  • Locate error conditions

For requirements:

  • Extract functional requirements
  • Identify constraints and rules
  • Find boundary conditions
  • Determine error scenarios
  • Specify expected behavior

Example code:

def withdraw(account, amount):
    if account.balance < amount:
        raise InsufficientFundsError()
    account.balance -= amount
    return account.balance

Analysis:

  • Parameters: account (object), amount (number)
  • Return: new balance (number)
  • State change: account.balance decreases
  • Error: raises exception if insufficient funds
  • Constraints: amount should be positive, account must exist

Step 2: Identify Contract Elements

Determine what to specify:

Preconditions (requires/assume):

  • What must be true before execution?
  • Parameter validity requirements
  • Object state requirements

Postconditions (ensures/guarantee):

  • What is guaranteed after execution?
  • Return value properties
  • State changes

Invariants:

  • What is always true?
  • Class-level properties
  • Loop properties

Example identification:

# withdraw function
Preconditions:
- account is not None
- amount > 0
- account.balance >= amount (to succeed without exception)

Postconditions:
- If successful: account.balance == old(account.balance) - amount
- If successful: return value == new balance
- If insufficient: raises InsufficientFundsError
- account object still valid

Invariants (Account class):
- balance >= 0 (always)
- account_number is immutable

Step 3: Choose Specification Language

Select appropriate format:

Specification languages:

| Language | Use Case | Example | |----------|----------|---------| | JML (Java) | Java programs | //@ requires, //@ ensures | | ACSL (C) | C programs | /@ requires, /@ ensures | | Dafny | Verified code | requires, ensures | | Eiffel | Design-by-contract | require, ensure | | Python docstring | Documentation | :param:, :raises:, :returns: | | TypeScript | Type annotations | Type predicates, assertions | | Hoare logic | Formal proofs | {P} S {Q} notation |

Example language choice:

  • Java method → Use JML
  • C function → Use ACSL
  • Python function → Use docstring assertions
  • Verification task → Use Dafny

Step 4: Write Specifications

Generate formal contracts:

Format depends on language:

JML (Java):

/*@ requires amount > 0;
  @ requires account != null;
  @ requires account.balance >= amount;
  @ ensures account.balance == \old(account.balance) - amount;
  @ ensures \result == account.balance;
  @ signals (InsufficientFundsError e) account.balance < amount;
  @*/
public int withdraw(Account account, int amount) {
    // implementation
}

ACSL (C):

/*@ requires amount > 0;
  @ requires \valid(account);
  @ requires account->balance >= amount;
  @ ensures account->balance == \old(account->balance) - amount;
  @ ensures \result == account->balance;
  @*/
int withdraw(Account *account, int amount) {
    // implementation
}

Dafny:

method Withdraw(account: Account, amount: int) returns (newBalance: int)
    requires amount > 0
    requires account.balance >= amount
    ensures account.balance == old(account.balance) - amount
    ensures newBalance == account.balance
    modifies account
{
    // implementation
}

Python (docstring):

def withdraw(account: Account, amount: float) -> float:
    """
    Withdraw amount from account.

    :param account: The account to withdraw from
    :param amount: The amount to withdraw (must be positive)
    :raises InsufficientFundsError: If balance < amount
    :raises ValueError: If amount <= 0
    :returns: The new account balance

    Preconditions:
        - account is not None
        - amount > 0
        - account.balance >= amount (for successful withdrawal)

    Postconditions:
        - account.balance == old_balance - amount
        - return value == account.balance
        - If insufficient funds: InsufficientFundsError raised
        - account.balance >= 0 (invariant preserved)
    """
    # implementation

Step 5: Verify Specifications

Ensure specifications are correct:

Verification steps:

  1. Check preconditions are sufficient (not too strong)
  2. Verify postconditions are achievable (not too weak)
  3. Confirm invariants always hold
  4. Test specifications with examples
  5. Use formal verification tools if available

Example verification:

# Test preconditions
assert amount > 0  # Valid
assert account is not None  # Valid
assert account.balance >= amount  # Valid for success case

# Test postconditions
old_balance = account.balance
result = withdraw(account, 100)
assert account.balance == old_balance - 100  # Check
assert result == account.balance  # Check

# Test invariants
assert account.balance >= 0  # Should always hold

Specification Patterns

Pattern 1: Simple Function Contract

Code:

def sqrt(x):
    """Compute square root."""
    return x ** 0.5

Generated specification:

def sqrt(x: float) -> float:
    """
    Compute the square root of x.

    :param x: The number to compute square root of
    :returns: The square root of x
    :raises ValueError: If x < 0

    Preconditions:
        - x >= 0

    Postconditions:
        - result >= 0
        - abs(result * result - x) < 1e-10  # Precision tolerance
        - If x == 0, then result == 0
        - If x == 1, then result == 1
    """
    if x < 0:
        raise ValueError("Cannot compute square root of negative number")
    return x ** 0.5

JML version:

/*@ requires x >= 0;
  @ ensures \result >= 0;
  @ ensures Math.abs(\result * \result - x) < 1e-10;
  @ ensures x == 0 ==> \result == 0;
  @ ensures x == 1 ==> \result == 1;
  @ signals (IllegalArgumentException e) x < 0;
  @*/
public double sqrt(double x) {
    if (x < 0) throw new IllegalArgumentException();
    return Math.sqrt(x);
}
Compartilhar X LinkedIn