Skip to content

docs: v2 content audit — source-of-truth resync, tools catalogue, troubleshooting#35

Merged
indykish merged 10 commits into
mainfrom
chore/v2-content-audit-source-resync
May 5, 2026
Merged

docs: v2 content audit — source-of-truth resync, tools catalogue, troubleshooting#35
indykish merged 10 commits into
mainfrom
chore/v2-content-audit-source-resync

Conversation

@indykish
Copy link
Copy Markdown
Contributor

@indykish indykish commented May 5, 2026

Summary

Reviewed every user-facing page from the persona of an engineer who wants to create a zombie. Reconciled docs against zombiectl/src/ + src/errors/ + src/zombie/ source-of-truth. Added the two missing-but-needed pages (tools catalogue, troubleshooting). Surfaced the existing Discord channel and enabled per-page feedback.

DX scorecard: ~4/10 → ~7/10 across the eight DX dimensions. Biggest jumps: error-message correctness (3→8 — the prior state cited fictional codes like `UZ-TRIGGER-001` and used inconsistent schemes like `WORKSPACE_NOT_FOUND`) and DX measurement (2→7 — Mintlify feedback widgets enabled).

What changed

CLI surface alignment with `zombiectl/src/commands/*.js`

  • `workspace add` takes optional `[name]`, not ``
  • `credential add` heading uses safe `--data=@-` form (was advertising the unsafe inline-JSON form)
  • `install --from` correctly described as read-and-upload, not write-files
  • `tenant provider` documented then removed when BYOK was descoped

Quickstart — new "Create a workspace" step (without it, first-run hit `ERR_NO_WORKSPACE` with no diagnostic context); skill install via `curl https://usezombie.sh/skills.md\` (replaces broken `npx skills add` form); BYOK setup removed per descope; `op inject` example for credential rotation with the silent-failure caveat.

Error codes resynced against `src/errors/error_registry.zig` + `error_entries.zig` + `error_entries_runtime.zig`

  • Removed retired `UZ-ZMB-007` (now `UZ-VAULT-002`)
  • Corrected `UZ-ZMB-010` title; added missing `UZ-ZMB-011`
  • New `## Vault`, `## Memory`, `## Integration grants` sections (codes existed in source, weren't documented)
  • Fictional `UZ-TRIGGER-001` in `cli/flags.mdx` replaced with real `UZ-ZMB-008`
  • `WORKSPACE_NOT_FOUND` in `api-reference/introduction.mdx` → canonical `UZ-WORKSPACE-001`
  • `memory.mdx`: `UZ-MEM-001` was mapped to the wrong cause (scope-denied vs. backend-down)
  • Credentials section reframed as inference-path errors since BYOK setup isn't user-documented

New pages

  • `zombies/tools.mdx` — 24 user-callable tools grouped into 9 categories (network, memory, cron, agent orchestration, browser, git, file, stateless, channel), descriptions sourced from nullclaw `tool_description` constants. Authoring page's inline catalogue (which surfaced only 3 of 24) replaced with a pointer. Pushover dropped after verifying `PUSHOVER_TOKEN`/`PUSHOVER_USER_KEY` aren't provisioned anywhere on hosted v2.
  • `zombies/troubleshooting.mdx` — 6-symptom decision tree mapping to wire codes and CLI diagnostics. Every command grounded in the existing CLI surface; no invented flags.

Authoring + webhooks

  • `trigger.type` expanded into a use-when table for `webhook`/`cron`/`api`. `chain` removed from user-facing surface (parser-accepted but no runtime dispatch — verified zero `.chain =>` switch arms in worker/http source). Continuation note clarifies they're runtime-emitted, not declared.
  • Webhooks: natively normalized providers table (`slack`/`github`/`linear`) derived directly from `PROVIDER_REGISTRY` in `webhook_verify.zig:48`. Generic-HMAC subsection references `jira` + `agentmail` (only providers with test fixtures in `config_helpers.zig`).

DX additions

  • Mintlify `feedback` block enabled in `docs.json` (`thumbsRating`, `suggestEdits`, `raiseIssue`) — readers can flag wrong content without leaving the site
  • Discord link surfaced in `index.mdx` Explore grid and `troubleshooting.mdx` "When to escalate" with concrete fast (Discord) vs. durable (GitHub Issues) framing

What's deliberately not in this PR

  • Custom-zombie tutorial. The audit identified "no walkthrough for non-platform-ops use cases" as the highest-leverage gap. Drafted a Stripe webhook example, then parked it on confirmation that the example wasn't tested end-to-end. Unblocked once a tested non-platform-ops sample ships in `@usezombie/zombiectl`.
  • Dashboard page. Mission Control is referenced from several pages but not separately documented. Per discussion, no dashboard page yet.
  • Migration guide v1 → v2. Out of scope; deferred to v3 milestone work.

Test plan

  • `mintlify dev` locally renders all 17 affected pages without schema errors
  • Mintlify preview deploy succeeds on this PR
  • Verify the new `feedback` block syntax is accepted by the Mintlify version usezombie/docs uses (drop `raiseIssue` if not)
  • Spot-check that internal links resolve: `/zombies/tools`, `/zombies/troubleshooting`, `/api-reference/error-codes#vault`, `/api-reference/error-codes#memory`
  • Skim `zombies/troubleshooting.mdx` against any current production failure logs to verify the wire codes and diagnostic commands still match runtime behavior
  • Confirm Discord card icon `discord` renders correctly in Mintlify (fallback: `comments` or `message` icon)

🤖 Generated with Claude Code

Greptile Summary

