LPD-Direct: Logical Process Design Language | unfck.tech


LPD-Direct

Simple Process Language Specification

1. Introduction and Philosophy

LPD-Direct (Logical Data Flow) is a declarative pseudocode language for designing, documenting, and automating business and technical processes.

Its main goal is to eliminate the communication barrier between business experts (who know why we do something) and technical teams (who know how to do it). The syntax forces you to connect technical instructions with their business justification.

LPD-Direct Fundamentals:

  • Readability: Code must be understandable by non-technical people.
  • Context: Every action must have an explicitly defined business purpose.
  • Full Control: The language handles not just success ("happy path"), but also errors, human decisions, and artificial intelligence.
  • Unambiguous: Each construct has exactly one interpretation.

2. Script Structure

Every process described in LPD-Direct consists of three main sections:

  1. Trigger (TRIGGER): Definition of what starts the process.
  2. Process Body: Logical sequence of operations divided into phases (e.g., Collection, Processing, Decisions).
  3. Completion: Explicit signal of flow end.

2.1. The Iron Rule: Double Comment

Every operational command must be preceded by two comments. This is not optional.

  • // What we're doing: (Technical description of the action)
  • // Why: (Business justification)

Exceptions: TRIGGER and SYSTEMS don't require double comments (they have built-in descriptions).

// What we're doing: Filter orders with status 'Cancelled'.
// Why: To avoid calculating commission on sales that didn't complete.
FILTER ORDERS WHERE Status != 'Cancelled' AS COMPLETED_ORDERS

2.2. System Declaration (SYSTEMS)

Optional section defining external systems and software used in the process. Placed directly after TRIGGER, before the first SET/LOAD.

Syntax:

// SYSTEMS:
// - <System Name>: <Type> - <Description of what it contains/does>
// - <System Name>: <Type> - <Description>

Example:

// TRIGGER: SCHEDULE EVERY DAY AT 09:00 CET

// SYSTEMS:
// - Company ERP: REST API - Invoicing and client payment management system
// - HR Database: PostgreSQL - Employee and organizational structure database
// - Salesforce: REST API - CRM for lead and contact management
// - Mail Service: SMTP - Mail server for automated notifications
// - Slack: Webhook - Team communicator for operational alerts

// What we're doing: Set today's date.
// Why: For deadline calculations.
SET TODAY = CURRENT_DATE()

Purpose: Documents process dependencies on external systems - facilitates onboarding new people and identifying failure points.

Entry format:

  • System Name: Name used in LOAD/SEND aliases
  • Type: REST API, GraphQL, SQL (PostgreSQL/MySQL), SMTP, Webhook, File System, etc.
  • Description: Brief description of system's role in the process (1 sentence)

3. Data Types and Literals

3.1. Basic Types

Type Example Description
STRING 'Text' Text in single quotes
NUMBER 123, 45.67 Integer and decimal numbers
BOOLEAN TRUE, FALSE Logical values
NULL NULL No value
DATE 2024-01-15 Date in ISO 8601 format
DATETIME 2024-01-15T09:00:00Z Date and time in ISO 8601 format

3.2. Complex Types

Type Example Description
DATASET CUSTOMERS Table (collection of records)
RECORD Customer_ID, Name Single row in dataset
LIST ['A', 'B', 'C'] Simple list of values

4. Variables and Naming Conventions

4.1. Variables (SET)

Syntax:

SET VARIABLE_NAME = value

Rules:

  • Variable names in UPPER_SNAKE_CASE
  • Each SET must have double comment
  • Variables are immutable - use OVERRIDE to change value

Example:

// What we're doing: Set the analysis start date.
// Why: To analyze last quarter's data.
SET START_DATE = '2024-01-01'

// What we're doing: Set calculation threshold.
// Why: We only want to process orders over $100.
SET MIN_AMOUNT = 100

4.2. Datasets (LOAD, FILTER, etc.)

Syntax:

LOAD <source> AS DATASET_NAME

Rules:

  • Dataset names in UPPER_SNAKE_CASE
  • Column names in PascalCase or in quotes if spaces

Example:

// What we're doing: Load customer data from database.
// Why: To analyze purchasing behavior.
LOAD SQL FROM 'CRM_DB' QUERY 'SELECT * FROM customers' AS CUSTOMERS

5. Basic Operations

5.1. LOAD - Data Loading

Loads data from external sources.

LOAD from SQL:

