An AI generated, agnostic prompt language for describing software logic to AI systems.

Write what.
Let AI write how.

LogicScript sits between plain English (too vague) and production code (too specific). Describe your system's logic once — any AI turns it into TypeScript, Python, SQL, Java, Rust, C++ -- or whatever language!

logicscript prompt
SHAPE User
  id        : UUID      required auto
  email     : String    required unique
  role      : Enum[admin, user]  default=user

FUNC createUser(email, password, name)
  --- Creates a new user account. ---
  VALIDATE
    email    matches email pattern
    password length >= 8
    email    not exists in User

  DO
    hash = bcrypt(password)
    user = User.create(email, hash, name)
    EMIT UserCreated WITH user

  RETURN user
  ON FAIL THROW ValidationError

ON UserCreated
  TRIGGER EmailService.sendWelcome(user.email)
  LOG "New signup: {user.email}"
Language-agnostic

Write one LogicScript prompt. Generate TypeScript, Python, SQL, Java, Rust, or C++ from the same source. The AI handles the translation.

Intentionally incomplete

LogicScript describes intent, not implementation. Plain English is valid inside any block. The AI fills gaps with sensible defaults for your target stack.

Readable by anyone

Power users write prompts without programming experience. Developers use the same format to generate production-grade code with precise contracts.

Building blocks

SHAPE
Data structure with typed fields
FUNC
Action with validate / do / return
FLOW
Multi-step process, parallel support
VALIDATE
Pre-flight precondition checks
GUARD
Reusable access control block
POLICY
Cross-cutting system rule
ON / EMIT
Event subscriptions and emissions
STATE
State machine with transitions
QUERY
Named data retrieval operation
SCHEDULE
Recurring automated job
@annotations
Cache, retry, transaction hints
MODULE
Service boundary and public API

Four steps to working code

01

Define your data

Use SHAPE to describe records — fields, types, and constraints like required, unique, and default.

02

Describe your logic

Use FUNC with VALIDATE and DO blocks to describe actions, rules, and what happens when things go wrong.

03

Choose a target

Pick any language or framework. TypeScript, Python, SQL, Java, Rust, C++. The same prompt works for all of them.

04

Prompt an AI

Paste your LogicScript prompt with the instruction: "Implement this in [language]." Review and deploy.

prompt template
Implement the following LogicScript prompt in [TARGET LANGUAGE].

Rules:
- Honor every VALIDATE condition as a precondition check.
- Map ON FAIL clauses to the language's error/exception mechanism.
- Translate EMIT to the appropriate event or message-bus call.
- Do not add behavior not described in the prompt.

[LOGICSCRIPT PROMPT]

REFERENCE: https://github.com/logicscript/logicscript/blob/main/logicscript-spec.md

What is LogicScript?

LogicScript is a way of writing down the rules of a piece of software in plain, structured English — precise enough that an AI can turn it into working code, but readable enough that a non-programmer can write and understand it.

Think of it like writing a Standard Operating Procedure. You describe what information exists, what actions are allowed, what the rules are, and what happens automatically. You do not describe how the computer carries out those actions — that is the AI's job.

The key idea: Write what, not how.

How it works

  1. Write a prompt in LogicScript describing the system's rules and behaviours.
  2. Give it to an AI (Claude, GPT-4, etc.) with an instruction like "Implement this LogicScript prompt in Python."
  3. The AI produces working code that follows your prompt exactly.
  4. A developer reviews and deploys the code.
Note

LogicScript is a prompt language, not an execution runtime. It has no interpreter. Its output is always AI-generated code in a target language.

Your first prompt

A LogicScript prompt follows a few simple rules:

  • Keywords are ALL CAPSSHAPE, FUNC, VALIDATE, etc.
  • Indentation matters — two spaces per level, like a nested bullet list
  • Plain English is valid inside any block
  • Comments start with --
logicscript
SHAPE Product
  id    : UUID    required auto
  name  : String  required
  price : Float   required min=0
  stock : Int     required default=0

FUNC buyProduct(productId, quantity, userId)
  --- Lets a user purchase a product. ---

  VALIDATE
    quantity > 0
    product exists with id = productId
    product.stock >= quantity
    user has valid payment method

  DO
    charge user for quantity * product.price
    reduce product.stock by quantity
    create an Order record
    EMIT OrderPlaced WITH order

  RETURN order
  ON FAIL THROW PurchaseError

Core concepts

Indentation

LogicScript uses indentation (two spaces) to express nesting. No braces, brackets, or end keywords.

Plain English is always valid

If a condition or step is hard to express structurally, write it out in plain English. The AI infers the most idiomatic implementation.

Design philosophy

  • Intentionally incomplete — the AI fills sensible defaults
  • Indentation over syntax — no braces or semicolons
  • Declarative over imperative — describe outcomes, not steps

SHAPE — describing data

A SHAPE describes a type of record — its fields, types, and constraints.

Type Stores
String Text of any length
Int Whole number
Float Decimal number
Bool True or false
UUID Unique identifier (auto-generated)
Timestamp Date and time
Enum[a,b,c] One of a fixed list of values
List<Type> Ordered collection
Constraint Meaning
required Must always be present
optional May be blank or null
unique No two records share this value
auto System-generated automatically
default=X Use X when not supplied
min=N / max=N Value or length limits
immutable Cannot change after creation
indexed Optimise lookups on this field

FUNC — describing actions

A FUNC defines something the system can do. It has four optional blocks:

logicscript
FUNC submitExpenseReport(reportId, userId)
  --- Submits a draft expense report for approval. ---

  VALIDATE
    report exists with id = reportId
    report.status IS draft
    report.ownerId IS userId
    report.totalAmount > 0

  DO
    report.status = pending
    report.submittedAt = NOW
    EMIT ReportSubmitted WITH { reportId, userId }

  RETURN report
  ON FAIL LOG error, THROW SubmissionError

FLOW — multi-step processes

A FLOW is for processes with distinct named stages. Use PARALLEL to run steps concurrently.

logicscript
FLOW OnboardNewEmployee(employeeId)
  STEP createAccounts
    create email, Slack, and HR system accounts

  STEP scheduleOrientation
    find next available orientation session
    send calendar invite to employee and manager

  STEP notify
    EMIT EmployeeOnboarded WITH { employeeId }
    send welcome email to employee

VALIDATE — input checks

Each line in a VALIDATE block is one check. If any fails, execution stops before any side effects run.

logicscript
VALIDATE
  email not empty
  email matches email pattern
  password length >= 8
  age between 18 and 120
  productId exists in Product
  email not exists in User
  startDate is before endDate
  cart.items not empty  MESSAGE "Cart cannot be empty"

GUARD & ALLOW / DENY

Define reusable access rules once and apply them anywhere.

logicscript
GUARD AdminOnly
  REQUIRE user.role IS admin
  ON FAIL THROW ForbiddenError

FUNC deleteRecord(recordId)
  GUARD AdminOnly
  DO
    Record.delete(recordId)

ALLOW publish WHEN user.role IS admin OR user.role IS editor
DENY  delete  WHEN document.locked IS true

POLICY — system-wide rules

logicscript
POLICY RateLimit
  APPLIES TO all API endpoints
  ALLOW 100 requests PER user PER minute
  ON EXCEED return error "Too many requests"

POLICY DataRetention
  APPLIES TO CustomerActivityLog
  KEEP 2 years
  THEN archive to cold storage
  DELETE after 7 years

QUERY — finding records

logicscript
QUERY overdueInvoices
  FROM Invoice
  WHERE status IS sent
  AND   dueDate < TODAY
  ORDER BY dueDate ASC

QUERY recentOrdersForUser(userId)
  FROM Order
  WHERE userId IS userId
  AND   createdAt WITHIN 90 days
  INCLUDE items, shippingAddress
  ORDER BY createdAt DESC

ON & EMIT — events

Events decouple producers from consumers. EMIT fires an event; ON reacts to it.

logicscript
EMIT OrderPlaced WITH { orderId, userId, total }

ON OrderPlaced
  send order confirmation to user.email
  notify fulfillment team
  LOG "Order {orderId} placed"

ON PaymentFailed 3 times
  suspend user account
  ALERT billing-team

STATE — status workflows

logicscript
STATE Invoice
  STATES  draft, sent, paid, overdue, cancelled

  TRANSITION draft   -> sent    ON sendInvoice
  TRANSITION sent    -> paid    ON paymentReceived
  TRANSITION sent    -> overdue ON dueDatePassed
  TRANSITION ANY     -> cancelled ON cancelInvoice
    WHEN status NOT IN [paid]

  ON ENTER overdue
    send reminder to invoice.customerEmail
    ALERT accounts-receivable-team

SCHEDULE — recurring jobs

logicscript
SCHEDULE cleanExpiredSessions
  EVERY 1 hour
  DO
    deleted = Session.deleteExpired()
    LOG "Purged {deleted} sessions"

SCHEDULE monthlyBilling
  AT "first day of month 00:01 UTC"
  DO
    FOR EACH active subscription
      charge subscriber for their plan

Annotations — hints for the AI

Annotation Meaning
@transaction All steps succeed or all roll back
@retryable attempts=3 Retry on failure up to N times
@cached ttl=5m Cache the result for 5 minutes
@idempotent key="..." Only run once per unique input
@rateLimit 10/minute Limit calls per user per minute
@deprecated since="2.0" Mark as replaced by a newer function

Tips for better prompts

  • Mix plain English freely. If something is hard to express structurally, just write it out.
  • Keep each FUNC focused. One function, one purpose. If your DO block has more than 7 steps, consider splitting.
  • Name things clearly. submitExpenseReport is better than submit.
  • Be explicit about failures. Always include ON FAIL so the AI knows what error contract to implement.
  • Use @transaction for money. Any function that moves funds or adjusts inventory should be atomic.
  • Include the spec reference. Add REFERENCE: https://github.com/logicscript/logicscript/blob/main/logicscript-spec.md to your prompt so the AI gets up to speed quickly.

Quick reference card

structure
SHAPE   Name          — define a data record
FUNC    name(inputs)  — define an action
FLOW    Name(inputs)  — multi-step process
  STEP  stepName      — one stage of a flow
  PARALLEL … WAIT all — concurrent steps
MODULE  Name          — group related functions
  ENTRY functionName  — mark a function as public
logic
VALIDATE              — pre-flight checks (stop if any fail)
DO                    — sequential side-effect steps
RETURN value          — output value
ON FAIL THROW Error   — error handling
REQUIRE x ELSE THROW  — inline check inside DO
IF condition … ELSE   — branching
FOR EACH item         — iteration
access + events
GUARD  Name           — define a reusable access rule
ALLOW action WHEN x   — grant permission
DENY  action WHEN x   — block permission
EMIT  Event WITH data — fire an event
ON    EventName       — react to an event
  TRIGGER fn(args)    — call a function
  ALERT team-name     — notify a team
MODULEService or component boundary

Groups related functions and declares the public API surface. ENTRY marks a function as publicly callable.

syntax
MODULE ServiceName
  [IMPORT Symbol1, Symbol2 FROM source]
  [USE Symbol.method AS alias]
  ENTRY functionName(params)
SHAPEData structure definition

Defines a data structure with typed, constrained fields. Types and constraints are implementation hints — the AI maps them to the most appropriate constructs in the target language.

syntax
SHAPE ShapeName
  fieldName : Type  constraint [constraint ...]
FUNCFunction definition

Defines a unit of logic. All four blocks are optional, but at least DO or RETURN must be present.

syntax
FUNC functionName(param1, param2, ...)
  [--- doc comment ---]
  [VALIDATE
    condition ...]
  [DO
    step ...]
  [RETURN value]
  [ON FAIL strategy]

ON FAIL strategies

options
ON FAIL THROW ErrorName
ON FAIL LOG error
ON FAIL RETURN defaultValue
ON FAIL retry N times THEN THROW ErrorName
ON FAIL LOG error, THROW ErrorName
VALIDATEPrecondition block

A block of precondition checks inside a FUNC. Each line is one condition, evaluated top to bottom. The first failure stops execution and triggers the ON FAIL handler. Nothing in DO runs if any check fails.

common patterns
VALIDATE
  email not empty
  email matches email pattern
  password length >= 8
  age between 18 and 120
  price > 0
  productId exists in Product
  email not exists in User
  startDate is before endDate
  cart.items not empty  MESSAGE "Cart cannot be empty"

Plain English is valid for complex conditions the AI will infer the implementation for.

FLOWMulti-step process

A named, multi-step operation. Use when a process has distinct named stages. PARALLEL runs steps concurrently; WAIT all or WAIT any synchronises.

syntax
FLOW FlowName(params)
  STEP stepName
    logic ...
  PARALLEL
    STEP stepA ...
    STEP stepB ...
  WAIT all
GUARDReusable access control
syntax
GUARD GuardName
  REQUIRE condition [OR condition]
  ON FAIL THROW ErrorName
POLICYCross-cutting system rule
syntax
POLICY PolicyName
  APPLIES TO target [, target ...]
  ALLOW N requests PER unit PER period
  ON EXCEED action
QUERYNamed data retrieval
syntax
QUERY queryName(params)
  FROM     ShapeName
  [WHERE   condition [AND condition ...]]
  [INCLUDE relatedShape, ...]
  [ORDER BY field ASC|DESC]
  [LIMIT   N]
  [OFFSET  N]
ON / EMITEvent-driven reactions
syntax
EMIT EventName WITH { field1, field2 }

ON EventName
  TRIGGER functionName(args)
  SEND MessageType TO recipient
  LOG "message {variable}"
  ALERT team-name

ON EventName N times   -- fires after N occurrences
  ...
STATEFinite state machine
syntax
STATE ShapeName
  STATES  state1, state2, ...

  TRANSITION a -> b ON eventName
  TRANSITION ANY -> b ON eventName
    WHEN status NOT IN [excludedState]

  ON ENTER stateName
    steps ...
  ON EXIT stateName
    steps ...
SCHEDULERecurring job
syntax
SCHEDULE jobName
  EVERY N unit        -- minutes | hours | days
  DO
    steps ...

SCHEDULE jobName
  AT "schedule expression"
  DO
    steps ...

Examples: "9:00 AM daily", "Monday 8:00 AM", "first day of month 08:00 UTC"

@annotationsImplementation hints
Annotation Meaning Hint
@transaction Atomic block DB transaction + rollback on error
@retryable attempts=N backoff=X Retry on failure X: linear, exponential, or duration
@cached ttl=Ns key="..." Cache result In-memory, Redis, or equivalent
@idempotent key="..." Deduplicate calls Return stored result for same key
@deprecated since="X" use=fn Mark as replaced Add deprecation warning
@observable metrics=[m1,m2] Instrument with metrics Latency, error_rate, throughput
@rateLimit N/period per=field Per-caller rate limit Middleware or decorator

Primitive types

Type Description
String UTF-8 text of any length
Int 64-bit signed integer
Float 64-bit floating-point
Bool Boolean true or false
UUID RFC 4122 UUID
Timestamp ISO 8601 date-time with timezone
List<T> Ordered collection of T
Map<K,V> Key-value map
Enum[a,b,c] Closed set of named values
JSON Arbitrary JSON-serializable value

Constraints

Constraint Applies to Meaning
required All Must be present and non-null
optional All May be null or absent
unique All Value must be unique across all records
auto UUID, Timestamp System-generated automatically
default=X All Default when not supplied
min=N Int, Float, String, List Minimum value or length
max=N Int, Float, String, List Maximum value or length
pattern="regex" String Must match the regular expression
immutable All Cannot change after creation
indexed All Add a database index

Keyword index

Keyword Category Role
MODULE Structure Named service/component boundary
ENTRY Structure Public function within MODULE
SHAPE Structure Data structure definition
FUNC Structure Function definition
FLOW Structure Multi-step process
STEP Structure Named stage within a FLOW
PARALLEL / WAIT Structure Concurrent steps
VALIDATE Logic Precondition block
DO Logic Ordered steps
RETURN Logic Output value
ON FAIL Logic Error handling
REQUIRE … ELSE Logic Inline assertion in DO
IF / ELSE Logic Conditional branching
FOR EACH Logic Iteration
ALLOW / DENY Access Permission rules
GUARD Access Reusable access block
POLICY Access Cross-cutting rule
QUERY Data Named data retrieval
EMIT … WITH Events Publish a named event
ON [event] Events Subscribe to an event
TRIGGER Events Invoke from event handler
ALERT Events Notify a team or channel
STATE State State machine definition
TRANSITION State Valid state change
ON ENTER / ON EXIT State State lifecycle hooks
SCHEDULE Jobs Recurring job
EVERY / AT Jobs Job timing

Formal grammar (BNF)

bnf — approximate
program     ::= (declaration | comment)*

declaration ::= module | shape | func | flow | guard
              | policy | query | on_handler | state | schedule

IDENT       ::= [a-zA-Z][a-zA-Z0-9_]*
PASCAL      ::= [A-Z][a-zA-Z0-9]*
CAMEL       ::= [a-z][a-zA-Z0-9]*

module      ::= "MODULE" PASCAL NL
                (INDENT import_stmt)*
                (INDENT "ENTRY" CAMEL "(" params? ")")*

shape       ::= "SHAPE" PASCAL NL
                (INDENT field_decl)*

field_decl  ::= CAMEL ":" type constraint*

type        ::= "String" | "Int" | "Float" | "Bool"
              | "UUID" | "Timestamp" | "JSON"
              | "List<" type ">" | "Map<" type "," type ">"
              | "Enum[" CAMEL ("," CAMEL)* "]"

func        ::= annotation* "FUNC" CAMEL "(" params? ")" NL
                doc_comment?
                validate_block?
                do_block?
                return_stmt?
                on_fail?

NL          ::= newline
INDENT      ::= "  " (two spaces)
👋
Hello world
The simplest possible LogicScript prompt.

Implement this LogicScript prompt in Python.

logicscript
FUNC greet(name)
  --- Returns a personalised greeting. ---
  VALIDATE
    name not empty
  DO
    message = "Hello, " + name + "."
    PRINT message
  RETURN message
  ON FAIL THROW ValidationError
Task list
SHAPE, FUNC, and QUERY working together — a minimal task manager.

Implement this LogicScript prompt in your preferred language or framework.

logicscript
SHAPE Task
  id        : UUID      required auto
  title     : String    required max=200
  done      : Bool      default=false
  createdAt : Timestamp auto

FUNC addTask(title)
  VALIDATE
    title not empty
  DO
    task = Task.create(title)
  RETURN task

FUNC completeTask(taskId)
  VALIDATE
    taskId exists in Task
    task.done IS false
  DO
    task.done = true
  RETURN task

QUERY openTasks
  FROM Task
  WHERE done IS false
  ORDER BY createdAt ASC
📬
Contact form
Validates a submission and routes it to the right team using events.

Implement this LogicScript prompt in your preferred language or framework.

logicscript
SHAPE ContactMessage
  id          : UUID      required auto
  name        : String    required min=2 max=100
  email       : String    required
  subject     : String    required max=200
  body        : String    required min=10 max=5000
  category    : Enum[general, sales, support, billing]  default=general
  submittedAt : Timestamp auto

FUNC submitContactForm(name, email, subject, body, category)
  VALIDATE
    name not empty
    email matches email pattern
    body length >= 10
  DO
    message = ContactMessage.create(name, email, subject, body, category)
    EMIT ContactFormSubmitted WITH message

ON ContactFormSubmitted
  send auto-reply to message.email confirming receipt
  forward message to the team inbox for message.category
📅
Room booking
Books a meeting room after checking availability and capacity.

Implement this LogicScript prompt in your preferred language or framework.

logicscript
SHAPE RoomBooking
  id        : UUID      required auto
  roomId    : UUID      required
  userId    : UUID      required
  title     : String    required
  startTime : Timestamp required
  endTime   : Timestamp required
  attendees : Int       required min=1
  createdAt : Timestamp auto

FUNC bookRoom(roomId, userId, title, startTime, endTime, attendees)
  VALIDATE
    roomId exists in Room
    startTime is before endTime
    attendees <= room.capacity
    no existing booking for roomId overlaps with startTime to endTime
  DO
    booking = RoomBooking.create(roomId, userId, title, startTime, endTime, attendees)
    EMIT RoomBooked WITH booking

ON RoomBooked
  send confirmation email to booking.userId
  add booking to the room calendar
🧾
Expense report
Approval workflow with status transition and manager notification.

Implement this LogicScript prompt in your preferred language or framework.

logicscript
SHAPE ExpenseReport
  id          : UUID      required auto
  employeeId  : UUID      required
  title       : String    required
  totalAmount : Float     required min=0
  status      : Enum[draft, submitted, approved, rejected]  default=draft
  submittedAt : Timestamp optional
  createdAt   : Timestamp auto

FUNC submitExpenseReport(reportId, employeeId)
  VALIDATE
    reportId exists in ExpenseReport
    report.status IS draft
    report.employeeId IS employeeId
    report.totalAmount > 0
  DO
    report.status = submitted
    report.submittedAt = NOW
    managerId = look up employeeId's direct manager
    EMIT ExpenseSubmitted WITH { reportId, employeeId, managerId }

ON ExpenseSubmitted
  send approval request to managerId
  send submission confirmation to employeeId
✍️
Blog publishing
Two-role publish flow: draft → review → published.

Implement this LogicScript prompt in your preferred language or framework.

logicscript
SHAPE BlogPost
  id          : UUID      required auto
  title       : String    required min=5 max=200
  body        : String    required min=100
  authorId    : UUID      required
  slug        : String    required unique
  status      : Enum[draft, review, published, archived]  default=draft
  publishedAt : Timestamp optional

FUNC submitForReview(postId, authorId)
  VALIDATE
    post.status IS draft
    post.authorId IS authorId
    post.body length >= 100
  DO
    post.status = review
    EMIT PostSubmittedForReview WITH post

FUNC publishPost(postId, editorId)
  VALIDATE
    post.status IS review
    editorId has role editor OR admin
  DO
    post.status = published
    post.publishedAt = NOW
    EMIT PostPublished WITH post

ON PostPublished
  notify post.authorId of publication
  update site RSS feed
📦
Inventory reorder
Automatically triggers a purchase order when stock falls below threshold.

Implement this LogicScript prompt in your preferred language or framework.

logicscript
SHAPE Product
  id         : UUID   required auto
  sku        : String required unique
  stockCount : Int    required default=0
  reorderAt  : Int    required default=10
  reorderQty : Int    required default=50
  supplierId : UUID   required

FUNC recordStockMovement(productId, quantityChange, reason)
  VALIDATE
    productId exists in Product
    quantityChange not equals 0
    new stock level would not go below 0
  DO
    product.stockCount = product.stockCount + quantityChange
    LOG "Stock for {product.sku}: {quantityChange} ({reason})"
    IF product.stockCount <= product.reorderAt
      EMIT LowStock WITH { productId, currentStock: product.stockCount }

ON LowStock
  TRIGGER PurchasingService.createPurchaseOrder(productId, supplierId, product.reorderQty)
  ALERT purchasing-team
🔄
Invoice state machine
Complete invoice lifecycle with automatic overdue detection and daily schedule.

Implement this LogicScript prompt in your preferred language or framework.

logicscript
STATE Invoice
  STATES  draft, sent, paid, overdue, cancelled

  TRANSITION draft   -> sent     ON sendInvoice
  TRANSITION sent    -> paid     ON markAsPaid
  TRANSITION sent    -> overdue  ON dueDatePassed
  TRANSITION overdue -> paid     ON markAsPaid
  TRANSITION ANY     -> cancelled ON cancelInvoice
    WHEN status NOT IN [paid]

  ON ENTER sent
    EMIT InvoiceSent WITH invoice
  ON ENTER paid
    EMIT InvoicePaid WITH invoice
  ON ENTER overdue
    send reminder to invoice.customerEmail
    ALERT accounts-receivable-team

ON InvoicePaid
  TRIGGER AccountingService.recordPayment(invoice)
  send receipt to invoice.customerEmail

SCHEDULE checkOverdueInvoices
  AT "9:00 AM daily"
  DO
    overdue = all invoices WHERE status IS sent AND dueDate < TODAY
    FOR EACH overdue invoice
      trigger dueDatePassed transition
🔐
Auth service
Login, signup, logout, brute-force protection, session cleanup — a complete MODULE.

Implement this LogicScript prompt in TypeScript (Node.js). Use Prisma for database access, bcryptjs for password hashing, and EventEmitter for events.

logicscript
MODULE AuthService
  ENTRY login(email, password)
  ENTRY signup(email, password, name)
  ENTRY logout(sessionToken)

SHAPE User
  id           : UUID      required auto
  email        : String    required unique
  passwordHash : String    required
  role         : Enum[admin, user, guest]  default=user
  status       : Enum[active, suspended]    default=active
  createdAt    : Timestamp auto

SHAPE Session
  id        : UUID      required auto
  userId    : UUID      required indexed
  token     : String    required unique auto
  expiresAt : Timestamp required
  createdAt : Timestamp auto

FUNC login(email, password)
  --- Authenticates a user and returns a new session. ---
  VALIDATE
    email not empty
    password not empty
  DO
    user = UserRepo.findByEmail(email)
    REQUIRE user exists ELSE THROW NotFoundError
    REQUIRE Crypto.verify(password, user.passwordHash)
      ELSE THROW AuthError
    REQUIRE user.status IS active
      ELSE THROW AccountSuspendedError
    session = SessionRepo.create(user.id, expiresIn=7 days)
  RETURN session
  ON FAIL LOG error, THROW AuthError

FUNC signup(email, password, name)
  VALIDATE
    email    matches email pattern
    password length >= 8
    name     length >= 2
    email    not exists in User
  DO
    hash = Crypto.hash(password)
    user = UserRepo.create(email, hash, name)
    EMIT UserCreated WITH user
  RETURN user

FUNC logout(sessionToken)
  DO
    SessionRepo.invalidate(sessionToken)

ON UserCreated
  TRIGGER EmailService.sendWelcome(user.email, user.name)

POLICY LoginProtection
  APPLIES TO login
  ALLOW 5 attempts PER ip PER 15 minutes
  ON EXCEED lockout for 30 minutes, ALERT security-team

SCHEDULE sessionCleanup
  EVERY 6 hours
  DO
    deleted = SessionRepo.deleteExpired()
    LOG "Purged {deleted} expired sessions"
💳
Monthly billing
Recurring billing schedule with per-subscriber charges and failure handling.

Implement this LogicScript prompt in your preferred language or framework.

logicscript
SCHEDULE monthlyBilling
  AT "first day of month 00:01 UTC"
  DO
    subscriptions = all Subscriptions WHERE status IS active
      AND nextBillingDate <= TODAY
    FOR EACH subscription
      charge subscription.customerId for subscription.pricePerMonth
      IF charge succeeded
        send receipt to subscription.billingEmail
      IF charge failed
        EMIT BillingFailed WITH { subscription, reason }

ON BillingFailed
  send payment failure notice to subscription.billingEmail
  retry the charge after 3 days
  IF charge fails 3 times in a row
    set subscription.status = paused
    ALERT billing-team

Output: JavaScript (Node.js)

JavaScript output targets Node.js with ES modules and async/await. SHAPE becomes a JSDoc-annotated object type, ON FAIL THROW becomes a named Error subclass, and EMIT maps to an EventEmitter call.

LogicScript JavaScript (Node.js)
SHAPE JSDoc @typedef or TypeScript interface
FUNC async function export
VALIDATE Guard if statements before any side effects
ON FAIL THROW Named class extending Error
EMIT … WITH eventBus.emit('EventName', payload)
PARALLEL + WAIT all await Promise.all([...])
@transaction db.$transaction() callback

createUser

logicscript — input
FUNC createUser(email, password, name)
  VALIDATE
    email    matches email pattern
    password length >= 8
    name     length >= 2
    email    not exists in User
  DO
    hash = bcrypt(password)
    user = User.create(email, hash, name)
    EMIT UserCreated WITH user
  RETURN user
  ON FAIL THROW ValidationError
javascript
// Generated from LogicScript — createUser
import bcrypt    from 'bcryptjs';
import { v4 as uuidv4 } from 'uuid';
import { db }    from './db.js';
import { eventBus } from './events.js';

export class ValidationError extends Error {
  constructor(message) {
    super(message);
    this.name = 'ValidationError';
    this.statusCode = 422;
  }
}

const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

/** @throws {ValidationError} */
export async function createUser(email, password, name) {
  // VALIDATE
  if (!EMAIL_RE.test(email))
    throw new ValidationError('Invalid email format');
  if (password.length < 8)
    throw new ValidationError('Password must be at least 8 characters');
  if (name.length < 2)
    throw new ValidationError('Name must be at least 2 characters');

  const existing = await db.user.findUnique({ where: { email } });
  if (existing)
    throw new ValidationError('Email is already registered');

  // DO
  const hash = await bcrypt.hash(password, 12);
  const user = await db.user.create({
    data: { id: uuidv4(), email, name, passwordHash: hash,
            role: 'user', createdAt: new Date() },
  });

  // EMIT UserCreated
  eventBus.emit('UserCreated', user);
  return user;
}

GenerateDashboard — parallel FLOW

javascript
// PARALLEL + WAIT all → Promise.all
export async function generateDashboard(userId) {
  const [stats, activity, notifications] = await Promise.all([
    Analytics.getUserStats(userId),
    ActivityLog.recent(userId, { limit: 20 }),
    Inbox.unread(userId),
  ]);
  return { stats, activity, notifications };
}

Output: Python

Python 3.11+ output. SHAPE becomes a @dataclass, Enum fields become enum.Enum, and ON FAIL THROW becomes a custom exception. Async functions use asyncio.

LogicScript Python
SHAPE @dataclass with typed fields
FUNC def or async def with type hints
VALIDATE if … raise guards before side effects
ON FAIL THROW Custom exception extending Exception
EMIT … WITH event_bus.emit('event_name', payload)
PARALLEL + WAIT all await asyncio.gather(...)
@transaction with db.begin(): context manager

createUser

python
import re, uuid, bcrypt
from dataclasses import dataclass, field
from datetime   import datetime, timezone
from enum       import Enum

class Role(Enum):
    ADMIN = "admin"
    USER  = "user"
    GUEST = "guest"

@dataclass
class User:
    id:            str      = field(default_factory=lambda: str(uuid.uuid4()))
    email:         str      = ""
    name:          str      = ""
    password_hash: str      = ""
    role:          Role     = Role.USER
    created_at:    datetime = field(
        default_factory=lambda: datetime.now(timezone.utc))

class ValidationError(Exception):
    def __init__(self, message: str):
        super().__init__(message)
        self.status_code = 422

EMAIL_RE = re.compile(r"^[^\s@]+@[^\s@]+\.[^\s@]+$")
_users: dict[str, User] = {}

def create_user(email: str, password: str, name: str) -> User:
    """Creates a new user account. Raises ValidationError on failure."""
    if not EMAIL_RE.match(email):
        raise ValidationError("Invalid email format")
    if len(password) < 8:
        raise ValidationError("Password must be at least 8 characters")
    if len(name) < 2:
        raise ValidationError("Name must be at least 2 characters")
    if any(u.email == email for u in _users.values()):
        raise ValidationError("Email is already registered")

    hashed = bcrypt.hashpw(password.encode(), bcrypt.gensalt()).decode()
    user   = User(email=email, password_hash=hashed, name=name)
    _users[user.id] = user
    event_bus.emit("UserCreated", user)
    return user

GenerateDashboard — parallel FLOW

python
import asyncio

async def generate_dashboard(user_id: str) -> dict:
    # PARALLEL + WAIT all → asyncio.gather
    stats, activity, notifications = await asyncio.gather(
        analytics.get_user_stats(user_id),
        activity_log.recent(user_id, limit=20),
        inbox.unread(user_id),
    )
    return {"stats": stats, "activity": activity, "notifications": notifications}

transferFunds — @transaction

python
def transfer_funds(from_id: str, to_id: str, amount: float, db, event_bus) -> dict:
    if amount <= 0:
        raise TransferError("Amount must be positive")
    if from_id == to_id:
        raise TransferError("Cannot transfer to the same account")

    from_acct = db.query(Account).filter_by(id=from_id).one()
    if from_acct.balance < amount:
        raise TransferError("Insufficient funds")

    try:
        with db.begin():              # @transaction → SQLAlchemy context manager
            from_acct.balance -= amount
            to_acct = db.query(Account).filter_by(id=to_id).one()
            to_acct.balance   += amount
    except Exception as exc:
        raise TransferError(f"Transaction failed: {exc}") from exc

    event_bus.emit("FundsTransferred", {"from": from_id, "to": to_id, "amount": amount})
    return {"success": True}

Output: SQL (PostgreSQL)

SQL output covers schema DDL from SHAPE declarations and stored functions/procedures from FUNC blocks. All examples target PostgreSQL 15+.

SHAPE User → CREATE TABLE

sql
-- Generated from LogicScript SHAPE User
CREATE TYPE user_role AS ENUM ('admin', 'user', 'guest');

CREATE TABLE users (
  id         UUID         PRIMARY KEY DEFAULT gen_random_uuid(),
  email      TEXT         NOT NULL UNIQUE,
  name       VARCHAR(100) NOT NULL CHECK (length(name) >= 2),
  role       user_role    NOT NULL DEFAULT 'user',
  created_at TIMESTAMPTZ  NOT NULL DEFAULT now()
);

CREATE INDEX idx_users_email ON users (email);
CREATE INDEX idx_users_role  ON users (role);

createUser → plpgsql function

sql
CREATE EXTENSION IF NOT EXISTS pgcrypto;

CREATE OR REPLACE FUNCTION create_user(
  p_email    TEXT,
  p_password TEXT,
  p_name     TEXT
) RETURNS users LANGUAGE plpgsql AS $$
DECLARE
  v_hash TEXT;  v_user users;
BEGIN
  IF p_email !~ '^[^\s@]+@[^\s@]+\.[^\s@]+$' THEN
    RAISE EXCEPTION 'ValidationError: invalid email'; END IF;
  IF length(p_password) < 8 THEN
    RAISE EXCEPTION 'ValidationError: password too short'; END IF;
  IF length(p_name) < 2 THEN
    RAISE EXCEPTION 'ValidationError: name too short'; END IF;
  IF EXISTS(SELECT 1 FROM users WHERE email = p_email) THEN
    RAISE EXCEPTION 'ValidationError: email taken'; END IF;

  v_hash := crypt(p_password, gen_salt('bf', 12));
  INSERT INTO users(email, password_hash, name)
    VALUES(p_email, v_hash, p_name) RETURNING * INTO v_user;
  PERFORM pg_notify('user_created', row_to_json(v_user)::text);
  RETURN v_user;
END; $$;

transferFunds → atomic procedure

sql
CREATE OR REPLACE PROCEDURE transfer_funds(
  p_from_id UUID, p_to_id UUID, p_amount NUMERIC(18,2)
) LANGUAGE plpgsql AS $$
DECLARE v_balance NUMERIC(18,2);
BEGIN
  IF p_amount <= 0 THEN
    RAISE EXCEPTION 'TransferError: amount must be positive'; END IF;
  IF p_from_id = p_to_id THEN
    RAISE EXCEPTION 'TransferError: same account'; END IF;
  SELECT balance INTO v_balance FROM accounts WHERE id = p_from_id FOR UPDATE;
  IF v_balance < p_amount THEN
    RAISE EXCEPTION 'TransferError: insufficient funds'; END IF;
  UPDATE accounts SET balance = balance - p_amount WHERE id = p_from_id;
  UPDATE accounts SET balance = balance + p_amount WHERE id = p_to_id;
  PERFORM pg_notify('funds_transferred',
    json_build_object('from',p_from_id,'to',p_to_id,'amount',p_amount)::text);
END; $$;

Output: Java

Java 21+ with Spring Boot. SHAPE becomes a record, FUNC becomes a @Service method, and @Transactional handles @transaction. Events use Spring's ApplicationEventPublisher.

createUser

java
// Generated from LogicScript — SHAPE User + FUNC createUser
public record User(UUID id, String email, String name,
                   String passwordHash, Role role, Instant createdAt) {
  public enum Role { ADMIN, USER, GUEST }
}

public class ValidationException extends RuntimeException {
  private final int statusCode;
  public ValidationException(String msg) { super(msg); this.statusCode = 422; }
  public int getStatusCode() { return statusCode; }
}

@Service
public class UserService {
  private static final Pattern EMAIL_PATTERN =
      Pattern.compile("^[^\s@]+@[^\s@]+\.[^\s@]+$");

  private final UserRepository userRepository;
  private final PasswordEncoder passwordEncoder;
  private final ApplicationEventPublisher eventPublisher;

  public User createUser(String email, String password, String name) {
    // VALIDATE
    if (!EMAIL_PATTERN.matcher(email).matches())
      throw new ValidationException("Invalid email format");
    if (password.length() < 8)
      throw new ValidationException("Password must be at least 8 characters");
    if (name.length() < 2)
      throw new ValidationException("Name must be at least 2 characters");
    if (userRepository.existsByEmail(email))
      throw new ValidationException("Email already registered");

    // DO: hash and persist
    String hash = passwordEncoder.encode(password);
    User   user = new User(UUID.randomUUID(), email, name, hash,
                           User.Role.USER, Instant.now());
    user = userRepository.save(user);

    // EMIT UserCreated
    eventPublisher.publishEvent(new UserCreatedEvent(this, user));
    return user;
  }
}

Order STATE machine

java
public enum OrderStatus { DRAFT, PENDING, PAID, SHIPPED, DELIVERED, CANCELLED }

@Service
public class OrderStateMachine {
  private record Transition(Set<OrderStatus> from, OrderStatus to) {}

  private static final Map<String, Transition> TRANSITIONS = Map.of(
    "submitOrder",       new Transition(Set.of(DRAFT),                          PENDING),
    "paymentReceived",   new Transition(Set.of(PENDING),                        PAID),
    "fulfillOrder",      new Transition(Set.of(PAID),                           SHIPPED),
    "deliveryConfirmed", new Transition(Set.of(SHIPPED),                        DELIVERED),
    "cancelOrder",       new Transition(Set.of(DRAFT,PENDING,PAID,SHIPPED),     CANCELLED)
  );

  public Order transition(Order order, String event) {
    Transition t = TRANSITIONS.get(event);
    if (t == null) throw new IllegalArgumentException("Unknown event: " + event);
    if (!t.from().contains(order.getStatus()))
      throw new IllegalStateException("Invalid transition");

    order.setStatus(t.to());
    order = orderRepository.save(order);

    if (t.to() == SHIPPED) {
      eventPublisher.publishEvent(new OrderShippedEvent(this, order));
      notificationService.notifyUser(order.getUserId(), order.getTrackingInfo());
    }
    if (t.to() == CANCELLED) refundService.refundIfPaid(order);
    return order;
  }
}

Output: Rust