This PR performs a comprehensive v2 documentation audit across 21 files, reconciling every user-facing page against the zombiectl source, error registry, and tool catalogue. Error codes are resynced from src/errors/, CLI commands are corrected to match zombiectl/src/commands/*.js, and two new pages (zombies/tools.mdx, zombies/troubleshooting.mdx) fill the most significant documentation gaps.

  • Error registry resync: adds UZ-WH-020/030, UZ-TOOL-004, UZ-ZMB-011, UZ-GRANT-001-003, UZ-VAULT-001-002, UZ-MEM-001-003; retires UZ-ZMB-007; replaces fictional UZ-TRIGGER-001 and WORKSPACE_NOT_FOUND with canonical codes throughout.
  • CLI surface alignment: workspace add [name] (not <repo-url>), workspace delete (not remove), agent add (not create), grant delete (not revoke), billing show introduced; stop/resume/kill/delete irreversibility ladder documented; --follow flag removal noted with polling workaround.
  • New pages: 23-tool catalogue with per-category network-allowlist behaviour, browser-tool limitations, and validation semantics; 6-symptom troubleshooting decision tree grounded in real wire codes and CLI diagnostics.

Confidence Score: 4/5

Safe to merge with one fix: UZ-VAULT-001 in the §1 install-rejected table points users at an error code that zombiectl install --from never emits, leaving them unable to match the row during a real install failure.

The UZ-VAULT-001 row in zombies/troubleshooting.mdx §1 is framed as a wire code from zombiectl install --from --json output, but the inline note explicitly states it comes from a prior credential add call rather than from install. A user debugging a failed install who searches their JSON output for a matching code will not find this code and will never land on the row, defeating the diagnostic purpose of the decision tree.

zombies/troubleshooting.mdx (§1 install-rejected table) and zombies/tools.mdx (terminology).

Important Files Changed

Filename Overview
zombies/troubleshooting.mdx New troubleshooting decision tree for 6 failure shapes; UZ-VAULT-001 is listed in the §1 install-rejected table but the inline note says it's not returned by install, making that row unreachable via the described diagnostic path.
zombies/tools.mdx New 23-tool catalogue grouped into 9 categories; uses "tool bridge" terminology where AGENTS.md style guide prescribes "credential firewall" (two occurrences).
api-reference/error-codes.mdx Error registry resynced: adds UZ-WH-020/030, UZ-TOOL-004, UZ-ZMB-011, UZ-GRANT-001-003, UZ-VAULT-001-002, UZ-MEM-001-003 with correct HTTP status codes; retires UZ-ZMB-007; adds observability note on UZ-TOOL-* codes.
cli/zombiectl.mdx Command reference aligned to actual CLI surface: workspace add/delete, agent add, grant delete, lifecycle verbs (stop/resume/kill/delete), billing show, logs vs events distinction all updated correctly.
quickstart.mdx Adds 'Create a workspace' step, replaces broken npx skills add with curl install, removes BYOK step, adds op inject credential rotation example with silent-failure caveat.
workspaces/overview.mdx Intro and lifecycle steps updated to drop GitHub App binding model; workspace now correctly described as tenant-scoped container, not repo-bound.
workspaces/managing.mdx REPO column removed from workspace list sample output; workspace show description updated; workspace remove → delete with updated caveat text; GitHub App references removed.
zombies/authoring.mdx chain trigger type removed; trigger.type expanded into use-when table; inline tool catalogue replaced with pointer to new tools catalogue page; continuation note added.
zombies/webhooks.mdx Natively normalized providers table (slack/github/linear) added from PROVIDER_REGISTRY; generic HMAC section with jira/agentmail documented; --follow removed in favour of logs.
zombies/running.mdx Lifecycle commands expanded: stop/resume/kill/delete irreversibility ladder added, logs vs events split documented, --follow flag removed with polling note.
docs.json New pages (tools, troubleshooting) added to nav; Mintlify feedback block (thumbsRating, suggestEdits, raiseIssue) enabled.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    Install["zombiectl install --from path"] --> Alive["Alive\nwebhook live"]
    Alive -->|event arrives| Processing["Processing\nagent reasoning"]
    Processing -->|stage exits| Alive
    Alive -->|zombiectl stop| Stopped["Stopped\npausable"]
    Stopped -->|zombiectl resume| Alive
    Alive -->|zombiectl kill| Killed["Killed\nterminal — row/history/URL persist"]
    Killed -->|zombiectl delete| Deleted["Deleted\nrow + URL gone → UZ-WH-001"]
    Killed -->|zombiectl install --from path| Alive
Loading

Comments Outside Diff (5)

  1. workspaces/overview.mdx, line 6-16 (link)

    P1 Page intro and "What a workspace contains" contradict the updated lifecycle step

    This PR updated lifecycle step 1 (line 36) to say workspaces are "not bound to a specific GitHub repo at creation time," but the page intro (line 6: "It binds a GitHub repository to usezombie via the usezombie GitHub App") and the "What a workspace contains" list (line 12: "Repository connection — a 1:1 binding to a GitHub repo via the usezombie GitHub App") still describe the old GitHub-App-binding model. Step 4 of the lifecycle (line 39) also retains "GitHub App connection uninstalled for that repo." A reader of this page now gets three contradictory descriptions of what a workspace is.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: workspaces/overview.mdx
    Line: 6-16
    
    Comment:
    **Page intro and "What a workspace contains" contradict the updated lifecycle step**
    
    This PR updated lifecycle step 1 (line 36) to say workspaces are "not bound to a specific GitHub repo at creation time," but the page intro (line 6: "It binds a GitHub repository to usezombie via the usezombie GitHub App") and the "What a workspace contains" list (line 12: "**Repository connection** — a 1:1 binding to a GitHub repo via the usezombie GitHub App") still describe the old GitHub-App-binding model. Step 4 of the lifecycle (line 39) also retains "GitHub App connection uninstalled for that repo." A reader of this page now gets three contradictory descriptions of what a workspace is.
    
    How can I resolve this? If you propose a fix, please make it concise.
  2. workspaces/managing.mdx, line 28-35 (link)

    P1 workspace list output still shows a REPO column after the no-repo-binding change

    The "Add a workspace" section on this same page was updated in this PR to say "There is no repo URL — workspaces are tenant-scoped containers," yet the workspace list output table (lines 28-35) still shows a REPO column populated with acme/backend, acme/frontend, and acme/infra, and the prose above it says the command "Displays … connected repository." A user reading straight down the page gets a direct contradiction: workspaces have no repo URL, but workspace list shows one. The sample output and the description need to be updated to match the new model (e.g. replace the REPO column with NAME or drop it, and update the description to remove "connected repository").

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: workspaces/managing.mdx
    Line: 28-35
    
    Comment:
    **`workspace list` output still shows a REPO column after the no-repo-binding change**
    
    The "Add a workspace" section on this same page was updated in this PR to say "There is no repo URL — workspaces are tenant-scoped containers," yet the `workspace list` output table (lines 28-35) still shows a `REPO` column populated with `acme/backend`, `acme/frontend`, and `acme/infra`, and the prose above it says the command "Displays … connected repository." A user reading straight down the page gets a direct contradiction: workspaces have no repo URL, but `workspace list` shows one. The sample output and the description need to be updated to match the new model (e.g. replace the `REPO` column with `NAME` or drop it, and update the description to remove "connected repository").
    
    How can I resolve this? If you propose a fix, please make it concise.
  3. workspaces/managing.mdx, line 28-35 (link)

    P1 workspace list description and sample output still reference the old repo-binding model

    Line 28 says the command displays "status, connected repository, and plan tier," and the sample output block (lines 30–35) still shows a REPO column populated with acme/backend, acme/frontend, and acme/infra. This directly contradicts the updated text on line 12 of this same file ("There is no repo URL — workspaces are tenant-scoped containers"). A reader who follows the page top-to-bottom gets three statements in conflict. The description and sample output need to drop the REPO column (e.g. replace with NAME) and remove the "connected repository" wording.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: workspaces/managing.mdx
    Line: 28-35
    
    Comment:
    **`workspace list` description and sample output still reference the old repo-binding model**
    
    Line 28 says the command displays "status, connected repository, and plan tier," and the sample output block (lines 30–35) still shows a `REPO` column populated with `acme/backend`, `acme/frontend`, and `acme/infra`. This directly contradicts the updated text on line 12 of this same file ("There is no repo URL — workspaces are tenant-scoped containers"). A reader who follows the page top-to-bottom gets three statements in conflict. The description and sample output need to drop the `REPO` column (e.g. replace with `NAME`) and remove the "connected repository" wording.
    
    How can I resolve this? If you propose a fix, please make it concise.
  4. workspaces/managing.mdx, line 59-78 (link)

    P1 workspace show and Remove sections still describe the old repo-binding / GitHub App model

    workspace show (line 59) says it prints "repo URL" and "default branch" — neither concept exists in the new model where workspaces are not bound to a repo at creation. The Remove section (line 74) says "Uninstalls the GitHub App connection for that repository," and the Warning (line 77) says "reinstall the GitHub App to reconnect" — both are leftovers from the old flow. A user who hits a removal error and reads this for guidance will take the wrong remediation path.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: workspaces/managing.mdx
    Line: 59-78
    
    Comment:
    **`workspace show` and `Remove` sections still describe the old repo-binding / GitHub App model**
    
    `workspace show` (line 59) says it prints "repo URL" and "default branch" — neither concept exists in the new model where workspaces are not bound to a repo at creation. The `Remove` section (line 74) says "Uninstalls the GitHub App connection for that repository," and the Warning (line 77) says "reinstall the GitHub App to reconnect" — both are leftovers from the old flow. A user who hits a removal error and reads this for guidance will take the wrong remediation path.
    
    How can I resolve this? If you propose a fix, please make it concise.
  5. workspaces/overview.mdx, line 6-16 (link)

    P1 Page intro and "What a workspace contains" still describe the old GitHub-App-binding model

    Line 6 says a workspace "binds a GitHub repository to usezombie via the usezombie GitHub App." Line 12 lists "Repository connection — a 1:1 binding to a GitHub repo via the usezombie GitHub App" as a first-class attribute of a workspace. Both statements contradict lifecycle step 1 (line 36 of this file), which was updated in this PR to say workspaces are not bound to a specific GitHub repo at creation time. The intro sentence and the "What a workspace contains" bullet need to be updated to reflect the new model — workspace as a tenant-scoped container, with repo webhooks wired later per-zombie.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: workspaces/overview.mdx
    Line: 6-16
    
    Comment:
    **Page intro and "What a workspace contains" still describe the old GitHub-App-binding model**
    
    Line 6 says a workspace "binds a GitHub repository to usezombie via the usezombie GitHub App." Line 12 lists "**Repository connection** — a 1:1 binding to a GitHub repo via the usezombie GitHub App" as a first-class attribute of a workspace. Both statements contradict lifecycle step 1 (line 36 of this file), which was updated in this PR to say workspaces are not bound to a specific GitHub repo at creation time. The intro sentence and the "What a workspace contains" bullet need to be updated to reflect the new model — workspace as a tenant-scoped container, with repo webhooks wired later per-zombie.
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
Fix the following 3 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 3
zombies/troubleshooting.mdx:27-35
**`UZ-VAULT-001` is not an install-time error code**

The table header says "The `--json` output carries the wire error code" — meaning these are codes a user would see in `zombiectl install --from --json` output. But the Fix column for `UZ-VAULT-001` explicitly says "The error is from a prior `credential add` call, not from `install` itself." If the install command doesn't return this code, the row is unreachable by the diagnostic path described: a user who runs the diagnostic command and grep-matches the JSON output for a code will never find `UZ-VAULT-001` there, so they'd never land on this row. Either this code should be moved to a "Related checks before you install" note outside the table, or the framing of the table needs to broaden to "codes you may encounter during this workflow" (not just from the `--json` output).

### Issue 2 of 3
zombies/tools.mdx:25
**`tool bridge` should be `credential firewall` per the project style guide**

`AGENTS.md` defines "credential firewall" as the canonical term for "the network-layer proxy that injects secrets outside the sandbox." Two new uses of "tool bridge" in this file describe that exact component — both in the `http_request` table row and in the "How tools, credentials, and the network allowlist combine" section.

```suggestion
| `http_request` | HTTPS calls (`GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `HEAD`, `OPTIONS`) to external APIs. The credential firewall substitutes credential references (`${secrets.NAME.FIELD}`) into headers and bodies outside the sandbox. Default response cap: 1 MB. | **Yes.** Off-list hosts dropped by the sandbox firewall before the request leaves. | Any third-party API. Slack, GitHub, Linear, your hosting provider, your monitoring — everything goes through this. |
```

### Issue 3 of 3
zombies/tools.mdx:113
Same "credential firewall" terminology fix in the conceptual explanation section.

```suggestion
Tools are the *what* (verbs the agent may invoke). Credentials are the *what-with* (named secrets the credential firewall substitutes into outbound calls — see [Credentials](/zombies/credentials)). The network allowlist is the *to-where* (hostnames the sandbox firewall lets traffic reach).
```

Reviews (7): Last reviewed commit: "docs(error-codes): add UZ-TOOL-004, docu..." | Re-trigger Greptile

Greptile also left 1 inline comment on this PR.

Context used:

  • Context used - AGENTS.md (source)

…ubleshooting

Reviewed every user-facing page from the persona of an engineer who wants to
create a zombie. Reconciled against zombiectl/src + src/errors/ + src/zombie/.

CLI surface fixed:
- workspace add takes optional [name], not <repo-url> (workspace.js:27-37)
- tenant provider section added then removed per BYOK descope
- credential add heading uses safe --data=@- form
- install --from now correctly described as read-and-upload, not write
- zombiectl events example uses concrete zmb_2041 + zombiectl list pointer

Quickstart:
- new "Create a workspace" step (was missing — first-run hit ERR_NO_WORKSPACE)
- skill install via curl from usezombie.sh/skills.md (replaces broken npx form)
- BYOK setup step removed; sign-in copy reflects platform-managed default
- op inject example for credential rotation with op signin caveat
- workflow_run filter visibility note linking authoring

Error codes resynced against error_registry.zig + error_entries.zig:
- removed retired UZ-ZMB-007 (now UZ-VAULT-002)
- corrected UZ-ZMB-010 title to "Zombie already stopped or killed"
- added UZ-ZMB-011 (SKILL.md/TRIGGER.md name disagree)
- added Vault section (UZ-VAULT-001/002)
- added Memory section (UZ-MEM-001/002/003)
- added Integration grants section (UZ-GRANT-001/002/003 — all 403)
- fictional UZ-TRIGGER-001 in cli/flags replaced with real UZ-ZMB-008
- WORKSPACE_NOT_FOUND in api-reference/introduction → canonical UZ-WORKSPACE-001
- memory.mdx: UZ-MEM-001 corrected (it's scope-denied, not backend-down → UZ-MEM-003)
- Credentials section reframed as inference-path errors with cross-link to
  UZ-VAULT and UZ-ZMB-003 since BYOK setup is no longer documented

New pages:
- zombies/tools.mdx — 24 user-callable tools grouped into 9 categories,
  descriptions sourced from nullclaw tool_description constants. Authoring
  page's inline catalogue (which surfaced only 3 of 24) replaced with a
  pointer. Pushover dropped from catalogue (env vars not provisioned on
  hosted v2; tool silently no-ops for end users).
- zombies/troubleshooting.mdx — 6 symptom decision-tree mapping to wire
  codes and CLI diagnostics. Every command grounded in cli/zombiectl.mdx
  surface; no invented flags.

Authoring + webhooks:
- trigger.type table expanded: webhook | cron | api with use-when guidance.
  chain removed from user-facing surface (parser-accepted but no runtime
  dispatch — verified zero .chain => switch arms in worker/http source).
  Continuation note clarifies they're runtime-emitted, not declared.
- webhooks: natively normalized providers table (slack/github/linear)
  derived from webhook_verify.zig PROVIDER_REGISTRY. Generic-HMAC subsection
  references jira + agentmail (only providers with test fixtures in
  config_helpers.zig).

Workspace + zombie overview:
- workspace add corrected in 3 places to optional [name]
- mermaid case alignment in zombies/overview lifecycle diagram

DX additions:
- Mintlify feedback block enabled in docs.json (thumbsRating, suggestEdits,
  raiseIssue) — readers can flag wrong content without leaving the site
- Discord link surfaced in index Explore grid + troubleshooting "When to
  escalate" with concrete fast-vs-durable framing

Out of scope (parked, not in this commit):
- Custom-zombie tutorial (no tested non-platform-ops example yet)
- Dashboard page (Mission Control referenced but not separately documented)
- Migration guide v1 → v2 (deferred to v3 milestone)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Comment thread zombies/tools.mdx Outdated
Comment thread zombies/troubleshooting.mdx Outdated
…--from

There's no dry-run — the call uploads on success. Reframed as "catch schema
errors before committing" with the no-`--validate-only` caveat kept inline.

Addresses Greptile P2 on PR #35.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Comment thread zombies/troubleshooting.mdx Outdated
Greptile P1 caught two webhook codes cited in troubleshooting that weren't in
the registry. Both exist in src/errors/error_registry.zig:117-118 and
error_entries.zig:149-155 — they got missed in the original resync sweep.

Also fixed my own bug: troubleshooting listed UZ-WH-020 as HTTP 400, but
source says .unauthorized (401). Description now matches the runtime detail
string ("No webhook credential is configured for this zombie's source"),
and UZ-WH-030 size limit pinned to the actual 1 MiB cap from source.

Addresses Greptile P1 on PR #35.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Comment thread workspaces/overview.mdx Outdated
indykish and others added 2 commits May 5, 2026 21:44
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
…rb (remove → delete)

Greptile flagged four leftover repo-binding statements in workspaces/managing.mdx
and workspaces/overview.mdx that contradicted the new tenant-scoped-container
model from the v2 audit sweep. While verifying against zombiectl/src/commands/
workspace.js I also caught:

1. The CLI verb is `workspace delete` (workspace.js:182), NOT `workspace remove`.
   `remove` isn't even an alias — five doc references would have errored at the
   user's terminal. Fixed across managing.mdx, overview.mdx, cli/zombiectl.mdx.

2. The actual `workspace list` output (workspace.js:90-101) has three columns:
   ACTIVE marker, WORKSPACE (id), NAME. The doc's sample showed REPO/STATUS/PLAN
   columns with `acme/backend`-style row content — completely fictional.

3. The actual `workspace show` fields (workspace.js:145-148) are workspace_id,
   active, name, created_at. The doc claimed "repo URL" and "default branch."

Changes:
- managing.mdx: list output rewritten to match real CLI columns; show + delete
  sections rewritten to match real fields; Warning explains the practical
  consequence (zombie_ids regenerate, upstream webhooks must be re-wired)
- overview.mdx: intro and "What a workspace contains" no longer mention
  GitHub App binding or repository connection; lifecycle step 4 says "Deleted"
  with the UZ-WH-001 consequence for stale upstream webhooks
- cli/zombiectl.mdx: command-groups table + section heading + example all
  switch from `workspace remove` to `workspace delete`; show fields corrected

Addresses Greptile findings 1-4 on PR #35.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@indykish
Copy link
Copy Markdown
Contributor Author

indykish commented May 5, 2026

Greptile round 3 — all four workspace findings applied in 2629540, plus a verb bug I surfaced while verifying.

Source-of-truth pre-checks

Before fixing, I verified actual CLI behaviour against ~/Projects/usezombie/zombiectl/src/commands/workspace.js:

  • The CLI verb is workspace delete (line 182). workspace remove is not a valid verb — it errors at the user's terminal. Your accepted Greptile suggestion for finding fix: update logo SVGs and add favicon.ico #4 (commit 5724daa) used workspace remove because Greptile didn't have CLI source as context. I rebased over it with the correct verb.
  • workspace list real columns (line 90-101) are ACTIVE marker / WORKSPACE / NAME — three columns. The doc's previous "REPO / STATUS / PLAN" sample with acme/backend rows was completely fictional.
  • workspace show real fields (line 145-148) are workspace_id / active / name / created_at. The doc's previous "repo URL" / "default branch" was wrong.

Fixes applied (commit 2629540)

Finding #1workspaces/managing.mdx list section

Replaced fictional REPO/STATUS/PLAN table with the actual three-column output:

```diff
-Displays all workspaces in your account with their status, connected repository, and plan tier.

-```
-ID REPO STATUS PLAN
-ws_01J8XV9R2M acme/backend ACTIVE Scale
-ws_01J8XVKA3M acme/frontend ACTIVE Hobby
-ws_01J8XVKB7N acme/infra PAUSED Scale
-```
+Lists every workspace under your tenant that the local CLI knows about, with the active marker.
+
+```

  • WORKSPACE NAME
    +* ws_01J8XV9R2M platform-ops
  • ws_01J8XVKA3M stripe-recon
  • ws_01J8XVKB7N sentry-triage
    +```
    ```

Finding #2workspaces/managing.mdx show + delete sections

workspace show description fields now match workspace.js:145-148 (workspace_id, name, created_at). The ## Remove a workspace heading became ## Delete a workspace, the bullet list dropped "Uninstalls the GitHub App connection," and the Warning explains the practical consequence: zombie_ids regenerate on recreation, so any upstream webhook configurations need to be re-wired.

Finding #3workspaces/overview.mdx intro + "What a workspace contains"

Intro rewritten to define a workspace as "a tenant-scoped container for zombies, their credentials, and their webhooks" — repos enter the picture per-zombie, not at workspace creation. "Repository connection" bullet removed from the contents list.

Finding #4workspaces/overview.mdx lifecycle step 4

Same intent as your accepted Greptile suggestion (drop the GitHub-App line) but with the real verb (delete not remove) and a concrete consequence callout:

```diff
-4. Removed — `zombiectl workspace remove `. Stage history retained 30 days.
+4. Deleted — `zombiectl workspace delete `. Stage history retained 30 days. Webhook URLs are gone — any upstream pointing at a zombie in this workspace starts hitting `UZ-WH-001` (zombie not found).
```

Verb sweep (opportunistic)

Five total references to workspace remove existed across the docs — none would have worked at the user's terminal. Also fixed in cli/zombiectl.mdx:

  • Command-groups table (line 13)
  • Section heading (line 197)
  • Code example (line 202)
  • Plus the show field corrections that were wrong on the same page (line 195)

Verification

```
$ grep -rn 'workspace remove|GitHub App|repo URL|repository connection|connected repository' docs/ | \
grep -v changelog | grep -v 'v2/done'
```

Returns only benign hits: README.md/AGENTS.md mentions of "default branch" in Mintlify deploy context, and two correct explanatory negations ("There is no repo URL — workspaces are tenant-scoped containers") in managing.mdx:12 and cli/zombiectl.mdx:160.

Pattern note

Three Greptile rounds on this PR have all caught the same shape: citations in body prose that don't resolve in the registry/CLI surface. Round 1: tools-page heading singular/plural false positive. Round 2: UZ-WH-020/030 cited in troubleshooting but missing from error-codes. Round 3: workspace verb + sample output drifted from actual CLI. Worth filing as a kishore-babysit-prs learning: "after any docs sweep, grep every doc for UZ-[A-Z]+-[0-9]+ and zombiectl [a-z]+ [a-z]+, then verify the union against error_registry.zig and commands/*.js."

Comment thread zombies/troubleshooting.mdx Outdated
The user-facing --help table in zombiectl/src/program/io.js is curated and
omits several dispatched commands. Switching the doc baseline from --help
to the actual dispatcher (routes.js + commands/*.js) caught nine errors and
three missing surfaces.

Wrong verbs (would fail at user's terminal):
- agent create → agent add (agent.js:16)
- grant revoke → grant delete (grant.js:22)

Removed (don't exist anywhere in source):
- workspace upgrade-scale (plan changes are dashboard-only)
- workspace billing (replaced by tenant-level `billing show`)
- "up" command was never a thing (already absent, table claim removed)
- --follow flag — neither logs nor events streams; was wishful

Added (exist in routes.js but were never documented):
- stop / resume / kill / delete zombie lifecycle as a four-row table
  with reversibility column. Killing without delete keeps the webhook URL
  reserved (returns same response shape but routes nowhere new); delete
  releases the URL and any upstream pointing at it starts hitting UZ-WH-001.
- billing show — tenant wallet balance + charge history, replaces the
  fictional `workspace billing` reference. Per-zombie spend stays via
  `logs --json` aggregated client-side.
- ZOMBIE_API_KEY env var (machine-bound service auth from agent add) +
  NO_COLOR — both real per io.js:64-67, missing from configuration.mdx.

Logs vs events split clarified:
- logs <zombie_id> is the simple tail in --help (--limit, --cursor, --json)
- events <zombie_id> is the power filter surface (--actor, --since,
  --cursor, --limit, --json). Wired in routes.js:23 and zombie.js:32 but
  intentionally omitted from the curated --help. Documented per user's
  source-of-truth-over-help directive — the troubleshooting decision tree
  depends on actor filtering to disambiguate webhook failure shapes.

Files changed: cli/zombiectl.mdx (heavy rewrite of zombie + agent + grant
+ workspaces sections, new billing section), zombies/running.mdx (new
lifecycle table + logs/events split), quickstart, webhooks, overview,
managing, cli/install (events --follow → logs everywhere), billing/plans
(drop upgrade-scale CLI), billing/budgets (workspace billing → billing show),
cli/configuration (env var additions).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@indykish
Copy link
Copy Markdown
Contributor Author

indykish commented May 5, 2026

Round 4 — CLI surface resync against the dispatcher source-of-truth (zombiectl/src/program/routes.js + commands/*.js), not the curated --help table. Pushed in 36bbfc2.

The user-facing --help (in program/io.js:42-52) is hand-curated and omits several dispatched commands. Switching the doc baseline to the dispatcher caught nine bugs.

Wrong verbs (would have errored at the user's terminal)

Doc claimed Actual (per dispatcher) Source
zombiectl agent create zombiectl agent add commands/agent.js:16
zombiectl grant revoke zombiectl grant delete commands/grant.js:22

Removed (don't exist anywhere in source)

  • workspace upgrade-scale — never wired. Plan changes go through the dashboard.
  • workspace billing — never wired. Replaced by tenant-level billing show.
  • up (in the command-groups table) — never a real verb.
  • --follow flag (on events and logs) — neither command streams; was wishful documentation. Replaced with a one-liner pointing at events --since 30s polling for near-live.

Added (exist in routes.js but were never documented)

  • Zombie lifecycle table in cli/zombiectl.mdx and zombies/running.mdx: stop / resume / kill / delete with a reversibility column. Killing reserves the webhook URL (response shape unchanged, routes nowhere new). Delete releases the URL — any upstream pointing at it then hits UZ-WH-001.
  • billing show — tenant wallet balance + charge history, the actual replacement for the fictional workspace billing. Per-zombie spend stays via logs --json aggregated client-side.
  • ZOMBIE_API_KEY env var (machine-bound service auth from agent add) and NO_COLOR — both real per io.js:64-67, missing from cli/configuration.mdx.

logs vs events split

Both are dispatched (routes.js:21,23). The split is intentional:

  • logs <zombie_id> — simple tail surface, in --help. Flags: --limit, --cursor, --json.
  • events <zombie_id> — power filter surface, hidden from --help but fully wired (zombie.js:32, usage on zombie_events.js:24). Flags: --actor, --since, --cursor, --limit, --json.

Documented both per the source-of-truth-over-help directive. The troubleshooting decision tree leans on --actor 'webhook:*' and --since 1h to disambiguate webhook failure shapes — without events documented, those examples become unverifiable for a reader.

Files in this commit

  • cli/zombiectl.mdx — heavy rewrite of zombie lifecycle / agent / grant / workspaces sections, new billing section, command-groups table aligned with dispatcher
  • zombies/running.mdx — new lifecycle table, logs/events split documented
  • quickstart.mdx, zombies/webhooks.mdx, zombies/overview.mdx, workspaces/managing.mdx, cli/install.mdxevents --followlogs (or kept as filtered events where filter flags are needed)
  • billing/plans.mdx — drop the fictional workspace upgrade-scale CLI, point at dashboard
  • billing/budgets.mdxworkspace billingbilling show
  • cli/configuration.mdxZOMBIE_API_KEY, NO_COLOR added; ZOMBIE_TOKEN description tightened (user-bound vs the new key's machine-bound)

Verification

$ grep -rnE 'workspace upgrade-scale|workspace billing|agent create|grant revoke|--follow' \
    --include=*.mdx | grep -v changelog | grep -v v2/done

Returns only the intentional "no --follow flag today" callout in cli/zombiectl.mdx:138. Every CLI verb in user-facing docs now resolves to a dispatched action in routes.js or a sub-action in commands/*.js.

Pattern observation for round 5+: the gap that produced this round was using --help as the doc baseline. --help is curated; the dispatcher is authoritative. Any future CLI doc sweep should grep routes.js + commands/*.js directly.

indykish and others added 2 commits May 5, 2026 22:03
…install rejection

Greptile P1 surfaced a deeper bug in my own original claim. tools.mdx
Validation section had asserted that `zombiectl install --from <path>`
rejects unknown tool names with UZ-TOOL-005. Source check
(tool_bridge.zig:178-184) shows install does not reject — unknown names
get logged at warn level and silently skipped during tool building.
UZ-TOOL-005 is registered as .bad_request in error_entries.zig:165 but
no code path emits it as an HTTP response.

Net: UZ-TOOL-005 is a server-side observability signal, not a wire code
returned to a webhook caller, and definitely not something a user will see
during install.

tools.mdx Validation section rewritten to describe the actual behaviour:
typos pass install, surface as silent skips at runtime, audit via
zombiectl logs. Calls out UZ-TOOL-004 (Tool not attached) as the runtime
guard the agent actually hits when it tries to invoke a missing tool.

troubleshooting.mdx §3 wire-code table replaces UZ-TOOL-005 with
UZ-TOOL-004 (the real runtime surface), plus a Note explaining that
typos surface as log warnings rather than wire codes, with a pointer to
the Validation section.

This resolves Greptile's "stale section placement" finding by fixing the
underlying mis-claim that produced it: UZ-TOOL-005 isn't an install-time
error, so it never belonged in §1, and isn't a wire-stage error, so it
doesn't belong in §3 either.

Addresses Greptile P1 #r3190015354 on PR #35.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Greptile R6 P1+P1. Both findings valid; verifying against source surfaced
deeper bugs.

Issue 1 (network.allow per tool):
- http_request: gated by network.allow: (PolicyHttpRequestTool wraps and
  enforces via tool_builders.zig:184-200)
- web_search: platform-managed provider chain (searxng/duckduckgo/etc),
  bypasses network.allow:
- web_fetch: built with empty allowed_domains in tool_builders.zig:225,
  which NullClaw treats as allow-all (web_fetch.zig:23). Currently
  unconstrained on hosted v2 — known limitation.

Network section table now has a dedicated "network.allow: enforced?"
column with honest answers per row, plus a Note that calls out the
three different stories.

Issue 2 (browser tool overlap):
- browser action 'screenshot' explicitly redirects to standalone tool
  (browser.zig:42)
- browser actions 'click'/'type'/'scroll' fail with "CDP not available"
  (browser.zig:47-52)
- browser action 'open' shells out to OS browser — useless on headless
  cloud executor
- browser_open: empty allowed_domains in tool_builders.zig:252,
  browser_open.zig:50-51 fails closed on empty. Non-functional on
  hosted v2 today (same shape as Pushover earlier).
- screenshot: captures executor display, which doesn't exist on
  hosted v2 cloud workers

Browser section rewrites the table to: (a) acknowledge the three tools
are independent (declaring 'browser' doesn't unlock 'screenshot' or
'browser_open'), (b) add an "actually works on hosted v2" column
documenting the headless-executor limitations honestly, (c) add a
Warning explaining the declaration semantics so users don't pick the
wrong set.

Addresses Greptile #r3190015354 follow-up findings on PR #35.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@indykish
Copy link
Copy Markdown
Contributor Author

indykish commented May 5, 2026

Round 6 — both tools.mdx findings applied in 1484fc4. Source-of-truth verification turned up two non-trivial bugs beyond what Greptile flagged.

Issue 1 — network.allow: semantics per tool

The original "every outbound call is gated by network.allow:" claim was wrong. Source check:

Tool Builder (tool_builders.zig) Effective behaviour
http_request Lines 184-200 — wrapped in PolicyHttpRequestTool which enforces policy.network_policy.allow Gated by network.allow:
web_search Lines 210-219 — uses platform-managed provider chain (searxng/duckduckgo/brave/firecrawl/tavily/perplexity/exa/jina), no allowlist field exposed Bypasses network.allow: entirely
web_fetch Line 225 — built with allowed_domains = &.{} (empty), and NullClaw's web_fetch.zig:23 documents // empty = allow all Currently unconstrained on hosted v2

web_fetch's lack of host filter is a real gotcha. An agent declaring web_fetch can fetch arbitrary HTTPS URLs regardless of network.allow:. The Network table now has a dedicated "network.allow: enforced?" column with the honest answer per row, plus a Note that calls out the three different stories.

Issue 2 — Browser tools

Greptile spotted the overlap, but the deeper finding is that all three browser tools are partially or fully non-functional on hosted v2:

  • browser — schema advertises six actions (open, screenshot, click, type, scroll, read). Source check (browser.zig:37-56):

    • screenshot action: explicitly returns "Use the screenshot tool instead" — redirects to the standalone tool
    • click/type/scroll: always fail with "requires CDP (Chrome DevTools Protocol) which is not available"
    • open: shells out to open/xdg-open/cmd.exe start — needs a display, which a headless cloud executor doesn't have
    • read: works (curl-based, capped at 8 KB), but web_fetch is strictly better
  • screenshot — captures executor's screen. The hosted v2 executor is headless; there's no display.

  • browser_opennon-functional on hosted v2. Same shape as Pushover from earlier. Platform builder passes empty allowed_domains (tool_builders.zig:252). The underlying tool fails closed on empty (browser_open.zig:50-51: "No allowed_domains configured for browser_open"). The tool is effectively unreachable until the platform wires the user's network.allow: through to it.

The Browser section now has an "actually works on hosted v2" column for each tool, plus a Warning making the declaration semantics explicit:

Declaring browser does NOT unlock screenshot or browser_open capabilities. Each tool is independent; the sub-action names overlap by accident.

Decisions for you

Two of these tools have zero working code path for end users on hosted v2:

  1. browser_open — same shape as Pushover (which we already dropped). Empty allowlist, fails closed, no path for users to fix it. Recommend dropping from the catalogue until the platform wires the allowlist through.
  2. screenshot — needs a display the cloud executor doesn't have. Recommend dropping unless self-hosting is on the near-term roadmap.

browser has one working path (read) that's strictly inferior to web_fetch. Could go either way — keep with the warning, or drop the whole section.

For now I've documented the limitations rather than removing the tools, so a curious reader gets the honest story. Tell me whether to drop any of these like we did with Pushover.

Pattern note

Round 6 is the second time a Greptile-flagged surface review has uncovered a deeper "tool builder passes empty allowlist; underlying tool fails closed" bug (first was Pushover env vars, now browser_open). Worth a runtime fix: the executor should either pass the user's network.allow: through to all network-aware tools, or refuse to dispatch tools whose builder produces a guaranteed-fail configuration. Source-side issue, not docs.

Same shape as the earlier Pushover removal. The platform builder passes
empty allowed_domains (tool_builders.zig:252) and the underlying tool
fails closed on empty (browser_open.zig:50-51 returns "No allowed_domains
configured for browser_open"). Zero working code path for end users
today; advertising it in the catalogue is misleading.

Removed the row from zombies/tools.mdx Browser section and updated the
Warning to drop browser_open from the declaration-semantics callout.
Tool count: 24 → 23 in tools.mdx and authoring.mdx.

If/when the platform wires the user's network.allow: through to
browser_open's allowed_domains, the row can come back.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@indykish
Copy link
Copy Markdown
Contributor Author

indykish commented May 5, 2026

Decision applied: dropped browser_open from the catalogue in 65c2401. Same shape as the earlier Pushover removal — empty allowed_domains passed by the platform builder (tool_builders.zig:252), tool fails closed on empty (browser_open.zig:50-51), zero working path for end users on hosted v2.

Changes:

  • zombies/tools.mdx Browser table: removed the browser_open row
  • zombies/tools.mdx Warning: updated to drop the browser_open reference (now just calls out browser vs screenshot independence)
  • zombies/tools.mdx + zombies/authoring.mdx: tool count corrected 24 → 23

screenshot is kept documented per your decision — the headless-executor caveat remains in the table, useful for self-hosted users with a display attached. If/when the platform wires network.allow: through to browser_open's allowed_domains, the row can come back.

Source-side note for whoever owns the executor: two tools now silently dropped from the user-facing catalogue solely because the builder produces a guaranteed-fail configuration. The Pushover case (no env var provisioning) and browser_open case (empty allowlist passed through) are both fixable on the source side without docs work, and would each restore a useful capability. Not blocking this PR; just flagging for the runtime backlog.

Comment thread zombies/tools.mdx Outdated
…veat

Greptile R7 P1: I cited UZ-TOOL-004 in tools.mdx and troubleshooting.mdx
without adding it to the registry. Same pattern as the earlier UZ-WH-020/030
finding — body prose references that don't resolve in error-codes.mdx.

Source check turned up the same issue I hit with UZ-TOOL-005: registered
in error_registry.zig:123 + error_entries.zig:163 (.bad_request, 400),
but no code path emits it as a wire response. Grep returns only the
registry/entry definitions. The user-facing failure for "agent tried to
call a tool not in tools:" is a NullClaw "no such tool" message in the
activity stream, not a UZ-TOOL-004 wire code.

Three fixes:

1. error-codes.mdx Tool section: add UZ-TOOL-004 row alongside UZ-TOOL-005,
   plus a Note explaining both codes are registered for meaning but
   user-facing failures land in the activity stream rather than as wire
   responses today. Treats the registry as authoritative for semantics
   while being honest about emission surface.

2. troubleshooting.mdx §3 wire-code table: drop the UZ-TOOL-004 row (it's
   not a wire code today). Expand the existing UZ-TOOL-005 Note to cover
   both codes — typos vs missing-tool invocations both surface in the
   activity stream, not as wire responses.

3. tools.mdx Validation: drop the false "runtime guard the agent actually
   hits" claim about UZ-TOOL-004. Reframe honestly as "underlying agent
   runtime returns no-such-tool error in-prompt" with a pointer to the
   error-codes registry.

Pattern: this is the third round catching "registered codes that aren't
emitted." The pattern's worth a runtime-side note — the executor team
might want to either start emitting these as wire codes (so the registry
matches user-facing reality) or mark them as internal-only.

Addresses Greptile #r3190187792 on PR #35.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Comment thread zombies/troubleshooting.mdx
@indykish indykish merged commit b10840f into main May 5, 2026
4 checks passed
@indykish indykish deleted the chore/v2-content-audit-source-resync branch May 5, 2026 17:17
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