// What we're doing: Load sales data.
// Why: To calculate monthly revenue.
LOAD SQL FROM 'Database' QUERY 'SELECT * FROM sales WHERE month = 1' AS SALES
ON ERROR: RETRY 3 TIMES THEN STOP

LOAD from API:

// What we're doing: Fetch customer list from CRM.
// Why: To send marketing emails.
LOAD API FROM 'https://crm.company.com/api/customers' AS CUSTOMERS
ON ERROR: SKIP AND LOG 'CRM unavailable'

LOAD from FILE:

// What we're doing: Load price list from CSV.
// Why: To update product prices.
LOAD FILE FROM '/data/prices.csv' FORMAT CSV AS PRICES
ON ERROR: STOP AND ALERT 'Data Team'

5.2. FILTER - Data Filtering

Filters dataset based on condition.

Syntax:

FILTER DATASET WHERE condition AS NEW_DATASET

Example:

// What we're doing: Filter active customers only.
// Why: To avoid sending offers to inactive accounts.
FILTER CUSTOMERS WHERE Status = 'Active' AS ACTIVE_CUSTOMERS

5.3. CALCULATE - Calculations

Performs calculations on dataset.

Syntax:

CALCULATE on DATASET:
    New_Column = expression
    Another_Column = expression
AS NEW_DATASET

Example:

// What we're doing: Calculate profit margin per transaction.
// Why: To identify most and least profitable products.
CALCULATE on SALES:
    Profit_Amount = Sale_Price - Cost_Price
    Profit_Margin = (Profit_Amount / Sale_Price) * 100
AS SALES_WITH_MARGIN

5.4. GROUP - Grouping and Aggregation

Groups data and calculates aggregates.

Syntax:

GROUP DATASET BY column_list:
    Aggregate_Column = AGGREGATE_FUNCTION(column)
AS NEW_DATASET

Aggregate functions: SUM, AVG, COUNT, MIN, MAX

Example:

// What we're doing: Calculate total sales per salesperson.
// Why: For commission calculation.
GROUP SALES BY Salesperson_ID:
    Total_Sales = SUM(Amount)
    Order_Count = COUNT(Order_ID)
AS SALES_BY_PERSON

5.5. SORT - Sorting

Sorts dataset.

Syntax:

SORT DATASET BY column1 ASC, column2 DESC AS NEW_DATASET

Example:

// What we're doing: Sort customers by total spending.
// Why: To identify VIP customers first.
SORT CUSTOMERS BY Total_Spent DESC AS VIP_CUSTOMERS

5.6. JOIN - Joining Datasets

Joins two datasets.

Syntax:

JOIN DATASET1 WITH DATASET2 
    ON DATASET1.column = DATASET2.column 
    TYPE INNER/LEFT/RIGHT/FULL
AS NEW_DATASET

Example:

// What we're doing: Match orders with customer data.
// Why: To add customer info to each order.
JOIN ORDERS WITH CUSTOMERS 
    ON ORDERS.Customer_ID = CUSTOMERS.Customer_ID 
    TYPE LEFT
AS ORDERS_WITH_CUSTOMERS

6. Control Flow

6.1. IF/ELSE - Conditional Execution

Syntax:

IF condition THEN
    // operations
ELSE
    // alternative operations
END IF

Logical operators: AND, OR, NOT

Comparison operators: =, !=, <, >, <=, >=

Example:

// What we're doing: Check if sales threshold is met.
// Why: To decide if bonus should be paid.
IF TOTAL_SALES > 100000 AND Month = 'December' THEN
    
    // What we're doing: Calculate bonus.
    // Why: Year-end bonus for achieving target.
    SET BONUS = TOTAL_SALES * 0.05
    
ELSE
    // What we're doing: Set bonus to zero.
    // Why: Target not met.
    SET BONUS = 0
    
END IF

6.2. FOR EACH - Iteration

Syntax:

FOR EACH row IN DATASET DO
    // operations on each row
END FOR

Example:

// What we're doing: Process each customer individually.
// Why: Each customer needs personalized calculation.
FOR EACH customer IN VIP_CUSTOMERS DO
    
    // What we're doing: Calculate individual discount.
    // Why: VIP customers get tiered discounts.
    IF customer.Total_Spent > 50000 THEN
        SET customer.Discount = 15
    ELSE
        SET customer.Discount = 10
    END IF
    
END FOR

7. Error Handling (ON ERROR)

Every risky operation (LOAD, SEND, ASK_AI) must have ON ERROR handling.

