You are an expert VS Code extension developer. Build a complete, production-ready
VS Code extension for the Business Process Modeling Language (BPML) — an XML-based
language for defining executable business processes using constructs like packages,
process definitions, activities, contexts, properties, faults, signals, and
schedules.



The extension must follow all VS Code Extension API conventions documented at
https://code.visualstudio.com/api/language-extensions/overview and mirror the
quality and behavior of first-class language extensions like "redhat.vscode-xml",
"vscode-bpel", and "ms-python.python".



---



## 📁 REQUIRED PROJECT STRUCTURE



Generate every file below. Do not skip any.



bpml-extension/
├── package.json
├── tsconfig.json
├── .vscodeignore
├── src/
│   ├── extension.ts               ← Activation entrypoint
│   ├── completionProvider.ts      ← CompletionItemProvider
│   ├── hoverProvider.ts           ← HoverProvider
│   ├── diagnosticsProvider.ts     ← DiagnosticCollection
│   └── snippets/
│       └── bpml.snippets.ts       ← Programmatic snippets registry
├── syntaxes/
│   └── bpml.tmLanguage.json       ← TextMate grammar for syntax highlighting
├── snippets/
│   └── bpml.json                  ← Declarative snippet definitions
├── language-configuration.json    ← Bracket matching, auto-close, comments
└── README.md



---



## 🗂️ package.json — CONTRIBUTION POINTS



Configure the following in package.json "contributes":



1. LANGUAGE REGISTRATION:
   - id: "bpml"
   - aliases: ["BPML", "Business Process Modeling Language"]
   - extensions: [".bpml", ".bpml.xml"]
   - configuration: "./language-configuration.json"



2. GRAMMAR:
   - language: "bpml"
   - scopeName: "source.bpml"
   - path: "./syntaxes/bpml.tmLanguage.json"



3. SNIPPETS:
   - path: "./snippets/bpml.json"



4. ACTIVATION EVENTS:
   - "onLanguage:bpml"



5. COMMANDS:
   - "bpml.validateDocument" — Validate current BPML document
   - "bpml.insertTemplate"   — Insert a starter BPML package template
   - "bpml.wrapInSequence"   — Wrap selected activities in <sequence>



---



## 🔤 language-configuration.json



Include full configuration for:
- Auto-closing pairs: all BPML XML tag pairs, <package></package>, etc.
- Surrounding pairs: quotes, angle brackets
- Comment toggling: <!-- --> for block comments
- Word pattern: match BPML identifiers including colons (bpml:activity etc.)
- Bracket pairs: <>, (), {}
- Folding markers: startPattern = /<(process|sequence|all|switch|foreach|context)/
                   endPattern  = <\/( process|sequence|all|switch|foreach|context)>
- onEnterRules: auto-indent when pressing Enter inside a tag pair



---



## 🎨 syntaxes/bpml.tmLanguage.json — TEXTMATE GRAMMAR



Provide a complete TextMate grammar with scopes for:



ROOT ELEMENTS:
  <package>           → entity.name.tag.bpml
  <process>           → entity.name.tag.process.bpml
  <context>           → entity.name.tag.context.bpml



SIMPLE ACTIVITIES (scope: keyword.control.activity.bpml):
  <action>, <assign>, <call>, <compensate>, <delay>,
  <empty>, <fault>, <raise>, <spawn>, <synch>



COMPLEX ACTIVITIES (scope: keyword.control.complex.bpml):
  <sequence>, <all>, <switch>, <foreach>



DEFINITIONS (scope: storage.type.bpml):
  <property>, <schedule>, <import>, <documentation>



CONTROL STRUCTURES:
  <case>   → keyword.control.case.bpml
  <otherwise> → keyword.control.otherwise.bpml
  <exception> → keyword.control.exception.bpml
  <compensation> → keyword.control.compensation.bpml



