Skip to content

Traffic, automatic Copilot, a scan sandbox, and launch prep - #2

Open
diip3sh wants to merge 7 commits into
mainfrom
cli-redesign
Open

diip3sh wants to merge 7 commits into
mainfrom
cli-redesign

Conversation

@diip3sh

@diip3sh diip3sh commented Oct 13, 2026 •

Copy link
Copy Markdown
Collaborator

Everything left before launch, except billing: production traffic for dead routes, Copilot hand-off without the click, a container sandbox for zomb Cloud scans, three CLI bugs the published package would have shipped with, and the launch setup (study on Pages, 0.1.0, a release workflow).

CLI

  • A new look, and zomb show <n> (0ebed5e). The scan reads as one numbered to-do list grouped by area, with a shape per severity, a loader while it scans, and a calendar plus the study comparison at the end. zomb show <n> prints one finding in full. Only the terminal text changed: --json, --markdown, the report, the baseline, fix and guard are byte-for-byte the same.
  • --traffic <log>: routes no request reached (af4b153). Reads nginx/Apache access logs, JSON lines or arrays (Vercel drains, most shippers) and /path count exports, .gz or not, and credits each request to the route Next.js would serve it from (static before [param] before catch-alls; locale prefixes ignored). With traffic, an unlinked route with no requests becomes delete-route ("no links and no traffic"), and a linked one with none is asked about. The JSON only gains summary.traffic when traffic is given.
  • Fixes for the published CLI (b54dff8):
    • dist/ had no baseline.json, so the built CLI crashed on start. It is a JSON import now, which tsc emits.
    • process.exit right after printing cut piped output at 64 KB on macOS (zomb --json | jq, or an agent reading stdout). The CLI flushes stdout first.
    • In a repo that doesn't gitignore node_modules, the scan read installed packages as the repo's code, and a mention in them kept dead files alive.

zomb Cloud

  • Log drains (5184f71). Each repo's settings page has a drain endpoint and token: Vercel drains are checked by x-vercel-signature, anything else sends a bearer token, gzipped or not. Only a path and a daily count are kept, for 90 days. Static files are skipped, and a repo keeps at most 10,000 paths a day. After 14 days, push and weekly scans pass the last 30 days to --traffic.
  • Copilot, automatically (5184f71). "Hand issues to Copilot every week" keeps the person's GitHub token, sealed with AES-256-GCM (ZOMB_SECRET_KEY or a generated key), refreshes it one at a time, and assigns the weekly issue as them. A refused or revoked token is deleted, the issue gets its manual line back, and the dashboard says "Copilot stopped".
  • Sandbox (31270c2). ZOMB_SANDBOX=docker runs each install and scan in a throwaway container: uid 1000, no capabilities, no new privileges, 2 GB, 2 CPUs, 512 processes, 10 minutes. The server still fetches, so the GitHub token never enters the container. The checkout goes in as a tar on stdin, nothing is mounted, and it works from a server container on the host's socket. ZOMB_SANDBOX_IMAGE and ZOMB_SANDBOX_NETWORK are optional. The image now has the Docker CLI and starts cloud/server.ts, and there's a .dockerignore.

Launch

  • The Pages workflow publishes site/ with The State of AI Code at /study/. The CLI, README, landing page and dashboard link there (f8e275f).
  • Version 0.1.0, plus the repository field npm provenance needs.
  • release.yml: a v* tag checks the tag matches package.json, runs the tests, and publishes with provenance. It uses trusted publishing, or an NPM_TOKEN secret for the first release.
  • The last .js names (Knip entries, research usage lines) point at the .ts files (ea92d00).

Checked

  • npm test: 43/43 on Node 24, also in a clean clone with no global git identity (as on a CI runner). tsc --noEmit is clean.
  • The Docker sandbox test ran against a locally built zomb-cloud image and matches the host scan, traffic included. It skips when the image isn't there, as in CI.
  • The built package: npm pack contents, dist/bin.js --help, a scan and guard on Node 24 and on Node 22.18 (the engine minimum). Installed from the tarball into a fresh project.
  • The server image starts and serves /setup. With ZOMB_SANDBOX=docker it reports the sandbox, and it warns when Docker or the image is missing.
  • Self-scan: no security or zombie findings. The low findings left are copy-pasted test setup and cloud/server.ts at 677 lines.

After merging

  1. Pages: a repo admin sets Settings → Pages → Source to GitHub Actions (or runs gh api -X POST repos/Open-Dev-Society/zomb/pages -f build_type=workflow). The site then deploys on merge, or from the site workflow's Run button.
  2. npm: publish 0.1.0 by pushing the v0.1.0 tag, with an NPM_TOKEN secret for this first release. Then add release.yml as the package's trusted publisher on npmjs.com, allow npm publish, and delete the token.

Billing is not in this PR.

diip3sh and others added 7 commits October 8, 2026 00:07
The scan now reads as a single numbered to-do list grouped by area, with
a shape per severity (● ◐ ○) so it still reads without colour, the first
task marked as where to start, and a status bar at the end with the
report, the gate and the next commands. The numbers are what the new
`zomb show <n>` takes: one finding in full, with where, how to fix it,
and whether zomb fix does it for you.

