Repository navigation
docs: add a BetterMan verification skill and feature map - #306
amanthanvi wants to merge 23 commits into
Conversation
Teach agents how to launch the local app, run a read-only doctor check, and drive the UI with Playwright, including a feature map and an optional manual smoke workflow. Co-authored-by: Aman Thanvi <amanthanvi@users.noreply.github.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configuration
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Reviewer's GuideThis PR adds a project-local, loopback-isolated BetterMan verification system: extensive feature-map guidance, tmux-managed Convex/Next launch and health scripts, Playwright smoke/full-drive evidence capture, cleanup/reporting conventions, agent guidance, and an optional manually triggered CI workflow. Sequence diagram for the BetterMan verification smoke flowsequenceDiagram
participant Agent
participant Smoke as smoke.mjs
participant Doctor as doctor.mjs
participant Next as Next.js
participant Browser as Playwright
participant Evidence
Agent->>Smoke: pnpm verify:smoke
Smoke->>Doctor: checkHealth(baseUrl)
Doctor->>Next: GET /
Next-->>Doctor: Search box HTML
Doctor->>Next: GET /api/v1/info
Next-->>Doctor: pageCount
Doctor->>Next: GET /api/v1/search?q=tar&limit=5
Next-->>Doctor: tar(1) result
Doctor-->>Smoke: READY
Smoke->>Browser: run smoke.spec.ts
Browser->>Next: Open home
Browser->>Next: Search tar
Browser->>Next: Open tar(1)
Browser->>Evidence: Write screenshots and traces
Sequence diagram for launching and cleaning up BetterMansequenceDiagram
participant Agent
participant Launch as launch.mjs
participant Doctor as checkHealth
participant Convex as Convex tmux session
participant Next as Next tmux session
participant Cleanup as cleanup.mjs
participant Evidence
Agent->>Launch: pnpm verify:launch
Launch->>Doctor: checkHealth(baseUrl)
alt READY
Doctor-->>Launch: Existing instance ready
else Not ready and port available
Launch->>Convex: Start convex dev
Convex-->>Launch: Convex functions ready
Launch->>Next: Start Next.js dev
Next-->>Launch: Port 3000 ready
Launch->>Doctor: checkHealth(baseUrl)
alt empty-dataset
Launch->>Convex: Seed E2E fixture
Launch->>Next: Restart Next.js
Launch->>Doctor: checkHealth(baseUrl)
end
end
Launch->>Evidence: Create evidence directory
Agent->>Cleanup: pnpm verify:cleanup
Cleanup->>Convex: killTmuxSession
Cleanup->>Next: killTmuxSession
Cleanup-->>Agent: Evidence remains on disk
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
Seed an empty dataset without killing a foreign Next process, treat a stale info cache as ready when search returns tar(1), bind Next to 127.0.0.1, and match the section URL and JSON-LD locators the app actually emits. Co-authored-by: Aman Thanvi <amanthanvi@users.noreply.github.com>
|
Sorry @amanthanvi, you've used your own review budget of 250,000 diff characters for the last 7 days. You can request another review in 2 days and 10 hours by commenting |
[Low impact] The latest changes appear safe to merge and address the reported cleanup overwrite.
|
…tate Doctor refuses an IPv6-only listener and requires a hydration click before READY. Launch records each tmux session as it starts, keeps /tmp state private to the current user, and cleanup restores the files next dev rewrites. Co-authored-by: Aman Thanvi <amanthanvi@users.noreply.github.com>
pnpm inserts a -- before extra arguments. Drop that token so -g reaches Playwright instead of ending option parsing. Co-authored-by: Aman Thanvi <amanthanvi@users.noreply.github.com>
Scrub inherited Convex deploy credentials before setup and seed, and refuse any target that is not an anonymous loopback deployment. Key tmux sessions and the state directory by checkout, confirm the Next listener by pid, start time, and repo cwd, and wait for 127.0.0.1:3000 plus hydration after restart. Co-authored-by: Aman Thanvi <amanthanvi@users.noreply.github.com>
The test runner loads the specs as CommonJS, so importing runtime.mjs failed before any drive. Specs now read VERIFY_EVIDENCE_DIR, which the smoke wrapper already sets to this checkout's evidence directory. Co-authored-by: Aman Thanvi <amanthanvi@users.noreply.github.com>
The variant select is controlled. selectOption before its change listener is attached leaves the page on Debian. The drive now retries until the URL contains distro=ubuntu, matching the product end-to-end helper. Co-authored-by: Aman Thanvi <amanthanvi@users.noreply.github.com>
|
@greptileai review |
A cached /api/v1/info response can stay at pageCount 0 for an hour after seeding while search already returns tar(1). Doctor treats that as not ready, and launch deletes the Next fetch cache and waits until the count is positive. Co-authored-by: Aman Thanvi <amanthanvi@users.noreply.github.com>
Reuse a READY server only when its pid and start time still match this checkout. Listener capture stays on Linux /proc and exits with Linux-only elsewhere. The distro drive retries only a URL miss, three times. Co-authored-by: Aman Thanvi <amanthanvi@users.noreply.github.com>
A sibling directory such as the repo root plus a suffix no longer counts as this checkout. VERIFY_ID is 3 to 32 characters again, so ci is rejected. Co-authored-by: Aman Thanvi <amanthanvi@users.noreply.github.com>
|
@greptileai review |
Smoke exits with a message when the state directory belongs to another user. The convex env set child gets an allowlisted environment, so it does not inherit BETTERMAN_DATASET_STAGE. Co-authored-by: Aman Thanvi <amanthanvi@users.noreply.github.com>
|
@greptileai review |
A cwd or argv belongs to this checkout only when it equals the repo root or starts with that root plus a separator. A launch that exits before it owns Next unlinks the generated-file snapshot. tsc --noEmit over the skill passes with the path helper types. Co-authored-by: Aman Thanvi <amanthanvi@users.noreply.github.com>
Name the tsc project tsconfig.typecheck.json so Node does not apply its paths while loading the Playwright specs. Co-authored-by: Aman Thanvi <amanthanvi@users.noreply.github.com>
|
@greptileai review |
baseUrlParts uses isLoopbackUrl, so http://[::1] runs the Linux /proc check. Listener paths are resolved before the repo boundary check. Co-authored-by: Aman Thanvi <amanthanvi@users.noreply.github.com>
|
@greptileai review |
Launch exits 2 before starting servers when the base URL is http://[::1]:3000 and tells you to use http://127.0.0.1:3000. Doctor still treats [::1] as loopback. Co-authored-by: Aman Thanvi <amanthanvi@users.noreply.github.com>
|
@greptileai review |
A non-zero launch exit unlinks generated-snapshot.json only when this launch wrote it and bmv-<id>-next is not still running. Snapshot tests compare generated-file git status before and after, and skip the foreign directory check when /usr belongs to the current user. Co-authored-by: Aman Thanvi <amanthanvi@users.noreply.github.com>
|
@greptileai review |
A non-zero launch unlinks generated-snapshot.json unless a live owned bmv-<id>-next session exists. Cleanup leaves next-env.d.ts in place when that file was edited after the snapshot. Co-authored-by: Aman Thanvi <amanthanvi@users.noreply.github.com>
|
@greptileai review |
* docs: record CodeRabbit and Greptile feedback census Capture recurring review findings from PRs #306 and #318-#326 for the cleanup recall step, including counts, example links, and guards. Co-authored-by: Aman Thanvi <amanthanvi@users.noreply.github.com> * docs: qualify stacked CodeRabbit coverage Greptile noted that #322 did receive a completed review. CodeRabbit's markdownlint MD018 warning was a line that started with a pull-request number. Co-authored-by: Aman Thanvi <amanthanvi@users.noreply.github.com> * docs: record that project 5 is not visible to this token The cleanup board already exists. Item creation and repo linking both fail with user.projectV2, and this app owns no duplicate project. Co-authored-by: Aman Thanvi <amanthanvi@users.noreply.github.com> * docs: state the project query result directly Say that every project query from this token fails the same way, and that the three draft titles are still unfiled. Co-authored-by: Aman Thanvi <amanthanvi@users.noreply.github.com> * docs: fold PR Checker findings into the feedback census Add checker themes for ingest status, the 512-page batch, and checkpoint edges, list the seven unthemed bot threads, and correct the CodeRabbit and test-config claims. Co-authored-by: Aman Thanvi <amanthanvi@users.noreply.github.com> * docs: note main rate limits and who files the board items Pull requests into main also spend CodeRabbit's hourly review. The three draft titles on project 5 will be filed by the repo owner's bots. Co-authored-by: Aman Thanvi <amanthanvi@users.noreply.github.com> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Aman Thanvi <amanthanvi@users.noreply.github.com>
What
Adds a project-local verification skill at
.agents/skills/verify-betterman/(linked from.cursor/skills/verify-betterman) plus a feature map, helper scripts, and an optional manual smoke workflow.pnpm verify:launchstarts Convex and Next onhttp://127.0.0.1:3000only when that port is free. Next binds with--hostname 127.0.0.1. Session names and the state directory are per checkout.VERIFY_IDis 3 to 32 characters of lowercase letters, digits, or hyphens. A 2-character value was briefly accepted so aciproof could run. That widening is reverted.VERIFY_ID=ciis rejected withVERIFY_ID must be 3-32 characters of lowercase letters, digits, or hyphens. The manual workflow setsVERIFY_ID=cix.REUSEDonly when doctor isREADYand the live listener matches the recorded pid and start time and is under this repo. Otherwise it exits 2 and leaves that process running. The message says to stop that process yourself, then runpnpm verify:launchagain.path.resolve, equals this repo root or starts with that root plus a path separator. A sibling such as<repoRoot>-otherdoes not match, a path that uses..to leave the checkout does not match, and neither does an argument that only contains the root, such as--config=<repoRoot>/nextjs. A listener that fails the check is refused. Launch exits 2, does not seed it, and does not stop it.pnpm verify:smokeandpnpm verify:driverefuse unless that same pid, start time, repo, and Next session match. When the state directory belongs to another user, smoke printssmoke: refusing <dir>: owned by uid ...and exits 1./procfor a loopback base URL. Loopback is127.0.0.1,localhost, or[::1], so doctor runs that check forhttp://[::1]. A doctor URL that is not loopback skips it. On any other platform, the loopback check exits 2 and printsLinux-only.http://[::1]:3000with exit 2 before it creates state or starts Convex or Next. The message says to usehttp://127.0.0.1:3000. Next is started with--hostname 127.0.0.1.[::1].npx convex env setreceives an allowlisted environment (PATH,HOME,USER,LOGNAME,SHELL, locale and temp variables,NVM_DIR,PNPM_HOME,CONVEX_AGENT_MODE=anonymous, ananonymous:deployment name, and the loopback Convex URLs). That child does not receiveBETTERMAN_DATASET_STAGEorCONVEX_DEPLOY_KEY. The seed process setsBETTERMAN_DATASET_STAGE=proditself. Doctor isREADYonly when/api/v1/inforeportspageCountgreater than 0.generated-snapshot.jsononly after it owns the Next server, and only before that server starts. A non-zero exit deletes that file whenbmv-<id>-nextis not running, including a stale snapshot whose Next process already died, and leaves it when that session is still running. Cleanup restores an owned snapshot. Cleanup does not overwritenextjs/next-env.d.tsedited after the snapshot. If a file changed since a snapshot this checkout does not own, cleanup leaves the file in place, warns, and copies it undergenerated-backup/.0700.run.jsonand the other state files are mode0600.scripts/verify-paths.d.ctstypes the CommonJS path helper imported byevidence.ts.pnpm verify:typecheckrunstsc --noEmit -p .agents/skills/verify-betterman/tsconfig.typecheck.json. The project is not namedtsconfig.json, so Node does not apply itspathswhile loading the Playwright specs.nextjs/tsconfig.jsonandconvex/tsconfig.jsondo not include.agents..github/workflows/verify-smoke.ymlisworkflow_dispatchonly, withpermissions: contents: read. It setsVERIFY_ID=cixand uploads/tmp/betterman-verify-cix/evidence.Why
Agents need a scripted way to launch BetterMan, drive it like a reader, and attach evidence. The feature map is the sweep order and the per-feature driving notes.
Checklist
pnpm verify:doctorandpnpm verify:driverecorded below after a local run.CHANGELOG.mdupdated under Unreleased.pnpm next:lint,pnpm next:grammar,pnpm next:test(not required: no Next.js or Convex code changes)pnpm ingest:lint,pnpm ingest:test(not required: no ingestion changes)How launch actually behaves
127.0.0.1,localhost, or[::1]) and/procis missing, launch and doctor exit 2 withLinux-only. A doctor URL that is not loopback skips that listener check. Launch refuseshttp://[::1]before that check and before any server starts.READYandrun.jsonmatches the listener pid and start time, and that process is under this repo, launch printsREUSEDand exits 0. If the pid, start time, or repo does not match, launch exits 2 and leaves that process running. A non-zero exit deletesgenerated-snapshot.jsonwhenbmv-<id>-nextis not running, and leaves the snapshot when that session is still live.path.resolve, launch exits 2 without seeding. It deletesgenerated-snapshot.jsonwhenbmv-<id>-nextis not running, and leaves the snapshot when that session is still live. When the listener belongs to this repo, launch may seed it and leave that process running./tmp/betterman-verify-<id>mode0700, starts Convex with remote Convex variables unset, deletes the Next fetch cache, snapshotsnextjs/next-env.d.ts,nextjs/AGENTS.md, andnextjs/CLAUDE.md, and starts Next on127.0.0.1:3000. It records the listener pid, start time, and cwd inrun.jsonmode0600. When launch exits after owning Next, it restores that snapshot. A non-zero exit then deletes the snapshot file whenbmv-<id>-nextis not running.[::1].npx convex env setgets the allowlisted environment above and does not inheritBETTERMAN_DATASET_STAGE. The seed process setsBETTERMAN_DATASET_STAGE=prod. After seeding a Next process this skill started, launch clears the fetch cache, restarts Next, and waits untilpageCountis greater than 0.nextjs/next-env.d.tsedited after the snapshot, and a snapshot this checkout does not own is not written over a file that has changed. Cleanup warns and backs that file up undergenerated-backup/. Evidence stays.Proof
Head
fc022b03fa6021751269b95a296565aaf2cbad02. Delta sincef72bdb8013ea7e5001b86ae295423d78ad95085f:pnpm verify:testpassed, 6 tests, 0 skipped.tmuxis present, so the live-session test ran. An owned snapshot whoserun.jsonlistsbmv-snastale-next, with no tmux session, is removed on a refusedhttp://[::1]:3000launch. stderr containsremoving generated-snapshot.json; Next session is not running. A livebmv-snalive-nextsession keeps those snapshot bytes. stderr containsleaving generated-snapshot.json; Next session is still running. That live test skips whentmux -Vfails. Cleanup leaves anextjs/next-env.d.tsedit whose mtime is newer than the owned snapshot, printschanged since the recorded snapshot, and copies the bytes undergenerated-backup/. An edit with an older mtime is restored.pnpm verify:typecheckexited 0.Delta on
347bf14:launch.mjs --base-url http://[::1]:3000withVERIFY_ID=v6refexits 2, printsUse http://127.0.0.1:3000, leaves the state directory empty, and does not createbmv-v6ref-convexorbmv-v6ref-next. Doctor still treatshttp://[::1]:3000as loopback.Delta on
548e2ff:http://[::1]:3000is loopback with port 3000,http://172.30.0.2:9is not, andpath.resolvekeeps a..escape outside the repo.The
VERIFY_ID=cixlaunch, smoke, and cleanup proof below is from176da33and was not re-run on this head.origin/main(cd2583853df856700c12915e5c4d15ef69a9453a) is an ancestor.Results on
176da33:pnpm verify:typecheck(tsc --noEmit -p .agents/skills/verify-betterman/tsconfig.typecheck.json) exited 0. The same command reportsTS7016onevidence.tsfor./verify-paths.cjswhenscripts/verify-paths.d.ctsis absent.pnpm verify:testpassed, 2 tests on that head. The refused-launch test starts a foreign server with cwd/tmpand argv--config=<repoRoot>/nextjs, expects exit 2 andRefusing to seed. It also checks file mode0600, directory mode0700, and that a cwd or argv belongs to this repo only when it equals the repo root or starts with that root plus a separator.VERIFY_ID=ci pnpm verify:launchexited 1. The message isVERIFY_ID must be 3-32 characters of lowercase letters, digits, or hyphens.VERIFY_ID=cix pnpm verify:launchexited 0. Doctor printedinfo pageCount=7 release=e2e-debian-1792066324688,pid 35091,cwd=/workspace/nextjs,start=642731, andREADY. Evidence is/tmp/betterman-verify-cix/evidence./tmp/betterman-verify-cixis mode0700.run.jsonis mode0600. The dataset was already populated, so this launch did not runconvex env set.VERIFY_ID=cix pnpm verify:smokepassed 1 test (3.1s). Screenshots aresmoke-home.png,smoke-search.png, andsmoke-tar.pngin that evidence directory.VERIFY_ID=cix pnpm verify:cleanupstoppedbmv-cix-convexandbmv-cix-next. Evidence remains at/tmp/betterman-verify-cix/evidence.git status --shortwas empty.Home search from the VERIFY_ID=cix smoke
tar(1) from the VERIFY_ID=cix smoke
Command log:
/opt/cursor/artifacts/verify/cix-proof.log.INCONCLUSIVE:
next devleaves the worker unregistered. Cached pages neednext start.Suggested CI smoke
.github/workflows/verify-smoke.ymlstaysworkflow_dispatchonly. Permissions arecontents: read. It setsVERIFY_ID=cix, runs launch, doctor, and smoke, uploads/tmp/betterman-verify-cix/evidence, then runs cleanup. It does not editci.yml.To show artifacts inline, enable in settings.
Summary by Sourcery
Add an isolated, evidence-producing verification workflow that lets agents launch BetterMan locally and exercise its reader experience end to end.
New Features:
Enhancements:
Build:
CI:
Documentation:
Tests: