feat(aterm): tag every role bundle so one Spotlight word finds the set #1371

Merged
coilyco-ops merged 3 commits from aos/claude/mt75-bundle-tag into main 2026-08-29 02:07:31 +00:00
Owner

Kai asked whether an app tag exists so typing acompose surfaces all seven role apps at once. It does, and this writes one on every bundle.

Verified before building, not after

Finder tags live in the com.apple.metadata:_kMDItemUserTags xattr. The question that mattered was whether a plain query matches them, or only tag:acompose, since Kai wants to type one word:

mdfind -onlyin ~/Applications "acompose"   ->  matches the tagged bundle

Plain text matches. Finder writes a binary plist there; I checked that the XML form indexes identically, which is what lets this emit one without pulling in a plist encoder.

Shape

  • --tag defaults to acompose, the shell verb that already means "the role apps".
  • An empty value writes no xattr rather than a blank tag, so opting out is clean.
  • The tag lands last, after the bundle is otherwise complete, so a tag failure is never a half-written bundle.

golang.org/x/sys/unix rather than stdlib, because darwin has no syscall.Setxattr. It was already in the module graph as an indirect dependency, so this promotes it rather than adding surface. Linux gets a no-op behind a build tag: only macOS grows .app bundles, and aterm still ships linux/amd64 and linux/arm64.

The .app suffix, asked in the same breath

It cannot go, and there is nothing to build. macOS requires the extension for a bundle to be an app. The per-bundle extension-hidden flag is overridden by Finder's show-all-extensions preference, which is set to 1 on this host.

Measured rather than assumed — I set the flag on a stale bundle and re-read the display name:

before: "Gale // Game Developer.app"
after:  "Gale // Game Developer.app"

Unchanged. That preference is one global Finder setting, so it is Kai's toggle rather than anything a launcher can decide per app. Reverted after testing.

Tests

  • TestABundleCarriesTheSharedFinderTag — an untagged bundle is a silently unfindable one, which is the whole failure mode.
  • TestAnEmptyTagWritesNothing--tag "" writes no xattr rather than an empty one.

Five existing writeBundle call sites updated for the widened signature. Full aterm suite green, go vet clean, and a GOOS=linux cross-build to prove the no-op compiles.

Docs, and a cap that is now genuinely spent

docs/aterm.md sits at exactly 8000 of its 8000-character cap after one clause about the tag. To fit it I had to drop the .app finding from the doc entirely and compress five existing sentences.

That is the third PR in a row to pay this tax, and it is the strongest evidence yet for #1341. The next aterm fact has nowhere at all to go.

Not included

Applying the tag to the installed bundles. That is a regeneration against the user's ~/Applications and belongs with the release, not the PR.

