Skip to content

feat(desktop): edit the bound Hermes profile from Crew (model + SOUL.md write-through, optional description) - #149

Merged
oscarlehuu merged 24 commits into
mainfrom
agents/hermes-profile-editing
Aug 11, 2026
Merged

feat(desktop): edit the bound Hermes profile from Crew (model + SOUL.md write-through, optional description)#149
oscarlehuu merged 24 commits into
mainfrom
agents/hermes-profile-editing

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Aug 11, 2026

Copy link
Copy Markdown

Summary

Crew becomes the editing surface for the bound Hermes profile, without becoming a second source of truth. Three deliverables plus docs.

1. Model write-through. The bound profile's real model is read from ~/.hermes/profiles/<name>/config.yaml (model.provider / model.default) and edited through hermes -p <name> config set model.provider|model.default. Crew persists nothing: the write-through model field descriptor carries persistence: { kind: "none" }, buildRuntimeModelProviderPayload drops model/provider from the save payload for such runtimes (test-pinned), and BUZZ_ACP_MODEL stripping at spawn is untouched. The control always shows the shared-everywhere note and the next-fresh-session timing.

2. SOUL.md write-through. HermesSoulEditor opens populated with the real current file; a read failure is a named error, never a blank textarea presented as the persona. Writes are atomic (temp file in the same directory + rename), byte-exact, and touch no other profile file. Create-in-place gets a skippable persona step so Crew-born profiles aren't generic.

3. Description is optional. Empty "Agent instructions" already produced None → no BUZZ_ACP_SYSTEM_PROMPT env and no session/new systemPrompt field; that's now pinned by tests and the UI labels it optional with a three-layer helper (L1 profile SOUL.md, L2 harness office rules, L3 this box).

Capability contract, not runtime branches (D-025). Each catalog entry now carries { modelSource, personaDoc, layer3 }, derived once at the fromRawAcpRuntimeCatalog projection boundary — zero upstream Rust catalog changes. modelSource comes from the existing fact triple (profileArg && providerLocked && no modelEnvVar); runtimeOwnsModelViaProfile is re-expressed through it rather than kept as a rival truth. personaDoc cannot be derived from those facts (a profile-locked runtime does not imply a persona document), so it is a table in the capability module — the only place the string hermes appears. Render code never branches on runtime.id, and runtimes without a persona document render nothing at all: no disabled editor, no implication of profile memory.

Two settled sub-decisions, both recorded in D-038:

  • No "Reset to Hermes default". Hermes generates SOUL.md at profile creation and there is no trustworthy source to reset from; shipping a Crew copy would drift from Hermes. Recorded as a known gap in HERMES.md.
  • Provider and model are two config set invocations, so a failure on the second can leave the profile partially updated. No rollback is invented without a verified Hermes unset operation.

Related issue

Fixes #118. Decision D-038 (allocated by the orchestrator; D-028..D-037 and D-039 are taken by PRs #120/#124/#127/#128/#129/#134/#122/#135).

