| name | platform-adapter |
| description | Platform-agnostic layer for the SIA loop. Use at session start on any surface, when capabilities.env shows SURFACE=unknown, when a tool call fails with unavailable/unreachable, when switching between Claude Code, Cowork, web, or desktop mid-project, or when the user asks "what can you do here" / "continue this on web/code". Defines the capability matrix, per-surface degradation, and the STATE.md continuity carrier. |
Platform Adapter
Capability matrix (what each surface actually has)
| Capability | Code (CLI) | Cowork | Web/Mobile | Desktop chat |
|---|
| Hooks (tick enforcement) | YES | YES | NO | NO |
| Local stdio MCP (agentmemory) | YES | YES | YES via Desktop Commander MCP | YES |
| Filesystem | direct | direct | REAL, via Desktop Commander (proven: web session wrote STATE.md) | via DC |
| Sub-agents | YES | YES | NO | NO |
| Git | YES | YES | container git (needs remote) | via DC |
| Scheduled/unattended | YES (cron+claude -p) | agent threads | NO | NO |
Canonical STATE.md path: $SIA_STATE_PATH, default ~/Documents/02/STATE.md (Windows: C:\Users\kevin\Documents\02\STATE.md). .sia/ holds machine state (ledger, capabilities, dangling); STATE.md holds human-readable project state in the doctrine schema. Read .sia/capabilities.env if present; if absent you are on a hook-less surface — that fact IS the detection.
Enforcement degradation ladder (never pretend a layer exists)
- Code/Cowork — full runtime: hooks inject ticks, Stop nudges, probe on boot. Nothing extra needed.
- Desktop chat — no hooks. Ticks carried by project instructions (paste
templates/web-shim.md). Filesystem + agentmemory via Desktop Commander MCP — recall and ledger writes still real.
- Web/Mobile WITH Desktop Commander connected — no hooks, but filesystem and agentmemory are LIVE through DC: read/write STATE.md at its canonical path directly, real recall, real ledger appends. Ticks still carried by project instructions. Only degrade to queued writes when DC is absent.
- Web/Mobile WITHOUT DC — no hooks, no local MCP. Recall = Claude memory + past-chats; state = project-knowledge copy of STATE.md. Ledger writes are QUEUED: append intended entries to the reply as a fenced
sia-ledger block; the next Code session ingests them (/state resume checks for pasted queues). Never claim a memory write on web — there is no artifact.
Continuity carrier (cross-surface state)
STATE.md + ledger.jsonl are the carriers (living state); carry-packets in $SIA_PACKET_DIR are handoffs (one-shot, foreign-receive). Git remote is the transport for both. All paths derive from SIA_ENV_DIR in config/env.conf — one line to configure.
- Code/Cowork sessions commit
.sia/ on /state (if GIT_REPO=1).
- Web sessions read STATE.md from project knowledge (synced copy) and end by emitting an updated STATE.md block for the user to commit — one paste, not a ritual.
- Conflict rule: filesystem copy wins over project-knowledge copy (project knowledge lags); newest
PROBED_AT/timestamp wins between git and local.
Fallback chain (model/tool unavailability)
- Primary tool unreachable → check capabilities.env before retrying; if surface lacks it structurally, degrade per ladder above — retries against a structural absence are the category error (capability search applied to a non-capability problem).
- agentmemory unreachable/stale on a surface that should have it → check write-side separately from read-side (read can work while capture hooks are dead: INJECT_CONTEXT default false, rules files not installed). Report last-observation timestamp as the staleness evidence. Never init a fresh DB silently. NOTE: environment is Windows 11 NATIVE, no WSL — bash hooks require Git-Bash on PATH (probe reports GITBASH).
- Model switch mid-project → STATE.md is model-agnostic by design (prose + paths, no model-specific schema). Re-run probe; re-read STATE.md; capability re-audit is mandatory (hard rule 7) because tool schemas may differ.
Failure modes — do NOT use when
- Mid-task on a working surface — the adapter is for boundaries and breakage, not ambient overhead.
- To justify skipping ticks ("web can't enforce so skip") — enforcement degrades, semantics don't; ticks still run, carried by instructions.
- To build per-surface skill variants — skills are the portable layer precisely because they are surface-identical; fork behavior here in the adapter, never in the skills.