ATTRIBUTES (scope: entity.other.attribute-name.bpml):
  name, type, namespace, features, target, source,
  condition, expression, deadline, duration, signal,
  property, process, activity, fault, schedule



ATTRIBUTE VALUES (scope: string.quoted.double.bpml)



XML CONSTRUCTS:
  XML declaration <?xml ... ?> → meta.tag.preprocessor
  Comments <!-- --> → comment.block.bpml
  CDATA blocks → string.unquoted.cdata.bpml
  Namespace prefixes bpml: → support.type.bpml



---



## ⚡ snippets/bpml.json — DECLARATIVE SNIPPETS



Create at least the following 20+ snippets with tab stops ($1, $2),
placeholders, and choices where appropriate:



PACKAGE & PROCESS SCAFFOLDING:
1.  bpml-package       → Full <package> boilerplate with namespace declaration
2.  bpml-process       → <process name="$1"> with context + sequence skeleton
3.  bpml-import        → <import namespace="$1" location="$2"/>
4.  bpml-documentation → <documentation>$1</documentation>



SIMPLE ACTIVITIES:
5.  bpml-action        → <action name="$1" activity="$2"/>
6.  bpml-assign        → <assign name="$1" property="$2" expression="$3"/>
7.  bpml-call          → <call name="$1" process="$2"> with <input>/<output>
8.  bpml-compensate    → <compensate name="$1" process="$2"/>
9.  bpml-delay         → <delay name="$1" deadline="$2"/> with duration variant
10. bpml-empty         → <empty name="$1"/>
11. bpml-fault         → <fault name="$1" fault="$2"/>
12. bpml-raise         → <raise name="$1" signal="$2"/>
13. bpml-spawn         → <spawn name="$1" process="$2"/>
14. bpml-synch         → <synch name="$1" signal="$2"/>



COMPLEX ACTIVITIES:
15. bpml-sequence      → <sequence name="$1"> with placeholder activities
16. bpml-all           → <all name="$1"> parallel execution block
17. bpml-switch        → <switch name="$1"> with one <case> and <otherwise>
18. bpml-foreach       → <foreach name="$1" property="$2"> with activity block



DEFINITIONS:
19. bpml-property      → <property name="$1" type="$2"> with initial value
20. bpml-schedule      → <schedule name="$1"> with <startTime>/<endTime>
21. bpml-context       → Full <context> block with properties + exception handlers
22. bpml-exception     → <exception fault="$1"> with catch body
23. bpml-compensation  → <compensation> handler block



CONTROL FLOW:
24. bpml-case          → <case condition="$1"> activity body
25. bpml-otherwise     → <otherwise> fallback body



---



## 🧠 src/completionProvider.ts — INTELLISENSE



Implement vscode.CompletionItemProvider with:



CLASS: BPMLCompletionProvider
implements: vscode.CompletionItemProvider
register with: vscode.languages.registerCompletionItemProvider(
  { language: 'bpml' },
  new BPMLCompletionProvider(),
  '<', '/', ' ', '"', ':'   ← trigger characters
)



COMPLETION LOGIC — implement these 5 scenarios:



SCENARIO 1 — TAG COMPLETION (triggered by '<'):
  Parse cursor context to determine valid child elements.
  Return CompletionItems for every valid BPML child tag at that position.
  Example: inside <process>, suggest <context>, <sequence>, <all>, <switch>, <foreach>
  Each item must include:
    - label: tag name
    - kind: CompletionItemKind.Class (for complex) or .Method (for simple)
    - insertText: SnippetString with closing tag and cursor positioned inside
    - documentation: MarkdownString explaining the tag
    - detail: "(BPML Activity)" or "(BPML Definition)" etc.



SCENARIO 2 — CLOSING TAG COMPLETION (triggered by '</'):
  Read backwards to find the nearest unclosed opening tag.
  Return a single CompletionItem that closes it.
  insertText should complete the tag: e.g. </sequence>