Branched off agents/profile-lifecycle-hardening (#134 / issue #119) per the sequencing plan, and targets main — until #134 merges this PR's diff contains #134's readiness/lifecycle commits as well. Doc edits are composed on top of the #124 (docs/state-truth-and-gate-audit) and #134 text, not main's stale version. The model read path reuses #134's read_profile_yaml rather than duplicating a parser.

Testing

Not verifiable here, stated plainly: this VM has no hermes binary, no ~/.hermes, and the repo has no install path, so the issue's live probe (real profile write, live-turn model pickup) could not be run. Evidence below is Rust tests against a temp HERMES_HOME with a fake hermes, contract tests, and Playwright against the mock bridge.

  • Hermes profile Rust tests (model read/write classification, SOUL round-trip incl. CRLF/trailing-newline preservation, missing/orphan profile): 46 passed.
  • ACP layer-3 tests: empty description removes BUZZ_ACP_SYSTEM_PROMPT and omits session/new systemPrompt; non-empty still uses SystemPromptTransport::Field for hermes-agent at protocol v2+.
  • pnpm --filter buzz check, pnpm --filter buzz typecheck, check:px-text, check:file-sizes, cargo fmt --all -- --check: pass. pnpm --filter buzz test: 5053 passed / 0 failed / 1 skipped. just test-unit: pass.
  • Playwright (mock bridge) Hermes specs: 18 passed — editable model control + shared-everywhere note, populated SOUL editor with persisting save, empty optional instructions accepted, non-Hermes runtime shows no persona editor.
  • Local full smoke has a large pre-existing red set on this base; channel-activity-popover.spec.ts:274/368/459/753 reproduce identically on origin/agents/profile-lifecycle-hardening with no diff to that spec. CI is the arbiter — known-broken advisory lanes (Desktop Smoke E2E 1/3/4, baseline run 31362178966) and the missionInbox flake (Flaky merge-gating test: missionInbox 'reference-stable snapshot' fails intermittently on main (fails Desktop Fast + NuncioCrew Gate) #135, fix in flight as fix(desktop): memoize mission inbox snapshots on inputs, not the wall clock #138) are excluded from the required Gate by design (D-032).

Screenshots are posted as follow-up comments via scripts/post-screenshots.sh per the repo's PR-screenshot rule.

Hand-driven UI run (headed Chromium against the mock bridge) caught and fixed a real bug plus copy problems, detailed in a follow-up comment: the create-in-place persona step rendered an error instead of an editor because HermesSoulEditor treated a missing SOUL.md as fatal (a brand-new profile has none) — missing now opens an empty editor that creates the file on save, while does_not_exist stays a named error. Also suppressed a contradictory "Not configured" global-defaults summary under the profile model, dropped the L1/L2/L3 numbering (it started at "L2" for non-Hermes runtimes), reworded the helper to lead with meaning over filenames, and made a failed model write keep the user's typed edit like the persona editor does.

CI: required NuncioCrew Gate and all required checks green; the only red lanes are Desktop Smoke E2E shards 1/3, the known-broken advisory lane excluded from the Gate by design (D-032).

Docs: D-038 in DECISIONS.md; HERMES.md rule 2 + hiring flow + reset gap; Slice 2 C-03..C-12 reconciled against what actually shipped in features/0001-hermes-first-class-runtime.md; STATE.md per the anti-drift rule; desktop/src/features/agents/AGENTS.md rules 3 and 8 rewritten (model resolution is a capability; ownedByProfile survives only for runtimes that genuinely cannot expose a model).

Link to Devin session: https://app.devin.ai/sessions/1c69da96697d48b68f30f159b1310f9c
Requested by: @oscarlehuu

@oscarlehuu oscarlehuu self-assigned this Aug 11, 2026
@devin-ai-integration

Copy link
Copy Markdown
Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@devin-ai-integration

Copy link
Copy Markdown
Author

Screenshots

pr-149--agent-instructions-optional

pr-149--hermes-model-write-through

pr-149--hermes-soul-editor

devin-ai-integration Bot added a commit that referenced this pull request Aug 11, 2026
devin-ai-integration Bot added a commit that referenced this pull request Aug 11, 2026
…t ownership

Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
devin-ai-integration Bot added a commit that referenced this pull request Aug 11, 2026
…123 plan

Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
@devin-ai-integration

Copy link
Copy Markdown
Author

Screenshots

pr-149--03c-failed-persona-save-keeps-unsaved-text

pr-149--06-regression-claude-advanced-no-hermes-surfaces

pr-149--07-persona-step-after-create-in-place-BUG

pr-149--10-copy-concern-not-configured-under-profile-model

pr-149--11-create-dialog-hermes-all-surfaces-L1-L2-L3

devin-ai-integration Bot added a commit that referenced this pull request Aug 11, 2026
@devin-ai-integration

Copy link
Copy Markdown
Author

Runtime UI verification (and what it caught)

Driven by hand through the real UI — headed Chromium against the E2E mock bridge (pnpm --filter buzz build:e2e). Real write-through isn't exercisable on this VM (no hermes binary / ~/.hermes), so the mocked IPC boundary is the limit of the run. Screenshots for all of the below are in the preceding comment.

One real bug found and fixed: the create-in-place persona step rendered only red text ("Hermes profile 'recruit' has no SOUL.md") with no textarea and no save — HermesSoulEditor treated every non-ok read as fatal, and a freshly created profile has no SOUL.md yet, so the step could not do the one thing it exists for. missing is a real status from the Rust side, so this also put a red error inside the ordinary edit dialog for any Hermes agent whose profile lacks a SOUL.md. Now missing opens an empty editor that says saving will create the file (the "never a blank editor" rule is about not blanking real founder prose — there is none to blank here), while does_not_exist stays a named error. E2E coverage added for creating a persona on a brand-new profile.

Three copy problems fixed, all of them versions of the confusion this issue exists to end:

  • A Provider: Not configured / Model: Not configured global-defaults summary rendered directly under the configured profile model — two adjacent, contradictory statements about which model the agent runs. Now suppressed when the model is profile-owned (via the capability, not a runtime id check).
  • The layer helper started at "L2" for non-Hermes runtimes, implying a first layer the user never sees. Numbering dropped.
  • The helper led with filenames and called the third layer "the Crew agent description" while the field is labelled "Agent instructions". Rewritten to lead with what each layer is.

One consistency fix: a failed profile-model write used to discard the user's typed edit; it now keeps the typed values alongside the error, matching the SOUL editor.

Verified passing: profile model shows the profile's real values and re-reads after save; a classified write failure shows the message, keeps values, and persists nothing; SOUL editor opens populated, gates save on dirty, persists, and keeps unsaved text on a failed save; empty Agent instructions saves fine; Skip for now leaves the Hermes default; and — the regression that matters most — Claude/Buzz Agent surfaces are untouched, with no persona editor, no profile-model control, and no implication of profile memory. No reset-to-default affordance anywhere.

Not covered: real write-through against a live hermes binary, and end-to-end create submission (the Create button didn't submit under the mock bridge; the non-Hermes dialog gates the same button on required provider config, so it looks like a harness limitation — empty-instructions save is proven via the edit dialog instead).

Devin session: https://app.devin.ai/sessions/1c69da96697d48b68f30f159b1310f9c

@devin-ai-integration

Copy link
Copy Markdown
Author

Rebased onto current main and resolved conflicts in docs/crew/DECISIONS.md (kept both D-035 and D-038, with D-039 from main appended in number order) and other docs by keeping both sides' content.

Post-rebase local gates: pnpm --filter buzz check, pnpm --filter buzz typecheck, cargo fmt --all --check, and just test-unit all pass.

The Desktop Smoke E2E advisory shards show the same failures as the latest full main run before the rebase:

  • shard 1: 8 failures, identical set to main run 31362178966 job 93373095535
  • shard 3: 4 failures, identical set to main run 31362178966 job 93373095539

The required NuncioCrew Gate is green.

@devin-ai-integration
devin-ai-integration Bot force-pushed the agents/hermes-profile-editing branch from cc974d5 to 44e8879 Compare August 11, 2026 09:29
devin-ai-integration Bot added a commit that referenced this pull request Aug 11, 2026
…t ownership

Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
devin-ai-integration Bot added a commit that referenced this pull request Aug 11, 2026
…123 plan

Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
@devin-ai-integration
devin-ai-integration Bot force-pushed the agents/hermes-profile-editing branch from 44e8879 to 79f5229 Compare August 11, 2026 10:45
@oscarlehuu
oscarlehuu force-pushed the agents/hermes-profile-editing branch from 79f5229 to 7bf12a5 Compare August 11, 2026 11:03
devin-ai-integration Bot and others added 11 commits August 11, 2026 22:34
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
devin-ai-integration Bot and others added 13 commits August 11, 2026 22:35
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
The force-pushed sync introduced a duplicate D-039 and dropped the blank
line before D-031. Move D-037 ahead of D-038/D-039 and keep each decision
once. No other content changed.

Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
@oscarlehuu
oscarlehuu force-pushed the agents/hermes-profile-editing branch from cc7c394 to c9dee9b Compare August 11, 2026 13:05
oscarlehuu added a commit that referenced this pull request Aug 11, 2026
…t ownership

Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
oscarlehuu added a commit that referenced this pull request Aug 11, 2026
…123 plan

Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
@oscarlehuu
oscarlehuu merged commit a5f0406 into main Aug 11, 2026
8 of 12 checks passed
devin-ai-integration Bot added a commit that referenced this pull request Aug 11, 2026
…t ownership

Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
devin-ai-integration Bot added a commit that referenced this pull request Aug 11, 2026
…123 plan

Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
oscarlehuu added a commit that referenced this pull request Aug 11, 2026
…t ownership

Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
oscarlehuu added a commit that referenced this pull request Aug 11, 2026
…123 plan

Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>
oscarlehuu added a commit that referenced this pull request Aug 11, 2026
…lose the epic, keep a three-item remainder (#145)

* docs(plans): scope audit and completion plan for Hermes first-class operations (#104)

Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>

* docs(plans): use repository relay verification commands

Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>

* docs(plans): use in-repo citations and non-colliding contract ids

Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>

* docs(plans): record founder decisions on #104 model-config supersession and disposition

Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>

* docs(plans): fix section separators around the decided-questions table

Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>

* docs(plans): add #104 closeout artifacts and record the #149 amendment ownership

Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>

* docs(plans): cite #149's shipped capability descriptor instead of the #123 plan

Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Oscar Le <oscar.lehuu@gmail.com>

---------

Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Oscar Le <oscar.lehuu@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Hermes profile editing from Crew: model write-through, SOUL.md editor, optional description (layered prompt model)

1 participant