7.1. Error Strategies

STOP: Terminates process immediately

ON ERROR: STOP

STOP AND ALERT: Terminates and sends alert

ON ERROR: STOP AND ALERT 'Admin Team'

RETRY: Attempts operation again

ON ERROR: RETRY 3 TIMES THEN STOP

SKIP: Skips failed operation and continues

ON ERROR: SKIP AND LOG 'Optional data unavailable'

Example:

// What we're doing: Load pricing data from external API.
// Why: To update product catalog.
LOAD API FROM 'https://vendor.com/api/prices' AS VENDOR_PRICES
ON ERROR: RETRY 3 TIMES THEN SKIP AND LOG 'Vendor API unavailable'

8. Human and AI Integration

8.1. AWAIT APPROVAL - Human Decisions

Pauses process for human approval.

Syntax:

AWAIT APPROVAL FROM 'role' ON DATASET
    SHOW: 'column1', 'column2'
    QUESTION: 'Question text?'
    TIMEOUT: duration
AS NEW_DATASET

Example:

// What we're doing: Request approval for large refunds.
// Why: Amounts over $10K need management approval.
AWAIT APPROVAL FROM 'Finance Manager' ON LARGE_REFUNDS
    SHOW: 'Customer_Name', 'Amount', 'Reason'
    QUESTION: 'Approve these refunds?'
    TIMEOUT: 24 HOURS
AS APPROVED_REFUNDS

8.2. ASK_AI - AI Agent Tasks

Delegates task to AI agent.

Syntax:

ASK_AI on DATASET:
    TASK: 'Task description with [Column] references'
    RETURN: New_Column_Name
AS NEW_DATASET

Example:

// What we're doing: Generate personalized email copy.
// Why: AI writes better personalized messages than templates.
ASK_AI on CUSTOMERS:
    TASK: 'Write friendly email to [First_Name] mentioning their recent purchase of [Product]. Max 100 words.'
    RETURN: Email_Body
AS CUSTOMERS_WITH_EMAILS

9. Output Operations

9.1. SEND - Sending Data

SEND to API:

// What we're doing: Send processed orders to fulfillment system.
// Why: To trigger warehouse shipping.
SEND READY_ORDERS TO API 'https://warehouse.com/api/orders'
ON ERROR: RETRY 5 TIMES THEN ALERT 'Operations'

SEND to FILE:

// What we're doing: Export report to Excel file.
// Why: For manual review by finance team.
SEND MONTHLY_REPORT TO FILE '/reports/january_2024.xlsx' FORMAT XLSX
ON ERROR: STOP AND ALERT 'IT Support'

SEND EMAIL:

// What we're doing: Email report to management.
// Why: Daily summary for executives.
SEND EMAIL TO 'ceo@company.com' 
    SUBJECT 'Daily Sales Report' 
    BODY 'Total: [TOTAL_SALES]'
ON ERROR: SKIP AND LOG 'Email failed'

SEND ALERT:

// What we're doing: Send Slack alert.
// Why: Notify team of critical issue.
SEND ALERT 'Inventory below minimum!' TO 'Slack / #operations'

10. Complete Examples

10.1. Collections Process with AI and Approvals

// TRIGGER: SCHEDULE EVERY DAY AT 09:00 CET

// What we're doing: Set current date.
// Why: For calculating payment deadlines.
SET TODAY = CURRENT_DATE()

// --- Phase 1: Data Collection ---
// What we're doing: Load all unpaid invoices from ERP.
// Why: To identify customers with outstanding payments.
LOAD API FROM 'https://erp.company.com/api/invoices?status=unpaid' AS ALL_OVERDUE
ON ERROR: STOP AND ALERT 'ERP Admin'

// What we're doing: Filter invoices overdue by more than 7 days.
// Why: Give customers 7-day grace period before collections.
FILTER ALL_OVERDUE WHERE Payment_Due <= SUBTRACT_DAYS(TODAY, 7) AS OVERDUE_TO_COLLECT

// --- Phase 2: AI and Decisions ---
// What we're doing: Ask AI to generate personalized, polite email for each customer.
// Why: So communication is customer-specific, not robotic.
ASK_AI on OVERDUE_TO_COLLECT:
    TASK: 'Write brief reminder about invoice [Invoice_No] amount [Amount]. Use polite tone.'
    RETURN: Email_Body
AS PREPARED_EMAILS

// What we're doing: Split process based on amount.
// Why: Large amounts are relationally risky, want human review before sending.
IF PREPARED_EMAILS.Amount > 10000 EUR THEN

    // --- VIP Path (requires approval) ---
    // What we're doing: Pause process for these records and send request to Finance Manager.
    // Why: Avoid mistakes with key customers.
    AWAIT APPROVAL FROM 'Finance Manager' ON PREPARED_EMAILS
        SHOW: 'Customer', 'Amount', 'Email_Body'
        QUESTION: 'Send this VIP reminder?'
    AS APPROVED_VIP

    // What we're doing: Send only approved VIP emails.
    // Why: To reach key customers with confirmed communication.
    SEND APPROVED_VIP TO API 'https://mail.company.com/send'

ELSE
    // --- Standard Path (automatic) ---
    // What we're doing: Send emails automatically for smaller amounts.
    // Why: Save manager time on routine reminders.
    SEND PREPARED_EMAILS TO API 'https://mail.company.com/send'

END IF

10.2. Sales Reporting with Margin Analysis

// TRIGGER: SCHEDULE EVERY 1st DAY OF MONTH AT 00:00 UTC

// What we're doing: Set time variables for previous month.
// Why: So report covers complete month.
SET START_DATE = SUBTRACT_DAYS(CURRENT_DATE(), 30)
SET END_DATE = CURRENT_DATE()

// What we're doing: Load sales data from production database.
// Why: To analyze last month's sales performance.
LOAD SQL FROM 'ProductionDB' QUERY 'SELECT * FROM sales WHERE sale_date BETWEEN @START_DATE AND @END_DATE' AS SALES
ON ERROR: RETRY 3 TIMES THEN STOP AND ALERT 'DBA Team'

// What we're doing: Calculate margin for each transaction.
// Why: To identify most and least profitable products.
CALCULATE on SALES:
    Margin_Amount = Sale_Price - Cost_Price
    Margin_Percent = (Margin_Amount / Sale_Price) * 100
AS SALES_WITH_MARGIN

// What we're doing: Filter transactions with negative margin.
// Why: To identify products sold at a loss.
FILTER SALES_WITH_MARGIN WHERE Margin_Amount < 0 AS LOSS_PRODUCTS

// What we're doing: Check if there are loss products.
// Why: To decide if we need to alert management.
IF LOSS_PRODUCTS IS NOT EMPTY THEN
    // What we're doing: Send alert about loss products.
    // Why: So management can quickly respond to the issue.
    SEND ALERT 'Warning: Products sold at a loss detected!' TO 'Slack / #management-alerts'
    
    // What we're doing: Export details to file.
    // Why: So management has full data for analysis.
    SEND LOSS_PRODUCTS TO FILE '/reports/loss_products_month.xlsx' FORMAT XLSX
END IF

// What we're doing: Generate overall summary.
// Why: To get key sales metrics for the month.
CALCULATE on SALES_WITH_MARGIN:
    Total_Sales = SUM(Sale_Price)
    Total_Margin = SUM(Margin_Amount)
    Average_Margin_Percent = AVG(Margin_Percent)
AS MONTHLY_REPORT

// What we're doing: Email monthly report.
// Why: So sales director receives automatic report.
SEND EMAIL TO 'sales.director@company.com' SUBJECT 'Monthly Sales Report' BODY 'Total sales: [Total_Sales], Margin: [Total_Margin]'

11. Author Checklist

Before deploying a process, verify:

  • Every operational command has // What we're doing: and // Why:
  • All variables and datasets use UPPER_SNAKE_CASE
  • Columns are in PascalCase or in quotes (if they contain spaces)
  • String literals are in single quotes '...'
  • All risky operations (LOAD, SEND, ASK_AI) have ON ERROR
  • Conditions IF use AND/OR/NOT (not &&/||/!)
  • CALCULATE, GROUP, and ASK_AI blocks have 4-space indentation
  • Every JOIN has specified type (INNER/LEFT/RIGHT/FULL)
  • Every SORT has specified direction (ASC/DESC) for each column
  • AWAIT APPROVAL has TIMEOUT if process can't wait indefinitely
  • Use SET for declaration, OVERRIDE to overwrite (don't use SET twice on same variable)
  • Process has clear TRIGGER at the beginning
  • If process uses external systems, consider adding SYSTEMS section
  • If using SKIP in ON ERROR, handle NULL case

Full specification with all examples: LPD-Direct Language Documentation (GitHub Gist)