Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Every Swarm release, newest first. Each one starts with a short summary, then th

| Version | Date | Summary |
| --- | --- | --- |
| [0.18.1](#0181--2026-10-24) | Oct 24 | The news as a paper: datelines, tiers, pictures, a calendar |
| [0.18.0](#0180--2026-10-24) | Oct 24 | What each project runs, what of it is known-bad, what is happening around it · two new rules · `swarm security` |
| [0.17.0](#0170--2026-10-16) | Oct 16 | Codex gets the whole hook pipeline · cost by MCP, skill and subagent · CI resumes the run · signals |
| [0.16.0](#0160--2026-10-01) | Oct 1 | The guards ask by default · sandboxed runs · a reviewer on prompts · scheduled workflows |
Expand Down Expand Up @@ -31,6 +32,17 @@ Every Swarm release, newest first. Each one starts with a short summary, then th
| [0.2.2](#022--2026-08-21) | Aug 21 | The npm package |
| [0.0.6](#006--2026-08-21) | Aug 21 | The first signed macOS build |

## [0.18.1] — 2026-10-24

The News view reads like a paper now. The table it shipped with a few hours ago was a list of headlines; nobody reads news as a list.

### Changes

- **News as a paper.** A dateline for each day, stuck to the top of the pane while the day scrolls, and under it the day's articles set in tiers as a front page is: the first two as heroes across the width (one alone sets with its picture beside the text), the next three as features in a row, the rest as briefs in as many columns as fit. Each card is the link to the article and a click marks it read. **Paper / Table** in the heading switches back to the table.
- **Pictures.** An article's picture comes from its feed, or — since 13 of the 27 built-in sources give a picture to no article at all — from the article's own page: the daemon reads the head of the page once for its Open Graph picture, with the same user agent as a feed read, and never asks that page again. `[security] pictures = false` keeps the daemon to the feeds; the privacy guide says what the default fetches.
- **A calendar.** A month calendar beside the items shades the days by how many articles they hold; a day narrows the paper and the table to itself, and the chip over them lets it go.
- **A newspaper icon** for News in the Guard menu, which shared the RSS glyph with Team.

## [0.18.0] — 2026-10-24

The security release. There are a lot of security incidents in the package ecosystems right now, and Swarm could watch every agent on the machine without knowing what any project actually ran. Now it reads the lockfiles, can ask OSV about the exact versions (off until you turn it on — the query is your dependency list), follows the security news that concerns that stack, tells the agent, and can dispatch the upgrade. Nothing new leaves the machine by default except the public feed reads, and `SWARM_OFFLINE=1` silences all of it.
Expand Down
1 change: 1 addition & 0 deletions docs/06-roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@ Goal: Security stops being only a log of what agents reached for. Swarm reads ea
| M14.8 | **Advisories in the agent's context**: the `SessionStart` context (M1.3) and `swarm_context` list the project's open advisories with their fixed versions, so an agent avoids a vulnerable version before a rule has to ask, and can upgrade one unprompted | M14.4, M1.3 | ✅ 2026-10-24 `store.advisoryContextLine`: the project's open hits, worst first, one per package and version, at most six, each with its fixed version and advisory id, as one `[swarm] known advisories …` line in `sessionContext` — which both the `SessionStart` hook and `swarm_context` (`/v1/context`) render; null while advisories are off or the project is clean. `vulnerable_install` joins the rule modes the context names. Daemon test: the line appears after the fake OSV hit and is absent while the switch is off. The test also found that `/v1/context` was registered twice and Hono answered from the first (the M9.6 context-waste report), so `swarm_context` had always said *nothing to report*; one handler now serves both by the presence of `cwd` |
| M14.9 | **Dispatch a fix**: an **Upgrade** action on an advisory row creates a task (*bump X to ≥ fixed, run the gates*) and dispatches it through M7 into its own worktree, gated and PR'd — Dependabot behaviour, local, on any forge, through code that exists | M14.4, M7.5, M7.3 | ✅ 2026-10-24 `core/src/advisories.ts` `fixTaskId` (`sec/<package>-<fixed>`) + `fixPrompt` (what, why with the OSV link, which manifest, the package manager the lockfile belongs to, gates, a commit naming the advisory, a PR; nothing unrelated, no other vulnerable install); `POST /v1/advisories/fix` finds the open hit and starts the M3.1 runner on that task — which claims the worktree fail-closed and honours `[dispatch]` (profile, sandbox, `require_pr`) — or answers the task and prompt with `dry`; the report marks a hit `fixing` while a claim holds its task; **Upgrade** on the Advisories row (disabled while fixing, the failure shown beside the grid). Daemon test: dry answers the task and the prompt; missing fields 400, an unknown hit 404 |
| M14.10 | **`secret_commit` rule family**: `git add` / `git commit` naming a path on the secrets list, and a `git commit` whose staged diff (read with `git diff --cached` at `PreToolUse`) carries a known token prefix — `ask` by default, counted on Security like the other families | M12.5 | ✅ 2026-10-24 `guards.ts` `secretCommit` (a `git add` / `stage` / `commit` / `rm --cached` segment naming a file on the secrets list, quoted strings dropped so a commit message is not a leak) + `secretTokensIn` (added lines of a unified diff against ten vendor-prefixed shapes: private key blocks, AWS, GitHub, Anthropic, OpenAI, Slack, GitLab, Google, Stripe, npm — the shape is named, never the value); the diff comes lazily from `git diff --cached -U0` (`daemon/src/git.ts stagedDiff`) through `guardBash`'s `ctx.stagedDiff`, read only when the command commits and the family is on; family `secret_commit` (`ask`), counted on Activity from the text, named in the session context; without a reader (the offline shim, a non-repo) it fails open. Daemon test on a real temporary repository: `git add .env` asks, a commit whose staged file adds an AWS key asks naming the shape, a clean commit is allowed |
| M14.11 | **News as a paper**: a dateline per day stuck to the top, hero / feature / brief tiers, pictures from the feed or the article's own page (read once, head only; `[security] pictures`), a Paper / Table switch, a month calendar that narrows to a day, a newspaper icon in the nav | M14.2 | ✅ 2026-10-24 (v0.18.1) |

## Later (not scheduled)
Hosted (SaaS) team daemon wrapping the M8.3 binary · adapters for other agent CLIs · M14.8 GitHub Dependabot / code-scanning / secret-scanning alerts through `gh` (OQ-34) · Rust, Go and Ruby lockfiles for the stack. *(plan-gate-check — ✅ unreachable without a passing gate — is now M13.1.)*
Expand Down
2 changes: 1 addition & 1 deletion docs/08-interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ The first three are surfaces you *go to*. The fourth comes to you: it is the onl

- **Nav**: grouped sidebar nav from the view registry (M9.1) — Observe: Fleet / Timeline / Graphs · Work: Board / PRs / Trials / Hygiene · Insight: Outcomes / Gates / MCP / Context / Files / Spend / Stats / Search · Guard: Security / News / Provenance / Incidents / Signals / Rules / Team — plus a Session detail reached from any session row, and a ⌘K palette. Every list is a data-grid (sortable, resizable, filterable columns, layouts persisted per table).
- **Board** = a KPI strip (live / held / worktrees / ready or projects / incidents) + Tasks as a kanban (Ready · In progress · Blocked · Done) + Dispatch + Gates + Processes + Resources + Claims + a Worktree map (one tile per worktree, grouped by project, colored by live / dirty / unpushed / merged) + Incidents. Tasks and Worktrees carry a Cards/Table toggle (persisted). Every row, card and tile has one menu — the hover kebab, right-click, or Enter when focused — instead of inline action links; the menu carries the row's actions (open, diff, PR, run, claim, gates, release, stop, ack, codify, merge, copy …) with destructive ones last and confirmed. "View 4 — Incidents" ships as its own **Incidents** view (feed, Open/All, ack, ack-all) with a short open-only section on the Board.
- **Security** (M14, [16-security](16-security.md)) has chip tabs: **Activity** (the M9.9 scan) and **Stack** (M14.1, what each project runs from its lockfiles). **News** (M14.2) is its own Guard view: the security news feed, each item matched against every project's stack and narrowed to the selected project's keywords; kind / Unread / All items chips, Mark all read. Its **Sources** chip (M14.3) opens every source with its state and a per-URL format check, and shows the `[[security.feeds]]` block to paste for one that parses. The **Advisories** tab (M14.4) shows known advisories on the exact versions each project runs once `[security] advisories = true`, and the Enable card with the TOML to paste while it is off.
- **Security** (M14, [16-security](16-security.md)) has chip tabs: **Activity** (the M9.9 scan) and **Stack** (M14.1, what each project runs from its lockfiles). **News** (M14.2) is its own Guard view: the security news feed, each item matched against every project's stack and narrowed to the selected project's keywords; kind / Unread / All items chips, Mark all read. Its items set as a paper — a dateline per day, the articles in hero / feature / brief tiers with their pictures — or as a table, with a month calendar that narrows both to a day (M14.11). Its **Sources** chip (M14.3) opens every source with its state and a per-URL format check, and shows the `[[security.feeds]]` block to paste for one that parses. The **Advisories** tab (M14.4) shows known advisories on the exact versions each project runs once `[security] advisories = true`, and the Enable card with the TOML to paste while it is off.
- **Steering** (M13): Fleet rows carry the permission-broker Allow/Deny card for *interactive* sessions, not just spawned runs, and Incidents carry Codify → Apply. The Session input box exists for spawned runs (M3.3).
- **Not yet**: the full keyboard map (`g f`, `j/k`, `?`) and the Settings page — project settings live in the sidebar menu, hook/rule status in `swarm doctor`. The ⌘K palette shipped with M9.1.
- **CLI** and **MCP** sections below are split into *Today* / *Planned*; section D lists the HTTP routes the daemon actually serves and section E the in-session surface.
Expand Down
2 changes: 2 additions & 0 deletions docs/13-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,8 @@ stack = true
# SWARM_OFFLINE=1 also stops it.
news = true
news_days = 30 # keep items this long (1–365)
pictures = true # M14.11: fetch the page of an article whose feed gave no picture, once, for its
# Open Graph picture — the head of the page only. false: one fetch per feed.
refresh_minutes = 30 # how often the sources are re-read (10–1440); conditional requests
kinds = ["vendor", "authority", "press"] # built-in kinds to read; add "ai" for the AI press.
# "vendor" / "ai" items are shown whole; "authority" / "press" only
Expand Down
4 changes: 3 additions & 1 deletion docs/16-security.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ This doc records where the code is today and what changes, so M14 lands as seven
- **Keywords come from the stack.** The earlier feed kept a hand-written list of vendors, products and words. Swarm derives the set per project from the detected packages (plus `[security] keywords`), so relevance follows what the project actually runs and needs no upkeep. The heuristics are OQ-35.
- **SQLite, not a JSON file in the temp dir.** Items, per-source state and the advisory cache are tables in `~/.swarm/swarm.db`, pruned on the daily schedule, so a project added later is matched against items already fetched and a restart loses nothing.
- **Conditional requests.** `ETag` / `Last-Modified` per source, and a per-source backoff, so thirty feeds every half hour cost little on a metered connection.
- **No page scraping for images.** The earlier feed fetched each article page for an Open Graph image. Swarm's News is a list, not a paper; one fetch per feed, none per article.
- **Pictures from the article page, once.** A feed that gives no picture would leave a hero blank, so the daemon asks the article's own page for its Open Graph picture — the head of the page only, once in the item's life, `[security] pictures = false` keeps it to one fetch per feed. (v0.18.0 shipped the News as a table without this; M14.11 made it a paper.)
- **Malicious-package advisories rank `critical`.** OSV `MAL-*` entries carry no CVSS; a malicious package is the worst case, not an unknown.

## M14.1 — Stack detection (`core`, local, always on)
Expand Down Expand Up @@ -404,3 +404,5 @@ Everything above landed the same day as ten PRs, in the cut order, each useful a
- **The format check is scriptable.** `swarm security feeds check` without a URL checks every configured source and exits 1 when one parses as none; the Sources panel does the same for one URL.
- **No schema version bump** was needed: every table is `CREATE TABLE IF NOT EXISTS` and nothing back-fills.
- Measured on this repository against the real services: 159 packages from 4 manifests; all 27 default sources parsed, 360 items in 30 days, 98 relevant; 19 open advisories (1 critical, 4 high, 14 medium) with fixed versions.

**2026-10-24, v0.18.1 — News as a paper (M14.11).** The table was not how anyone reads news. The News view now sets its items as a paper by default — a dateline per day, stuck to the top of the pane while the day scrolls, and under it the day's articles in tiers as a front page sets them: the first two as heroes across the width (one alone with its picture beside the text), the next three as features in a row, the rest as briefs; the pictured articles fill the big slots first. Each card is the link to the article and a click marks it read. A **Paper / Table** switch sits in the heading, and a month calendar beside the items shades the days by how many articles they hold; a day narrows both views to itself. The pictures come from the feed, or from the article's own page (`pageImage`: `og:image`, then the Twitter card; never an SVG), fetched by the daemon once per item with the same user agent as a feed read, six at a time, the first 300 KB only; `news_items.page_at` remembers that the page was asked, picture or not. `[security] pictures = false` keeps the daemon to the feeds. The nav's News entry carries a newspaper icon. Measured on this repository: 265 of 360 items pictured, 13 of 27 sources giving a picture to no item of their own.
2 changes: 1 addition & 1 deletion docs/guide/10-privacy-and-faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Eight things, each optional and under your control:
4. **Team forwarding** — only if you set `[team] url` to your own self-hosted [team daemon](11-teams.md). What is sent is the `forward` list: audit events (claims, gates, incidents, with actors) and daily spend rollups by default; transcript titles/text only if you opt in, and always after your `[privacy] redact` rules. Off entirely by default.
5. **Incident webhook** — only if you set `[notify] webhook`; each incident is POSTed to that URL as `{text}` JSON.
6. **OTLP export** — only if you set `[otel] endpoint` to a collector of your choosing. Session spans (tool names, timings, success) and token / cost metrics go there; commands, file paths and prompt text do not unless you also set `include_content = true`.
7. **Security news sources** (M14.2) — on by default: every `[security] refresh_minutes` the daemon reads the built-in list of public RSS / Atom feeds (the projects' own security channels, CISA and CERT-Bund, the security press; the [Observatory guide](12-observatory.md) names them) plus any `[[security.feeds]]` you add. The request carries a `swarm/<version>` user agent and nothing about you or your projects; what your projects run is matched *locally* against what came back. `[security] news = false` or `SWARM_OFFLINE=1` stops it.
7. **Security news sources** (M14.2) — on by default: every `[security] refresh_minutes` the daemon reads the built-in list of public RSS / Atom feeds (the projects' own security channels, CISA and CERT-Bund, the security press; the [Observatory guide](12-observatory.md) names them) plus any `[[security.feeds]]` you add. The request carries a `swarm/<version>` user agent and nothing about you or your projects; what your projects run is matched *locally* against what came back. With `pictures = true` (the default) the daemon also fetches the page of an article whose feed gave no picture, once, for its Open Graph picture — the same user agent, the head of the page only — and the dashboard loads the pictures from the publishers' hosts without a referrer; `pictures = false` keeps it to the feeds. `[security] news = false` or `SWARM_OFFLINE=1` stops it.
8. **OSV advisories** (M14.4) — **off until you set `[security] advisories = true`**. Then, every six hours and after a lockfile changes, the daemon asks `api.osv.dev` about the exact versions your projects run. The query carries each dependency's ecosystem, name and version — the project's dependency list — and nothing else: no project name, no path, no machine identifier beyond a `swarm/<version>` user agent. `SWARM_OFFLINE=1` wins over the switch.

With none of those configured, no session content, command, transcript, token count or cost ever leaves your machine.
Expand Down
Loading
Loading