Abstraksi adapter harness
Protokol HarnessAdapter — bagaimana adapter Apothem menerjemahkan profil bersama.
Apothem menggunakan satu profil YAML tervalidasi-skema sebagai sumber kebenaran
semantik dan menurunkan setiap permukaan pemasangan spesifik-harness melalui kelas
adapter yang mengimplementasikan protokol HarnessAdapter. Setiap adapter menulis
ke lokasi pengguna atau proyek yang didokumentasikan oleh harness dan menggunakan
jalur dukungan milik Apothem hanya ketika harness tidak memiliki primitif asli
yang setara.
Mengapa abstraksi adapter
Setiap harness berbicara dengan dialek konfigurasi yang berbeda: satu menginginkan
berkas pengaturan JSON, yang lain sebuah direktori berkas aturan .mdc, yang
ketiga sebuah berkas instruksi Markdown tunggal. Jika Apothem mengodekan
pengetahuan itu secara keras ke dalam CLI, setiap harness akan membocorkan
asumsinya ke inti, dan menambahkan sebuah harness berarti menyentuh logika
pemasangan, pembaruan, pencopotan, dan verifikasi secara serentak.
Pola adapter membalikkan hal itu. Inti hanya mengetahui protokol HarnessAdapter
— sebuah kontrak kecil berisi metode siklus-hidup. Dialek setiap harness hidup di
dalam satu subpaket mandiri yang mengimplementasikan kontrak tersebut. Inti
meminta sebuah adapter untuk memasang tanpa mengetahui apakah itu berarti
merender berkas JSON, menulis direktori aturan, atau meletakkan pohon pendukung.
Harness baru bergabung dengan memenuhi protokol dan menambahkan entri
HARNESS_REGISTRY di src/apothem/lib/harness_registry_data.py (dengan menaikkan
SUPPORTED_HARNESS_COUNT di sana), mencerminkannya pada entry point
apothem.harnesses di pyproject.toml, dan menambahkan ID ke enum harnessId
di src/apothem/schemas/profile.schema.json. Inilah alasan struktural mengapa
Apothem tetap agnostik-host — abstraksi adalah batas yang menjaga pengetahuan
spesifik-harness agar tidak menyebar.
Bentuk sebuah adapter
Adapter terbagi menjadi dua bentuk materialisasi, keduanya terlihat di registri:
- Perender berkas-tunggal menerjemahkan bidang profil menjadi satu berkas konfigurasi native-harness. Adapter OpenCode, misalnya, merender berkas konfigurasi native-nya dari profil bersama melalui sebuah materializer.
- Adapter permukaan-aturan dan pohon-pendukung menyebarkan kohor muatan Apothem
ke lokasi aturan yang didokumentasikan oleh harness, mengonversi kohor ke
format native di tempat format itu ada dan memarkir sisanya di bawah pohon
pendukung milik Apothem yang dirujuk dari jangkar native. Adapter Cursor menulis
satu
.cursor/rules/apothem-rules.mdcke akar proyek yang disuplai. Sebelum berkas itu, ia menulis dua folder bersama di direktori home pengguna: skill, dan command yang dibungkus sebagai skill, masuk ke~/.agents/skills/, dan aturan serta templat yang dikutip skill-skill tersebut masuk ke~/.config/apothem/. Adapter Claude Code tidak merendersettings.jsondari profil. Ia menyalin templat pengaturan yang dibundel ke~/.claude/settings.jsondengan interpreter hook sudah terisi, meratakan direktori konvensi Apothem (agents/,rules/,skills/, …) di sampingnya, dan menulis profil ke dalam blok terkelola yang dibatasi sentinel diCLAUDE.md.
Sebuah adapter tertentu bersifat lingkup-pengguna (menulis di bawah direktori
home) atau lingkup-proyek (memerlukan --project <path> dan menulis berkas
proyeknya di dalam pohon itu); registri mencatat yang mana. Tujuh adapter
lingkup-proyek (cursor, github-copilot, windsurf, zed, codebuddy, kiro, dan trae)
juga menulis folder bersama di direktori home pengguna, seperti
~/.agents/skills/ dan ~/.config/apothem/, dan --project tidak mengubah ke
mana folder-folder itu ditulis.
Topologi adapter saat ini
%% provenance: hand-authored %%
%% verified: 2026-10-25 %%
%% cross-reference: src/apothem/harnesses/ (adapter sub-packages) %%
flowchart TD
accTitle: Apothem adapter topology
accDescr: The single shared profile at the center feeds the adapter layer, which fans out to one adapter per supported harness; each adapter writes to a user-scope or project-scope native surface, rendering a single config file or propagating a rules and support-tree cohort.
P["Shared profile (YAML)<br/>~/.config/apothem/profile.yaml<br/>+ packaged payload cohorts"]
P --> AL["Adapter layer<br/>HarnessAdapter protocol<br/>(17 registered adapters)"]
AL --> CC["claude-code adapter<br/>(user scope)"]
AL --> CX["codex adapter<br/>(user scope)"]
AL --> CU["cursor adapter<br/>(project scope)"]
AL --> CO["github-copilot adapter<br/>(project scope)"]
AL --> WS["windsurf adapter<br/>(project scope)"]
AL --> ETC["… 12 more registered adapters<br/>(antigravity, gemini-cli, glm, hermes,<br/>kimi-code, open-claw, opencode, qwen-code,<br/>codebuddy, kiro, trae, zed)"]
CC --> CCN["~/.claude/settings.json<br/>+ flattened convention dirs<br/>(template copy)"]
CX --> CXN["~/.codex/AGENTS.md + hooks.json<br/>+ converted TOML agents<br/>(render + support tree)"]
CU --> CUN["<project>/.cursor/rules/apothem-rules.mdc<br/>+ ~/.agents/skills/ and ~/.config/apothem/<br/>(project rules file + user-home folders)"]
CO --> CON["<project>/.github/copilot-instructions.md<br/>+ ~/.agents/skills/ and ~/.config/apothem/<br/>(project rules file + user-home folders)"]
WS --> WSN["<project>/.devin/rules/apothem-rules.md<br/>+ ~/.agents/skills/ and ~/.config/apothem/<br/>(project rules file + user-home folders)"]
ETC --> ETCN["each harness's documented<br/>native surface or Apothem-owned<br/>support subtree"]Pemencaran dari pusat-ke-tepi adalah arsitektur yang dikodekan oleh nama proyek: satu profil di inti, setiap harness berada pada jarak yang sama di sepanjang adapternya sendiri.
Definisi protokol
from pathlib import Path
from typing import Protocol
class HarnessAdapter(Protocol):
name: str
output_path: Path
def install(self, profile: dict[str, object]) -> object:
...
def update(self, profile: dict[str, object]) -> object:
...
def uninstall(self) -> None:
...
def is_installed(self) -> bool:
...
def verify(self) -> bool:
...Adapter lingkup-proyek dapat secara tambahan menerima project: Path | None pada
metode siklus-hidup dan mengekspos resolve_output_path(project). CLI hanya
meneruskan --project PATH ke adapter yang tanda tangan metodenya menerimanya.
Pendaftaran entry point
Adapter mendaftar melalui grup entry-point setuptools apothem.harnesses:
[project.entry-points."apothem.harnesses"]
cursor = "apothem.harnesses.cursor:CursorAdapter"Registri pusat di src/apothem/lib/harness_registry.py mencatat tujuh belas ID
publik yang persis, entry point, jalur dokumentasi, jalur target, persyaratan
data-paket, status kapabilitas, dan jalur pin konvensi standar. CLI memuat adapter
melalui registri itu alih-alih menemukan kembali fakta produk di setiap perintah.
Pemetaan profil-ke-asli
Setiap adapter mengimplementasikan logika penerjemahan yang sesuai untuk harness-nya:
YAML profile + payload cohort Harness-native surface
----------------------------- ----------------------
identity / preferences --> native config fields or rendered instruction context
commands/*.md --> native commands or SKILL.md folders
rules/*.md --> native rules where supported, otherwise support trees
hooks/messages/*.md --> native hooks where supported, otherwise support trees
agents/*.md --> native agent formats where supported
skills/*/SKILL.md --> native skill folders where supportedSel kapabilitas yang tidak didukung dan yang menunggu-penemuan menjadi peringatan terstruktur sebelum penulisan. Sel-sel itu tidak diproyeksikan secara diam-diam ke permukaan vendor yang direka.
Menambahkan adapter baru
Lihat Menulis adapter harness untuk panduan langkah demi langkah.