Skip to content
Back to skills

Implement

ASecurity

Coordinate one backend ticket through the approved architect, developer, review, QA, and publish handoffs.

  • 3 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 19, 2026
testingpythongoshellbashcode-reviewgitbackenddocumentation

Works with

  • claude code
  • terminal
  • cli

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned October 19, 2026

npx -y skills add PVMalove/claude-agent-harness --skill implement --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Implement?

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

Security grade badge for Implement
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/pvmalove-implement/badge)](https://www.skillsdirectory.com/skills/pvmalove-implement)

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: implement
description: "Coordinate one backend ticket through the approved architect, developer, review, QA, and publish handoffs."
disable-model-invocation: true
---

# Implement

**Objective:** Coordinate exactly one ticket through `architect → developer → code-review → qa → publish`, then offer `/to-pull-requests`. This session **is** the coordinator: it creates and observes dispatches but never implements the ticket itself.

Language contract: agents communicate with each other and write free-text protocol/state evidence in
English. Every completion report addressed to this coordinator is in Russian and includes
`"report_language": "ru"`; preserve commands, paths, IDs, and quoted evidence verbatim.
Machine-read report values stay exact English enums: `outcome: completed | blocked | failed`,
check `result: pass | fail | not_run`, and `blockers.status` / `risks.status: none | present`.
Each blockers/risks field is a status/details object; translate only its description.
This binds the text this session writes, not only the text it reads: translate the ticket into
English before it reaches a batch or a worker prompt. `definition_of_done` and `prohibited_changes`
are rejected outright when they carry Cyrillic, and a worker prompt carrying the untranslated
ticket body is the same contract violation the coordinator cannot see.

## Route

This is the opt-in `backend-orchestration` route. Confirm that its installed coordinator is usable:

```bash
python .harness/orchestration/coordinator.py --repo . dispatch status
```

If the command is unavailable or cannot read its state, stop and tell the developer to run `/fast-implement` instead.
A `ledger_busy` answer is not unavailability: another coordinator operation holds the ledger lock,
so repeat the command after its `retry_after_seconds`.
Do not infer or repair an opt-in capability. Process one ticket to a terminal batch state before
beginning another.

If another batch holds the same unfinished ticket, branch or worktree, or the `concurrency_budget`
is exhausted, inspect `batch list --open`, the conflicting dispatch,
and its decision packet. Tell the developer which batch is blocking and how to finish it normally.
If its worker can no longer produce a report, first run `batch auto-report`,
`batch decision-packet`, `dispatch status` and `ledger validate`, and quote the dispatch's
`startup` assessment: worker state, classification and unknowns. Explain which of waiting, launch
repair, human-approved `batch resume-stop`, `batch rewind` and cancelling an unsent dispatch
applies, and why the others do not. Offer `batch abandon` only after that, as a separate explicit
human choice for the whole batch: show a copyable command with the actual batch ID, the verified
operator name, `--approved-at "$(date -u +%Y-%m-%dT%H:%M:%SZ)"`, and a reason grounded in the
observed failure. Never supply `--approved-by` as though they already approved, or execute the
command for them without that approval. `ledger clean` only removes orphaned evidence, and
`ledger reset` does not clear an active batch.

## Batch preparation

The coordinator must take every procedure from agent sources only: this skill, `.harness/orchestration/playbook.md`,
`.harness/orchestration/roles/`, the guides in `docs/agents/`, and the `--help` and `remedy` output of
the coordinator CLI. The coordinator must not take a procedure from a Russian human document
(`backend-orchestration.md`, `harness-guide.md`, `ARCHITECTURE.md`, `docs/skills/`, `docs/hooks/`).
The coordinator must not copy conventions from another batch and must not read ledger files in
`.harness/orchestration/state/`. The coordinator must read state only through CLI commands (`batch list`,
`batch decision-packet`, `dispatch status`). If these sources do not give a step, that gap is a
blocker: the coordinator must stop and report it to the developer, and must not reconstruct the step.

Start these steps only after the ticket pre-flight in "Coordinator contract" (blockers, `status::in-progress`).

1. **Integration ref.** Use the ticket's `## Integration Branch` value. If the ticket has no such
   section, use its `## Git base` value. If it has neither, use the same section of the parent epic.
   A missing value for a ticket that has a parent epic is a blocker; do not infer it from the
   checkout or from memory. A ticket without a parent epic uses `base_branch`: omit `--integration-ref`.
2. **Issue worktree.** Create it before `batch create`. `batch create` refuses a worktree that
   `git worktree list` does not show. Use the exact commands, and the recovery after a half-done
   `git worktree add -b`, in `docs/agents/worktrees.md` → Coordinator issue worktree. Stay in the main checkout.
3. **Batch scope.** Run `batch preflight` with the same scope flags as `batch create`. Translate the
   ticket into English first: `batch create` rejects Cyrillic in `--goal`, `--definition-of-done`
   and `--prohibited-change`. Keep commands, paths, and IDs verbatim.
4. **Create the batch.** Repeat the list flags once for each value.

   ```bash
   python .harness/orchestration/coordinator.py --repo . batch create \
     --ticket "#<ID>" --branch "feature/issue-<ID>-<slug>" --worktree "<absolute worktree path>" \
     --integration-ref "<integration-branch>" --goal "<English goal>" \
     --definition-of-done "<English item>" --prohibited-change "<English item>" \
     --allowed-path "<path or glob>" --expected-file "<path>" --expected-service "<service>" \
     --expected-changed-lines <N> --required-gate review --required-gate qa
   ```

   `--ticket`, `--branch`, `--worktree`, `--definition-of-done`, `--prohibited-change` and at least
   one `--allowed-path` are mandatory. `--branch` must match `branch_pattern`. `--expected-file`,
   `--expected-service` and `--expected-changed-lines` are mandatory when the project policy
   requires estimates. The CLI refuses an oversized ticket and prints a `remedy`.
5. **Approve the batch.** `batch approve --batch <id> --approved-by <operator> --approved-at <UTC time>`
   moves the batch from `planned` to `awaiting-approval`. This needs the operator's explicit
   approval: present the command, as for `batch abandon`, and do not run it for them.

**Commit plan file.** Pin the architect's plan with `batch decide --batch <id> --decision accept --approved-by <operator> --approved-at <UTC time> --commit-plan-file <path>`. The operator approves this decision; never supply `--approved-by` for them.
The file is a JSON object with the single key `commit_plan`, a non-empty list in commit order:

```json
{"commit_plan": [{"id": "tests", "summary": "Add failing tests", "expected_paths": ["tests/**"], "covers": [1]}]}
```

Each entry has exactly these fields: `id` (unique; up to 64 characters of letters, digits, `.`, `_`, `-`; the first character is a letter or digit),
`summary` (non-empty), `expected_paths` (non-empty list of relative paths or globs, with no leading `/`
and no `..`), and `covers` (non-empty list of 1-based `--definition-of-done` item numbers, without
repeats). Every definition-of-done item must appear in at least one entry. The CLI rejects a
broken file and prints the expected format.

## Coordinator contract

Resolve the tracker ticket, issue branch and blockers without opening a second batch for the same
work. Ticket status is part of that pre-flight, before `batch create` and before the issue branch
exists: check the ticket's blockers whatever its current label (any still open → stop, name them,
and make sure it carries `status::blocked`); otherwise replace its `status::*` label with
`status::in-progress` exactly as `/fast-implement` Phase 1 steps 2–3 do, and confirm it is the
only `status::*` label. A failed label write is a blocker, not a warning. Before `batch create`, run the batch-level preflight with bounded expected files, services and
diff size. Pin the writer's explicit scope with `--allowed-path` (repeat it; a path or glob inside
the developer's write ceiling): batches with overlapping files run in parallel in their own
worktrees, and a change outside the scope is rejected. If it rejects the ticket, split it with `/to-tickets`; never ask an architect to discover
whether an oversized ticket should have been split. When creating the batch with `batch create`,
specify `--required-gate review --required-gate qa`: the full implement pipeline explicitly sets
both independent Standards/Spec review and serialized clean-room QA gates. Before dispatching the
write-role (`developer`) worker, verify that these mandatory gates are recorded in the batch's
`required_gates`; halt early if missing rather than sending a worker into a risk-gate omission.

For each handoff, choose the worker checkout and pass its absolute path as `--worktree` to
`dispatch preflight`. Show `batch decision-packet`, then create an approved immutable brief. Pass
the same explicit `--worktree` to `dispatch send`; code-review also keeps `--checkout`. Preflight
and send verify the selected path, branch and startup SHA. Start the worker in exactly
`send.worker_worktree` using a runtime-supported mechanism for that existing directory. Verify that
mechanism before launch: `isolation: worktree` alone does not prove attachment to an existing
worktree. If the runtime cannot select that checkout, report a blocker. The coordinator stays in the
main checkout. A selected path is intent; self-report proves the worker's actual CWD. Pass the
brief's `report_staging_path` to the worker verbatim; a role that has to guess where its report
belongs writes it outside the project.

**Claude Code runtime.** The Agent tool cannot select an existing checkout: a subagent starts in the
main checkout, and `EnterWorktree` refuses it there. Two paths exist; state which one the batch uses.
- `external` (strict): set the worker roles' `transport` to `external` in `.harness/orchestration.json`
  and send with `--adapter <main-repo>/.harness/adapters/claude_worker.py` (absolute path).
  `dispatch send` runs the adapter in `send.worker_worktree`, and it starts a detached headless
  `claude -p` there on the brief's model, effort and `allowed_tools`, so the worker's CWD is the
  issue worktree. The adapter builds the prompt; for a retry, put the retry lines in a file inside the
  repository and pass `--adapter-arg=--extra-prompt-file=<path>`. A permission layer may refuse
  launching an agent from the coordinator session; that refusal is a stop, so show the developer the
  exact `dispatch send` command to run in their own terminal, then continue with `dispatch wait`.