Rust 2021 edition with tokio and sqlx. SHAPE becomes a struct with #[derive], errors use thiserror, and Result<T, E> replaces ON FAIL THROW.

createUser

rust
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct User {
    pub id:            Uuid,
    pub email:         String,
    pub name:          String,
    pub password_hash: String,
    pub role:          Role,
    pub created_at:    DateTime<Utc>,
}

#[derive(Debug, thiserror::Error)]
pub enum ValidationError {
    #[error("Invalid email format")]    InvalidEmail,
    #[error("Password too short")]      PasswordTooShort,
    #[error("Name too short")]          NameTooShort,
    #[error("Email already registered")] EmailTaken,
    #[error("Database error: {0}")]
    Database(#[from] sqlx::Error),
}

static EMAIL_RE: OnceLock<Regex> = OnceLock::new();

pub async fn create_user(
    pool: &PgPool, bus: &impl EventBus,
    email: String, password: String, name: String,
) -> Result<User, ValidationError> {
    let re = EMAIL_RE.get_or_init(|| Regex::new(r"^[^\s@]+@[^\s@]+\.[^\s@]+$").unwrap());

    if !re.is_match(&email) { return Err(ValidationError::InvalidEmail); }
    if password.len() < 8   { return Err(ValidationError::PasswordTooShort); }
    if name.len() < 2        { return Err(ValidationError::NameTooShort); }

    let exists: bool = sqlx::query_scalar(
        "SELECT EXISTS(SELECT 1 FROM users WHERE email=$1)")
        .bind(&email).fetch_one(pool).await?;
    if exists { return Err(ValidationError::EmailTaken); }

    let hash = bcrypt::hash(&password, bcrypt::DEFAULT_COST).unwrap();
    let user: User = sqlx::query_as(
        "INSERT INTO users(id,email,name,password_hash,role,created_at)
         VALUES($1,$2,$3,$4,'user',NOW()) RETURNING *")
        .bind(Uuid::new_v4()).bind(&email).bind(&name).bind(&hash)
        .fetch_one(pool).await?;

    bus.emit("UserCreated", &user).await;
    Ok(user)
}

transferFunds — @transaction

rust
pub async fn transfer_funds(
    pool: &PgPool, bus: &impl EventBus,
    from_id: Uuid, to_id: Uuid, amount: Decimal,
) -> Result<(), TransferError> {
    if amount <= Decimal::ZERO { return Err(TransferError::InvalidAmount); }
    if from_id == to_id        { return Err(TransferError::SameAccount); }

    let mut tx = pool.begin().await?;
    let balance: Decimal = sqlx::query_scalar(
        "SELECT balance FROM accounts WHERE id=$1 FOR UPDATE")
        .bind(from_id).fetch_one(&mut *tx).await?;

    if balance < amount { tx.rollback().await?; return Err(TransferError::InsufficientFunds); }

    sqlx::query("UPDATE accounts SET balance=balance-$1 WHERE id=$2")
        .bind(amount).bind(from_id).execute(&mut *tx).await?;
    sqlx::query("UPDATE accounts SET balance=balance+$1 WHERE id=$2")
        .bind(amount).bind(to_id).execute(&mut *tx).await?;
    tx.commit().await?;

    bus.emit("FundsTransferred", &json!({"from":from_id,"to":to_id,"amount":amount})).await;
    Ok(())
}

Output: C++

C++20 output using RAII, std::regex, std::async for parallel flows, and exceptions derived from std::runtime_error.

createUser

cpp
// Generated from LogicScript — SHAPE User + FUNC createUser
enum class Role { Admin, User, Guest };

struct User {
    std::string email, name, password_hash, id;
    Role        role{Role::User};
    std::chrono::system_clock::time_point created_at;
};

class ValidationError : public std::runtime_error {
public:
    explicit ValidationError(const std::string& msg)
        : std::runtime_error(msg), status_code_(422) {}
    int status_code() const { return status_code_; }
private:
    int status_code_;
};

class UserService {
public:
    UserService(Database& db, EventBus& bus)
        : db_(db), bus_(bus)
        , email_re_(R"(^[^\s@]+@[^\s@]+\.[^\s@]+$)", std::regex::ECMAScript) {}

    User create_user(std::string_view email, std::string_view password, std::string_view name) {
        if (!std::regex_match(email.begin(), email.end(), email_re_))
            throw ValidationError("Invalid email format");
        if (password.size() < 8u)
            throw ValidationError("Password must be at least 8 characters");
        if (name.size() < 2u)
            throw ValidationError("Name must be at least 2 characters");
        if (db_.user_exists_by_email(email))
            throw ValidationError("Email already registered");

        std::string hash = bcrypt::generate_hash(password, 12);
        User user{.id=uuid::v4(), .email=std::string(email),
                  .name=std::string(name), .password_hash=std::move(hash),
                  .role=Role::User, .created_at=std::chrono::system_clock::now()};
        user = db_.insert_user(user);
        bus_.emit("UserCreated", user);
        return user;
    }

private:
    Database&   db_;
    EventBus&   bus_;
    std::regex  email_re_;
};

GenerateDashboard — parallel FLOW

cpp
#include <future>

struct DashboardResult { Stats stats; std::vector<Activity> activity; std::vector<Notification> notifications; };

DashboardResult DashboardService::generate_dashboard(const std::string& user_id) {
    // PARALLEL + WAIT all → std::async + .get()
    auto stats_fut    = std::async(std::launch::async, [&] { return analytics_.get_user_stats(user_id); });
    auto activity_fut = std::async(std::launch::async, [&] { return activity_log_.recent(user_id, 20); });
    auto notif_fut    = std::async(std::launch::async, [&] { return inbox_.unread(user_id); });

    return { stats_fut.get(), activity_fut.get(), notif_fut.get() };
}