Skip to content
Back to skills

Aevatar Feasibility Advisor

ASecurity

Use before building when a user asks whether Aevatar can achieve a goal, what prerequisites it has, or why it is unavailable. Triggers include bots and third-party APIs, inbound channels, external HTTP triggers, schedules, service exposure, Agent Profiles and tool ceilings, and bounded managed or private-host codex_exec work. It distinguishes outbound connectors from inbound channels and separates not connected, host-gated, not deployed, and genuinely unsupported outcomes. It chooses managed_...

  • 37 stars
  • 0 votes
  • 0 copies
  • 6 views
  • Added September 2, 2026
ai-agentsrustgoshellbashreactnodeexpressgitapidocumentation

Works with

  • terminal
  • cli
  • api

Security analysis

A100/100

Scanned September 2, 2026

npx -y skills add ChronoAIProject/NyxID --skill aevatar-feasibility-advisor --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Aevatar Feasibility Advisor?

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

Security grade badge for Aevatar Feasibility Advisor
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/chronoaiproject-aevatar-feasibility-advisor/badge)](https://www.skillsdirectory.com/skills/chronoaiproject-aevatar-feasibility-advisor)

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: aevatar-feasibility-advisor
description: Use before building when a user asks whether Aevatar can achieve a goal, what prerequisites it has, or why it is unavailable. Triggers include bots and third-party APIs, inbound channels, external HTTP triggers, schedules, service exposure, Agent Profiles and tool ceilings, and bounded managed or private-host codex_exec work. It distinguishes outbound connectors from inbound channels and separates not connected, host-gated, not deployed, and genuinely unsupported outcomes. It chooses managed_sandbox versus private_ssh without promising repository, model, credential, runtime, or deployment capabilities the caller does not control, then routes feasible work to the owning Aevatar skill.
version: "1.10"
metadata:
  category: plain
  tag:
    - aevatar
    - feasibility
    - capability
    - scoping
    - nyxid
    - prerequisites
    - advisor
    - negotiation
    - agent-profile
    - codex-exec
---

# Aevatar feasibility advisor

Before you (or the user) commit to building something on Aevatar, answer three questions
**honestly**: *Is it possible? What must be in place first? If not, why — and what's the
alternative?* This skill exists so you negotiate scope up front instead of discovering a
hard blocker halfway through. It only **advises** — once a plan is feasible, hand off to
`aevatar-workflow-authoring` → `aevatar-team-builder` → `aevatar-service-publisher` →
`aevatar-scheduler`, or to `aevatar-agent-profile-management` for the Agent Profile surface
(see `aevatar-platform-map`). For `codex_exec`, choose the target here, then hand setup or
repair to `aevatar-codex-exec-node-setup`, require the public
`aevatar-codex-exec-workflow-sample` proof, and only then author the real workflow.

## Three different reasons a thing can be unavailable — never blur them

They have different owners and different fixes. Collapsing them into "it's host-gated" is the most
common wrong answer here.

| Reason | What it looks like | Who fixes it |
|---|---|---|
| **Not connected** | The connector is in `/api/v1/catalog` but missing from authoritative `/api/v1/keys` | **The user**, self-serve |
| **Host-gated** | The capability is deployed and works, but a host policy governs one aspect (NyxID external exposure; Agent Profile *rollout admission*) | **The host** — not you, not the user |
| **Not deployed** | The capability's whole API surface is absent from the running build | **The host**, by deploying a build that exposes it |

"Not deployed" is the one people get wrong most: the feature exists in the codebase and in design
docs, so it *sounds* available. **Probe the live surface, never a branch or a memory** —
`GET /api/openapi.json` and check whether the complete route family is advertised.

Agent Profile management is an **owner-managed** capability — an authenticated user manages their
own profile; it is not host-only configuration. It remains deployment-gated, so probe the live
`GET /api/openapi.json` and require the complete `agent-profiles` route family before mutation.
Do not preserve a historical claim that production lacks or exposes it; the live OpenAPI is the
only answer for the current deployment.

## Choose the `codex_exec` target before workflow authoring

`codex_exec` is an in-session workflow capability with two separate infrastructure targets. It is
not an HTTP endpoint or a Studio lifecycle stage. Choose exactly one target from the requirement;
never mix their fields.

| Requirement | Feasibility verdict | Exact boundary and prerequisite |
|---|---|---|
| Bounded one-shot Codex work that can start from a clean empty Git repository | ✅ Use `managed_sandbox` | Requires the exact native NyxID user to be admitted by the internal rollout and to directly own one active usable `chrono-sandbox` UserService plus one usable `chrono-llm-public` route. The request must use `workspace.kind=empty_git`; timeout defaults to and is capped at 180 seconds. |
| Codex work that requires an existing private repository, host files, or host Codex login/configuration | ✅ Use `private_ssh` | Requires a user-owned hardened NyxID SSH service, fixed principal and host workspace, and a working host Codex CLI/login. Send no `workspace`; the host wrapper owns the repository path. Timeout defaults to 30 seconds and is capped at 300 seconds. |
| Persistent managed repository/session, caller-selected repository/path, image, model, provider, credential, shell, or work beyond the bounded synchronous contract | ❌ Not provided by `managed_sandbox` | Narrow or split the work so it can start from `empty_git`, or use a separately authorized private-host/long-running workflow. Do not promise managed repository persistence. |

Both targets accept only a nonblank prompt of at most 6000 UTF-8 bytes plus their typed target
fields and optional timeout. A managed caller cannot select a repository, path, image, model,
provider, credential, Codex profile, command, approval policy, or sandbox flag. A private caller
supplies only `target.private_ssh.service` and `principal`; that service is a UserService slug or
UUID, not a node ID.

Configuration, health, service inventory, a direct chrono call, or a direct SSH command is only a
prerequisite. Readiness requires mounting the public `aevatar-codex-exec-workflow-sample` and
getting exact `CODEX_EXEC_READY` through Aevatar:

- Managed proof: `status=succeeded`, `target=managed_sandbox`, trimmed
  `output=CODEX_EXEC_READY`, `exit_code=0`, and a non-empty sanitized `diagnostic_id`.
- Private proof: the original NyxID SSH result has `exit_code=0`, `timed_out=false`, and trimmed
  stdout exactly `CODEX_EXEC_READY`.

After choosing `managed_sandbox`, explicitly call authenticated `POST /api/managed-codex/credential` to provision or reconcile, then read `GET /api/managed-codex/credential`. Proceed only when `execution_ready=true` and `execution_readiness_reason=ready`; `status=active` alone is insufficient. Normal `codex_exec` is credential-read-only and never provisions, reconciles, rotates, repairs, or retries after a credential failure. The caller never supplies or sees the key. Then use `aevatar-codex-exec-workflow-sample` for the mandatory proof and load `aevatar-workflow-authoring` only after it succeeds. Preserve the deadline chain: chrono execution 180s < Aevatar managed request 300s < NyxID/ingress at least 315s < NyxID client 330s < workflow canary at least 360s. Landlock, Bubblewrap, sandbox-side Credential Vault substitution, and a credential proxy are not repair paths for the managed runtime.

## The one premise: NyxID is the universal gateway

Aevatar holds **no third-party credentials and talks to no external service directly.**
Every external capability is brokered by **NyxID**. That single fact drives every feasibility answer below. Keep inbound channels separate from three outbound invocation modes:

| Surface | What it gives you | How it's used | Supported set |
|---|---|---|---|
| **Connector** (outbound) | Your workflow/agent **calls** a third-party API (read data, post, act) | Raw `nyxid_proxy` requires exact `service_id + slug + path`; current-turn dynamic `nyxid_service_operation__*` tools are retired; a compiled workflow uses exact `capability.nyxid_operation` or typed `capability.nyxid_request` admission | Anything in the live NyxID catalog/inventory — broad |
| **Channel** (inbound) | A third-party chat platform **delivers user messages to your agent**, which replies **in that platform** | An Aevatar **channel module** + NyxID relay webhook | **Narrow** — only platforms with a built module |

> **The trap:** "I want a Twitter bot." A Twitter *connector* (`api-twitter`) exists, so your
> agent **can post/read tweets** (outbound). But there is **no Twitter inbound channel
> module**, so you **cannot** have an agent that auto-replies to mentions/DMs the way a Lark
> or Telegram bot does. Same word, two very different feasibility answers. Always separate
> "call the API" from "be a bot on that platform."

## Step 0 — Inspect what is actually connectable (don't guess)

Use the authenticated NyxID CLI; never read its stored access token or build an Authorization
header. Two read-only CLI calls tell you the ground truth:

```bash
nyxid service list --output json
nyxid catalog list --output json
```
(Inside an Aevatar session, use the typed connected-service tools actually present.) For a request
to connect, add, or authorize a named service, `nyxid_catalog` is discovery only: use it to resolve
the exact catalog slug when necessary, then **always** call `nyxid_require_service`. Finish from
that typed readiness result; it is the authority for a missing-service blocker and interactive
`service.connect` handoff. Never stop at catalog prose.

**The live catalog and authoritative `/api/v1/keys` instance inventory are the source of truth —
never assert a connector exists or does not without checking them.** `/api/v1/keys` is the exact
UserService authority for execution. `/api/v1/user-services` is only a routing projection; it
cannot prove discovery, readiness, or execution authority. The examples below are illustrative,
not a fixed list.

### Reading a catalog entry (this is the "what's the prerequisite" answer)
- `requires_credential: true` → the user must connect it before any call works.
- `credential_mode: user` + `auth_method: bearer`/`provider_type: oauth2` → **the end user
  self-connects via an OAuth flow** in the NyxID console (their own account). Low friction.
  *(e.g. `api-twitter`, `api-slack`, `api-github`, `api-google`, `api-lark`, `api-reddit`,
  `api-tiktok`, `api-facebook`, `api-microsoft`.)*
- `credential_mode: admin` (`auth_method: api_key`/`bot_bearer`/`token_exchange`/`path`) → a
  **token/secret must be supplied** (often a bot token or an org/admin key), per the entry's
  `api_key_instructions` + `api_key_url`. *(e.g. `api-telegram-bot` — a @BotFather token;
  `api-discord-bot` — a Bot Token; `api-lark-bot`/`api-feishu-bot` — token_exchange; the
  `llm-*` provider keys.)*
- The entry's `api_key_instructions`, `api_key_url`, and `documentation_url` are exactly what
  you relay to the user as "here's how to connect it."

## The feasibility procedure

1. **Restate the goal as a capability, not a product.** "A bot that tweets a daily summary"
   = *(a)* generate text (pure LLM — always available) + *(b)* **post to X** (outbound
   connector `api-twitter`) + *(c)* run **daily** (schedule). Decompose into capability
   classes before judging.
2. **Classify each piece** against the matrix below and collect its prerequisite.
   In-session connect/add/authorize requests must resolve the catalog slug, then pass it to
   `nyxid_require_service`; do not substitute prose or `/api/v1/user-services` for typed readiness.
3. **Find the gating piece** — the answer to the whole request is the *weakest* piece (a
   single host-gated or impossible piece caps the whole thing).
4. **Report honestly** with the template at the end: possible + prereqs, or host-action-needed,
   or not-feasible + alternative.

## Prerequisite matrix (capability class → can we? → prerequisite)

| The user wants… | Possible? | Prerequisite / who must do it |
|---|---|---|
| Pure LLM / text / transform / branching pipeline | ✅ Always | Author a workflow (`aevatar-workflow-authoring`). No external anything. |
| Bounded one-shot Codex work that can start from empty Git | ✅ With the managed target | Choose `managed_sandbox`; require internal eligibility, the user's own usable `chrono-sandbox` and `chrono-llm-public` UserServices, `workspace.kind=empty_git`, timeout ≤ 180 seconds, and the public `CODEX_EXEC_READY` proof. |
| Codex work requiring an existing private repository or host Codex configuration | ✅ With the private target | Choose `private_ssh`; require the user's hardened NyxID SSH service, fixed principal/workspace and working host Codex setup, no request `workspace`, timeout ≤ 300 seconds, and the private public-sample proof. |
| **Call** a third-party API (read/post): GitHub, Slack, Google, X/Twitter, Reddit, a custom HTTP API… | ✅ If the connector and an exact operation/request contract are discoverable | User **connects the `api-*` connector in NyxID** (OAuth for `user` mode, or supplies a token for `admin` mode — per the catalog entry). A compiled published call additionally needs an exact `user_service_id + endpoint_id` from the supported operation list/picker; `/api/v1/keys` alone is not that picker. If the caller surface cannot discover one, report a tooling blocker instead of guessing. |
| A connector that is **NOT in the catalog** | ⚠️ Only if it's a plain HTTP API | If it speaks HTTP + a supported `auth_method`, NyxID can add it (platform/admin work — not self-serve). If not HTTP, ❌. |
| **Inbound bot** that replies in-platform: **Lark / Telegram** | ✅ Yes | Connect the bot connector (`api-lark-bot` / `api-telegram-bot`) **and** register the channel (channel-admin / `channel_registrations`); NyxID provisions the webhook to Aevatar's relay. |
| **Inbound bot** on a platform with a connector but **no channel module** (Discord, Slack, X, …) | ❌ Not self-serve | Outbound calls work, but inbound-reply needs a new Aevatar **channel module** + relay wiring = Aevatar platform work. Offer the outbound-only version as the alternative. |
| **Publish** a workflow/team as an **invocable service** in-scope | ✅ Yes | Just bind it (`aevatar-service-publisher`). Usable within the user's scope immediately. |
| An external automation **triggers an existing Aevatar workflow** (e.g. Lark Base row status changed → HTTP request → run member workflow) | ✅ Usually, without service externalExposure | Use a dedicated NyxID API key on the explicit member/team invoke path, or a NyxID trigger feeding the signed webhook ingress (bindings are self-serve scope resources on current hosts; host-managed appsettings on older ones). Decide whether fields are trusted push input or unverified claims before authoring a Base read. This is an external trigger, not a NyxID connector registration. See `aevatar-service-publisher`. |
| Have that service **registered as a NyxID-brokered connector** (callable by others/externally) | ⚠️ Host-gated | The **host** must enable external exposure (`GAgentService:ExternalExposure: Enabled=true` + `RegisterAllPublishedServices` or an opt-in policy). You **cannot** turn this on as a client — verify `externalExposure` on the service and, if empty, tell the user to ask the host. |
| Give an agent a **fixed persona + pinned Ornn skills + an enforced tool ceiling** (an Agent Profile) | ⚠️ Modelled, owner-managed, deployment-dependent | Probe `GET /api/openapi.json` for the complete `agent-profiles` route family. Absent means unavailable in this deployment; present means the owner can manage it through `aevatar-agent-profile-management`. |
| Have a published Profile actually **drive a running agent** | ⚠️ Host-gated, and narrow | Publication is not runtime binding. Only *newly created* NyxID direct conversations admitted by a **host-owned rollout** consume a Profile; existing conversations never hot-upgrade, and workflows/teams/services/schedules/channels/AgentRuns are not consumers at all. |
| Schedule an already-bound **Studio Team member** workflow | ✅ For admitted definitions; authored writes may be host-gated | Use `aevatar_schedule_member_workflow` or the member automation route. It can admit an existing interactive member to an exact durable revision and provisions a dedicated restricted Agent Key. Raw REST preflight is read-only. A host without scheduled-operation authority rejects any authored write call site even when a sample prompt chooses preview; do not route it through generic `/api/schedules` to bypass this. |
| Create an independent recurring **Ornn skill agent** | ✅ Yes | Use `scheduled_agent_creator`, then `agent_builder`. It has its own dedicated Agent Key and is not a Team member automation alias. |
| Schedule a generic typed **service invocation** | ⚠️ Yes, with its declared credential source | Use generic `/api/schedules`. A `scopeOwnerNyxId` or `senderNyxId` source needs the corresponding durable NyxID broker binding; this requirement does not apply to the two dedicated-Agent-Key resources above. |
| A service backed by an **arbitrary custom agent / actor type** | ⚠️ Constrained | Member implementations are `workflow`, `script`, or **registered** `gagent` kinds (`GET /api/scopes/gagent-types`). You can't point a service at an arbitrary actor; wrap custom logic in a workflow or script, or use a registered gagent kind. |
| A genuinely **new service *shape*** (e.g. streaming/WebSocket/gRPC endpoint, a runtime kind beyond workflow/script/gagent) | ❌ Not currently | Service endpoints are unary **HTTP** over the fixed implementation kinds. A new shape needs Aevatar platform work. |
| **Exactly-once** external side effects (e.g. "charge exactly once") | ❌ Not guaranteed | The workflow saga is **at-least-once** with idempotency keys. Require an idempotent connector endpoint, or do the exactly-once elsewhere. |

## Hard engine/platform limits (make some asks impossible or need a workaround)

State these plainly when they bite:
- **No ambient workflow clock.** "When it's 9am" and recurrence are owned by a **schedule**, not a
  loop inside the workflow. A schedule can deterministically inject logical-fire fields with
  `{{@schedule.run_date}}`, year/month/month-end variables and an explicit IANA timezone; a webhook
  binding can inject `{{@run_date}}` from received time and its configured timezone. Ordinary runs
  still require caller-supplied dates. Never ask the model to guess the time.
- **No unbounded background loops / polling / fan-out-forever.** A run is a finite stepped
  pipeline with **one terminal step**; long waits use durable `delay`/`wait_signal` events, not
  busy loops. "Watch a feed continuously and react" → model as a *scheduled* run that polls.
- **Step/tool execution timeouts** — long synchronous external calls fail; design around it
  (chunk, or use `wait_signal`/human-in-the-loop for long external waits).
- **`nyxid_proxy` file artifacts cap at 100 MiB.** Bigger downloads aren't feasible that way.
- **Async settling.** Bindings/deployments/runs are eventually consistent — never promise a
  result from a 2xx alone.
- **A Lark Base read has two permission layers.** `bitable:app:readonly` is an application API scope;
  it does not grant the Bot access to a specific Base document. Lark error `91403` means the
  Base document ACL denied that application. In the current Base UI, open the Base's `...`/More
  menu, choose **Add Applications** (the document-application entry), and add the exact Bot
  application used by the selected NyxID UserService. With advanced permissions, the application
  also needs a role covering the target table; `1254302 RolePermNotAllow` means that role coverage
  is insufficient. When the workflow reads Base, require an authorized read-only probe of a known sample
  `record_id` using the same UserService/Base/table. A 2xx without expected fields is not a pass.
  A source-verified Base automation may instead push the required fields through a dedicated
  credential or signed adapter; if the workflow makes no Base API call, do not demand Bot read
  permission or add a zero-value read-back step.
  Do not ask the user to change API scopes when that scope is already enabled, and do not confuse a
  Base with a spreadsheet file.
- **No string replacement primitive.** Workflow expressions and transforms have no `replace` or
  `regex_replace`. Unknown transform names currently fall back to identity while the step can stay
  green. A goal that requires deterministic string replacement needs an explicitly admitted bounded
  `code_execute` workaround or platform work; never promise `transform op: replace` or use an LLM
  for deterministic identifiers, money, or counts.

## How to satisfy each prerequisite (what you tell the user to do)

- **Connect a connector** → "In the NyxID console, connect **`<slug>`**. <`credential_mode:user`:
  it's a one-click OAuth to your own account.> <`admin`: you'll paste a token — `<api_key_instructions>`;
  get it at `<api_key_url>`.>" In-session, finish through `nyxid_require_service`; for REST/CLI
  verification, confirm the exact UserService and readiness through `/api/v1/keys`, not merely the
  `/api/v1/user-services` projection.
- **Select a workflow operation** → in-session, copy the exact `user_service_id + endpoint_id` from
  `list_external_workflow_capabilities` and inspect readiness. The tool is not a REST endpoint, and
  `/api/v1/keys` is not an operation picker. If the client has no supported picker/list, stop with a
  discovery blocker. `nyxid_request` is a separately admitted exact HTTP contract, not a second
  selector to combine with `nyxid_operation` on one step.
- **Register an inbound channel** (Lark/Telegram) → connect the bot connector, then register the
  channel via the channel-admin tool so NyxID wires the webhook to Aevatar's relay.
- **External HTTP trigger** (Lark Base / webhook sender / external cron) → do **not** ask for
  Aevatar `externalExposure` first. If the external system can call a public HTTPS URL with
  headers and JSON, call NyxID's proxy route for the already-connected `aevatar` service using
  a NyxID API key with `proxy` scope, and include the real scope/member/team id in the Aevatar
  path. Dedicate that key to one automation before trusting pushed fields. If the sender can set a
  bearer token but cannot sign, prefer a NyxID trigger with webhook delivery into the Aevatar
  ingress (register the scope-owned binding self-serve on current hosts); NyxID verifies inbound,
  signs outbound, and provides durable delivery history.
  If neither authority boundary exists, accept only a locator and read the provider. If the sender
  cannot tolerate SSE or cannot shape the typed payload, add the signed adapter path rather than
  weakening verification.
  A self-serve Aevatar webhook binding must pin an exact same-scope committed Definition actor and
  revision, require a signed-body delivery ID and a 32-byte-or-longer HMAC secret, and set
  `timeZoneId` explicitly when UTC is not correct. HMAC allows a run start; unattended effects need
  the separate direct-human durable opt-in and still remain subject to NyxID/provider policy.
- **NyxID service registration** → ask the **host** to enable external exposure for the service;
  you can only drive publish + verify the `externalExposure` block.
- **Scheduling** → choose the resource first. An already-bound Team member uses its owner-scoped
  automation route; an independent Ornn skill agent uses `scheduled_agent_creator`; only a generic
  `/api/schedules` request using a NyxID owner/sender binding needs the corresponding interactive
  broker authorization.
- **Missing connector / new shape / new channel** → this is NyxID/Aevatar **platform work**;
  it's a request to the platform team, not something you or the user can self-serve. Say so and
  offer the closest feasible alternative.

## Negotiation / report template

Give the user a straight answer in this shape — never a vague "maybe":

- ✅ **Yes** — "<goal> is possible. One thing to do first: connect **`api-github`** in NyxID
  (OAuth, your account). After that I can build it as a workflow + schedule it."
- ⚠️ **Yes, but it needs an action you can't self-serve** — "The pipeline is fine, but exposing
  it as a NyxID connector for *others* to call requires the **host** to enable external exposure.
  In your own scope it works today without that."
- ✅ **Yes, no externalExposure needed for this shape** — "Lark Base can trigger your existing
  member workflow by sending an HTTPS request to NyxID's `aevatar` proxy with a NyxID API key,
  targeting `/api/scopes/{scopeId}/members/{memberId}/invoke/chat:stream`. ExternalExposure is
  only needed if you want this workflow registered as a reusable NyxID connector/slug."
- ⚠️ **Yes in the product, but not in this deployment** — "Aevatar models exactly that: an Agent
  Profile with a purpose, instructions, an always-on skill, a billing-triggered skill, and a hard
  tool ceiling — and it would be **yours** to manage, not the host's. But this deployment
  advertises no `agent-profiles` routes, so I can't create one today. What I *can* build now is
  the same behavior expressed in a workflow member with on-demand skill discovery; the pinned-skill
  and enforced-ceiling guarantees need a build that exposes the contract."
- ❌ **Not as described** — "An auto-replying **Twitter bot** isn't possible: there's no inbound
  Twitter channel on Aevatar (only Lark and Telegram). What *is* possible: a workflow that
  **posts** to X on a schedule (via the `api-twitter` connector), or an inbound bot on **Telegram**
  instead. Want either of those?"

Always: name the exact connector/prereq, say who must do it, and offer the nearest feasible
alternative when you say no.

## Honesty rules

- **Check the live catalog and `/api/v1/keys` inventory** before claiming a connector exists or not. Examples in
  this doc are illustrative and can drift.
- **Connector ≠ channel.** Outbound API access never implies an inbound bot.
- **Never promise host-gated outcomes** (NyxID registration, Agent Profile rollout admission,
  anything needing host config) or features that need platform work — surface them as
  dependencies, not done deals.
- **Distinguish not-connected / host-gated / not-deployed.** Each has a different owner and a
  different fix. Probe the live OpenAPI before calling a capability available or unavailable —
  source on a feature branch proves the code exists, never that production exposes it.
- **Don't quietly substitute a different resource.** If the user asked for an Agent Profile and the
  contract isn't deployed, say that and offer the nearest alternative explicitly — never build a
  workflow member and present it as the profile they asked for.
- If you genuinely can't determine feasibility from the catalog + this matrix, say what you'd
  need to confirm rather than guessing.

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.