Kai asked whether an app tag exists so typing `acompose` surfaces all seven role apps at once. It does, and this writes one on every bundle. ## Verified before building, not after Finder tags live in the `com.apple.metadata:_kMDItemUserTags` xattr. The question that mattered was whether a **plain** query matches them, or only `tag:acompose`, since Kai wants to type one word: ``` mdfind -onlyin ~/Applications "acompose" -> matches the tagged bundle ``` Plain text matches. Finder writes a binary plist there; I checked that the **XML** form indexes identically, which is what lets this emit one without pulling in a plist encoder. ## Shape * `--tag` defaults to `acompose`, the shell verb that already means "the role apps". * An empty value writes no xattr rather than a blank tag, so opting out is clean. * The tag lands **last**, after the bundle is otherwise complete, so a tag failure is never a half-written bundle. `golang.org/x/sys/unix` rather than stdlib, because darwin has no `syscall.Setxattr`. It was already in the module graph as an indirect dependency, so this promotes it rather than adding surface. Linux gets a no-op behind a build tag: only macOS grows `.app` bundles, and aterm still ships `linux/amd64` and `linux/arm64`. ## The `.app` suffix, asked in the same breath **It cannot go, and there is nothing to build.** macOS requires the extension for a bundle to be an app. The per-bundle extension-hidden flag is overridden by Finder's show-all-extensions preference, which is set to `1` on this host. Measured rather than assumed — I set the flag on a stale bundle and re-read the display name: ``` before: "Gale // Game Developer.app" after: "Gale // Game Developer.app" ``` Unchanged. That preference is one global Finder setting, so it is Kai's toggle rather than anything a launcher can decide per app. Reverted after testing. ## Tests * `TestABundleCarriesTheSharedFinderTag` — an untagged bundle is a silently unfindable one, which is the whole failure mode. * `TestAnEmptyTagWritesNothing` — `--tag ""` writes no xattr rather than an empty one. Five existing `writeBundle` call sites updated for the widened signature. Full aterm suite green, `go vet` clean, and a `GOOS=linux` cross-build to prove the no-op compiles. ## Docs, and a cap that is now genuinely spent `docs/aterm.md` sits at **exactly 8000 of its 8000-character cap** after one clause about the tag. To fit it I had to drop the `.app` finding from the doc entirely and compress five existing sentences. That is the third PR in a row to pay this tax, and it is the strongest evidence yet for #1341. The next aterm fact has nowhere at all to go. ## Not included Applying the tag to the installed bundles. That is a regeneration against the user's `~/Applications` and belongs with the release, not the PR.
feat(aterm): tag every role bundle so one Spotlight word finds the set
All checks were successful
ci / aos-eval-tests (pull_request) Successful in 9s
ci / aos-cli-tests (pull_request) Successful in 27s
ci / gate (pull_request) Successful in 54s
272877d660
Kai asked whether an app tag exists that would make typing `acompose` surface
all seven. It does: Finder tags live in the `_kMDItemUserTags` xattr, and
Spotlight matches them on a plain text query, not only on `tag:`.

Verified before building rather than after. A tag written by hand on one
bundle came back from `mdfind -onlyin ~/Applications acompose`, so a plain
word finds it. Finder writes a binary plist there and the XML form indexes
identically, which is what lets this emit one without a plist encoder.

`--tag` renames it and an empty value writes none, so opting out is clean
rather than a blank tag on every bundle. The write lands last, after the
bundle is otherwise complete, so a tag failure is never half a bundle.

stdlib has no darwin `Setxattr`, so this uses `golang.org/x/sys/unix`, which
was already in the graph as an indirect dependency rather than new surface.
Linux keeps a no-op: only macOS grows `.app` bundles to carry tags, and aterm
still ships linux/amd64 and linux/arm64.

On the `.app` suffix, which Kai asked about in the same breath: it cannot go.
macOS requires it for a bundle to be an app, and the per-bundle
extension-hidden flag is overridden by Finder's show-all-extensions
preference, which is set on this host. Measured, not assumed: setting the
flag left `kMDItemDisplayName` unchanged. That is one global Finder setting
rather than anything a launcher can decide, so there is nothing to build.

docs/aterm.md is at exactly 8000 of its 8000-char cap after one clause about
the tag. The `.app` finding had to be dropped from it for the tag to fit, and
five existing sentences were compressed. agentic-os#1341.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Kai Siren <coilysiren@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
Agent-Role: platform
Merge branch 'main' into aos/claude/mt75-bundle-tag
All checks were successful
ci / aos-eval-tests (pull_request) Successful in 8s
ci / aos-cli-tests (pull_request) Successful in 27s
ci / gate (pull_request) Successful in 49s
0d71ba5012
Merge branch 'main' into aos/claude/mt75-bundle-tag
All checks were successful
ci / aos-eval-tests (pull_request) Successful in 8s
ci / aos-cli-tests (pull_request) Successful in 33s
ci / gate (pull_request) Successful in 51s
95930f249a
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-flight-deck/agentic-os!1371
No description provided.