While it scans, a dot matrix ripples above a checklist of the seven
checks, ticking each off as it lands, then collapses to one line. Whole-
repo scans end with a calendar of lines added per day and the study's
deleted-per-100 numbers drawn as bars; --since leaves both out. zomb fix
shows its plan and each step as a checklist, blueprint uses the same
headers, and --help gets a block-letter title, the commands in a box and
the flags in two columns.

Nothing but the terminal text changed: --json, --markdown, the HTML
report, the baseline, blueprint.yml, fix's branches and commits, guard,
and every exit code are byte-for-byte what they were, checked against
the previous commit on the same repos. The Knip warning now prints after
the loader, since a line written mid-redraw was drawn over.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
zomb --traffic <file> reads access logs, JSON lines or arrays (Vercel
drains and most log shippers) and plain "/path count" exports, .gz or
not, and keeps only paths, counts and dates. Each request is credited to
the route Next.js would serve it from, so /blog/hello keeps
/blog/[slug] alive and /blog/new stays its own route; a locale prefix
is ignored.

With traffic, a route nobody requested is the finding: "no links and no
traffic" (delete-route) when nothing in the repo points to it, "no
traffic" when something still links to it. API-only repos are checked
too. A file with no readable requests fails rather than calling every
route dead, and under a week of traffic gets a warning. Without the
flag, every output is what it was.

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Each repo gets a settings page with a drain endpoint and token. Vercel
drains are checked by their x-vercel-signature, anything else sends the
token as a bearer, gzipped or not. zomb keeps a path and a daily count
for 90 days, skips static files and caps a repo at 10,000 paths a day.
Once a repo has 14 days of it, push and weekly scans pass the last 30
days to zomb --traffic, so the weekly issue lists the routes nobody
requests.

"Hand issues to Copilot every week" signs the person in again and keeps
that token, sealed with AES-256-GCM (ZOMB_SECRET_KEY, or a key
generated into DATA_DIR). The weekly job refreshes it one at a time,
since a refresh token works once, and assigns the issue as them when
.zomb/config.yml says handoff: copilot. A refused or revoked token is
deleted, the issue gets its manual line back, and the dashboard says
Copilot stopped.

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
ZOMB_SANDBOX=docker runs each job's install and scan in a container of
the zomb-cloud image, as uid 1000 with no capabilities, no new
privileges, 2 GB, 2 CPUs and 512 processes, for at most 10 minutes. The
server still fetches the repo, so the GitHub token never enters the
container; the checkout (and its traffic file) arrives as a tar on
stdin, which also works when the server runs in Docker on the host's
socket. Nothing is mounted. ZOMB_SANDBOX_IMAGE and ZOMB_SANDBOX_NETWORK
pick the image and the network; the server checks the image at startup.

The image now carries the Docker CLI and a /work folder for uid 1000,
makes its sources readable whatever their modes in the build context,
and starts cloud/server.ts. A .dockerignore keeps node_modules and .git
out of the build context.

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Knip's entries in package.json named cloud/server.js, research/*.js
and test/*.test.js, which no longer exist; the research usage lines and
a comment in blueprint.ts did too.

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
- dist/ had no baseline.json, so the built CLI crashed on start: the
  file was loaded with require, which tsc doesn't copy. It is a JSON
  import now, which tsc emits next to benchmark.js.
- process.exit right after printing drops what a pipe hasn't taken yet,
  and pipes are asynchronous on macOS: zomb --json | jq (or an agent
  reading stdout) got the first 64 KB. The CLI flushes stdout first.
- In a repo that doesn't gitignore node_modules, the scan read the
  installed packages as the repo's code, and a mention inside them kept
  a dead file alive. node_modules is never the repo now.

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
The Pages workflow now publishes site/ with The State of AI Code at
/study/, and the CLI, the README, the landing page and the dashboard
link there instead of the research folder. Version 0.1.0, with the
repository field npm provenance needs. Pushing a v* tag tests and
publishes to npm with trusted publishing, or an NPM_TOKEN secret for
the first release.

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
@coderabbitai

coderabbitai Bot commented Oct 13, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 0daa1ca9-17c0-4899-b9e3-a35515a186cf
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown

zomb: 13 findings in this change (since b02f40c)

13 low

Area Finding Where
⚪ low shortcuts Casts to any cloud/grants.ts:18
⚪ low shortcuts Casts to any cloud/jobs.ts:135
⚪ low shortcuts Casts to any cloud/jobs.ts:137
⚪ low shortcuts Casts to any cloud/server.ts:92
⚪ low shortcuts Casts to any cloud/server.ts:173
⚪ low shortcuts Casts to any cloud/server.ts:242
⚪ low shortcuts Casts to any cloud/server.ts:261
⚪ low shortcuts Casts to any test/cloud.test.ts:271
⚪ low sprawl 10 copy-pasted lines test/cloud.test.ts:69-78 and test/cloud.test.ts:158-167
⚪ low sprawl 8 copy-pasted lines test/e2e.test.ts:40-47 and test/e2e.test.ts:91-98
⚪ low sprawl 8 copy-pasted lines test/e2e.test.ts:41-48 and test/e2e.test.ts:115-122
⚪ low sprawl 7 copy-pasted lines test/blueprint.test.ts:109-115 and test/e2e.test.ts:43-49
⚪ low architecture Split cloud/server.ts (677 lines) cloud/server.ts

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant