diff --git a/.claude/skills/onboarding-e2e/SKILL.md b/.claude/skills/onboarding-e2e/SKILL.md new file mode 100644 index 0000000..e5ed189 --- /dev/null +++ b/.claude/skills/onboarding-e2e/SKILL.md @@ -0,0 +1,80 @@ +--- +name: onboarding-e2e +description: "Live end-to-end test of BearDrive's agent-first onboarding: spawn a fresh agent that role-plays a real user conversation ('keep our wiki synced…') against a running hub, following the plugin's SKILL/install instructions verbatim, and report the full transcript plus doc-vs-reality findings. Use when the plugin onboarding copy, the CLI init/login/hooks flow, or hub auth changed and you want proof the conversation still works. Args: [hub-url] [authenticated BDRIVE_HOME] [bdrive-binary]" +--- + +# Agent-onboarding live E2E + +Tests the thing unit tests can't: that a *conversation* driven by the plugin +instructions actually onboards a user end to end against a real hub. The +deliverable is a transcript + findings, not a pass/fail bit — instruction +drift (docs promising what the binary doesn't do) is exactly what this +catches. + +## Inputs (ask if not provided) + +- `HUB` — a running hub URL (dev default: the local cloud hub). +- `HOME_AUTH` — a `BDRIVE_HOME` directory already signed in to that hub + (`bdrive login --status` must show an account). Browser signup can't run + headlessly; if none exists, create a synthetic user first (hub-dependent — + on a PropelAuth hub: Backend API `POST /api/backend/v1/user/` then a magic + link, or the device flow approved from an authenticated browser session). +- `BDRIVE` — path to the `bdrive` binary to test (build it from the tree + under test: `go build -o /tmp/bdrive-e2e ./cmd/bdrive`). Don't trust PATH. + +## Procedure + +1. **Stage a realistic repo** in a scratch dir (never inside the real repo): + ```sh + A=/agent-e2e && mkdir -p $A/repo/wiki $A/repo/src $A/plugin + # 3 markdown pages with [[wikilinks]] in wiki/, a token src/ file, + # git init + commit (the wiki MUST be git-tracked — the handoff step + # is part of the test). + ``` +2. **Materialize the instructions under test** — from the branch being + tested, not the working tree: + ```sh + git show :plugin/commands/install.md > $A/plugin/install.md + git show :plugin/skills/beardrive/SKILL.md > $A/plugin/SKILL.md + ``` +3. **Spawn a fresh agent** (Task/Agent tool, general-purpose) with a prompt + that makes it role-play a real Claude Code session. The prompt must: + - confine all writes to the scratch dir; + - name the two instruction files as its ONLY operating manual and demand + it follow them faithfully, noting friction instead of papering over it; + - require `BDRIVE_HOME=$HOME_AUTH` on every bdrive call and forbid bare + `bdrive login` (no browser available); + - fix the project name (avoid collisions with earlier runs); + - open with the exact user message + `"keep our wiki synced with the team and give me a link to it"`; + - script the simulated user: consent to the sync + synced AGENTS.md, but + DECLINE one optional step (e.g. the root pointer) so the transcript + proves the consent gates are real; + - require every command's real output in the transcript — no fabrication; + - end with cleanup: `bdrive stop ` so no daemon lingers; + - demand a two-part report: **TRANSCRIPT** (User/Claude turns with real + command output) and **TEST FINDINGS** (numbered: worked-as-written / + doc-vs-reality gaps with quoted instruction text / first-timer + confusion / whether the `bdrive url` payoff link served real content — + verify with an authenticated `curl` against the project API). +4. **Independently verify** the agent's headline claims before relaying: + the project exists on the hub (`/api/projects` with the token), the file + content round-trips, the daemon is stopped. +5. **Relay** the transcript verbatim and triage findings into: fix-now doc + patches, behavior bugs (file/branch them), and cosmetics. + +## Pass bar + +The conversation must reach the payoff (a working hub link) with no step +where the agent had to contradict the instructions silently. Any place the +agent adapted beyond the written instructions is a finding, even if the run +"worked". + +## Known environment quirks + +- `command -v bdrive` may find a Homebrew binary that's older than the tree + under test — always pass `BDRIVE` explicitly and watch for version skew. +- On hubs with PropelAuth + "must be in at least one org": brand-new users + are gated at PropelAuth's create-org screen unless the `user.created` + webhook can reach the hub — synthetic-user setup must account for it + (deliver the webhook by hand or pre-create the org). diff --git a/plugin/commands/install.md b/plugin/commands/install.md index 1ba3aff..86c80ac 100644 --- a/plugin/commands/install.md +++ b/plugin/commands/install.md @@ -29,9 +29,9 @@ browser window is coming, then sign in: If `$ARGUMENTS` gives a project name and/or `--shared `, use them. Otherwise ask the user two questions (or infer from their request): -- **Create a new project or connect an existing one?** (`bdrive share --list` - isn't needed here — `bdrive init --name ` creates-or-joins by name; - `bdrive init --project ` connects by id.) +- **Create a new project or connect an existing one?** (`bdrive init + --name ` creates-or-joins by name; `bdrive init --project ` + connects by id.) - **Sync the whole folder, or only a shared subfolder?** Hard rule: **never sync a repo root** — inside a repo, knowledge always syncs as a scoped subfolder via `--shared`. Whole-folder is only for a dedicated @@ -41,6 +41,12 @@ Otherwise ask the user two questions (or infer from their request): markdown-heavy, not source code) and propose the best candidate for confirmation, e.g. "I found `./wiki` — sync that?". +**One transport per folder.** If the chosen folder is currently git-tracked, +BearDrive and git would both write it — the silent-revert hazard. Get consent, +then hand it off: `git rm -r --cached ` and add `/` to `.gitignore`; +stage the change but let the user commit. (Full detection ladder — git, +Obsidian, symlinks — in the beardrive skill's "Connecting knowledge tooling".) + Then run it non-interactively, e.g.: ```sh bdrive init --name --yes # dedicated knowledge folder @@ -49,6 +55,11 @@ bdrive init --name --shared wiki # in a repo: only ./wiki sync Re-running `bdrive init --yes` later is always safe: it resumes syncing (including after the folder was renamed or moved). +After init, tell git what's what: add `.bdrive/` to `.gitignore` (per-machine +state, never committed) and COMMIT `.bdriveignore` (on a `--shared` mount the +root `.bdriveignore` is local-only to each clone, so git is how the team +shares it). + ## 4. Teach agents about the shared folder (ask first — never do this silently) Two files with different jobs (full rationale: the beardrive skill's @@ -118,6 +129,9 @@ Tell the user which platforms got hooks (`bdrive hooks` shows the status table). If Codex is among them, mention they must run `/hooks` inside Codex once to trust the project's `.codex` layer. To register a platform that wasn't detected: `bdrive hooks install --agent claude,codex,gemini,hermes`. +Heads-up before installing: Hermes hooks are PER-USER (`~/.hermes/config.yaml`, +outside the repo) — mention that when it's among the targets, and skip it +unless the user actually uses Hermes. ## 6. Verify and summarize diff --git a/plugin/skills/beardrive/SKILL.md b/plugin/skills/beardrive/SKILL.md index 8ae7a1c..048c598 100644 --- a/plugin/skills/beardrive/SKILL.md +++ b/plugin/skills/beardrive/SKILL.md @@ -37,7 +37,7 @@ Use this skill whenever the user is working with the `bdrive` CLI: initializing Two files at the mount root control a folder's sync behavior: - **`.bdrive/`** — the folder's settings **directory**; `config.json` inside holds the **stable mount id** (`m-xxxxxxxx`) plus `volume`, `remote`, optional `include`. Written by `bdrive init`; safe to hand-edit (a running daemon picks changes up on its next tick). It is **never synced**, holds **no credentials** (the token lives in `~/.bdrive/settings.json`), and because all state is keyed by the mount id — not the path — the folder can be **renamed or moved freely**; the daemon exits on a move and the next bdrive command at the new location resumes. -- **`.bdriveignore`** — opt-out list, gitignore-style. **Syncs like a normal file**, so all devices share the same rules. Syntax subset: `#` comments, `*` within a segment, `**` across segments, `?`, trailing `/` for directories-only, a `/` elsewhere anchors to the mount root, `!` re-includes. +- **`.bdriveignore`** — opt-out list, gitignore-style. On a whole-folder mount it **syncs like a normal file**, so all devices share the same rules; on a `--shared ` mount the seeded root `.bdriveignore` sits OUTSIDE the include list and is **local-only** — commit it to git (or place ignore rules inside the shared dir) if the team should share it. Syntax subset: `#` comments, `*` within a segment, `**` across segments, `?`, trailing `/` for directories-only, a `/` elsewhere anchors to the mount root, `!` re-includes. ```jsonc // .bdrive/config.json