Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d238ec7ff9 | ||
|
|
98f8b8f7b0 | ||
|
|
2d936369b4 | ||
|
|
41c0469a60 | ||
|
|
f140f6d83d | ||
|
|
03a55fb8f7 | ||
|
|
b9acb415aa | ||
|
|
e47b15169e | ||
|
|
c1d439f83c | ||
|
|
9cafb7c376 | ||
|
|
0acbc866cf | ||
|
|
b01216e6ed | ||
|
|
c6a9d37840 | ||
|
|
5266bc6456 | ||
|
|
b53ab3f6ad | ||
|
|
f5fe3ff444 | ||
|
|
5538ff53b8 | ||
|
|
2f8439e23e | ||
|
|
7aae2d0ce5 | ||
|
|
4e8815069c | ||
|
|
787f71d3ed | ||
|
|
af7a8930e8 | ||
|
|
b75dfa14b8 | ||
|
|
66fe641c0e | ||
|
|
66de47afcb | ||
|
|
9647ec07ca | ||
|
|
4398c5061e | ||
|
|
fe849db257 | ||
|
|
8a3561c551 | ||
|
|
8712206499 | ||
|
|
ca8ec4e92c | ||
|
|
25df458b5d | ||
|
|
598e495175 | ||
|
|
18f50c85ea | ||
|
|
021b9ad2e8 | ||
|
|
1c13c5b7a3 | ||
|
|
b0035d7771 | ||
|
|
6b451bf47e | ||
|
|
e9ffcab695 | ||
|
|
836d575374 | ||
|
|
8f01ec8ed8 | ||
|
|
baabfa40b5 | ||
|
|
7cf1043fae | ||
|
|
845fc5050d | ||
|
|
a4972acb93 | ||
|
|
6069fc3f07 | ||
|
|
5ea6905b19 | ||
|
|
8acfa5aa78 | ||
|
|
3d315c96dd | ||
|
|
9dcf246bc2 | ||
|
|
0d1b14faf5 | ||
|
|
74d346f5a2 | ||
|
|
e86050b1bc | ||
|
|
07791fe470 | ||
|
|
de1d1dc848 | ||
|
|
a7a537aac0 | ||
|
|
618400f40c | ||
|
|
66e762fe87 | ||
|
|
3674dd72ca | ||
|
|
d8549a7ac3 | ||
|
|
8f7bba35ff | ||
|
|
b434eb4c83 | ||
|
|
7f4107ba81 | ||
|
|
9ee3d3ffad | ||
|
|
d683d05a3c | ||
|
|
099f002089 | ||
|
|
9e6d801418 | ||
|
|
538c2c0713 | ||
|
|
3ad8006f64 | ||
|
|
6e986b1e41 | ||
|
|
4dbc18e490 | ||
|
|
4c7ec72c8e | ||
|
|
5cba745702 | ||
|
|
aa6fa9d39c | ||
|
|
6f5a5312bc | ||
|
|
7b7bd713e3 | ||
|
|
84bb6339a8 | ||
|
|
55b3a9dbe3 | ||
|
|
406d02599c | ||
|
|
1f29641fb3 | ||
|
|
f048c9adc0 | ||
|
|
8c62dc88f1 | ||
|
|
1d75ea93f4 | ||
|
|
c83dc7a42c | ||
|
|
88ef239b76 | ||
|
|
221ff269fd | ||
|
|
07ebe1e23e | ||
|
|
d6786c1ef1 | ||
|
|
7ed0334696 | ||
|
|
0fc7fb2993 | ||
|
|
62676305da | ||
|
|
5999247584 | ||
|
|
5ac1acef42 | ||
|
|
0188f16f04 | ||
|
|
297e95b9a4 | ||
|
|
26af383cf8 | ||
|
|
47c519ba69 | ||
|
|
a7c82ecd88 | ||
|
|
fa8864e49d | ||
|
|
2339a744d4 | ||
|
|
69d5ef4c72 | ||
|
|
bd4762be9f | ||
|
|
beaa5aecad | ||
|
|
8fdb9224b2 | ||
|
|
99790afd64 | ||
|
|
93f57b6c83 | ||
|
|
c148e51c1a | ||
|
|
7f51db60eb | ||
|
|
8e8227978c | ||
|
|
0da9bce27c | ||
|
|
e0e4def7e0 | ||
|
|
75b4af13ac | ||
|
|
33a47200f1 | ||
|
|
c4c142b6fa | ||
|
|
b8eee3a668 | ||
|
|
4222a94ad9 | ||
|
|
94027972d8 | ||
|
|
91601c2395 | ||
|
|
623c77c9e3 | ||
|
|
cb1b807d22 | ||
|
|
8f8e07c270 | ||
|
|
5cc7e02544 | ||
|
|
90e4e7ee9b | ||
|
|
95be288c27 | ||
|
|
d5305b3d78 | ||
|
|
1caec236fa | ||
|
|
14e71d6b4a | ||
|
|
5918258de9 | ||
|
|
a7561c8b6c | ||
|
|
92ccdf82be | ||
|
|
47a7a8db80 | ||
|
|
353ee15fce | ||
|
|
346da20fe4 | ||
|
|
8c6db59def | ||
|
|
39ee8b1d24 | ||
|
|
e5b86164e1 |
@@ -1,19 +0,0 @@
|
||||
# Frontend
|
||||
VITE_CONVEX_URL=
|
||||
VITE_CONVEX_SITE_URL=
|
||||
VITE_SOULHUB_SITE_URL=
|
||||
VITE_SOULHUB_HOST=
|
||||
VITE_SITE_MODE=
|
||||
SITE_URL=http://localhost:3000
|
||||
CONVEX_SITE_URL=
|
||||
|
||||
# Convex Auth (GitHub OAuth App)
|
||||
AUTH_GITHUB_ID=
|
||||
AUTH_GITHUB_SECRET=
|
||||
|
||||
# Convex Auth JWT keys (generated via @convex-dev/auth CLI)
|
||||
JWT_PRIVATE_KEY=
|
||||
JWKS=
|
||||
|
||||
# Embeddings
|
||||
OPENAI_API_KEY=
|
||||
@@ -1,40 +0,0 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
bun-version: 1.3.6
|
||||
|
||||
- name: Install
|
||||
run: bun install --frozen-lockfile
|
||||
- name: Peer deps
|
||||
run: bun run check:peers
|
||||
|
||||
- name: Lint
|
||||
run: bun run lint
|
||||
|
||||
- name: Test
|
||||
run: bun run test
|
||||
|
||||
- name: Coverage
|
||||
run: bun run coverage
|
||||
|
||||
- name: Typecheck packages
|
||||
run: |
|
||||
bunx tsc -p packages/schema/tsconfig.json --noEmit
|
||||
bunx tsc -p packages/clawdhub/tsconfig.json --noEmit
|
||||
|
||||
- name: Build
|
||||
run: bun run build
|
||||
@@ -1,26 +0,0 @@
|
||||
node_modules
|
||||
.DS_Store
|
||||
.bun-build
|
||||
*.bun-build
|
||||
bin/docs-list
|
||||
dist
|
||||
dist-ssr
|
||||
!packages/schema/dist
|
||||
!packages/schema/dist/**
|
||||
*.local
|
||||
.vercel
|
||||
count.txt
|
||||
.env
|
||||
.nitro
|
||||
.tanstack
|
||||
.wrangler
|
||||
.output
|
||||
.vinxi
|
||||
todos.json
|
||||
.cta.json
|
||||
.vscode
|
||||
.env*.local
|
||||
coverage
|
||||
playwright-report
|
||||
test-results
|
||||
.playwright
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"ignorePatterns": ["node_modules", "dist", "coverage", "convex/_generated", ".tanstack", "public"]
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
# Repository Guidelines
|
||||
|
||||
## Project Structure & Module Organization
|
||||
- `src/` — TanStack Start app code (routes, components, styles).
|
||||
- `convex/` — Convex backend (schema, queries/mutations/actions, HTTP routes).
|
||||
- `convex/_generated/` — generated Convex API/types; committed for builds.
|
||||
- `docs/` — product/spec docs (see `docs/spec.md`).
|
||||
- `public/` — static assets.
|
||||
|
||||
## Build, Test, and Development Commands
|
||||
- `bun run dev` — local app server at `http://localhost:3000`.
|
||||
- `bun run build` — production build (Vite + Nitro).
|
||||
- `bun run preview` — preview built app.
|
||||
- `bunx convex dev` — Convex dev deployment + function watcher.
|
||||
- `bunx convex codegen` — regenerate `convex/_generated`.
|
||||
- `bun run lint` — Biome + oxlint (type-aware).
|
||||
- `bun run test` — Vitest (unit tests).
|
||||
- `bun run coverage` — coverage run; keep global >= 80%.
|
||||
|
||||
## Coding Style & Naming Conventions
|
||||
- TypeScript strict; ESM.
|
||||
- Indentation: 2 spaces, single quotes (Biome).
|
||||
- Lint/format: Biome + oxlint (type-aware).
|
||||
- Convex function names: verb-first (`getBySlug`, `publishVersion`).
|
||||
|
||||
## Testing Guidelines
|
||||
- Framework: Vitest 4 + jsdom.
|
||||
- Tests live in `src/**` and `convex/lib/**`.
|
||||
- Coverage threshold: 80% global (lines/functions/branches/statements).
|
||||
- Example: `convex/lib/skills.test.ts`.
|
||||
|
||||
## Commit & Pull Request Guidelines
|
||||
- Commit messages: Conventional Commits (`feat:`, `fix:`, `chore:`, `docs:`…).
|
||||
- Keep changes scoped; avoid repo-wide search/replace.
|
||||
- PRs: include summary + test commands run. Add screenshots for UI changes.
|
||||
|
||||
## Configuration & Security
|
||||
- Local env: `.env.local` (never commit secrets).
|
||||
- Convex env holds JWT keys; Vercel only needs `VITE_CONVEX_URL` + `VITE_CONVEX_SITE_URL`.
|
||||
- OAuth: GitHub OAuth App credentials required for login.
|
||||
|
||||
## Convex Ops (Gotchas)
|
||||
- New Convex functions must be pushed before `convex run`: use `bunx convex dev --once` (dev) or `bunx convex deploy` (prod).
|
||||
- For non-interactive prod deploys, use `bunx convex deploy -y` to skip confirmation.
|
||||
- If `bunx convex run --env-file .env.local ...` returns `401 MissingAccessToken` despite `bunx convex login`, workaround: omit `--env-file` and use `--deployment-name <name>` / `--prod`.
|
||||
@@ -1,153 +0,0 @@
|
||||
# Changelog
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Added
|
||||
|
||||
### Changed
|
||||
|
||||
### Fixed
|
||||
|
||||
## 0.4.0 - 2026-01-30
|
||||
|
||||
### Added
|
||||
- Web: show published skills on user profiles (thanks @njoylab, #20).
|
||||
- CLI: include OpenClaw + Moltbot fallback skill roots for sync scans.
|
||||
- CLI: support OpenClaw configuration files (`OPENCLAW_CONFIG_PATH` / `OPENCLAW_STATE_DIR`).
|
||||
|
||||
### Changed
|
||||
- Brand: rebrand to OpenClaw and publish CLI as `clawhub` (legacy `clawdhub` supported).
|
||||
- Domain: default site/registry now `https://clawhub.ai`; `.well-known/clawhub.json` preferred.
|
||||
- Theme: persist theme under `clawhub-theme` (legacy key still read).
|
||||
|
||||
### Fixed
|
||||
- Registry: drop missing skills during search hydration (thanks @aaronn, #28).
|
||||
- CLI: use path-based skill metadata lookup for updates (thanks @daveonkels, #22).
|
||||
- Search: keep highlighted-only filtering and clamp vector candidates to Convex limits (thanks @aaronn, #30).
|
||||
|
||||
## 0.3.0 - 2026-01-19
|
||||
|
||||
### Added
|
||||
- CLI: add `explore` command for latest updates, with limit clamping + tests/docs (thanks @jdrhyne, #14).
|
||||
- CLI: `explore --json` output + new sorts (`installs`, `installsAllTime`, `trending`) and limit up to 200.
|
||||
- API: `/api/v1/skills` supports installs + trending sorts (7-day installs).
|
||||
- API: idempotent `POST/DELETE /api/v1/stars/{slug}` endpoints.
|
||||
- Registry: trending leaderboard + daily stats backfill for installs-based sorts.
|
||||
|
||||
### Fixed
|
||||
- Web: keep search mode navigation and state in sync (thanks @NACC96, #12).
|
||||
|
||||
## 0.2.0 - 2026-01-13
|
||||
|
||||
### Added
|
||||
- Web: dynamic OG image cards for skills (name, description, version).
|
||||
- CLI: auto-scan Clawdbot skill roots (per-agent workspaces, shared skills, extraDirs).
|
||||
- Web: import skills from public GitHub URLs (auto-detect `SKILL.md`, smart file selection, provenance).
|
||||
- Web/API: SoulHub (SOUL.md registry) with v1 endpoints and first-run auto-seed.
|
||||
|
||||
### Fixed
|
||||
- Web: stabilize skill OG image generation on server runtimes.
|
||||
- Web: prevent skill OG text overflow outside the card.
|
||||
- Registry: make SoulHub auto-seed idempotent and non-user-owned.
|
||||
- Registry: keep GitHub backup state + publish backups intact (thanks @joshp123, #1).
|
||||
- CLI/Registry: restore fork lineage on sync + clamp bulk list queries (thanks @joshp123, #1).
|
||||
- CLI: default workdir falls back to Clawdbot workspace (override with `--workdir` / `CLAWHUB_WORKDIR`).
|
||||
|
||||
## 0.0.6 - 2026-01-07
|
||||
|
||||
|
||||
### Added
|
||||
- API: v1 public REST endpoints with rate limits, raw file fetch, and OpenAPI spec.
|
||||
- Docs: `docs/api.md` and `DEPRECATIONS.md` for the v1 cutover plan.
|
||||
|
||||
### Changed
|
||||
- CLI: publish now uses single multipart `POST /api/v1/skills`.
|
||||
- Registry: legacy `/api/*` + `/api/cli/*` marked for deprecation (kept for now).
|
||||
|
||||
## 0.0.5 - 2026-01-06
|
||||
|
||||
### Added
|
||||
- Telemetry: track installs via `clawhub sync` (logged-in only), per root, with 120-day staleness.
|
||||
- Skills: show current + all-time installs; sort by installs.
|
||||
- Profile: private "Installed" tab with JSON export + delete telemetry controls.
|
||||
- Docs: add `docs/telemetry.md` (what we track + how to opt out).
|
||||
- Web: custom Open Graph image (`/og.png`) + richer OG/Twitter tags.
|
||||
- Web: dashboard for managing your published skills (thanks @dbhurley!).
|
||||
|
||||
### Changed
|
||||
- CLI: telemetry opt-out via `CLAWHUB_DISABLE_TELEMETRY=1`.
|
||||
- Web: move theme picker into mobile menu.
|
||||
|
||||
### Fixed
|
||||
- Web: handle shorthand hex colors in diff theme (thanks @dbhurley!).
|
||||
|
||||
## 0.0.5 - 2026-01-06
|
||||
|
||||
### Added
|
||||
- Maintenance: admin backfill to re-parse `SKILL.md` and repair stored summaries/parsed metadata.
|
||||
|
||||
### Fixed
|
||||
- CLI sync: ignore plural `skills.md` docs files when scanning for skills.
|
||||
- Registry: parse YAML frontmatter (incl multiline `description`) and accept YAML `metadata` objects.
|
||||
|
||||
## 0.0.4 - 2026-01-05
|
||||
|
||||
### Added
|
||||
- Web: `/skills` list view with sorting (newest/downloads/stars/name) + quick filter.
|
||||
- Web: admin/moderator highlight toggle on skill detail.
|
||||
- Web: canonical skill URLs as `/<owner>/<slug>` (legacy `/skills/<slug>` redirects).
|
||||
- Web: upload auto-generates a changelog via OpenAI when left blank (marked as auto-generated).
|
||||
|
||||
### Fixed
|
||||
- Web: skill detail shows a loading state instead of flashing "Skill not found".
|
||||
- Web: user profile shows avatar + loading state (no "User not found" flash).
|
||||
- Web: improved mobile responsiveness (nav menu, skill detail layout, install command overflow).
|
||||
- Web: upload now unwraps folder picks so `SKILL.md` can be at the bundle root.
|
||||
- Registry: cap embedding payload size to avoid model context errors.
|
||||
- CLI: ignore legacy `auth.clawdhub.com` registry and prefer site discovery.
|
||||
|
||||
### Changed
|
||||
- Web: homepage search now expands into full search mode with live results + highlighted toggle.
|
||||
- CLI: sync no longer prompts for changelog; registry auto-generates when blank.
|
||||
|
||||
## 0.0.3 - 2026-01-04
|
||||
|
||||
### Added
|
||||
- CLI sync: concurrency flag to limit registry checks.
|
||||
- Home: install command switcher (npm/pnpm/bun).
|
||||
|
||||
### Changed
|
||||
- CLI sync: default `--concurrency` is now 4 (was 8).
|
||||
- CLI sync: replace boxed notes with plain output for long lists.
|
||||
|
||||
### Fixed
|
||||
- CLI sync: wrap note output to avoid terminal overflow; cap list lengths.
|
||||
- CLI sync: label fallback scans as fallback locations.
|
||||
- CLI package: bundle schema internally (no external `clawhub-schema` publish).
|
||||
- Repo: mark `clawhub-schema` as private to prevent publishing.
|
||||
|
||||
## 0.0.2 - 2026-01-04
|
||||
|
||||
### Added
|
||||
- CLI: delete/undelete commands for soft-deleted skills (owner/admin).
|
||||
|
||||
### Fixed
|
||||
- CLI sync: dedupe duplicate slugs across scan roots; skip duplicates to avoid double-publish errors.
|
||||
- CLI sync: show parsing progress while hashing local skills.
|
||||
- CLI sync: prompt only actionable skills; preselect all by default; list synced separately; condensed synced summary when nothing to sync.
|
||||
- CLI sync: cap long status lists to avoid massive terminal boxes.
|
||||
- CLI publish/sync: allow empty changelog on updates; registry accepts empty changelog for updates.
|
||||
- CLI: use `--cli-version` to avoid conflict with skill `--version` flags.
|
||||
- Registry: hide soft-deleted skills from search/skill/download unless restored.
|
||||
- Tests: add delete/undelete coverage (unit + e2e).
|
||||
|
||||
## 0.0.1 - 2026-01-04
|
||||
|
||||
### Features
|
||||
- CLI auth: login/logout/whoami; browser loopback auth; token storage; site/registry discovery; config overrides.
|
||||
- CLI workflow: search, install, update (single/all), list, publish, sync (scan workdir + legacy roots), dry-run, version bumping, tags.
|
||||
- Registry/API: skills + versions with semver; tags (latest + custom); changelog per version; SKILL.md frontmatter parsing; text-only validation; zip download; hash resolve; stats (downloads/stars/versions/comments).
|
||||
- Web app: home (highlighted + latest), search, skill detail (README, versions, tags, stats, files), upload UI, user profiles, stars, settings (profile + API tokens + delete account).
|
||||
- Social: stars + comments with moderation hooks; admin console for roles + highlighted curation.
|
||||
- Search: semantic/vector search over skill content with limit/approved filters.
|
||||
- Security: GitHub OAuth; role-based access (admin/moderator/user); audit logging for admin actions.
|
||||
@@ -1,7 +0,0 @@
|
||||
# Deprecations
|
||||
|
||||
## Legacy /api routes (pre-v1)
|
||||
|
||||
- Deprecated: 2026-01-07
|
||||
- TODO: remove legacy `/api/*` and `/api/cli/*` routes after clients migrate to `/api/v1`.
|
||||
- Legacy handlers live in `convex/http.ts` and `convex/httpApi.ts`.
|
||||
@@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 Peter Steinberger
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -1,150 +0,0 @@
|
||||
# OpenClaw
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/openclaw/clawhub/actions/workflows/ci.yml?branch=main"><img src="https://img.shields.io/github/actions/workflow/status/openclaw/clawhub/ci.yml?branch=main&style=for-the-badge" alt="CI status"></a>
|
||||
<a href="https://discord.gg/clawd"><img src="https://img.shields.io/discord/1456350064065904867?label=Discord&logo=discord&logoColor=white&color=5865F2&style=for-the-badge" alt="Discord"></a>
|
||||
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg?style=for-the-badge" alt="MIT License"></a>
|
||||
</p>
|
||||
|
||||
OpenClaw is the **public skill registry for Clawdbot**: publish, version, and search text-based agent skills (a `SKILL.md` plus supporting files).
|
||||
It’s designed for fast browsing + a CLI-friendly API, with moderation hooks and vector search.
|
||||
|
||||
onlycrabs.ai is the **SOUL.md registry**: publish and share system lore the same way you publish skills.
|
||||
|
||||
Live: `https://clawhub.ai`
|
||||
onlycrabs.ai: `https://onlycrabs.ai`
|
||||
|
||||
## What you can do
|
||||
|
||||
- Browse skills + render their `SKILL.md`.
|
||||
- Publish new skill versions with changelogs + tags (including `latest`).
|
||||
- Browse souls + render their `SOUL.md`.
|
||||
- Publish new soul versions with changelogs + tags.
|
||||
- Search via embeddings (vector index) instead of brittle keywords.
|
||||
- Star + comment; admins/mods can curate and approve skills.
|
||||
|
||||
## onlycrabs.ai (SOUL.md registry)
|
||||
|
||||
- Entry point is host-based: `onlycrabs.ai`.
|
||||
- On the onlycrabs.ai host, the home page and nav default to souls.
|
||||
- On OpenClaw, souls live under `/souls`.
|
||||
- Soul bundles only accept `SOUL.md` for now (no extra files).
|
||||
|
||||
## How it works (high level)
|
||||
|
||||
- Web app: TanStack Start (React, Vite/Nitro).
|
||||
- Backend: Convex (DB + file storage + HTTP actions) + Convex Auth (GitHub OAuth).
|
||||
- Search: OpenAI embeddings (`text-embedding-3-small`) + Convex vector search.
|
||||
- API schema + routes: `packages/schema` (`clawhub-schema`).
|
||||
|
||||
## Telemetry
|
||||
|
||||
OpenClaw tracks minimal **install telemetry** (to compute install counts) when you run `clawhub sync` while logged in.
|
||||
Disable via:
|
||||
|
||||
```bash
|
||||
export CLAWHUB_DISABLE_TELEMETRY=1
|
||||
```
|
||||
|
||||
Details: `docs/telemetry.md`.
|
||||
|
||||
## Repo layout
|
||||
|
||||
- `src/` — TanStack Start app (routes, components, styles).
|
||||
- `convex/` — schema + queries/mutations/actions + HTTP API routes.
|
||||
- `packages/schema/` — shared API types/routes for the CLI and app.
|
||||
- `docs/spec.md` — product + implementation spec (good first read).
|
||||
|
||||
## Local dev
|
||||
|
||||
Prereqs: Bun + Convex CLI.
|
||||
|
||||
```bash
|
||||
bun install
|
||||
cp .env.local.example .env.local
|
||||
|
||||
# terminal A: web app
|
||||
bun run dev
|
||||
|
||||
# terminal B: Convex dev deployment
|
||||
bunx convex dev
|
||||
```
|
||||
|
||||
## Auth (GitHub OAuth) setup
|
||||
|
||||
Create a GitHub OAuth App, set `AUTH_GITHUB_ID` / `AUTH_GITHUB_SECRET`, then:
|
||||
|
||||
```bash
|
||||
bunx auth --deployment-name <deployment> --web-server-url http://localhost:3000
|
||||
```
|
||||
|
||||
This writes `JWT_PRIVATE_KEY` + `JWKS` to the deployment and prints values for your local `.env.local`.
|
||||
|
||||
## Environment
|
||||
|
||||
- `VITE_CONVEX_URL`: Convex deployment URL (`https://<deployment>.convex.cloud`).
|
||||
- `VITE_CONVEX_SITE_URL`: Convex site URL (`https://<deployment>.convex.site`).
|
||||
- `VITE_SOULHUB_SITE_URL`: onlycrabs.ai site URL (`https://onlycrabs.ai`).
|
||||
- `VITE_SOULHUB_HOST`: onlycrabs.ai host match (`onlycrabs.ai`).
|
||||
- `VITE_SITE_MODE`: Optional override (`skills` or `souls`) for SSR builds.
|
||||
- `CONVEX_SITE_URL`: same as `VITE_CONVEX_SITE_URL` (auth + cookies).
|
||||
- `SITE_URL`: App URL (local: `http://localhost:3000`).
|
||||
- `AUTH_GITHUB_ID` / `AUTH_GITHUB_SECRET`: GitHub OAuth App.
|
||||
- `JWT_PRIVATE_KEY` / `JWKS`: Convex Auth keys.
|
||||
- `OPENAI_API_KEY`: embeddings for search + indexing.
|
||||
|
||||
## Nix plugins (nixmode skills)
|
||||
|
||||
OpenClaw can store a nix-clawdbot plugin pointer in SKILL frontmatter so the registry knows which
|
||||
Nix package bundle to install. A nix plugin is different from a regular skill pack: it bundles the
|
||||
skill pack, the CLI binary, and its config flags/requirements together.
|
||||
|
||||
Add this to `SKILL.md`:
|
||||
|
||||
```yaml
|
||||
---
|
||||
name: peekaboo
|
||||
description: Capture and automate macOS UI with the Peekaboo CLI.
|
||||
metadata: {"clawdbot":{"nix":{"plugin":"github:clawdbot/nix-steipete-tools?dir=tools/peekaboo","systems":["aarch64-darwin"]}}}
|
||||
---
|
||||
```
|
||||
|
||||
Install via nix-clawdbot:
|
||||
|
||||
```nix
|
||||
programs.clawdbot.plugins = [
|
||||
{ source = "github:clawdbot/nix-steipete-tools?dir=tools/peekaboo"; }
|
||||
];
|
||||
```
|
||||
|
||||
You can also declare config requirements + an example snippet:
|
||||
|
||||
```yaml
|
||||
---
|
||||
name: padel
|
||||
description: Check padel court availability and manage bookings via Playtomic.
|
||||
metadata: {"clawdbot":{"config":{"requiredEnv":["PADEL_AUTH_FILE"],"stateDirs":[".config/padel"],"example":"config = { env = { PADEL_AUTH_FILE = \\\"/run/agenix/padel-auth\\\"; }; };"}}}
|
||||
---
|
||||
```
|
||||
|
||||
To show CLI help (recommended for nix plugins), include the `cli --help` output:
|
||||
|
||||
```yaml
|
||||
---
|
||||
name: padel
|
||||
description: Check padel court availability and manage bookings via Playtomic.
|
||||
metadata: {"clawdbot":{"cliHelp":"padel --help\\nUsage: padel [command]\\n"}}
|
||||
---
|
||||
```
|
||||
|
||||
`metadata.clawdbot` is preferred, but `metadata.clawdis` is accepted as an alias for compatibility.
|
||||
|
||||
## Scripts
|
||||
|
||||
```bash
|
||||
bun run dev
|
||||
bun run build
|
||||
bun run test
|
||||
bun run coverage
|
||||
bun run lint
|
||||
```
|
||||
@@ -1,41 +0,0 @@
|
||||
{
|
||||
"$schema": "https://biomejs.dev/schemas/2.3.13/schema.json",
|
||||
"files": {
|
||||
"includes": [
|
||||
"**",
|
||||
"!**/.cta.json",
|
||||
"!**/.vscode",
|
||||
"!**/node_modules",
|
||||
"!**/dist",
|
||||
"!**/.output",
|
||||
"!**/coverage",
|
||||
"!**/convex/_generated",
|
||||
"!**/test-results",
|
||||
"!**/src/routeTree.gen.ts",
|
||||
"!**/.tanstack",
|
||||
"!**/public",
|
||||
"!**/.devenv",
|
||||
"!**/.devenv"
|
||||
]
|
||||
},
|
||||
"assist": { "actions": { "source": { "organizeImports": "on" } } },
|
||||
"formatter": {
|
||||
"enabled": true,
|
||||
"indentStyle": "space",
|
||||
"indentWidth": 2,
|
||||
"lineWidth": 100
|
||||
},
|
||||
"linter": {
|
||||
"enabled": true,
|
||||
"rules": {
|
||||
"recommended": true
|
||||
}
|
||||
},
|
||||
"javascript": {
|
||||
"formatter": {
|
||||
"quoteStyle": "single",
|
||||
"semicolons": "asNeeded",
|
||||
"trailingCommas": "all"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
#!/usr/bin/env bun
|
||||
import { existsSync } from 'node:fs'
|
||||
import { stat } from 'node:fs/promises'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
const distCliUrl = new URL('./packages/clawdhub/dist/cli.js', import.meta.url)
|
||||
const distCliPath = fileURLToPath(distCliUrl)
|
||||
const srcRootPath = fileURLToPath(new URL('./packages/clawdhub/src/', import.meta.url))
|
||||
|
||||
const shouldBuild = await (async () => {
|
||||
if (!existsSync(distCliPath)) return true
|
||||
try {
|
||||
const dist = await stat(distCliPath)
|
||||
const latestSrcMtime = await getLatestMtime(srcRootPath)
|
||||
return latestSrcMtime > dist.mtimeMs
|
||||
} catch {
|
||||
return true
|
||||
}
|
||||
})()
|
||||
|
||||
if (shouldBuild) {
|
||||
const proc = Bun.spawn(['bunx', 'tsc', '-p', 'packages/clawdhub/tsconfig.json'], {
|
||||
stdin: 'inherit',
|
||||
stdout: 'inherit',
|
||||
stderr: 'inherit',
|
||||
})
|
||||
const code = await proc.exited
|
||||
if (code !== 0) process.exit(code)
|
||||
}
|
||||
|
||||
await import(distCliUrl.href)
|
||||
|
||||
async function getLatestMtime(root: string) {
|
||||
let latest = 0
|
||||
const glob = new Bun.Glob('**/*.ts')
|
||||
for await (const rel of glob.scan({ cwd: root, onlyFiles: true })) {
|
||||
const path = `${root}${root.endsWith('/') ? '' : '/'}${rel}`
|
||||
try {
|
||||
const entry = await stat(path)
|
||||
latest = Math.max(latest, entry.mtimeMs)
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
return latest
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
#!/usr/bin/env bun
|
||||
import { existsSync } from 'node:fs'
|
||||
import { stat } from 'node:fs/promises'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
const distCliUrl = new URL('./packages/clawdhub/dist/cli.js', import.meta.url)
|
||||
const distCliPath = fileURLToPath(distCliUrl)
|
||||
const srcRootPath = fileURLToPath(new URL('./packages/clawdhub/src/', import.meta.url))
|
||||
|
||||
const shouldBuild = await (async () => {
|
||||
if (!existsSync(distCliPath)) return true
|
||||
try {
|
||||
const dist = await stat(distCliPath)
|
||||
const latestSrcMtime = await getLatestMtime(srcRootPath)
|
||||
return latestSrcMtime > dist.mtimeMs
|
||||
} catch {
|
||||
return true
|
||||
}
|
||||
})()
|
||||
|
||||
if (shouldBuild) {
|
||||
const proc = Bun.spawn(['bunx', 'tsc', '-p', 'packages/clawdhub/tsconfig.json'], {
|
||||
stdin: 'inherit',
|
||||
stdout: 'inherit',
|
||||
stderr: 'inherit',
|
||||
})
|
||||
const code = await proc.exited
|
||||
if (code !== 0) process.exit(code)
|
||||
}
|
||||
|
||||
await import(distCliUrl.href)
|
||||
|
||||
async function getLatestMtime(root: string) {
|
||||
let latest = 0
|
||||
const glob = new Bun.Glob('**/*.ts')
|
||||
for await (const rel of glob.scan({ cwd: root, onlyFiles: true })) {
|
||||
const path = `${root}${root.endsWith('/') ? '' : '/'}${rel}`
|
||||
try {
|
||||
const entry = await stat(path)
|
||||
latest = Math.max(latest, entry.mtimeMs)
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
return latest
|
||||
}
|
||||
|
After Width: | Height: | Size: 832 KiB |
|
After Width: | Height: | Size: 67 KiB |
|
After Width: | Height: | Size: 112 KiB |
|
After Width: | Height: | Size: 214 KiB |
|
After Width: | Height: | Size: 835 KiB |
|
After Width: | Height: | Size: 69 KiB |
|
After Width: | Height: | Size: 116 KiB |
|
After Width: | Height: | Size: 210 KiB |
@@ -0,0 +1,23 @@
|
||||
# ClawHub UI Proof
|
||||
Status: pass
|
||||
Scenario: `/Users/patrickerichsen/.codex/worktrees/68a3/clawhub/.artifacts/proof-scenarios/sample-text-before-after.pw.ts`
|
||||
Baseline: `origin/main`
|
||||
Candidate: `worktree`
|
||||
Provider: `hetzner`
|
||||
## Artifacts
|
||||
### baseline
|
||||
|
||||
- Output: `/Users/patrickerichsen/.codex/worktrees/68a3/clawhub/.artifacts/clawhub-ui-proof/2026-05-13T00-12-37-146Z/baseline`
|
||||
- pass: baseline /skills - `baseline/screenshots/baseline-skills.png`
|
||||
- pass: baseline /plugins - `baseline/screenshots/baseline-plugins.png`
|
||||
- pass: baseline /souls - `baseline/screenshots/baseline-souls.png`
|
||||
- Video: `baseline/full-run.mp4`
|
||||
|
||||
### candidate
|
||||
|
||||
- Output: `/Users/patrickerichsen/.codex/worktrees/68a3/clawhub/.artifacts/clawhub-ui-proof/2026-05-13T00-12-37-146Z/candidate`
|
||||
- pass: candidate /skills - `candidate/screenshots/candidate-skills.png`
|
||||
- pass: candidate /plugins - `candidate/screenshots/candidate-plugins.png`
|
||||
- pass: candidate /souls - `candidate/screenshots/candidate-souls.png`
|
||||
- Video: `candidate/full-run.mp4`
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
{
|
||||
"baseline": "origin/main",
|
||||
"candidate": "worktree",
|
||||
"generatedAt": "2026-05-13T00:12:37.148Z",
|
||||
"lanes": [
|
||||
{
|
||||
"localOutputDir": "/Users/patrickerichsen/.codex/worktrees/68a3/clawhub/.artifacts/clawhub-ui-proof/2026-05-13T00-12-37-146Z/baseline",
|
||||
"name": "baseline",
|
||||
"ref": "origin/main",
|
||||
"remoteOutputDir": "/work/crabbox/cbx_2ac97d8c7cd2/clawhub/.artifacts/clawhub-ui-proof/remote-2026-05-13T00-12-37-146Z/baseline",
|
||||
"status": "pass",
|
||||
"steps": [
|
||||
{
|
||||
"lane": "baseline",
|
||||
"name": "baseline /skills",
|
||||
"screenshot": "screenshots/baseline-skills.png",
|
||||
"slug": "baseline-skills",
|
||||
"status": "pass"
|
||||
},
|
||||
{
|
||||
"lane": "baseline",
|
||||
"name": "baseline /plugins",
|
||||
"screenshot": "screenshots/baseline-plugins.png",
|
||||
"slug": "baseline-plugins",
|
||||
"status": "pass"
|
||||
},
|
||||
{
|
||||
"lane": "baseline",
|
||||
"name": "baseline /souls",
|
||||
"screenshot": "screenshots/baseline-souls.png",
|
||||
"slug": "baseline-souls",
|
||||
"status": "pass"
|
||||
}
|
||||
],
|
||||
"videoPath": "/Users/patrickerichsen/.codex/worktrees/68a3/clawhub/.artifacts/clawhub-ui-proof/2026-05-13T00-12-37-146Z/baseline/full-run.mp4"
|
||||
},
|
||||
{
|
||||
"localOutputDir": "/Users/patrickerichsen/.codex/worktrees/68a3/clawhub/.artifacts/clawhub-ui-proof/2026-05-13T00-12-37-146Z/candidate",
|
||||
"name": "candidate",
|
||||
"ref": "worktree",
|
||||
"remoteOutputDir": "/work/crabbox/cbx_2ac97d8c7cd2/clawhub/.artifacts/clawhub-ui-proof/remote-2026-05-13T00-12-37-146Z/candidate",
|
||||
"status": "pass",
|
||||
"steps": [
|
||||
{
|
||||
"lane": "candidate",
|
||||
"name": "candidate /skills",
|
||||
"screenshot": "screenshots/candidate-skills.png",
|
||||
"slug": "candidate-skills",
|
||||
"status": "pass"
|
||||
},
|
||||
{
|
||||
"lane": "candidate",
|
||||
"name": "candidate /plugins",
|
||||
"screenshot": "screenshots/candidate-plugins.png",
|
||||
"slug": "candidate-plugins",
|
||||
"status": "pass"
|
||||
},
|
||||
{
|
||||
"lane": "candidate",
|
||||
"name": "candidate /souls",
|
||||
"screenshot": "screenshots/candidate-souls.png",
|
||||
"slug": "candidate-souls",
|
||||
"status": "pass"
|
||||
}
|
||||
],
|
||||
"videoPath": "/Users/patrickerichsen/.codex/worktrees/68a3/clawhub/.artifacts/clawhub-ui-proof/2026-05-13T00-12-37-146Z/candidate/full-run.mp4"
|
||||
}
|
||||
],
|
||||
"outputDir": "/Users/patrickerichsen/.codex/worktrees/68a3/clawhub/.artifacts/clawhub-ui-proof/2026-05-13T00-12-37-146Z",
|
||||
"provider": "hetzner",
|
||||
"scenario": "/Users/patrickerichsen/.codex/worktrees/68a3/clawhub/.artifacts/proof-scenarios/sample-text-before-after.pw.ts",
|
||||
"status": "pass",
|
||||
"crabbox": {
|
||||
"createdLease": true,
|
||||
"leaseId": "cbx_2ac97d8c7cd2"
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 29 KiB |
@@ -0,0 +1,11 @@
|
||||
# ClawHub UI Proof
|
||||
|
||||
Status: pass
|
||||
Mode: `feature`
|
||||
Scenario: `e2e/local-auth/security-scan-management-proof.pw.test.ts`
|
||||
Provider: `local-auth`
|
||||
|
||||
## Artifacts
|
||||
|
||||
- pass: Desktop management security scans - `candidate/screenshots/desktop-security-scans.png`
|
||||
- pass: Mobile management security scans - `candidate/screenshots/mobile-security-scans.png`
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"baseline": "not run",
|
||||
"candidate": "pe/security-scan-admin-tooling",
|
||||
"generatedAt": "2026-05-18T21:32:12.809Z",
|
||||
"lanes": [
|
||||
{
|
||||
"localOutputDir": "/Users/patrickerichsen/Git/openclaw/clawhub/.artifacts/clawhub-ui-proof/2026-05-18T21-29-29Z-security-scans/candidate",
|
||||
"name": "candidate",
|
||||
"ref": "pe/security-scan-admin-tooling",
|
||||
"status": "pass",
|
||||
"steps": [
|
||||
{
|
||||
"lane": "candidate",
|
||||
"name": "Desktop management security scans",
|
||||
"screenshot": "screenshots/desktop-security-scans.png",
|
||||
"slug": "desktop-security-scans",
|
||||
"status": "pass"
|
||||
},
|
||||
{
|
||||
"lane": "candidate",
|
||||
"name": "Mobile management security scans",
|
||||
"screenshot": "screenshots/mobile-security-scans.png",
|
||||
"slug": "mobile-security-scans",
|
||||
"status": "pass"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"mode": "feature",
|
||||
"outputDir": "/Users/patrickerichsen/Git/openclaw/clawhub/.artifacts/clawhub-ui-proof/2026-05-18T21-29-29Z-security-scans",
|
||||
"provider": "local-auth",
|
||||
"scenario": "e2e/local-auth/security-scan-management-proof.pw.test.ts",
|
||||
"status": "pass"
|
||||
}
|
||||
|
After Width: | Height: | Size: 9.8 KiB |
|
After Width: | Height: | Size: 100 KiB |
@@ -0,0 +1,5 @@
|
||||
# Owner-Scoped Skill Slugs UI Proof
|
||||
|
||||
- Scenario: owner-scoped skill slug UI surfaces.
|
||||
- Skill detail page proof: owner-qualified route and install command render as `@local/padel`.
|
||||
- Install command proof: copyable command uses `openclaw skills install @local/padel`.
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"status": "passed",
|
||||
"mode": "feature",
|
||||
"scenario": "owner-scoped skill slug UI surfaces",
|
||||
"provider": "Codex local browser proof",
|
||||
"candidate": "pe/owner-scoped-skill-slugs",
|
||||
"lanes": [
|
||||
{
|
||||
"name": "owner-scoped-skill-slugs",
|
||||
"steps": [
|
||||
{
|
||||
"name": "Skill detail page shows owner-qualified route and install ref",
|
||||
"slug": "skill-page-owner-ref",
|
||||
"status": "passed",
|
||||
"screenshot": "skill-page-owner-ref.png"
|
||||
},
|
||||
{
|
||||
"name": "Install command uses @owner/slug",
|
||||
"slug": "install-command-owner-ref",
|
||||
"status": "passed",
|
||||
"screenshot": "install-command-owner-ref.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 593 KiB |
|
After Width: | Height: | Size: 611 KiB |
|
After Width: | Height: | Size: 512 KiB |
@@ -0,0 +1,7 @@
|
||||
# Management Security Scan Overview
|
||||
|
||||
Feature proof for PR #2403.
|
||||
|
||||
- Desktop overview shows ClawScan-first current verdict totals, pipeline status, recent scan window, category rollups, and failed scan samples.
|
||||
- Desktop drilldown shows a selected artifact with ClawScan verdict/category/summary first, followed by pipeline status and supporting scanner evidence.
|
||||
- Mobile view keeps the management security overview usable at narrow width without overlapping controls.
|
||||
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"status": "passed",
|
||||
"mode": "feature",
|
||||
"scenario": "management-security-scan-overview",
|
||||
"provider": "local-playwright",
|
||||
"candidate": "pe/clawscan-visibility",
|
||||
"lanes": [
|
||||
{
|
||||
"name": "candidate",
|
||||
"steps": [
|
||||
{
|
||||
"name": "Management security overview",
|
||||
"slug": "management-security-overview-desktop",
|
||||
"status": "passed",
|
||||
"screenshot": "management-security-overview-desktop.png"
|
||||
},
|
||||
{
|
||||
"name": "Artifact drilldown",
|
||||
"slug": "management-security-drilldown-desktop",
|
||||
"status": "passed",
|
||||
"screenshot": "management-security-drilldown-desktop.png"
|
||||
},
|
||||
{
|
||||
"name": "Mobile management security overview",
|
||||
"slug": "management-security-mobile",
|
||||
"status": "passed",
|
||||
"screenshot": "management-security-mobile.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 162 KiB |
|
After Width: | Height: | Size: 59 KiB |
|
After Width: | Height: | Size: 161 KiB |
|
After Width: | Height: | Size: 61 KiB |
@@ -0,0 +1,12 @@
|
||||
# ClawHub UI Proof
|
||||
|
||||
Status: pass
|
||||
Scenario: Skill grid card metadata layout with nearby skills
|
||||
|
||||
Screenshots:
|
||||
- baseline desktop: baseline/screenshots/desktop-grid-context.png
|
||||
- candidate desktop: candidate/screenshots/desktop-grid-context.png
|
||||
- baseline mobile: baseline/screenshots/mobile-grid-context.png
|
||||
- candidate mobile: candidate/screenshots/mobile-grid-context.png
|
||||
|
||||
Observed target card: Self-Improving + Proactive Agent.
|
||||
@@ -0,0 +1,156 @@
|
||||
{
|
||||
"baseline": "origin/main",
|
||||
"candidate": "jesse/fix-skill-card-date-overlap",
|
||||
"generatedAt": "2026-06-01T16:29:49.092Z",
|
||||
"lanes": [
|
||||
{
|
||||
"name": "baseline",
|
||||
"lane": "baseline",
|
||||
"ref": "origin/main",
|
||||
"baseURL": "http://127.0.0.1:3038",
|
||||
"localOutputDir": "/Users/jmerhi/repos/claw-working-space/clawhub-fix-skill-card-date-overlap/.artifacts/clawhub-ui-proof/skill-card-grid-context-1780331337362/baseline",
|
||||
"status": "pass",
|
||||
"steps": [
|
||||
{
|
||||
"name": "Desktop skills grid context",
|
||||
"slug": "desktop-grid-context",
|
||||
"screenshot": "screenshots/desktop-grid-context.png",
|
||||
"status": "pass"
|
||||
},
|
||||
{
|
||||
"name": "Mobile skills grid context",
|
||||
"slug": "mobile-grid-context",
|
||||
"screenshot": "screenshots/mobile-grid-context.png",
|
||||
"status": "pass"
|
||||
}
|
||||
],
|
||||
"metrics": [
|
||||
{
|
||||
"step": "desktop grid context",
|
||||
"viewport": "desktop",
|
||||
"children": [
|
||||
{
|
||||
"className": "skill-card-tags",
|
||||
"text": "LinuxmacOSWindows"
|
||||
},
|
||||
{
|
||||
"className": "skill-card-header",
|
||||
"text": "Self-Improving + Proactive Agent"
|
||||
},
|
||||
{
|
||||
"className": "skill-card-summary",
|
||||
"text": "Self-reflection + Self-criticism + Self-learning + Self-organizing memory. Agent evaluates its own work, catches mistakes, and improves permanently. Use when..."
|
||||
},
|
||||
{
|
||||
"className": "skill-card-footer",
|
||||
"text": "by@ivangdavilaUpdated 3w ago1.2k·195k"
|
||||
}
|
||||
],
|
||||
"tagsBelowSummary": false,
|
||||
"authorToUpdatedGap": 14
|
||||
},
|
||||
{
|
||||
"step": "mobile grid context",
|
||||
"viewport": "mobile",
|
||||
"children": [
|
||||
{
|
||||
"className": "skill-card-tags",
|
||||
"text": "LinuxmacOSWindows"
|
||||
},
|
||||
{
|
||||
"className": "skill-card-header",
|
||||
"text": "Self-Improving + Proactive Agent"
|
||||
},
|
||||
{
|
||||
"className": "skill-card-summary",
|
||||
"text": "Self-reflection + Self-criticism + Self-learning + Self-organizing memory. Agent evaluates its own work, catches mistakes, and improves permanently. Use when..."
|
||||
},
|
||||
{
|
||||
"className": "skill-card-footer",
|
||||
"text": "by@ivangdavilaUpdated 3w ago1.2k·195k"
|
||||
}
|
||||
],
|
||||
"tagsBelowSummary": false,
|
||||
"authorToUpdatedGap": 14
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "candidate",
|
||||
"lane": "candidate",
|
||||
"ref": "jesse/fix-skill-card-date-overlap",
|
||||
"baseURL": "http://127.0.0.1:3037",
|
||||
"localOutputDir": "/Users/jmerhi/repos/claw-working-space/clawhub-fix-skill-card-date-overlap/.artifacts/clawhub-ui-proof/skill-card-grid-context-1780331337362/candidate",
|
||||
"status": "pass",
|
||||
"steps": [
|
||||
{
|
||||
"name": "Desktop skills grid context",
|
||||
"slug": "desktop-grid-context",
|
||||
"screenshot": "screenshots/desktop-grid-context.png",
|
||||
"status": "pass"
|
||||
},
|
||||
{
|
||||
"name": "Mobile skills grid context",
|
||||
"slug": "mobile-grid-context",
|
||||
"screenshot": "screenshots/mobile-grid-context.png",
|
||||
"status": "pass"
|
||||
}
|
||||
],
|
||||
"metrics": [
|
||||
{
|
||||
"step": "desktop grid context",
|
||||
"viewport": "desktop",
|
||||
"children": [
|
||||
{
|
||||
"className": "skill-card-header",
|
||||
"text": "Self-Improving + Proactive Agent"
|
||||
},
|
||||
{
|
||||
"className": "skill-card-summary",
|
||||
"text": "Self-reflection + Self-criticism + Self-learning + Self-organizing memory. Agent evaluates its own work, catches mistakes, and improves permanently. Use when..."
|
||||
},
|
||||
{
|
||||
"className": "skill-card-tags",
|
||||
"text": "LinuxmacOSWindows"
|
||||
},
|
||||
{
|
||||
"className": "skill-card-footer",
|
||||
"text": "by@ivangdavilaUpdated 3w ago1.2k·195k"
|
||||
}
|
||||
],
|
||||
"tagsBelowSummary": true,
|
||||
"authorToUpdatedGap": 8
|
||||
},
|
||||
{
|
||||
"step": "mobile grid context",
|
||||
"viewport": "mobile",
|
||||
"children": [
|
||||
{
|
||||
"className": "skill-card-header",
|
||||
"text": "Self-Improving + Proactive Agent"
|
||||
},
|
||||
{
|
||||
"className": "skill-card-summary",
|
||||
"text": "Self-reflection + Self-criticism + Self-learning + Self-organizing memory. Agent evaluates its own work, catches mistakes, and improves permanently. Use when..."
|
||||
},
|
||||
{
|
||||
"className": "skill-card-tags",
|
||||
"text": "LinuxmacOSWindows"
|
||||
},
|
||||
{
|
||||
"className": "skill-card-footer",
|
||||
"text": "by@ivangdavilaUpdated 3w ago1.2k·195k"
|
||||
}
|
||||
],
|
||||
"tagsBelowSummary": true,
|
||||
"authorToUpdatedGap": 8
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"mode": "before-after",
|
||||
"outputDir": "/Users/jmerhi/repos/claw-working-space/clawhub-fix-skill-card-date-overlap/.artifacts/clawhub-ui-proof/skill-card-grid-context-1780331337362",
|
||||
"provider": "local",
|
||||
"scenario": "Skill grid card metadata layout with nearby skills",
|
||||
"status": "pass"
|
||||
}
|
||||
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 19 KiB |
@@ -0,0 +1,6 @@
|
||||
# ClawHub UI Proof
|
||||
|
||||
Status: pass
|
||||
Mode: before-after
|
||||
Scenario: Skill grid card metadata layout
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"baseline": "origin/main",
|
||||
"candidate": "jesse/fix-skill-card-date-overlap",
|
||||
"lanes": [
|
||||
{
|
||||
"baseURL": "http://127.0.0.1:3038",
|
||||
"lane": "baseline",
|
||||
"name": "baseline",
|
||||
"localOutputDir": "/Users/jmerhi/repos/claw-working-space/clawhub-fix-skill-card-date-overlap/.artifacts/clawhub-ui-proof/skill-card-metadata-1780328491887/baseline",
|
||||
"ref": "origin/main",
|
||||
"status": "pass",
|
||||
"steps": [
|
||||
{
|
||||
"name": "Desktop skill card",
|
||||
"slug": "desktop-skill-card",
|
||||
"screenshot": "screenshots/desktop-skill-card.png",
|
||||
"status": "pass"
|
||||
},
|
||||
{
|
||||
"name": "Mobile skill card",
|
||||
"slug": "mobile-skill-card",
|
||||
"screenshot": "screenshots/mobile-skill-card.png",
|
||||
"status": "pass"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"baseURL": "http://127.0.0.1:3037",
|
||||
"lane": "candidate",
|
||||
"name": "candidate",
|
||||
"localOutputDir": "/Users/jmerhi/repos/claw-working-space/clawhub-fix-skill-card-date-overlap/.artifacts/clawhub-ui-proof/skill-card-metadata-1780328491887/candidate",
|
||||
"ref": "jesse/fix-skill-card-date-overlap",
|
||||
"status": "pass",
|
||||
"steps": [
|
||||
{
|
||||
"name": "Desktop skill card",
|
||||
"slug": "desktop-skill-card",
|
||||
"screenshot": "screenshots/desktop-skill-card.png",
|
||||
"status": "pass"
|
||||
},
|
||||
{
|
||||
"name": "Mobile skill card",
|
||||
"slug": "mobile-skill-card",
|
||||
"screenshot": "screenshots/mobile-skill-card.png",
|
||||
"status": "pass"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"mode": "before-after",
|
||||
"outputDir": "/Users/jmerhi/repos/claw-working-space/clawhub-fix-skill-card-date-overlap/.artifacts/clawhub-ui-proof/skill-card-metadata-1780328491887",
|
||||
"provider": "local",
|
||||
"scenario": "Skill grid card metadata layout",
|
||||
"status": "pass"
|
||||
}
|
||||
|
After Width: | Height: | Size: 74 KiB |
@@ -0,0 +1,14 @@
|
||||
# ClawHub UI Proof
|
||||
|
||||
Status: `passed`
|
||||
|
||||
Mode: `feature`
|
||||
|
||||
Scenario: `manual-plugin-download-counts`
|
||||
|
||||
Provider: `local-playwright`
|
||||
|
||||
## Candidate
|
||||
|
||||
- `http://127.0.0.1:3001/plugins/clawbits-openclaw-plugin`
|
||||
- Confirms plugin detail pages render `Downloads` as the first sidebar stat, above repository and owner metadata.
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"status": "passed",
|
||||
"mode": "feature",
|
||||
"scenario": "manual-plugin-download-counts",
|
||||
"provider": "local-playwright",
|
||||
"baseline": "not-run",
|
||||
"candidate": "pe/plugin-download-counts",
|
||||
"lanes": [
|
||||
{
|
||||
"name": "candidate",
|
||||
"steps": [
|
||||
{
|
||||
"name": "Plugin detail downloads top stat",
|
||||
"slug": "plugin-downloads-top",
|
||||
"status": "passed",
|
||||
"screenshot": "plugin-downloads-top.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 52 KiB |
@@ -0,0 +1,6 @@
|
||||
# ClawHub UI Proof
|
||||
|
||||
- Status: passed
|
||||
- Mode: feature
|
||||
- Scenario: plugin-list-downloads-sort
|
||||
- Proof: plugin list shows the Most downloaded sort option selected and download counts in list rows.
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"status": "passed",
|
||||
"mode": "feature",
|
||||
"scenario": "plugin-list-downloads-sort",
|
||||
"provider": "codex-in-app-browser",
|
||||
"candidate": "pe/plugin-download-counts",
|
||||
"lanes": [
|
||||
{
|
||||
"name": "candidate",
|
||||
"steps": [
|
||||
{
|
||||
"name": "Plugin list downloads and sort",
|
||||
"slug": "plugin-list-downloads-sort",
|
||||
"status": "passed",
|
||||
"screenshot": "plugin-list-downloads-sort.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 30 KiB |
@@ -0,0 +1,6 @@
|
||||
# ClawHub UI Proof
|
||||
|
||||
- Status: passed
|
||||
- Mode: feature
|
||||
- Scenario: plugin-list-no-family-badges
|
||||
- Proof: plugin list still shows download counts while Code Plugin and Bundle Plugin family badges are absent.
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"status": "passed",
|
||||
"mode": "feature",
|
||||
"scenario": "plugin-list-no-family-badges",
|
||||
"provider": "codex-in-app-browser",
|
||||
"candidate": "pe/plugin-download-counts",
|
||||
"lanes": [
|
||||
{
|
||||
"name": "candidate",
|
||||
"steps": [
|
||||
{
|
||||
"name": "Plugin list without family badges",
|
||||
"slug": "plugin-list-no-family-badges",
|
||||
"status": "passed",
|
||||
"screenshot": "plugin-list-no-family-badges.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 124 KiB |
@@ -0,0 +1,6 @@
|
||||
# PR #2520 proof
|
||||
|
||||
Status: pass
|
||||
|
||||
- Rendered the account-ban and artifact-level scanner rejection emails from the real email builders; the account-ban email no longer includes scan-results appeal guidance, while the artifact-level email still includes local scan guidance.
|
||||
- Captured the dedicated banned-account appeal page from a running local ClawHub preview after `/dashboard?error_description=Account%20banned` redirected to `/account-banned`.
|
||||
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"generatedAt": "2026-06-05T23:54:26.000Z",
|
||||
"mode": "feature",
|
||||
"status": "pass",
|
||||
"provider": "rendered email builder plus live in-app browser preview",
|
||||
"scenario": "account-ban email without scan-results block plus dedicated banned-account route",
|
||||
"candidate": "worktree 3b4cc2d9",
|
||||
"outputDir": ".artifacts/pr-2520-proof",
|
||||
"lanes": [
|
||||
{
|
||||
"name": "candidate",
|
||||
"ref": "worktree 3b4cc2d9",
|
||||
"status": "pass",
|
||||
"steps": [
|
||||
{
|
||||
"lane": "candidate",
|
||||
"name": "Rendered moderation emails",
|
||||
"slug": "rendered-emails",
|
||||
"status": "pass",
|
||||
"screenshot": "screenshots/rendered-emails.png"
|
||||
},
|
||||
{
|
||||
"lane": "candidate",
|
||||
"name": "Dedicated banned-account appeal page",
|
||||
"slug": "banned-sign-in",
|
||||
"status": "pass",
|
||||
"screenshot": "screenshots/banned-sign-in.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 77 KiB |
|
After Width: | Height: | Size: 119 KiB |
@@ -0,0 +1,6 @@
|
||||
# PR #2520 proof
|
||||
|
||||
Status: pass
|
||||
|
||||
- Rendered the account-ban and artifact-level scanner rejection emails from the real email builders.
|
||||
- Captured the banned-account sign-in copy from a full-stack local ClawHub preview with local Convex on `/dashboard?error_description=Account%20banned`.
|
||||
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"generatedAt": "2026-06-05T23:09:45.000Z",
|
||||
"mode": "feature",
|
||||
"status": "pass",
|
||||
"provider": "rendered email builder plus full-stack local-auth Playwright",
|
||||
"scenario": "email builder rendering plus live ClawHub dashboard auth-error route",
|
||||
"candidate": "worktree 03bc802e",
|
||||
"outputDir": ".artifacts/pr-2520-proof",
|
||||
"lanes": [
|
||||
{
|
||||
"name": "candidate",
|
||||
"ref": "worktree 03bc802e",
|
||||
"status": "pass",
|
||||
"steps": [
|
||||
{
|
||||
"lane": "candidate",
|
||||
"name": "Rendered moderation emails",
|
||||
"slug": "rendered-emails",
|
||||
"status": "pass",
|
||||
"screenshot": "screenshots/rendered-emails.png"
|
||||
},
|
||||
{
|
||||
"lane": "candidate",
|
||||
"name": "Live banned-account dashboard sign-in copy",
|
||||
"slug": "banned-sign-in",
|
||||
"status": "pass",
|
||||
"screenshot": "screenshots/banned-sign-in.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 77 KiB |
|
After Width: | Height: | Size: 119 KiB |
@@ -0,0 +1,6 @@
|
||||
# PR #2520 proof
|
||||
|
||||
Status: pass
|
||||
|
||||
- Rendered the account-ban and artifact-level scanner rejection emails from the real email builders.
|
||||
- Captured the banned-account sign-in copy from a full-stack local ClawHub preview with local Convex on `/dashboard?error_description=Account%20banned`.
|
||||
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"generatedAt": "2026-06-05T23:09:45.000Z",
|
||||
"mode": "feature",
|
||||
"status": "pass",
|
||||
"provider": "rendered email builder plus full-stack local-auth Playwright",
|
||||
"scenario": "email builder rendering plus live ClawHub dashboard auth-error route",
|
||||
"candidate": "worktree 03bc802e",
|
||||
"outputDir": ".artifacts/pr-2520-proof",
|
||||
"lanes": [
|
||||
{
|
||||
"name": "candidate",
|
||||
"ref": "worktree 03bc802e",
|
||||
"status": "pass",
|
||||
"steps": [
|
||||
{
|
||||
"lane": "candidate",
|
||||
"name": "Rendered moderation emails",
|
||||
"slug": "rendered-emails",
|
||||
"status": "pass",
|
||||
"screenshot": "screenshots/rendered-emails.png"
|
||||
},
|
||||
{
|
||||
"lane": "candidate",
|
||||
"name": "Live banned-account dashboard sign-in copy",
|
||||
"slug": "banned-sign-in",
|
||||
"status": "pass",
|
||||
"screenshot": "screenshots/banned-sign-in.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 63 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 350 KiB |
|
After Width: | Height: | Size: 332 KiB |
@@ -0,0 +1,13 @@
|
||||
# PR 2520 live local proof
|
||||
|
||||
Status: pass
|
||||
|
||||
Captured from a live local ClawHub dev server started with `bun run dev` at `http://localhost:3000`.
|
||||
|
||||
Screenshots cover:
|
||||
|
||||
- dedicated account-banned page at desktop and mobile widths
|
||||
- moderation email output generated from `convex/lib/emails.ts` and served through the same local ClawHub dev server
|
||||
- account-ban email appeal-only copy
|
||||
- skill rejection email with `clawhub scan download demo-skill --version 1.2.3`
|
||||
- plugin rejection email with `clawhub scan download @scope/demo --version 2.0.0 --kind plugin`
|
||||
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"status": "pass",
|
||||
"mode": "feature",
|
||||
"provider": "local ClawHub dev server",
|
||||
"localServer": "bun run dev -> http://localhost:3000",
|
||||
"commit": "03bcca63",
|
||||
"generatedAt": "2026-06-06T00:39:17.133Z",
|
||||
"screenshots": [
|
||||
{
|
||||
"slug": "account-banned-desktop",
|
||||
"url": "http://localhost:3000/account-banned",
|
||||
"viewport": {
|
||||
"width": 1440,
|
||||
"height": 980
|
||||
},
|
||||
"screenshot": "candidate/screenshots/account-banned-desktop.png"
|
||||
},
|
||||
{
|
||||
"slug": "account-banned-mobile",
|
||||
"url": "http://localhost:3000/account-banned",
|
||||
"viewport": {
|
||||
"width": 390,
|
||||
"height": 844
|
||||
},
|
||||
"screenshot": "candidate/screenshots/account-banned-mobile.png"
|
||||
},
|
||||
{
|
||||
"slug": "moderation-emails-desktop",
|
||||
"url": "http://localhost:3000/__pr-2520-email-proof.html",
|
||||
"viewport": {
|
||||
"width": 1440,
|
||||
"height": 1200
|
||||
},
|
||||
"screenshot": "candidate/screenshots/moderation-emails-desktop.png"
|
||||
},
|
||||
{
|
||||
"slug": "moderation-emails-mobile",
|
||||
"url": "http://localhost:3000/__pr-2520-email-proof.html",
|
||||
"viewport": {
|
||||
"width": 390,
|
||||
"height": 1200
|
||||
},
|
||||
"screenshot": "candidate/screenshots/moderation-emails-mobile.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 30 KiB |
@@ -0,0 +1,6 @@
|
||||
# ClawHub UI Proof
|
||||
|
||||
- Status: passed
|
||||
- Mode: feature
|
||||
- Scenario: plugin-list-no-family-badges
|
||||
- Proof: plugin list still shows download counts while Code Plugin and Bundle Plugin family badges are absent.
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"status": "passed",
|
||||
"mode": "feature",
|
||||
"scenario": "plugin-list-no-family-badges",
|
||||
"provider": "codex-in-app-browser",
|
||||
"candidate": "pe/plugin-download-counts",
|
||||
"lanes": [
|
||||
{
|
||||
"name": "candidate",
|
||||
"steps": [
|
||||
{
|
||||
"name": "Plugin list without family badges",
|
||||
"slug": "plugin-list-no-family-badges",
|
||||
"status": "passed",
|
||||
"screenshot": "plugin-list-no-family-badges.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 98 KiB |
|
After Width: | Height: | Size: 44 KiB |
@@ -0,0 +1,6 @@
|
||||
# ClawHub UI Proof
|
||||
|
||||
Status: pass
|
||||
|
||||
- Account deletion confirmation renders one row per affected skill/plugin, with icon, name, publisher handle, and type badge.
|
||||
- Post-cleanup navigation to the deleted plugin shows `Plugin not found`, confirming the resource was removed by the account deletion flow.
|
||||
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"status": "pass",
|
||||
"mode": "feature",
|
||||
"scenario": "e2e/local-auth/delete-account-resources.pw.test.ts",
|
||||
"provider": "local-auth Playwright",
|
||||
"baseline": null,
|
||||
"candidate": "pe/account-deletion-hard-delete",
|
||||
"generatedAt": "2026-06-06T00:37:39.268Z",
|
||||
"lanes": [
|
||||
{
|
||||
"name": "candidate",
|
||||
"ref": "pe/account-deletion-hard-delete",
|
||||
"status": "pass",
|
||||
"steps": [
|
||||
{
|
||||
"lane": "candidate",
|
||||
"name": "Account deletion confirmation lists each resource row",
|
||||
"screenshot": "screenshots/account-deletion-confirmation.png",
|
||||
"slug": "account-deletion-confirmation",
|
||||
"status": "pass"
|
||||
},
|
||||
{
|
||||
"lane": "candidate",
|
||||
"name": "Deleted plugin route shows resource removed",
|
||||
"screenshot": "screenshots/account-deletion-post-cleanup.png",
|
||||
"slug": "account-deletion-post-cleanup",
|
||||
"status": "pass"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 99 KiB |
|
After Width: | Height: | Size: 156 KiB |
@@ -0,0 +1,10 @@
|
||||
# Skill Settings Delete Action
|
||||
|
||||
Real-browser feature proof for the skill settings delete action.
|
||||
|
||||
- Route: local-auth seeded skill settings page
|
||||
- Browser: Playwright chromium
|
||||
- Candidate: pe/skill-settings-delete-action
|
||||
- Screenshots:
|
||||
- `local/delete-action.png`
|
||||
- `local/delete-dialog.png`
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"status": "passed",
|
||||
"mode": "feature",
|
||||
"scenario": "skill-settings-delete-action",
|
||||
"provider": "local-auth Playwright chromium",
|
||||
"candidate": "pe/skill-settings-delete-action",
|
||||
"lanes": [
|
||||
{
|
||||
"name": "local",
|
||||
"steps": [
|
||||
{
|
||||
"name": "Skill settings delete action",
|
||||
"slug": "delete-action",
|
||||
"status": "passed",
|
||||
"screenshot": "delete-action.png"
|
||||
},
|
||||
{
|
||||
"name": "Skill settings delete confirmation dialog",
|
||||
"slug": "delete-dialog",
|
||||
"status": "passed",
|
||||
"screenshot": "delete-dialog.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 505 KiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 439 KiB |
@@ -0,0 +1,11 @@
|
||||
# PR 2581 prod-backed UI proof
|
||||
|
||||
Status: passed
|
||||
Mode: feature
|
||||
Backend: production Convex read data (`wry-manatee-359`).
|
||||
Pages captured:
|
||||
- `/skills?sort=installs&dir=desc` showing prod skill rows and install sort.
|
||||
- `/search?q=swarm` showing prod search results.
|
||||
- `/chair4ce/swarm` showing a prod-backed skill detail page.
|
||||
|
||||
Note: default `/plugins` was not used because this PR head can request `sort=recommended`, which requires matching backend code that is not deployed to prod yet.
|
||||
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"status": "passed",
|
||||
"mode": "feature",
|
||||
"scenario": "manual prod-backed PR proof: skills browse, search, and detail",
|
||||
"provider": "local Playwright against http://127.0.0.1:3007 with prod Convex",
|
||||
"candidate": "PR #2581 rebased head f43b8ed3",
|
||||
"lanes": [
|
||||
{
|
||||
"name": "candidate",
|
||||
"steps": [
|
||||
{
|
||||
"name": "Skills browse sorted by installs",
|
||||
"slug": "skills-installs",
|
||||
"status": "passed",
|
||||
"screenshot": "skills-installs.png"
|
||||
},
|
||||
{
|
||||
"name": "Search results for swarm",
|
||||
"slug": "search-swarm",
|
||||
"status": "passed",
|
||||
"screenshot": "search-swarm.png"
|
||||
},
|
||||
{
|
||||
"name": "Skill detail for chair4ce/swarm",
|
||||
"slug": "skill-detail-swarm",
|
||||
"status": "passed",
|
||||
"screenshot": "skill-detail-swarm.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 691 KiB |
|
After Width: | Height: | Size: 62 KiB |
@@ -0,0 +1,5 @@
|
||||
# CLAW-283 Email Template Proof
|
||||
|
||||
- Rendered updated ClawHub transactional email templates with realistic sample data.
|
||||
- Rendered generic admin one-off email with sample title/body/action content.
|
||||
- Confirmed Plugin Inspector findings email renders without the removed ClawHub CTA button.
|
||||
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"status": "passed",
|
||||
"mode": "feature",
|
||||
"scenario": "CLAW-283 email template render proof",
|
||||
"provider": "local ClawHub email preview render",
|
||||
"candidate": "pe/claw-283-email-templates",
|
||||
"lanes": [
|
||||
{
|
||||
"name": "candidate",
|
||||
"steps": [
|
||||
{
|
||||
"name": "Rendered email template proof",
|
||||
"slug": "email-template-render-proof",
|
||||
"status": "passed",
|
||||
"screenshot": "email-template-render-proof.png"
|
||||
},
|
||||
{
|
||||
"name": "Generic one-off email proof",
|
||||
"slug": "admin-one-off-email",
|
||||
"status": "passed",
|
||||
"screenshot": "admin-one-off-email.png"
|
||||
},
|
||||
{
|
||||
"name": "Plugin Inspector findings proof",
|
||||
"slug": "plugin-inspector-findings",
|
||||
"status": "passed",
|
||||
"screenshot": "plugin-inspector-findings.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 98 KiB |
|
After Width: | Height: | Size: 96 KiB |