- `in-process` (weaker evidence): the subagent's CWD is the main checkout, so the template's CWD check
  would stop it. Replace that check in its prompt: probe `git -C <worker_worktree>` for the top-level,
  branch and HEAD, run every command with `git -C` or `cd <worker_worktree> &&`, and use absolute
  paths for every file. Its self-report then proves the checkout it works in, not its CWD; say so in
  the final report.

`dispatch send` checks the adapter's flags against its `dispatch --help` before the handoff and
refuses an unsupported one: fix the `--adapter-arg` values and send the same approved dispatch
again. Show any `limitation` in the send result's `adapter_preflight`. To diagnose an app-server
runtime without a worker, run `dispatch runtime-probe`; its result is evidence, and the worker's
model self-report stays mandatory.

The coordinator never writes feature code or repairs state by hand. A report is evidence, not
permission to advance. Architect precedes developer; accepted candidate proceeds through the
required review/QA/publish gates. A write-role worker stopped early before making changes returns a
truthful `outcome: blocked` report bound to the verified checkout commit with empty `changed_files`
and unrun checks; the coordinator decision packet returns an explicit recovery route (`retry`,
`block`, or a human-selected `abandon`) without registering a candidate or weakening `completed`
report validation.

Before every write-role dispatch, the immutable brief carries an ordered commit plan. Each entry
names one independently reviewable logical change, its expected files and the DoD items it covers;
use one entry only when the entire approved change is inseparable. The coordinator derives one entry
per DoD item; to use the architect's plan instead, pin it on the architect accept with
`batch decide --decision accept --commit-plan-file <path>`. A recovery preserves the accepted plan,
or replaces it with a newly approved plan that explains the changed boundary. The developer's
completion report maps every created commit to the entries it closes; a mapping that is not
one-to-one needs `dod_coverage` and `divergence_justification`, and a report with a `not_covered`
item can be accepted only by `override-warning` with a note other than `none`, or returned with
`retry`. A report whose `changed_files` lie outside the brief's `write_paths` is recorded with a
`scope_warnings` entry and is accepted only the same way. Do not collapse unrelated implementation, tests, documentation, or type-only repairs into a
recovery commit merely because they are staged together.

Follow the configured approval policy. Under `manual_all`, every transition needs explicit approval:
show the decision packet, ask, and wait. Under `low_risk`, a clean completed report of a batch whose
allowed paths lie inside `low_risk_paths` is accepted by the coordinator with an audited policy decision, and the next eligible dispatch
may already be approved. Under `milestone`, clean reports outside QA, publish and risk milestones
are also accepted automatically; stop for the remaining milestone decisions. Continue from the
recorded `next_action` without asking the operator to repeat a policy decision. Blockers, failed
checks, risk triggers, review findings and publish still require the applicable manual decision.
Never write `--approved-by` on the operator's behalf or
narrate a decision they did not make. `human_approval_gate: tty` requires confirmation on the
operator's terminal for transitions that still require human approval. When choosing a recovery
route for `retry` or `abandon`, show the decision packet's `route_preview` (with the
`--reason-category` or `--retry-role` you intend to pass to `batch decide`) and follow the
Recovery route table in `.harness/orchestration/playbook.md` (situation → route → who approves →
evidence). Report each startup failure under its own classification (unsupported flag, missing
or refused self-report, capacity, rate-limit, service-unavailable) together with its recovery
route.

Under `approval_policy: auto`, the coordinator takes every path decision by policy and records it
as `policy:auto`; follow "Automatic path" in `.harness/orchestration/playbook.md`. Do not write
`--approved-by` or `--approved-at`: run `batch approve`, `dispatch create` and a planned
`dispatch resume --trigger` without them. For every pending report that the `report submit` or
`qa run` chain did not accept, including the publish report, run
`batch auto-decide --batch <id>`. Pass `--commit-plan-file` with the architect's plan copied
exactly, `--findings-file` for coordinator findings on a developer report, `--bug-ticket` after
you file or reuse the tool's bug ticket through the tracker CLI, and `--block-bypass --note` when a
role worked around a block. Pass nothing else, and never choose the decision yourself. After a refused command, run `batch auto-report --batch <id>` to observe evidence. This read-only
command does not record a stop. If it shows `observed_stop`, run `batch auto-decide --batch <id>`
to record the pause, even without a pending report, then show `batch auto-report` again.
The automatic path ends permanently at that pause. Inspect `batch decision-packet`, `dispatch status`
and `ledger validate` before you propose waiting, launch repair, human-approved `batch resume-stop`,
or `batch rewind --to <gate>` to repeat an earlier gate. An exhausted infrastructure budget keeps
the batch paused for that human choice.
Use the playbook's "Operator recovery" procedure. The original stop stays historical; all later
approvals, including recognized 429 continuations, follow `manual_all`. Honor an approval already
explicitly given in this session for the concrete operation; never invent one.

When a stage's report is `blocked` only by an infrastructure failure although its work looks
complete (a developer's commits match the plan, for example), a human may decide
`batch decide --decision accept-conditional --infrastructure-failure --note <cause>`. The pipeline
advances as after `accept`, but the stage stays an open condition that a later code-review or qa
accept must independently close; publish refuses while one is open. Never choose it yourself, and
prefer `resume-stop` when the stage can simply be restarted.

A worker that works around a hook or tool block (another command form, tool, script file, `eval`,
interpreter or a split command) breaks the protocol: never accept or warning-override that report,
and record the violation in `--note`. For an architect or developer (publish included), decide
`retry` with a developer reason category (not `tooling`) or `block`. For a read-only code-review, qa
or verification role, pass `--reason-category block-bypass` to `batch decision-packet` and, once its
`route_preview.retry.route` is `bypass-rerun`, to `batch decide --decision retry`: the same stage
re-runs on the same SHA with no new candidate and no developer retry spent, and its new dispatch
needs explicit approval under every `approval_policy` except `auto`. A report that stops with
`tooling_blocker` instead is confirmed
before its retry: check that its `command` is legitimate under the brief (allowed paths and tool policy) and
that its `message` refuses that command. For a false positive, file or reuse a bug ticket against
the tool through the tracker CLI (tool, command, message, dispatch ID), name the ticket in `--note`,
and run `batch decide --decision retry` once `route_preview.retry.route` is `tooling-retry`; it
re-runs the same stage on the same SHA (a developer continues its last commit) and spends no
`retry_policy.max_developer_retries`. A command that is not legitimate is no false positive: retry
with the developer reason category its evidence supports. Resolve the `tooling-retry-repeated`
attention, raised by the third consecutive tooling retry on one candidate, only once the tool is
fixed.

When you find a defect in a clean developer report whose DoD is met inside its allowed paths, do not retry
it: accept it with `batch decide --findings-file <path>`, or after a policy auto-accept run
`batch carry-over --batch <id> --findings-file <path>` before its code-review dispatch exists. The
finding travels into the code-review brief as a carried item (route `carry-over`), and the one
developer retry is spent after review. Retry a developer report without accept only for an unmet
DoD item or an out-of-scope change.

Each worker records a model self-report and is observed by the event-driven watchdog; those facts
are evidence, never a reason to edit an immutable brief.

Use the brief's shared Context Package ID across architect, developer and resumed worker sessions
when the pinned base/candidate is unchanged. Read only its starting files and directly referenced
symbols before escalating. A changed candidate creates one new shared package for its review, not a
role-specific duplicate. Continuations and retries stop at the project budget; a 429 is not an
exception to that budget.

Run `dispatch wait` between send and report. `stale`, model/worktree mismatch, changed harness
snapshot, and a failed deterministic gate are blockers for the coordinator, not prompts for broad
LLM recovery. Silence or a timeout does not prove that a worker stopped. `batch resume-stop`
refuses a worker whose `startup` state is `live` or `unknown`: stop it through its runtime and
repeat the command with `--runtime-stopped`. In-process and external transports preserve the same
brief and evidence contract.

A busy ledger (`ledger is locked by another operation`, or `ledger_busy` from `dispatch status`) is
transient: repeat `dispatch wait` or `dispatch status`. When a relayed `report submit` result
carries `completion`, the report is already recorded: never ask the worker to submit it again. Run
its `command` (`report complete --dispatch <dispatch-id>`) yourself and repeat it until no step
fails; it is idempotent. When the failed step needs a human, follow its remedy instead. Never remove
the ledger lock or any state file by hand; a lock that stays held goes to
`coordinator.py --repo . ledger release-lock`, which refuses a lock whose owner process is alive.
`ledger lock-status` shows the holder and the time left until a timeout release without taking the
lock. For the lock of a stopped sandboxed worker, show the operator a copyable
`ledger release-lock --force --approved-by <operator> --approved-at <time> --reason <why>`; it is
their action, never yours, under every `approval_policy`.

## Worker prompt

Every worker prompt is this template, filled from the `dispatch send` result and the CLI invocation
used to send it. The brief and Context Package carry the task; the prompt also carries the mandatory
lifecycle. Fill `<coordinator CLI>` with the Python executable, absolute `coordinator.py` path and
absolute `--repo` (plus `--state-dir` when supplied) used for that dispatch. Quote paths for the
worker's shell. Keep this same ledger address even when the worker runs in another worktree.
Copy the heartbeat interval from `dispatch send.heartbeat.every_seconds` verbatim.

```text
You are the <role> worker for dispatch <dispatch_id>.
Brief: <brief path from dispatch send>
Report staging path: <report_staging_path from dispatch send, verbatim>
Coordinator CLI: <coordinator CLI>
Expected worker checkout: <worker_worktree from dispatch send, canonical absolute path>
Expected startup SHA: <worker_snapshot_commit from dispatch send>
Before task work, run git rev-parse --show-toplevel, git branch --show-current and git rev-parse HEAD
in your runtime's current directory. Compare the top-level path and HEAD with the expected values
above, and the branch with the brief. Stop on any mismatch; do not reset Git history or claim
another checkout as your actual directory. Confirm your active model and the probed Git top-level:
<coordinator CLI> dispatch self-report --dispatch <dispatch_id> --model "<actual active model>" --worktree "<probed Git top-level>"
Proceed only after a successful self-report; escalate a mismatch or unavailable model identity.
Immediately after self-report and at least every <heartbeat.every_seconds> seconds while working, run:
<coordinator CLI> dispatch heartbeat --dispatch <dispatch_id>
Context Package <context_package_id>: start from its starting_files, symbol_graph and
related_tests. For a starting file with non-empty sections, read only the start_line–end_line
ranges the task needs.
Work within the brief; escalate a blocker for anything the brief and the package leave out.
Before your final reply, write the completion report JSON to the exact report staging path using
the common and role-specific report contract, with report_language: ru.
Use exact English enums: outcome = completed | blocked | failed; checks_run[].result = pass | fail | not_run.
Set blockers and risks (also in every review axis) to {"status": "none", "details": ""} when absent,
or {"status": "present", "details": "<Russian description>"} when present. A none status requires empty
details; present requires a non-empty description. Put other explanations in output. Strings, translated
statuses, passed and not-run are invalid; no aliases or old report formats are accepted.
Then run:
<coordinator CLI> report submit --file "<report_staging_path>"
Completion means the report is recorded in the ledger. Include the submit result in your final reply.
If submission fails before recording, return the command and error as a blocker; keep the report file.
If the result includes completion, relay it to the coordinator for report complete; the report is
already recorded, so submit it only once. Chat text alone does not complete the dispatch.
```

An architect retry adds one line. `batch decide --note` does not reach the brief, and `retry_start` exists only for a developer retry. Pass the reason of the retry in `--note`, in English, and add this line after the template lines:

```text
Retry reason: <the exact --note text of the retry decision>; previous architect dispatch: <previous dispatch id>
```

The new architect uses the line as evidence of what the previous report lacked. The line does not widen the brief's scope.

A developer retry adds two lines from the `retry_start` of its `dispatch preflight`:

```text
Retry handoff: <retry_start.handoff, verbatim JSON>
Retry starting files: <paths from retry_start.starting_files>
```

Use this lifecycle for every new or resumed worker session, including developer-retry. A continuation
that stops at a checkpoint follows the checkpoint protocol instead of submitting a completion report.
The coordinator treats a final reply without recorded completion or a valid checkpoint as an
unfinished handoff and requests the missing protocol from the same available worker session.

Large documents (the role catalog, `playbook.md`, `git-workflow.md`) and
prior reports reach a worker only as Context Package section ranges or through the retry handoff.
The work a prompt asks for is exactly its brief plus, for a retry, the handoff's blocking findings (developer) or the retry reason line (architect).

A developer retry is always a new session started from its compact handoff, never a continuation of
the previous developer session's history. The preflight's decision packet carries the retry's
`retry_context_estimate` and `retry_context_warning` as evidence; they never gate the dispatch. Code-review and QA stay new
independent sessions; only their prompt follows this template. The playbook's "Developer-retry
handoff" defines the handoff, the smart-zone threshold and the compact.

## Authoritative guidance

This is a short coordinator contract, not a second orchestration manual. Full rules are module-owned guidance:

- `.harness/orchestration/playbook.md` owns lifecycle, authority, immutable brief, completion
  evidence, parallelism, and metric rules.
- `.harness/orchestration/roles/` owns each role's boundary, required proof, and specialist trigger.
- The `--help` output and the `remedy` of the coordinator CLI own command syntax and operational recovery.
- `docs/agents/git-workflow.md` owns issue-branch, commit, push, and PR boundaries.
- `docs/agents/worktrees.md` owns issue worktree creation and its recovery.

Follow those files rather than duplicating or weakening their rules here. In particular, do not
invent token metrics: use only provider- or runtime-observed telemetry and preserve missing-data
notes.

## Wrap-up

After an accepted publish, record the integration link before the branch is merged or deleted:
`python .harness/orchestration/coordinator.py --repo . integration prepare --ticket "#<ID>" --branch "<issue-branch>"`
(add `--batch <batch-id>` when several batches published the branch). It writes only an immutable
integration record and is safe to repeat; if it refuses, report its remedy to the developer and do
not work around it. Never edit the completed batch or its reports by hand.

Under `approval_policy: auto`, first show the final report of `batch auto-report --batch <id>`
(decisions, accepted risks, findings, retries, budget, DoD coverage, review and QA results).
Then offer `/to-pull-requests <ticket>`. Do not invoke it automatically, open
or merge a PR, write to an integration branch, or close the ticket in this skill. A pull request
needs the developer's explicit confirmation under every `approval_policy`; auto-merge is forbidden. Leave
`status::in-progress` on the ticket: closing it and moving its unblocked dependents to
`status::ready` belong to `/to-pull-requests` after the merge.

Files in this skill

  • SKILL.md27.5 KB
  • agents/openai.yaml139 B

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.