Skip to content

feat: auto-generate property read/write JXA templates from sdef class definitions #16

Description

@mickdarling

Summary

Build a template auto-generator that produces working JXA templates directly from sdef class/property definitions. This covers ~60-70% of operations for any macOS app adapter and is the highest-ROI automation for the pipeline.

Context

During the Apple Mail adapter build, we found that most READ and UPDATE operations follow a predictable pattern derivable from the sdef:

sdef: <class name="mailbox"><property name="unread count" type="integer"/></class>
generates: account.mailboxes.byName(specifier).unreadCount()

The pattern for property reads:

{parent}.{class_plural}.byName({{specifier}}).{camelCase(property)}()

The pattern for property writes:

{parent}.{class_plural}.byName({{specifier}}).{camelCase(property)} = {{value}};

The pattern for element listings:

var items = {parent}.{class_plural}.byName({{specifier}}).{element_plural}();
// iterate with index, NOT batch
for (var i = 0; i < Math.min(items.length, limit); i++) { ... }

What to Build

Template Generator Module (src/template-generator.ts)

Input: Parsed sdef (from sdef-parser.ts) — classes, properties, elements, types
Output: templates.json with working JXA for each operation

Transformations Needed

  1. Property name → JXA accessor: "unread count"unreadCount() (camelCase, remove spaces)
  2. Class name → JXA plural accessor: "account"accounts, "mailbox"mailboxes
  3. Type mapping: sdef type="integer" → template param {"type": "integer"}
  4. Access chain inference: sdef class hierarchy tells us mailbox is an element of account, so the access chain is mail.accounts.byName(x).mailboxes.byName(y)
  5. Read vs write: sdef access="r" → READ template only; access="rw" → READ + UPDATE templates

Hierarchy Resolution

The sdef defines containment:

<class name="account"><element type="mailbox"/></class>
<class name="mailbox"><element type="message"/></class>

The generator must resolve the full access chain:

  • message.subjectmail.accounts.byName(a).mailboxes.byName(m).messages[i].subject()
  • mailbox.unreadCountmail.accounts.byName(a).mailboxes.byName(m).unreadCount()
  • account.namemail.accounts.byName(a).name()

Performance-Safe Patterns

CRITICAL: The generator MUST use the index iterator pattern for element listings, NOT batch reads or whose filters. From Apple Mail testing:

Pattern Scales to Use
items[i].property() Any size ✅ Always use
items.property() (batch) ~500 items ❌ Never use
items.whose({...}) ~500 items ❌ Never for large collections

CLI Extension

mcpaql-sdef-interrogate --app Mail --out /tmp/pipeline --generate-templates

The --generate-templates flag runs the template generator after sdef parsing, producing templates.json alongside the discovery bundle.

Acceptance Criteria

  • Generates READ templates for all readable properties
  • Generates UPDATE templates for all writable properties
  • Generates element listing templates with index iteration
  • Resolves class hierarchy for access chains
  • camelCase conversion for property names
  • Pluralization for class/element accessors
  • All generated templates use the performance-safe index iterator pattern
  • Output format matches TemplateOverridesDocument from adapter-generator types
  • Tested against Mail.sdef — generated templates should match hand-authored ones

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions