Repository navigation
Onboarding is a conversation with the agent - #547
Open
alex-clickhouse wants to merge 10 commits into
Open
alex-clickhouse wants to merge 10 commits into
alex-clickhouse wants to merge 10 commits into
Conversation
The worker's onboarding was an autonomous cron-style session that researched a one-task description and configured the worker on its own, and a personal install had no onboarding at all. Users read the Mode step as "give it one task now". Finish now opens one web chat session titled Onboarding, for both modes, for the person who finished setup. The engine runs its first turn with an internal message, so the agent speaks first and the person sees only its answer. The prompt (`onboarding_prompt`) offers the list of what the agent can help with (personal installs lead with the personal assistant), asks for the repositories to onboard for engineering work, proposes cron jobs, the plan-and-approve loop, statuses (the built-in `backlog` and `plan_review`), tags and skills, and applies nothing before the person confirms. A worker also gets its `TASK.md` rules and the worker guide. The agent ends onboarding with the new `onboarding_done` tool, which only that session can call. Migration v060 adds the `onboarding` row: requested, running, done or skipped. `nerve.onboarding` derives pending, running, done or skipped from it, opens the conversation once (a compare-and-set, also for concurrent Finish clicks), and keeps installs from before correct: a worker without the TASK.md marker is done, and a worker that still has it gets the conversation when the daemon starts. When a restart is pending, Finish records a request and the next start opens it. A person can skip onboarding (`POST /api/setup/onboarding/skip`). The Mode step describes personal as working for you and worker as working for a team, with an optional note instead of the required task description and the starter buttons. The Ready screen leads into the conversation. Until onboarding is done or skipped, the setup banner shows a reminder with Continue on every page except the conversation (its close button hides it until the next page), and the setup page shows the conversation and Skip onboarding behind a confirmation. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Automation step read only `config/cron/system.yaml`. A job that the onboarding conversation turned on through a `jobs.yaml` job with the same id still showed as off, so a person saw "task planner not selected" while it ran. `merge_jobs` is the scheduler's merge (a user job replaces the system job with the same id), now a function that the scheduler and the setup checklist share. `list_optional_crons` reports the effective state and whether `jobs.yaml` replaces the job (`overridden`). The Automation step shows such a job read-only with "Set in jobs.yaml", and saving the step leaves its `system.yaml` entry alone, because a change there would not change what runs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The test asserted that the stop attribution columns are the last two entries of ACTOR_COLUMNS. The onboarding migration appends its own column, as the list's docstring asks, so the test now checks that both columns are in the list. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The daemon opens a requested conversation when it starts, through a task that `AgentEngine.initialize` schedules. The service function had tests; the call in `initialize` had none. The new test starts a real engine and checks that it asks `nerve.onboarding.start_on_boot` once, for its workspace. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`AgentEngine.initialize` opened a requested conversation, so the one-shot engines of `nerve cron` and `nerve sync` could open it and then stop in the middle of the first turn. It also opened it without a model credential. In both cases the row stayed `running` with a session whose first turn had failed, and nothing tried again. The gateway lifespan now calls `start_on_boot`, which does nothing without a model credential, as Finish. A first turn that ends as failed (`watch_turns`) puts the row back to `requested`, so the next Finish or daemon start opens a new conversation. `start` runs one start at a time in the process and creates the session before it releases the lock, so a second start sees the first one's session instead of claiming the row again. At start-up without a row, the session's cause is the system actor, as for other sessions that Nerve starts for itself. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`list_optional_crons` had its own copy of the rule that a `jobs.yaml` job replaces the built-in job, and it loaded `jobs.yaml` without building gates. The scheduler drops a job whose gate does not build and runs the built-in job instead, so the Automation step could show a state that did not run. It now loads both files as the scheduler does and uses `merge_jobs`; the Automation step's save uses the same list of jobs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Finish answers with the checklist read after it opened the conversation, so the Ready screen's separate `onboarding` answer only mattered once onboarding had ended, and then it showed an old "Start the conversation". The screen now reads the checklist only. When "Skip onboarding" asks for confirmation, "Keep it" takes the focus that the removed button had. Test comments use the terms of the onboarding conversation. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A worker set up by `nerve init --terminal` or `--non-interactive` with a task description sets itself up without a person again. `nerve init` records an autonomous onboarding in the onboarding row (new `kind` column), and the gateway runs it once at the next start with a model credential. The session gets the worker onboarding prompt (research, TASK.md, skills, cron jobs, tasks, a walkthrough by notify) as a cron session, and ends with `onboarding_done`, which removes the TASK.md marker. A failed first turn asks the next start again. The prompt keeps the planner rules: built-in `backlog` and `plan_review`, and no notify of its own after `plan_propose`. Finish in the browser opens the conversation for either kind. A worker without a task description, and a worker from before the onboarding row, wait for the conversation in the web UI: the start opens only a requested row. The terminal wizard takes an optional description and says which path follows. `onboarding_done` checks the stored row, so a session that removed the marker itself can still end onboarding. The setup API reports the kind as `mode.detail.onboarding_kind`. The README and the setup, worker, cron and API docs describe both paths. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The banner shows while the onboarding conversation is due and setup is complete, also when nobody pressed Finish: a personal install whose steps are all done, or an install from before onboarding. Its Start button runs Finish, which is idempotent, and opens the conversation. The setup page offers the same Start beside Skip onboarding, so such an install starts the conversation or skips it once. While a worker sets itself up without a person, the banner, the setup page, the Mode step and the Ready screen say so and only link to that session. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
alex-clickhouse
added this pull request to stack #548
October 21, 2026 20:34
alex-clickhouse
marked this pull request as ready for review
October 21, 2026 20:35
This was referenced Oct 21, 2026
…opener `nerve init` records the autonomous onboarding through `open_production_db`, as every other CLI path does, so only the shared opener constructs a `Database`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #542. After setup in the browser, the agent is set up by talking to it, in both
modes. A worker set up without the browser with a task description still sets itself up.
What changes:
person who finished setup. The agent speaks first: a hidden first message (not in the
transcript) tells it to say that it is set up by talking to it, offer what it can help
with (personal installs lead with the personal assistant), and ask which items apply.
For engineering work it asks which repositories to onboard and studies them. It proposes
cron jobs with gates, the plan-and-approve loop, statuses (the built-in
backlogandplan_review), tags, skills and, for a worker, theTASK.mdsections. It changes nothingbefore the person confirms, then applies, summarizes and calls the new
onboarding_donetool.
nerve init --terminalor--non-interactivewith a taskdescription records an autonomous onboarding. At the next start with a model, one session
without a person reads the description and the worker guide, fills
TASK.md, createsskills, cron jobs and tasks, notifies the operator, and calls
onboarding_done. It runsonce. With an empty description, the worker waits for the conversation in the web UI.
The terminal prompt is optional and says which path follows.
and the kind (conversation or autonomous). Finish is idempotent (also two clicks at once)
and always opens the conversation. With a pending restart, the next daemon start opens
it. A worker without the old
TASK.mdmarker stays done. The "ended without a plan"state and "Try again" are removed.
instead of the required task description and the starter buttons.
or skipped, a banner on every page except the conversation says the agent waits, with
Continue (it can be hidden until the next page). When setup is complete and nobody pressed
Finish (also an install from before), the banner offers Start, which runs Finish and opens
the conversation. While a worker sets itself up, the banner only links to that session.
The setup page offers Start and Skip onboarding (with a confirmation). Every signed-in
person sees the banner, because the conversation sets up the shared agent.
runs it:
system.yamlwithjobs.yamljobs of the same id replacing it (the samemerge). Such a job is read-only there, and saving the step leaves it alone.
Verification: backend tests for the changed code,
npm run build, Vitest for the changedspecs, migration number check; CI runs the full suites. Screenshots of the Mode step, Ready
screen, banner, setup page and the first agent message (a real run), in light and dark.
Known gaps: the hidden instructions can be shortened by a context compaction. A failed
first turn keeps its session with the error, and onboarding goes back to pending so the
next Finish or start opens a new one. An autonomous session cut by a restart stays open;
the banner links to it.
🤖 Generated with Claude Code