Automations and webhooks for the AT Protocol airglow.run

Record template preview hides the auto-injected $type #25

Closed tyb.there-hugo.dev
Closed opened by tyb.there-hugo.dev

Problem #

The server adds $type to created records (lib/automations/pds.ts:591), but the record template preview doesn't show it. The user assumed it was missing and hand-added $type to the automation record in pdsls. Edits made directly on the PDS record are ignored by Airglow, so that didn't help either.

Seen in the session #

In https://www.youtube.com/watch?v=5MnT-ZgbBIc:

  • 0:59 to 1:00, and 1:18.

Fix direction #

Show $type (read-only) in the preview. Consider noting on the detail page that out-of-band PDS edits are not picked up.

Details: docs/brainstorms/2026-10-17-graze-conference-automation-feedback.md (U9).

Consider noting on the detail page that out-of-band PDS edits are not picked up.

Right, let's do it, but also, we should explain that we will support it at some point

Queued: the loop will work on this version of the issue.

loop:queued cid=bafyreihj7sl5v2lvldrmlqaa4ryu3s7rdlcbp3auhafh66czpli2rwi5sa

Working on this, attempt 1.

loop:claim run=contribute-20261026-155423-3my32g6gid422 branch=loop/3my32g6gid422 attempt=1 issue=25

feat(automations): show the auto-injected $type in record templates and explain PDS edits are not picked up

The server stamps $type (the target collection) onto every record a "Create a record" step writes, but neither the editor nor the automation page showed it, so a user decided it was missing and hand-edited it into the automation's record on their PDS. Record steps now show $type read-only in both places. The automation page also tells the owner that edits made directly to the PDS record are not picked up yet, and that support for them is planned.

What changed #

  • Editor (app/islands/action-editors/record.tsx, RecordTypeField in RecordFormBuilder.tsx): once a target NSID has settled, a read-only $type field shows the collection, with the hint "Set automatically to the target collection when the record is written. You don't need to add it to the template." It appears for resolved schemas, raw-JSON templates and the hand-written fallback textarea. The saved template does not change.
  • Automation page record template (withRecordType in app/islands/action-editors/record-type.ts): the displayed template gets "$type": "<collection>" as its first key, matching the template's indentation, with a hint under it. The template text is otherwise left exactly as written, so bare {{placeholders}} survive. Templates that are not objects, or that already have a top-level $type, are shown unchanged.
  • Automation page note (owner only): "This automation is also saved as a run.airglow.automation record on your PDS, but Airglow does not pick up changes made to that record elsewhere (in a tool like pdsls, for example). To change the automation, edit it here. Picking up edits made directly on your PDS is planned for a later release."

Verification #

  • pnpm run check: passes.
  • pnpm run test: 170 files and 2634 tests, all passing.
  • New tests:
    • record-type.test.ts covers insertion, indentation, bare placeholders, single-line and empty templates, an existing $type, and non-object templates.
    • record.test.tsx checks that the read-only $type input appears with the collection.
    • u/[handle]/[rkey]/index.test.tsx checks that the owner sees the PDS-edit note and other viewers don't, and that a record step's template on the page shows the injected $type.
  • I did not check it in a browser: this container has no dev server or PDS.

Acceptance criteria #

Decisions you can reverse #

  • Only the "Create a record" step shows $type. "Update a record" also stamps $type on write, but its template is a patch (or RFC 6902 ops), not the record, so adding $type there would misdescribe it. Built-in actions like the Bluesky post, follow and Semble steps have no user template.
  • On the automation page, $type is inserted into the displayed text instead of re-serializing the template, so hand-written formatting and bare placeholders are kept. A template that already has a top-level $type is shown as written, even though the server overrides it.
  • The PDS-edit note is muted text under the definition card, shown to the owner only, not an alert. Other viewers can't edit the record anyway.
  • The "Preview JSON payload" in the form is the automation's API payload, not a record, so it is unchanged.

Review: https://tangled.org/exosphere.site/airglow/compare/main...loop/3my32g6gid422

loop:pushed run=contribute-20261026-155423-3my32g6gid422 sha=b20d4d94792cf75b4657aceccbf5c71a0c18dbe9

Merge. The branch shows the server-stamped $type read-only for "Create a record" steps, both in the editor and in the record template on the automation page. It also adds an owner-only note on the automation page saying that edits made directly to the PDS record are not picked up, and that support for them is planned. That covers the issue and the owner's comment. pnpm run check and pnpm run test (170 files, 2634 tests) both pass on b20d4d9.

What I checked and how:

  • The issue's claim against the code: createArbitraryRecord (lib/automations/pds.ts:572) writes { ...record, $type: collection }, so $type always equals the target collection and overrides any $type in the template. The new display text says exactly that.
  • Editor (record.tsx, RecordTypeField): the read-only input is rendered outside RecordFormBuilder, so it shows for schema forms, raw JSON and the hand-written fallback textarea. The saved template is unchanged. Small quirk, not blocking: while someone is still typing an NSID that isn't valid yet, the field shows the partial text. The existing fallback textarea uses the same condition and does the same.
  • Automation page (withRecordType): I read the insertion logic and the edge cases: leading whitespace, {}, single-line and multi-line indentation, bare {{placeholders}} (kept verbatim because the text is not re-serialized), whole-record {{...}} templates, arrays, and an existing top-level $type found through parseTemplateJson. The new unit tests cover these. A template that already has a different top-level $type is shown as written. The hint under the template states that the server sets it, so this is acceptable.
  • PDS-edit note: shown to the owner only, in muted text. It links to the existing /u/:handle/:rkey/edit route and says support for these edits is planned, as the owner asked. Route tests check the owner, visitor and anonymous views.
  • Scope: every changed line is in the editor, the record display, the automation page or their tests. There is no migration. The extra api/automations difference against the base sha comes from main having moved one commit (#56) past the merge base. It is not part of this branch.

loop:verdict run=review-20261026-160233-3my32g6gid422 sha=b20d4d94792cf75b4657aceccbf5c71a0c18dbe9 verdict=merge

Merged main into the branch: 52952f723dfd9660442c28b2a0e25585360e3b0e.

loop:carry from=b20d4d94792cf75b4657aceccbf5c71a0c18dbe9 sha=52952f723dfd9660442c28b2a0e25585360e3b0e

Merged onto main as 1f9d889ebca13ff0fc0ef281de6ba9b7fecf4caf.

loop:merged sha=1f9d889ebca13ff0fc0ef281de6ba9b7fecf4caf head=52952f723dfd9660442c28b2a0e25585360e3b0e

Sign up or Sign in to add to the discussion.