SCENARIO 3 — ATTRIBUTE COMPLETION (triggered by ' ' inside a tag):
  Detect which tag the cursor is in.
  Return only valid attributes for that tag (see BPML attribute map below).
  Mark required attributes with sortText '0_' prefix.
  Include description of each attribute.



SCENARIO 4 — ATTRIBUTE VALUE COMPLETION (triggered by '"'):
  If cursor is within an attribute value position:
    - For "type" attributes: suggest xs:string, xs:integer, xs:boolean, xs:date, xs:decimal
    - For "fault" attributes: suggest bpml:noSuchInstance, bpml:invalidExpression, custom faults
    - For boolean attributes: suggest "true", "false"



SCENARIO 5 — NAMESPACE PREFIX COMPLETION (triggered by ':'):
  After 'bpml:' suggest all BPML element local names
  After 'xs:' suggest XML Schema built-in types



BPML ATTRIBUTE MAP (which attributes belong to which elements):
  package:     name, targetNamespace, features
  process:     name, abstract, instantiation, compensation
  context:     name
  property:    name, type, isArray
  action:      name, activity
  assign:      name, property, expression
  call:        name, process
  compensate:  name, process
  delay:       name, deadline, duration
  fault:       name, fault
  raise:       name, signal
  spawn:       name, process
  synch:       name, signal
  sequence:    name
  all:         name
  switch:      name
  foreach:     name, property
  case:        condition
  exception:   fault
  schedule:    name



---



## 📖 src/hoverProvider.ts — HOVER DOCUMENTATION



Implement vscode.HoverProvider with:
  CLASS: BPMLHoverProvider
  register with: vscode.languages.registerHoverProvider({ language: 'bpml' }, ...)



For every BPML tag and attribute, return a Hover with MarkdownString containing:
  - Bold title: tag/attribute name
  - Category: Simple Activity / Complex Activity / Definition / Root Element
  - One-sentence description
  - Required attributes list
  - Valid children list (for complex elements)
  - Example code block in ```xml fenced block



Cover at minimum:
  package, process, context, property, schedule, import,
  action, assign, call, compensate, delay, empty, fault, raise, spawn, synch,
  sequence, all, switch, foreach, case, otherwise, exception, compensation



---



## 🔴 src/diagnosticsProvider.ts — VALIDATION & DIAGNOSTICS



Implement real-time document validation:
  CLASS: BPMLDiagnosticsProvider
  Use: vscode.languages.createDiagnosticCollection('bpml')
  Trigger on: vscode.workspace.onDidChangeTextDocument (debounced 500ms)
             vscode.workspace.onDidOpenTextDocument



VALIDATION RULES — detect and report:



ERROR RULES (vscode.DiagnosticSeverity.Error):
  1. Missing required "name" attribute on <process>, <action>, <assign>, etc.
  2. <process> element missing a <context> or direct activity child
  3. Unclosed tags — detect unmatched opening/closing tags
  4. <switch> with no <case> child — must have at least one <case>
  5. <foreach> missing required "property" attribute
  6. <raise> or <synch> missing required "signal" attribute
  7. <fault> missing required "fault" attribute



WARNING RULES (vscode.DiagnosticSeverity.Warning):
  8. <documentation> element is empty
  9. <process> has no <documentation> child (best practice)
  10. <switch> has no <otherwise> (unhandled default case)
  11. Unknown attribute on a known BPML element
  12. <package> missing xmlns:bpml namespace declaration



INFORMATION RULES (vscode.DiagnosticSeverity.Information):
  13. <empty> activity detected — consider replacing with meaningful activity
  14. <delay> with no deadline or duration attribute



For each diagnostic include:
  - range: exact line+character range of the offending node
  - message: human-readable description
  - code: rule ID string e.g. "BPML001"
  - source: "bpml"



---



## ⌨️ src/extension.ts — ACTIVATION



In the activate() function:
1. Register BPMLCompletionProvider
2. Register BPMLHoverProvider
3. Register BPMLDiagnosticsProvider and attach document listeners
4. Register command "bpml.validateDocument" — runs diagnostics on demand
5. Register command "bpml.insertTemplate" — inserts a full package template
   at the top of an empty document
6. Register command "bpml.wrapInSequence" — wraps the current selection in
   <sequence name="newSequence"> ... </sequence>
7. Show status bar item: "$(check) BPML" when a .bpml file is active
8. In deactivate(), dispose all providers and the diagnostic collection



---



## 🧪 IMPLEMENTATION QUALITY REQUIREMENTS



1. All TypeScript must be strictly typed — no `any` except in XML parse results
2. Use a lightweight XML parser (fast-xml-parser or node's built-in DOMParser
   via xmldom) to parse document context — do NOT use regex for tag matching
3. Completion trigger logic must be context-aware — read 200 chars before cursor
   to determine parent element, do not suggest invalid children
4. All CompletionItems must have documentation set — empty docs are not acceptable
5. Debounce diagnostics at 500ms to avoid thrashing on every keypress
6. Handle malformed/partially-written XML gracefully — never throw uncaught errors
7. All string constants (tag names, attribute names, docs) must be in a central
   constants file src/constants/bpml.ts for maintainability
8. Follow VS Code extension UX guidelines — use OutputChannel for logs, not console



---



## 📦 DEPENDENCIES (package.json devDependencies / dependencies)



devDependencies:
  @types/vscode: ^1.85.0
  @types/node: ^20.0.0
  typescript: ^5.3.0
  @vscode/vsce: ^2.22.0



dependencies:
  fast-xml-parser: ^4.3.0   (for context-aware parsing)



engines:
  vscode: ^1.85.0



---



## 📋 OUTPUT FORMAT



Generate every file completely. Do not truncate any file.
For each file output:
  === FILE: <relative path> ===
  <complete file content>
  === END FILE ===



Start with package.json, then language-configuration.json,
then syntaxes/bpml.tmLanguage.json, then snippets/bpml.json,
then all TypeScript source files, then README.md last.



---



## ⚡ EMMET-STYLE KEYWORD EXPANSIONS — "TYPE WORD + TAB/ENTER = FULL BLOCK"



Implement a dedicated expansion system exactly like VS Code's Emmet "!" → HTML
boilerplate behavior. When the user types a trigger keyword on an otherwise empty
line and presses Tab or Enter, the entire keyword is replaced with a complete,
ready-to-use BPML code block with tab stops.



---



### 📁 NEW FILE: src/expansionProvider.ts



Create a separate provider class: BPMLExpansionProvider
Implements: vscode.CompletionItemProvider
Register separately from BPMLCompletionProvider using:



  vscode.languages.registerCompletionItemProvider(
    { language: 'bpml' },
    new BPMLExpansionProvider(),
    // NO trigger characters — fires on word completion only
  )



DETECTION LOGIC — a keyword expansion fires when:
  1. The current line (trimmed) matches EXACTLY one of the trigger keywords below
  2. The line contains NO '<' character (user is not mid-tag)
  3. The keyword is at least 2 characters long



When detected:
  - Set item.range to cover the entire word on the current line
    (from lineStart to cursor position)
  - Set item.insertText as a SnippetString (full block with tab stops)
  - Set item.preselect = true
  - Set item.sortText = "!!" + keyword  (forces it to top of list)
  - Set item.filterText = keyword
  - Set item.kind = vscode.CompletionItemKind.Snippet
  - Set item.detail = "⚡ BPML Template — press Tab to expand"
  - Set item.documentation to a MarkdownString with a preview of what expands



---



### 📋 NEW FILE: src/constants/expansions.ts



Define all keyword-to-block mappings in a typed structure:



interface BPMLExpansion {
  keyword: string;          // The trigger word the user types
  aliases: string[];        // Alternative spellings that also trigger this
  label: string;            // Shown in the completion list
  detail: string;           // Short description shown in the dropdown
  category: string;         // "Integration" | "Control Flow" | "Transaction" | "Security"
  snippet: string;          // The full SnippetString body with $1, $2, ${3:default}
  documentation: string;    // Markdown shown in hover panel
}



---



### 🗂️ KEYWORD TRIGGER TABLE — IMPLEMENT ALL OF THESE



Implement every expansion in the table below. Each must produce a complete,
syntactically valid BPML block. Tab stops ($1, $2...) must be on every
configurable field. The last tab stop $0 places the cursor after the block.



════════════════════════════════════════════════════════════════════
TRIGGER KEYWORD    │ ALIASES            │ EXPANDS TO
════════════════════════════════════════════════════════════════════



── MESSAGING & EMAIL ──────────────────────────────────────────────



smtp                │ email, sendmail,   │ Full SMTP email send process:
                    │ emailsend          │ <process name="SendEmailProcess">
                                        │   <context>
                                        │     <property name="smtpHost" type="xs:string"/>
                                        │     <property name="smtpPort" type="xs:integer"/>
                                        │     <property name="fromAddress" type="xs:string"/>
                                        │     <property name="toAddress" type="xs:string"/>
                                        │     <property name="subject" type="xs:string"/>
                                        │     <property name="body" type="xs:string"/>
                                        │     <property name="emailStatus" type="xs:string"/>
                                        │   </context>
                                        │   <sequence name="EmailSequence">
                                        │     <action name="ValidateRecipient"
                                        │             activity="EmailValidationService"/>
                                        │     <action name="SendEmail"
                                        │             activity="SMTPMailService"/>
                                        │     <action name="LogDeliveryStatus"
                                        │             activity="AuditLogService"/>
                                        │   </sequence>
                                        │ </process>



emailwithattachment │ attachmail,        │ SMTP process with attachment handling:
                    │ mailatach          │ adds <property name="attachmentPath"/>
                                        │ adds ValidateAttachment + CompressAttachment
                                        │ actions before SendEmail



emailtemplate       │ templatemail,      │ Email with dynamic template substitution:
                    │ htmlemail          │ adds TemplateEngine action + MergeFields action
                                        │ includes <property name="templateId"/>
                                        │ and <property name="mergeData" type="xs:anyType"/>



── HTTP / REST ─────────────────────────────────────────────────────



http                │ rest, httprequest, │ HTTP REST call process:
                    │ apicall            │ <process name="HttpRequestProcess">
                                        │   <context>
                                        │     <property name="endpointUrl" type="xs:string"/>
                                        │     <property name="httpMethod" type="xs:string"/>
                                        │     <property name="requestHeaders" type="xs:anyType"/>
                                        │     <property name="requestPayload" type="xs:anyType"/>
                                        │     <property name="responseCode" type="xs:integer"/>
                                        │     <property name="responseBody" type="xs:anyType"/>
                                        │   </context>
                                        │   <sequence name="HttpSequence">
                                        │     <action name="BuildRequest"
                                        │             activity="HttpRequestBuilder"/>
                                        │     <action name="ExecuteHttp"
                                        │             activity="HttpClientService"/>
                                        │     <action name="ParseResponse"
                                        │             activity="ResponseParser"/>
                                        │   </sequence>
                                        │ </process>



httppost            │ post, restpost     │ HTTP POST with body + auth headers block
httpget             │ get, restget       │ HTTP GET with query params + response mapping
httpauth            │ oauth, bearer      │ OAuth2 token fetch + inject into header block



── FTP / FILE TRANSFER ─────────────────────────────────────────────



ftp                 │ filetransfer,      │ FTP file upload/download process:
                    │ ftpupload          │ includes properties: ftpHost, ftpPort,
                                        │ ftpUser, ftpPassword, remotePath, localPath
                                        │ actions: ConnectFTP, TransferFile, DisconnectFTP



ftpdownload         │ ftpget,            │ FTP download with retry logic:
                    │ downloadfile       │ wraps TransferFile in <switch> with
                                        │ <case condition="$connection.failed">
                                        │   <action name="RetryTransfer" .../>



sftp                │ sftpupload,        │ Secure FTP (SFTP/SSH) variant:
                    │ secureftp          │ adds sshKeyPath property + SSH handshake action



── DATABASE ────────────────────────────────────────────────────────



db                  │ database,          │ Database operation process:
                    │ dbquery, sql       │ <process name="DatabaseQueryProcess">
                                        │   <context>
                                        │     <property name="dbConnectionString" type="xs:string"/>
                                        │     <property name="sqlQuery" type="xs:string"/>
                                        │     <property name="queryParams" type="xs:anyType"/>
                                        │     <property name="resultSet" type="xs:anyType"/>
                                        │     <property name="rowCount" type="xs:integer"/>
                                        │   </context>
                                        │   <sequence name="DBSequence">
                                        │     <action name="OpenConnection"
                                        │             activity="DatabaseConnectionService"/>
                                        │     <action name="ExecuteQuery"
                                        │             activity="SQLExecutionService"/>
                                        │     <action name="ProcessResults"
                                        │             activity="ResultSetMapper"/>
                                        │     <action name="CloseConnection"
                                        │             activity="DatabaseConnectionService"/>
                                        │   </sequence>
                                        │ </process>



dbinsert            │ insert, sqlinsert  │ INSERT with rollback-on-failure compensation block
dbupdate            │ update, sqlupdate  │ UPDATE with optimistic locking + audit trail action
dbdelete            │ delete, sqldelete  │ DELETE with soft-delete flag + confirmation step
dbtransaction       │ sqltx, transaction │ Full BEGIN/COMMIT/ROLLBACK transaction wrapper:
                                        │ uses <context> with transactionId property +
                                        │ <compensation> handler for rollback



── MESSAGE QUEUING ─────────────────────────────────────────────────



mq                  │ queue,             │ Message queue publish/consume process:
                    │ messagequeue,      │ properties: queueName, brokerUrl,
                    │ amqp               │ messagePayload, correlationId, deliveryMode
                                        │ actions: ConnectBroker, PublishMessage,
                                        │          AcknowledgeDelivery



mqpublish           │ publish, mqsend    │ Publish-only block with retry + DLQ fallback
mqconsume           │ consume, mqreceive │ Consumer block with message deserialization
                                        │ + error queue routing on parse failure



── WEB SERVICES / SOAP ─────────────────────────────────────────────



soap                │ webservice,        │ SOAP web service call process:
                    │ wscall             │ properties: wsdlUrl, soapAction,
                                        │ soapEnvelope, soapResponse, faultCode
                                        │ actions: BuildSOAPEnvelope,
                                        │          InvokeWebService, ParseSOAPResponse



── SECURITY & AUTH ─────────────────────────────────────────────────



auth                │ authentication,    │ Authentication & authorization process:
                    │ login              │ properties: username, password, token,
                                        │ sessionId, roles, authStatus
                                        │ sequence: ValidateCredentials →
                                        │           GenerateToken → AssignRoles



jwt                 │ jwtauth,           │ JWT token generation + validation block:
                    │ tokengen           │ properties: jwtSecret, jwtPayload,
                                        │ jwtExpiry, jwtToken, validationResult



ldap                │ activedirectory,   │ LDAP directory lookup process:
                    │ adlookup           │ properties: ldapHost, bindDN, searchBase,
                                        │ searchFilter, ldapUser, groupMembership



── FILE / DOCUMENT ─────────────────────────────────────────────────



pdf                 │ pdfgen,            │ PDF document generation process:
                    │ generatepdf        │ properties: templatePath, outputPath,
                                        │ pdfData, pageCount
                                        │ actions: LoadTemplate, MergeData,
                                        │          RenderPDF, SaveDocument



csv                 │ csvread,           │ CSV file read + parse process:
                    │ parsecv            │ properties: filePath, delimiter, hasHeaders,
                                        │ rowCount, parsedData
                                        │ actions: ReadFile, ParseCSV, ValidateRows



xmltransform        │ xslt, transform    │ XSLT transformation process:
                    │                   │ properties: sourceXml, xsltPath, outputXml
                                        │ actions: LoadXSLT, TransformXML, ValidateOutput



── NOTIFICATIONS ───────────────────────────────────────────────────



sms                 │ textsms,           │ SMS notification process (Twilio/SNS style):
                    │ notification       │ properties: phoneNumber, messageText,
                                        │ senderId, deliveryStatus, messageId



push                │ pushnotify,        │ Mobile push notification process:
                    │ fcm, apns          │ properties: deviceToken, notificationTitle,
                                        │ notificationBody, platform, badgeCount



── CONTROL FLOW TEMPLATES ──────────────────────────────────────────



trycatch            │ exception,         │ Full exception handling scaffold:
                    │ errorhandle        │ <context> with <exception fault="bpml:*">
                                        │ + compensation handler + audit log action



retry               │ retrylogic,        │ Retry-with-backoff pattern:
                    │ retrypolicy        │ <foreach> with maxAttempts + delay between
                                        │ retries + <switch> on success/failure condition



parallel            │ concurrent,        │ Parallel execution block:
                    │ allactivities      │ <all name="ParallelBlock"> with 3 placeholder
                                        │ parallel branches pre-populated



approval            │ humanapproval,     │ Human approval / review step:
                    │ review, workflow   │ sequence: RequestApproval → WaitForDecision →
                                        │ <switch> on approved/rejected/escalated



audit               │ auditlog,          │ Audit trail wrapper:
                    │ logging            │ Wraps a <sequence> with LogStart + LogEnd
                                        │ actions + property: auditId, timestamp, actor



── FULL PACKAGE BOOTSTRAP ──────────────────────────────────────────



!                   │ bpml, bootstrap,   │ Full BPML package boilerplate (like HTML "!"):
                    │ init, package      │ <?xml version="1.0" encoding="UTF-8"?>
                                        │ <package name="$1"
                                        │   xmlns:bpml="http://www.bpmi.org/bpml-schema.owl#"
                                        │   xmlns:xs="http://www.w3.org/2001/XMLSchema"
                                        │   targetNamespace="$2"
                                        │   features="">
                                        │   <documentation>$3</documentation>
                                        │   <process name="$4Process"
                                        │            abstract="false"
                                        │            instantiation="call">
                                        │     <context name="$4Context">
                                        │       <property name="status" type="xs:string"/>
                                        │     </context>
                                        │     <sequence name="MainSequence">
                                        │       $0
                                        │     </sequence>
                                        │   </process>
                                        │ </package>



════════════════════════════════════════════════════════════════════



---



### 📋 ALSO ADD ALL KEYWORDS TO snippets/bpml.json



Every expansion above must also exist as a declarative snippet entry in
snippets/bpml.json following this format:



{
  "SMTP Email Send": {
    "prefix": ["smtp", "email", "sendmail", "emailsend"],
    "body": [
      "<process name=\"${1:SendEmailProcess}\">",
      "  <context name=\"${1:SendEmailProcess}Context\">",
      "    <property name=\"smtpHost\" type=\"xs:string\"/>",
      "    <property name=\"smtpPort\" type=\"xs:integer\"/>",
      "    <property name=\"fromAddress\" type=\"xs:string\"/>",
      "    <property name=\"toAddress\" type=\"xs:string\"/>",
      "    <property name=\"subject\" type=\"xs:string\"/>",
      "    <property name=\"body\" type=\"xs:string\"/>",
      "    <property name=\"emailStatus\" type=\"xs:string\"/>",
      "  </context>",
      "  <sequence name=\"EmailSequence\">",
      "    <action name=\"ValidateRecipient\" activity=\"${2:EmailValidationService}\"/>",
      "    <action name=\"SendEmail\" activity=\"${3:SMTPMailService}\"/>",
      "    <action name=\"LogDeliveryStatus\" activity=\"${4:AuditLogService}\"/>",
      "  </sequence>",
      "</process>$0"
    ],
    "description": "Full SMTP email send process with validation and audit logging"
  },
  // ... repeat for every keyword in the table above
}



Use multi-value "prefix" arrays so that ALL aliases for each keyword trigger
the same snippet. Each snippet body must:
  - Use proper 2-space indentation
  - Have tab stops on every name="..." and activity="..." attribute
  - Include a meaningful ${N:placeholder} default value for every tab stop
  - End with $0 to place final cursor inside the innermost logical edit point



---



### 🎯 UX BEHAVIOR REQUIREMENTS FOR KEYWORD EXPANSIONS



1. PRESELECTION: When the entire current line matches a keyword exactly,
   the expansion item must appear at position #1 in the completion list
   with preselect: true — the user only needs to press Enter or Tab once.



2. WORD REPLACEMENT: The insertText range must cover the full keyword word
   on the current line so it is completely replaced — not appended to.
   Compute range as:
     const wordRange = document.getWordRangeAtPosition(position);
     item.range = wordRange;



3. ICON DIFFERENTIATION: Use distinct CompletionItemKind per category:
   - Integration templates (smtp, http, ftp, db): CompletionItemKind.Module
   - Security templates (auth, jwt, ldap):        CompletionItemKind.Interface
   - Control flow templates (trycatch, retry):     CompletionItemKind.Event
   - Notification templates (sms, push):           CompletionItemKind.Color
   - File/Document templates (pdf, csv):           CompletionItemKind.File
   - Package bootstrap (!):                        CompletionItemKind.TypeParameter



4. DETAIL LINE: Every expansion item must show a one-line detail in the
   dropdown formatted as:
   "⚡ [Category] — N properties, M activities"
   Example: "⚡ Integration — 6 properties, 3 activities"



5. DOCUMENTATION PANEL: Each item's .documentation (MarkdownString) must show:
   - **Title** of the template
   - Short paragraph describing when to use it
   - ```xml code preview showing first 8 lines of the expanded block```
   - *Tab stops:* bullet list of what each $1, $2, $3 represents



6. CATEGORY FILTER COMMAND: Register a new command:
   "bpml.showExpansions" → opens a Quick Pick menu listing all available
   expansion keywords grouped by category (Integration, Security, Control Flow,
   Notifications, File Operations, Bootstrap). Selecting one inserts the
   expansion at the current cursor position.
   Add this to the Command Palette as: "BPML: Insert Integration Template"



---



### 🔴 DIAGNOSTICS FOR EXPANSION-GENERATED BLOCKS



Add these additional diagnostic rules specifically for expanded integration blocks:



WARNING — Placeholder not replaced:
  Detect if any activity="" attribute still contains a generic value like
  "SMTPMailService", "HttpClientService", "SQLExecutionService" (i.e., the
  user has not customized the tab stop values).
  Message: "BPML: Activity name appears to be a template placeholder —
            consider replacing with your actual service name [BPML050]"



WARNING — Missing error handling on integration block:
  If a process containing an <action> with activity matching known integration
  patterns (Mail*, Http*, FTP*, SQL*, LDAP*) has no <exception> handler in its
  <context>, warn:
  "BPML: Integration process has no exception handler —
         add an <exception> block to handle service failures [BPML051]"



WARNING — SMTP without authentication properties:
  If an smtp-pattern process has a SendEmail action but no property named
  smtpUser or smtpPassword:
  "BPML: SMTP process may lack authentication properties [BPML052]"