Skip to content
Back to skills

Changelog

ASecurity

Recent feature changes and implementation details for SAM. Use when understanding recent changes, checking what was modified recently, or understanding feature history.

  • 60 stars
  • 0 votes
  • 0 copies
  • 4 views
  • Added September 2, 2026
ai-agentsrustgosqlnodedockerawsgitapidatabase

Works with

  • claude code
  • terminal
  • cli
  • api
  • mcp

Security analysis

A100/100

Scanned October 5, 2026

npx -y skills add raphaeltm/simple-agent-manager --skill changelog --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Changelog?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Changelog
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/raphaeltm-changelog-simple-agent-manager/badge)](https://www.skillsdirectory.com/skills/raphaeltm-changelog-simple-agent-manager)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: changelog
description: Recent feature changes and implementation details for SAM. Use when understanding recent changes, checking what was modified recently, or understanding feature history.
user-invocable: false
---

# SAM Recent Changes

## Detailed Changes Moved From CLAUDE.md

These entries were removed from root `CLAUDE.md` so startup instructions stay compact. Use this skill when recent implementation context is needed.

- Compact archive shards: opt-in `PROJECT_DATA_ARCHIVE_COMPACT_ENABLED` pins lossless `r2-gzip-v1` raw history while keeping complete grouped text/search and metadata in SQL. `PROJECT_DATA_ARCHIVE_DAILY_WRITE_BUDGET` (250000), `PROJECT_DATA_ARCHIVE_WRITE_ESTIMATE_FACTOR` (32) and `PROJECT_DATA_ARCHIVE_R2_TIMEOUT_MS` (10000) bound admission/object I/O; see compact archive configuration for estimated versus measured costs and whole-session deletion limits. Legacy archives remain readable and unchanged.

Use the `/changelog` skill for structured queries.

- mcp-connection-custom-headers: Bring-your-own MCP servers can carry custom HTTP headers (Composio requires `x-api-key` / `x-consumer-api-key`). Headers are independent of `authType`; `Authorization` is accepted only with `none`. Names `^[A-Za-z0-9_-]{1,64}$` — exactly what the Amp bridge `mcp-remote@0.1.38` parses and a TOML bare key — pinned TS↔Go by the `headerNames` block of `mcp-server-name-contract.json`; transport headers are reserved (`headerNames.reserved` pins that list on both sides). D1 `0178` adds `header_names` (plaintext display projection) + `encrypted_headers`/`headers_iv` (one AES-GCM ciphertext of the `[{name,value}]` list, the only column injection reads). All rules and the storage format live in `services/mcp-connection-headers.ts`. PATCH `headers` is the full desired set and an entry without `value` keeps the stored value, so the UI edits without ever holding secrets. PATCH writes only if `updated_at` still matches the row it read (`nextUpdatedAt` keeps the column strictly increasing; a lost race is a 409): every derived field comes from that read, so without the guard a header-only edit racing a switch to bearer persisted an `Authorization` header beside a bearer token. Resolution re-validates decrypted headers, refuses that pair as a backstop, and skips a bad row. vm-agent: `McpServerEntry.ValidateHeaders` (charset, reserved names, case-insensitive duplicates including `Authorization` beside the bearer token — one repeated key makes the whole Codex/Vibe TOML unparseable, `sam-mcp` included) runs in `normalizeMcpServers` and again before any config file is written; headers are persisted (`migrateV18`; a row whose headers cannot be decoded is skipped on restore instead of dropping every server), converted by `toPersistedMcpServers`/`fromPersistedMcpServers`; ACP header list, Codex `env_http_headers` with `SAM_MCP_<NAME>_HEADER_<i>_SECRET` (the `_SECRET` suffix both classifies it for `isSecretEnvVar` and cannot collide with a bearer `_TOKEN` var), Vibe `headers` table, Amp `--header name:${SAM_MCP_HEADER_<i>}`. Wire shape pinned by `packages/shared/src/fixtures/mcp-server-entry-wire.json` (node-agent serializer + real Go handler). UI: `McpServerForm` (add + inline Edit), `McpServerHeadersField`. Limits `MAX_MCP_CONNECTION_HEADERS` (10), `MCP_CONNECTION_HEADER_VALUE_MAX_BYTES` (8192). Refactor in the same PR: MCP/Codex/Vibe code moved out of `gateway.go`/`session_host.go`/`workspaces.go`/`store.go` into `acp/mcp_servers.go`, `acp/codex_config.go`, `acp/vibe_config.go`, `server/mcp_servers.go`, `persistence/session_mcp_servers.go`.
- project-chat-instant-switching: Switching between project chats renders the target chat at once. Transcripts (`sessions/messages`) now keep a 24 h `gcTime` (`CHAT_TRANSCRIPT_CACHE_TTL_MS`, from shared `DEFAULT_CHAT_TRANSCRIPT_CACHE_TTL_MS`, override `VITE_CHAT_TRANSCRIPT_CACHE_TTL_MS`); previously the TanStack 5-minute default dropped an unobserved transcript from memory and, on the next write, from IndexedDB. Restored queries get `RESTORED_QUERY_GC_TIME_MS` via `hydrateOptions`, the dehydrate filter stops writing a transcript older than the TTL, and opening a chat evicts the least recently updated unobserved transcripts beyond `CHAT_TRANSCRIPT_CACHE_MAX_SESSIONS` (20; `evictStaleTranscripts` in `lib/query-options/chats.ts`); on disk each transcript keeps only its newest `CHAT_TRANSCRIPT_PERSIST_MAX_ROWS` rows (default: the 500-row page; `persistedQueryForDisk`). `ProjectMessageView` is keyed per session (`SessionMessageView`), and the transcript is read straight from the query cache (`useSessionTranscript`), so a cached chat paints in the switching commit and an uncached one shows a spinner, never the previous chat. The cold load requests the newest page (`fetchNewestPage`, `CHAT_SESSION_MESSAGE_LIMIT` = 500) instead of the 50,000-row `CHAT_SESSION_MESSAGE_MAX` ceiling (now only the server clamp); older history pages in through Virtuoso `startReached` once the reader scrolls up — wheel, swipe, or ArrowUp/PageUp/Home, not the list position (a page of tool calls can fold into a few rows that fit on screen, and a chat can open away from the bottom when its newest message is taller than the screen; an ungated `startReached` then paged the whole history in on open) and through the existing "Load earlier" button. The #2159 forward-delta refresh moved into the query function unchanged. Jumps to a specific message page back until that message id is loaded (`HistoryTarget` in `lib/message-paging.ts`) and then confirm the row is on screen, re-scrolling past Virtuoso's prepend compensation (`useConversationJump`), and an unloaded comment anchor reads "on a message". Composer drafts are per chat (`session-drafts.tsx`), report-issue config is a cached query, and server `session`/`state` snapshots hydrate only when the server reports new ones, which fixes a streamed row resetting a working agent to idle. Auth gating is unchanged: no persisted transcript renders before the session check resolves.
- archive-sweep-affordability-ceiling-and-fallthrough: The production ProjectData archive sweep stopped reclaiming anything on 2026-09-08 and reported `succeeded` for 226 hourly runs while the root object climbed from 94% to 96.7% of its 10 GB ceiling. Two independently configured ceilings had to agree and drifted: a GitHub `production` Environment override lowered `PROJECT_DATA_ARCHIVE_DAILY_WRITE_BUDGET` to 100000 (affordability ceiling `floor((100000-1000)/32)` = 3093 write units) while `PROJECT_DATA_ARCHIVE_SWEEP_MESSAGE_BUDGET` stayed at the checked-in 5000, and `selectCandidates` orders `message_count DESC ... LIMIT sweepProjects * sweepSessions` (deployed 1x1). Every tick therefore picked the same 4994-message session, estimated ~160,808 writes, was refused by `reserveArchiveWrites` BEFORE it touched D1 (so the UTC budget window also froze at `2026-09-08T00:00:00Z`), and `continue`d out of a one-element list — no journal row, no location change, no error. The selection ceiling is now DERIVED from the allowance (`archiveAffordableWriteUnits` / `archiveAffordableMessageCeiling` in `project-data-archive/write-budget.ts`, used as the `message_count <= ?` bind), so the two can no longer disagree at any configuration; an explicit session-scoped operator canary still bypasses it. `selectCandidates` over-reads `PROJECT_DATA_ARCHIVE_SWEEP_FALLTHROUGH_DEPTH` (4) spare candidates and the journaling loop descends past a refusal instead of ending the tick, with both per-tick bounds (session slots and the cumulative message budget) moved INTO that loop so a refused candidate — which opens no `migrating` fence and moves no rows — consumes neither. `reserveArchiveWrites` returns a discriminated outcome separating `exceeds_allowance` (waiting cannot help) from `window_exhausted` (normal end-of-day backpressure), and `PROJECT_DATA_ARCHIVE_BUDGET_STALL_ALERT_SWEEPS` (3) consecutive ticks that migrate nothing and see only the former flip the cadence row to `partial` with an actionable `last_error` — counted and escalated inside one atomic `UPDATE ... RETURNING` (migration `0156` adds `consecutive_budget_stalls`) so a failed read cannot silently restart a streak. `wrangler.toml` now ships `DAILY_WRITE_BUDGET=100000` (matching the production override, so staging and self-hosts derive the same ceiling), `SWEEP_MESSAGE_BUDGET=2000`, `SWEEP_SESSIONS=2`. Owner stubs are memoised per tick so the fall-through does not multiply `ensureProjectId` DO round trips. NOTE: within a 100000/day allowance the restored sweep reclaims on the order of 1-1.5 MB/day against ~66 MB/day of growth — it ends the deadlock but cannot reverse the storage curve; raising the budget is a spend decision.
- codex-astra-runtime-selection: Codex ACP is upgraded 1.8.0→1.10.0 and its Codex companion 0.153.2→0.153.4 across the canonical install manifest, VM-agent installer, and cf-container runtime image; the sandbox image's CLI-only pin is aligned to 0.153.4. VM-agent now validates both exact executable versions and supplies `CODEX_PATH=codex`, ensuring the adapter launches the explicitly pinned companion rather than a nested dependency resolved relative to itself. An explicit Codex profile model is applied through ACP `session/set_config_option`; rejection now fails session establishment with the requested model in the diagnostic instead of silently retaining the adapter default. A wire-level ACP regression test pins both the successful `gpt-6-astra` request and the fail-closed case. Process fix: `.claude/rules/23-cross-boundary-contract-tests.md` now treats adapter/companion resolution as one runtime contract.
- archive-drain-enable-unfence-and-throughput: (Cadence/budgets below superseded 2026-09-27 by the tripled 18-minute cadence and 2,400,000 daily write budget in PR #2161; the 2026-10-03 hourly billing firebreak, PR #2216, was reverted the same day. Current shipped values: `PROJECT_DATA_ARCHIVE_GLOBAL_SWEEP_INTERVAL_MS=1080000`, `_SWEEP_SESSIONS=8`, `_SWEEP_MESSAGE_BUDGET=10000`, `_WALL_TIME_MS=10000`; see the env-reference skill.) The production archive drain now runs on its own. Root cause of the never-running sweep: the GitHub `production` Environment variable `PROJECT_DATA_ARCHIVE_GLOBAL_SWEEP_ENABLED=false` (set 2026-09-04) replaced the `"true"` PR #2023 checked into `wrangler.toml`, so the deployed Worker kept `false` and every `cron.completed` reported `projectDataArchiveShardingSkipReason: disabled`; that Environment override is deleted as part of shipping this change (a deploy-time action, not a repo file: verify the deployed value per rule 70 before trusting it), and `sync-wrangler-config.ts` now prints every GitHub Environment override that differs from `wrangler.toml` (`listEnvironmentVarOverrides`). A pre-copy refusal no longer fences the session: the root object's `archiveSourcePrepareIntent` RPC RETURNS a typed `ProjectDataArchiveSourcePrepareRefusal` (`prepareArchiveSourceIntentOrRefuse`) for eligibility invariants that reject before any write, and the coordinator (`refusePreCopyMigration`) returns the D1 location to `root` in the same tick and freezes the journal as `precopy_refused` (no retry, no poison, no breaker) instead of leaving `failed` + `migrating`. `selectCandidates`/`selectScopedCandidates` skip a session with such a marker for `PROJECT_DATA_ARCHIVE_PRECOPY_REFUSAL_RETRY_MS` (default 7 days); an explicit session-scoped canary bypasses it. Stats gain `refused`; the problem-migrations list sorts self-healing `precopy_refused` rows after rows that need a human and the frozen-intent inspection skips them; `failed` journals wait `PROJECT_DATA_ARCHIVE_FAILED_RETRY_DELAY_MS` (default 1 h) before a sweep reclaims them so the 3-attempt poison budget spans hours at the shorter cadence; abandon, copy-back and the refusal unwind share one `restoreSessionLocationToRootStatement`; `project_data_archive_candidate_migrated` logs per-phase durations (prepare/copy/seal/manifest/finalize). Throughput was initially shipped at `PROJECT_DATA_ARCHIVE_GLOBAL_SWEEP_INTERVAL_MS=900000` and `PROJECT_DATA_ARCHIVE_WALL_TIME_MS=30000`; after the 2026-09-08 billing firebreak, `wrangler.toml` ships a one-hour cadence, one session per pass, a 5,000-message budget, and a 10s wall budget while the code fallback stays daily / 5s.
- archive-sharding-streaming-hash-abandon-size-budget: Archive sharding can now drain a large root ProjectData object without resetting it. The terminal-version hash (`computeTerminalVersion` → `tableAggregateSha256` in `durable-objects/project-data/archive-sharding.ts`) used to `toArray()` every row of a session per table and digest one string; a 100,000-message session and a tool-heavy 9,906-message session both reset the SAM root object with `Durable Object's isolate exceeded its memory limit`. It now streams pages of `PROJECT_DATA_ARCHIVE_HASH_PAGE_ROWS` (default 500) through `createCanonicalRowsHasher` (`node:crypto` incremental SHA-256), which is byte-identical to the one-shot definition so every recorded proof stays valid; `finalizeSourceDelete` and `rebuildTargetFts` page grouped rows the same way. New superadmin `POST …/archive-sharding/migrations/:migrationId/abandon` (`abandonProjectDataArchiveMigration`) recovers pre-copy migrations that copy-back cannot: it verifies on the root object that the source was never deleted, drops the partial shard copy (`abandonArchiveTargetSession`, which refuses `sealed` targets without that proof) and the source intent (`abandonArchiveSourceIntent`), freezes the journal as `operator_abandoned` without opening the project breaker, and returns the D1 location to `root`. Abandon reserves the journal lease first (`reserveAbandonLease`, epoch bump) and removes the source intent under the root transcript lock BEFORE dropping the shard copy, so a sweep finalizing concurrently cannot leave zero copies; the fence and the ordering are each pinned by a mutation-verified test. Candidate selection is largest-first (`session_summaries.message_count DESC`) under a new per-tick `PROJECT_DATA_ARCHIVE_SWEEP_MESSAGE_BUDGET` (default 20,000; a single oversize session is still selected alone); `PROJECT_DATA_ARCHIVE_SWEEP_SESSIONS` becomes the hard ceiling (default raised 1 → 10); the sweep now journals (fences) each candidate only immediately before processing it (`processArchiveMigrationBatch` `pending`), so a tick that runs out of wall time never leaves unreached sessions fenced `migrating` until the next cadence-gated sweep. `forEachGroupedRowPaged` seeks on the indexed `(created_at, id)` order (a `rowid` seek planned as a per-page sort of the whole session). Process fix: rule 69 gains the memory-ceiling case of harness-ceiling divergence.
- agent-client-version-refresh: Codex, Claude Code, and OpenCode client stacks brought current across every synchronized pin location (`agent-install-manifest.json`, `gateway.go` install constants, `Dockerfile.vm-agent-container`, gateway tests, e2e mock): `@agentclientprotocol/claude-agent-acp` 0.58.1→0.73.0 (bundles claude-agent-sdk 0.3.257; `emitRawSDKMessages`/`_claude/sdkMessage` harness-lifecycle contract verified unchanged), `@anthropic-ai/claude-code` 2.1.258→2.1.260, `@agentclientprotocol/codex-acp` 1.1.2→1.8.0 (CODEX_CONFIG env + `INITIAL_AGENT_MODE=agent-full-access` channels verified still supported; still no CLI `-c` parsing; depends on `@openai/codex@^0.152.0`), `@openai/codex` 0.144.6→0.153.2, `opencode-ai` 1.17.18→1.18.27 (`opencode acp` + `OPENCODE_CONFIG_CONTENT` verified). The implied adapter/companion compatibility was later invalidated: zero-major caret semantics mean `^0.152.0` excludes 0.153.x, so the adapter retained a nested 0.152.x runtime; see `codex-astra-runtime-selection` above. `claudeCodeMinVersion` floor stays 2.1.251. Also caught and fixed silent drift in `Dockerfile.sandbox` (the SandboxDO guided credential-setup image): it pinned claude-code 2.1.258 + codex 0.142.5 and installed the deprecated unpinned `@zed-industries/claude-agent-acp` that no sandbox surface execs — CLIs aligned to the manifest companions, dead adapter removed, and the contract test now pins sandbox codex alignment and bans the Zed adapter's return. `check-agent-install-manifest.ts` matching is boundary-aware (a stale `pkg@1.18.270` can no longer satisfy a `pkg@1.18.27` pin by substring). Existing live containers keep old binaries until restart/new session; cf-container images pick the new versions up at next deploy.

- knowledge-injection-relevance-ranking: Session-start knowledge injection (`get_instructions`) is ranked instead of alphabetical. `getAllHighConfidenceKnowledge` previously used `ORDER BY e.name ... LIMIT 50`, so the cap filtered on entity _spelling_: in production all 50 slots went to `AccountMap`..`AgentReliability`, 46 of them to the one `AgentBehavior` grab-bag, while `ContentStyle`/`CodeQuality`/`User`/`Architecture`/`BusinessStrategy` — entities the same payload tells agents to consult — had never been injected once, with no hint they existed. Now scored by the EXISTING formula (`computeRelevanceScore`: confidence × 1/(1 + age/30d) on `last_confirmed_at`, so `confirm_knowledge` restores rank), mirrored into SQL and pinned by a parity test; per-entity cap via `ROW_NUMBER() OVER (PARTITION BY entity_id)`; `now` bound as a parameter and ties broken to a total order (`score DESC, last_confirmed_at DESC, id ASC`) so output is reproducible. New `getKnowledgeEntityIndex` appends a compact `Name (type, N)` index to `knowledgeDirectives` disclosing what was NOT injected and naming `search_knowledge`/`get_relevant_knowledge` as the retrieval path; it returns `{entries, totalEntities}` (total via `COUNT(*) OVER ()`) so a truncated index can never be labelled "full". The three DO reads run as an isolated `Promise.allSettled` fan-out — a failed ranked read still leaves the index. Limits are clamped at the DO boundary (`clampRowLimit`): a negative `perEntityLimit` would otherwise make `entity_rank <= ?` unsatisfiable and inject nothing project-wide, and `LIMIT -1` means _unbounded_ in SQLite. New env vars `KNOWLEDGE_AUTO_RETRIEVE_PER_ENTITY_LIMIT` (8), `KNOWLEDGE_ENTITY_INDEX_LIMIT` (200). Process fix: `.claude/rules/65-capped-selection-must-rank-and-disclose.md`.

- byo-mcp-servers: Bring-your-own MCP endpoints. Users store `{name, url, authType, token, enabled}` at personal (`/api/mcp-connections`) or project (`/api/projects/:projectId/mcp-connections`) scope; SAM injects them into every agent session alongside `sam-mcp`. Both URL and token are AES-256-GCM encrypted and never returned by a read path (several providers issue pre-signed URLs with the credential in the URL, so the URL is a secret; `url_host` is the display value). Migration `0120_mcp_connections`. `buildSessionMcpServers` is the single composition point, called by `agent-session-bootstrap.ts` (covers VM + cf-container, rule 61) and the manual workspace agent-session route; the anonymous trial path is deliberately pinned to `sam-mcp` only. Resolution skips-and-warns per row so one bad connection cannot brick session start (rules 41/50). vm-agent: `McpServerEntry.Name` (additive, rule 54) plus `ResolveMcpServerNames` as the single naming source of truth — it replaced three drifted copies, one of which named a lone server `sam-mcp-0` for Vibe and `sam-mcp` everywhere else; persistence `migrateV12`. Codex's startup precondition, which required a bearer token for EVERY injected server, is now scoped to the reserved `sam-mcp` entry so a no-auth connection cannot break all Codex sessions. UI: Settings → MCP Servers (personal) and Project Settings → Runtime (project), one shared `McpServersManager`. v1 was bearer/none auth and personal/project scope only; custom headers shipped later (see `mcp-connection-custom-headers`), profile/skill attachment is tracked in idea `01M0QDASJCK3YWVX1GETZTSFWZ`. Limits: `MAX_MCP_CONNECTIONS_PER_SCOPE`, `MCP_CONNECTION_URL_MAX_BYTES`, `MCP_CONNECTION_TOKEN_MAX_BYTES`.
- policy-lifecycle-controls: Project policies gain a shelf life so one-shot workflow policies stop being injected into every session forever. Additive DO migration `034-policy-lifecycle-controls` adds `expires_at INTEGER` (nullable — `NULL` means never expires, preserving every existing policy's behaviour) and `scope TEXT NOT NULL DEFAULT 'always'` (`'always' | 'task'`). `getActivePolicies` filters at READ time (`active = 1 AND (expires_at IS NULL OR expires_at > ?)`) — no sweep, no cron; the row is retained and stays `active` so `get_policy` / `list_policies` / the Policies tab still show a human why a policy stopped applying, and the per-project cap COUNT excludes expired rows. A `scope: 'task'` policy MUST carry an `expiresAt`, enforced by one shared `validatePolicyLifecycle` at all three write boundaries (MCP `policy-tools.ts`, REST `routes/policies.ts`, sam-session `tools/add-policy.ts`) plus a DO-level choke point. `add_policy` / `update_policy` accept `scope` + `expiresAt`; `expiresAt: null` on update clears an expiry. Expiring policies render an inline `(task-scoped, expires YYYY-MM-DD)` annotation in `policyDirectives`, and the capture instruction now tells agents to scope dated work. New limit `POLICY_MAX_EXPIRY_MS` (default 365 days). Also hardened `scripts/quality/check-do-migration-safety.ts`, which extracted only backtick and single-quoted SQL — a `sql.exec("DROP TABLE ...")` in double quotes was invisible to the gate and reported PASS.
- claude-fable-51-model-catalog: Claude Fable 5.1 (`claude-fable-5-1`, released 2026-09-01, $10/$50 per MTok, native 1M context) added to both canonical model lists — `CLAUDE_MODELS` dropdown catalog and `PLATFORM_AI_MODELS` proxy allowlist/pricing. Claude Code CLI pinned to `@anthropic-ai/claude-code@2.1.258` because Fable 5.1 requires Claude Code 2.1.251 or newer; the VM-agent installer now validates the underlying `claude` binary instead of treating `claude-agent-acp` alone as sufficient. Focused tests pin dropdown presence, platform metadata, and the no-`[1m]` selector rule for native 1M Claude 5-family models.
- report-issue-idea-flow: Hosted "Report an Issue" flow that groups reports into private feedback incidents and creates/updates a linked draft Idea in the effective private feedback project (Admin → Integrations runtime setting, falling back to `PLATFORM_FEEDBACK_PROJECT_ID`). Two entry points: the session tool rail's Report action and ErrorBoundary crash screen. Users explicitly consent before technical refs (sessionId, taskId, nodeId) are attached. Server-side cross-tenant ref authorization validates project membership before storing references. User text sanitized with secret/PII redaction and fenced with provenance markers. Feature auto-hidden when no effective feedback project exists or it does not reference an existing project in the current deployment database. Configurable limits: `REPORT_ISSUE_TITLE_MAX_LENGTH`, `REPORT_ISSUE_DESCRIPTION_MAX_LENGTH`, `REPORT_ISSUE_CONTENT_MAX_LENGTH`.
- claude-opus-5-model-catalog: Claude Opus 5 (`claude-opus-5`, released 2026-07-24, $5/$25 per MTok, native 1M context) added to both canonical model lists — `CLAUDE_MODELS` dropdown catalog and `PLATFORM_AI_MODELS` proxy allowlist/pricing. Retired `claude-sonnet-4-20250514` pruned; stale defaults bumped to `claude-sonnet-5` (`DEFAULT_SAM_MODEL` — was pointing at the retired model, `DEFAULT_AI_PROXY_ANTHROPIC_MODEL`, `DEFAULT_TRIAL_MODEL_PRODUCTION`). New regression tests pin retired-Anthropic-model exclusion and default↔catalog registration; process rule `.claude/rules/52-model-catalog-lifecycle.md`.
- dispatch-task-runtime-routing: MCP `dispatch_task` now honors explicit and skill/profile `runtime` selection. Explicit `cf-container` decisions launch task-mode Instant sessions asynchronously without VM credential/quota gates or duplicate chat persistence; the Instant branch re-verifies repository owner access (`requireRepositoryOwnerAccess`) before launching, matching the VM branch; async Instant launch failures mark the task failed via the shared queued-guarded transition (`markQueuedTaskFailed`) instead of stalling `queued` until the stuck-task cron; VM-only arguments conflict with container runtime instead of silently downgrading; responses expose the effective runtime and decision reason, and `get_task_details` returns the task's chat `sessionId` once the async session exists.
- origin-tag-injected-messages: SAM-injected prompt text (e.g. the `get_instructions` reminder) is no longer concatenated into the visible user prompt. It is passed separately as `injectedInstructions` on the vm-agent create-session HTTP body (`startAgentSessionOnNode` → `buildInitialPromptParams`), emitted as a second ACP prompt block tagged `_meta["sam.origin"]="system"`. The vm-agent honors that marker ONLY from a trusted control-plane prompt (`HandlePrompt(..., trustedSource)`) — browser viewer prompts have it stripped so a user cannot hide their own content. Origin propagates through the messagereport outbox (new `origin` column), the ProjectData DO `chat_messages` table (additive migration `024-chat-message-origin`, NULL/absent = `user`), `ChatMessageResponse`, and the live `session/update` broadcast. The web collapses `origin=system` user messages behind a `<details>` "Show system context" disclosure (`AcpConversationItemView`). `origin=system` content is excluded from user-content dedup, LIKE/FTS search (materialization filters it out of `chat_messages_grouped`), topic auto-capture, and attention resolution.
- chat-full-load-timeline-jump: (Initial full load superseded 2026-09-27 by project-chat-instant-switching, which loads the newest page first.) Project chat loads the FULL conversation on open (`getSessionMessageLimit` split into a small default page size `CHAT_SESSION_MESSAGE_LIMIT` for the 3s poll/load-more and a large `CHAT_SESSION_MESSAGE_MAX` ceiling the initial load requests; new `DEFAULT_CHAT_SESSION_MESSAGE_MAX`). The 30 MiB RPC size guard + `hasMore` "Load earlier" remain the fallback for oversized sessions. Timeline jump-to-message now anchors by messageId+timestamp with a `loadUntil` fallback (no more dead clicks), every entry kind (user message, status update, activity) is clickable, and the jumped-to message flashes (`.sam-message-highlight`). Removed the now-dead `messageIndex`/`messageIndexMap` from the timeline.
- skills-profile-override-layer: Skills as a first-class profile-override layer (skill → profile → project → platform); additive migration `0063_skills.sql` adds `skills`, `skill_runtime_env_vars`, `skill_runtime_files` and `tasks.skill_id`/`tasks.skill_hint`/`triggers.skill_id`; shared mappers in `profile-fields.ts`/`profile-runtime-assets.ts`; CRUD + runtime routes under `/api/projects/:projectId/skills`; resolution wired through task/trigger/MCP/dispatch + workspace runtime asset injection; Skills UI + chat/task skill selectors in `apps/web`
- explicit-sam-provider-selection: Require explicit opt-in to SAM as AI provider via `providerMode: 'sam'`; three-mode agent auth (user-api-key, oauth, sam); AI proxy auth gate on all endpoints including /models
- compact-mode-lazy-load-tool-content: Chat compact mode strips tool content from RPC payload (80-90% reduction); lazy-loads on expand
- harness-track-d-integration-design: SAM-native harness architecture doc; Gemma 4 26B as default Workers AI model
- ai-proxy-universal-tracking: URL-path-based passthrough proxy for usage tracking without consuming auth headers
- user-ai-budget-controls: User-facing daily token budgets + monthly cost cap with 3-tier resolution
- anthropic-proxy-endpoint: Native Anthropic Messages API proxy through AI Gateway with Unified Billing
- user-ai-usage-dashboard: Per-user LLM usage dashboard from AI Gateway logs (by model, by day)
- cost-monitoring-dashboard: Admin cost dashboard aggregating LLM + compute costs with projections
- sam-observability-context-tools: SAM tools for searching task messages and browsing project codebases
- sam-agent-phase-a-tools: SAM orchestration tools (dispatch_task, create_mission, get_task_details)
- policy-propagation-phase4: Project policies with MCP tools + propagation to child tasks

For the latest changes, also check `git log --oneline -20`.

- **durable-project-eventing**: Operational same-chat event delivery, persisted one-off schedules and bounded standing watches, agent channels with atomic history/follow, and member project/session Events controls. Canonical source outbox covers configured lifecycle/GitHub CI/review/authenticated-webhook facts; credential-limit events use actual server-selected attribution. Shared mailbox/recovery guards preserve cancellation and membership authority. Retention uses incremental accounting and bounded durable orphan-scan progress. Delivery receipts and schedule admission remain separate from agent action.
- **session-visibility**: VM Agent enriches session responses with live `hostStatus` and `viewerCount`; shared `AgentHostStatus` type; new `listAgentSessionsLive()` browser API; enhanced status colors in workspace UI
- **devcontainer-runtime-user-consistency**: VM Agent resolves effective devcontainer execution user when `CONTAINER_USER` is unset; detection order: `devcontainer read-configuration` > `devcontainer.metadata` label > `docker exec id -un` fallback; per-workspace `ContainerUser` stored in runtime
- **workspace-runtime-identity**: VM Agent derives host workspace identity from canonical `workspaceId`; strict workspace label matching prevents cross-workspace routing
- **sam-workspace-env**: SAM platform metadata injected as env vars into devcontainers during bootstrap (`SAM_WORKSPACE_ID`, `SAM_NODE_ID`, `SAM_WORKSPACE_URL`, `SAM_API_URL`, `SAM_REPOSITORY`, `SAM_BRANCH`)
- **worktree-context**: Deep git worktree integration across VM agent, API, shared types, terminal, and workspace UI; worktree-aware terminal/chat session creation; `WorktreeSelector` UI
- **node-system-info**: VM Agent sysinfo package collects metrics from Linux procfs and Docker CLI; two-tier collection (quick for heartbeat, full for `/system-info` endpoint); Node detail page redesigned with composed section components
- **devcontainer-named-volumes**: Replaced bind-mount storage with named Docker volumes (`sam-ws-<workspaceId>`); eliminated permission normalization
- **command-palette-search**: Enhanced command palette with fuzzy file search and tab switching; camelCase-aware fuzzy matching
- **tab-reorder-rename**: Unified tab ordering, rename, and drag-and-drop reordering; useTabOrder hook with localStorage persistence
- **persistent-agent-sessions**: Agent processes survive browser disconnects; SessionHost owns agent lifecycle independently; fan-out message broadcasting; bounded message ring buffer for late-join replay
- **workspace-keyboard-shortcuts**: VS Code-style keyboard shortcuts; centralized shortcut registry with platform-aware matching
- **agent-settings-acp-protocol**: Wire agent settings through ACP protocol; all 5 permission modes exposed
- **comprehensive-lifecycle-logging**: End-to-end ACP/WebSocket lifecycle observability via CF Workers
- **vm-agent-error-reporting**: Go errorreport package with batching and periodic flushing
- **client-error-reporting**: Client-side error reporting pipeline with batched sends
- **agent-file-ops**: ACP ReadTextFile and WriteTextFile handlers via docker exec
- **file-browser**: File browser with directory listing and syntax-highlighted file viewer
- **git-changes-viewer**: GitHub PR-style git changes viewer with unified diff
- **voice-to-text**: Voice input with Workers AI Whisper transcription
- **014-multi-workspace-nodes**: First-class Nodes with multi-workspace hosting, async provisioning, workspace recovery
- **013-agent-oauth-support**: Dual credential support for Claude Code (API key + OAuth token)
- **012-pty-session-persistence**: PTY sessions survive page refresh with ring buffer replay

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.