You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Configure the platform and manage profiles from the UI instead of hand-editing profile.yaml
Problem
Configuring a deployment today means hand-editing profile.yaml under ~/.config/triagent/<profile>/, and there is no UI for picking or creating profiles at all. The schema has grown past the point where hand-editing is comfortable: auth, defaults, paths, linked repos, extra MCPs, investigation inputs, namespace derivation, models, prompt-file overrides, and now cloud sources (landing with feature/cloud-context-mcp). A new operator must learn the YAML shape, the ${XDG_*} path-expansion rules, and the base: merge semantics before the launcher will boot cleanly, and a single typo only surfaces as a load error at startup. The launcher exposes no profile read/write API beyond GET /api/profile/inputs and GET /api/profile/prom-defaults, and nothing to enumerate, create, or switch profiles. We want the whole configuration surface — both editing a profile's fields and managing which profile is active — to be point-and-fill and validated, so first-run setup is not YAML archaeology.
In scope
A guided, tabbed settings page that creates and edits a profile's configuration fields.
A read/write profile API (GET/PUT /api/profile) with server-side validation reusing internal/profile and atomic on-disk writes.
Inline editing of the prompt-file overrides' prose (architecture.md, strategies.md, editor.md, wiki_editor.md).
Profile lifecycle from the UI: list available profiles, show and switch the active one, create a new profile from scratch, delete an existing one.
Out of scope
Editing the system prompt (system.md) prose; it stays non-editable from the UI.
Storing or managing cloud credentials/secrets; the cloud config references source_profile and scope, not secret material.
Remote/multi-user config sync; this is local launcher state under ~/.config/triagent/.
Risks & mitigations
Writing an invalid profile bricks the next boot. Mitigate by validating server-side (the existing internal/profile validation) before any write, and writing through the existing atomicWrite tmp-file-then-rename helper so a failed write never leaves a half-file.
base: merge semantics make "what you see" ambiguous (resolved vs. raw overrides). Mitigate by being explicit in the API/UI about whether a field is inherited from base or set on this profile, and round-trip testing that a UI-saved profile loads identically to a hand-authored one.
Switching the active profile mid-session touches the launcher boot/reload path. Mitigate by treating switch as an explicit action with a clear reload boundary, scoped into its own sub-issue so the editor can ship first.
Cloud config schema is still in flight on feature/cloud-context-mcp. Mitigate by landing the editor against the merged schema and gating the cloud tab on that merge.
Design overview
Two seams, each a sub-issue. The first adds a profile read/write API in internal/server (handlers_profile.go) over the existing internal/profile package: GET /api/profile returns the active profile as structured JSON; PUT /api/profile validates with internal/profile's validate.go and, on success, writes ~/.config/triagent/<profile>/profile.yaml via atomicWrite (round-tripping through gopkg.in/yaml.v3), then reloads. Prompt-file overrides other than system.md are read and written as their own files alongside the profile. The frontend grows a Settings route under frontend/app/(main)/settings/, added to TopNav and the sidebar view union, following the existing "use client" + AppShell conventions, with a section per config group (Profile, Auth, Defaults, Paths, Repos & MCPs, Cloud, Investigations, Prompts, Advanced). The exact layout is left to the implementer to keep coherent and manageable; validation is surfaced inline on save.
The second seam adds profile lifecycle on top: endpoints to enumerate profiles and to create / delete / switch the active one, and the Profile section gains a picker plus create/delete controls. Switch and create reuse the same form and validation path as the editor.
flowchart LR
subgraph Frontend["frontend/app/(main)/settings/"]
Editor["Config editor<br/>(per-section form)"]
Picker["Profile picker<br/>(list / switch / create / delete)"]
end
Editor -->|GET/PUT /api/profile| H["internal/server<br/>handlers_profile.go"]
Picker -->|list / switch / create / delete| H
H -->|validate| V["internal/profile<br/>validate.go"]
V -->|ok: atomicWrite| D["~/.config/triagent/<profile>/profile.yaml"]
V -->|errors| H
H -->|reload| L["internal/profile loader"]
Configure the platform and manage profiles from the UI instead of hand-editing profile.yaml
Problem
Configuring a deployment today means hand-editing
profile.yamlunder~/.config/triagent/<profile>/, and there is no UI for picking or creating profiles at all. The schema has grown past the point where hand-editing is comfortable: auth, defaults, paths, linked repos, extra MCPs, investigation inputs, namespace derivation, models, prompt-file overrides, and now cloud sources (landing withfeature/cloud-context-mcp). A new operator must learn the YAML shape, the${XDG_*}path-expansion rules, and thebase:merge semantics before the launcher will boot cleanly, and a single typo only surfaces as a load error at startup. The launcher exposes no profile read/write API beyondGET /api/profile/inputsandGET /api/profile/prom-defaults, and nothing to enumerate, create, or switch profiles. We want the whole configuration surface — both editing a profile's fields and managing which profile is active — to be point-and-fill and validated, so first-run setup is not YAML archaeology.In scope
GET/PUT /api/profile) with server-side validation reusinginternal/profileand atomic on-disk writes.architecture.md,strategies.md,editor.md,wiki_editor.md).Out of scope
system.md) prose; it stays non-editable from the UI.source_profileand scope, not secret material.~/.config/triagent/.Risks & mitigations
internal/profilevalidation) before any write, and writing through the existingatomicWritetmp-file-then-rename helper so a failed write never leaves a half-file.base:merge semantics make "what you see" ambiguous (resolved vs. raw overrides). Mitigate by being explicit in the API/UI about whether a field is inherited frombaseor set on this profile, and round-trip testing that a UI-saved profile loads identically to a hand-authored one.feature/cloud-context-mcp. Mitigate by landing the editor against the merged schema and gating the cloud tab on that merge.Design overview
Two seams, each a sub-issue. The first adds a profile read/write API in
internal/server(handlers_profile.go) over the existinginternal/profilepackage:GET /api/profilereturns the active profile as structured JSON;PUT /api/profilevalidates withinternal/profile'svalidate.goand, on success, writes~/.config/triagent/<profile>/profile.yamlviaatomicWrite(round-tripping throughgopkg.in/yaml.v3), then reloads. Prompt-file overrides other thansystem.mdare read and written as their own files alongside the profile. The frontend grows aSettingsroute underfrontend/app/(main)/settings/, added toTopNavand the sidebarviewunion, following the existing"use client"+ AppShell conventions, with a section per config group (Profile, Auth, Defaults, Paths, Repos & MCPs, Cloud, Investigations, Prompts, Advanced). The exact layout is left to the implementer to keep coherent and manageable; validation is surfaced inline on save.The second seam adds profile lifecycle on top: endpoints to enumerate profiles and to create / delete / switch the active one, and the Profile section gains a picker plus create/delete controls. Switch and create reuse the same form and validation path as the editor.
flowchart LR subgraph Frontend["frontend/app/(main)/settings/"] Editor["Config editor<br/>(per-section form)"] Picker["Profile picker<br/>(list / switch / create / delete)"] end Editor -->|GET/PUT /api/profile| H["internal/server<br/>handlers_profile.go"] Picker -->|list / switch / create / delete| H H -->|validate| V["internal/profile<br/>validate.go"] V -->|ok: atomicWrite| D["~/.config/triagent/<profile>/profile.yaml"] V -->|errors| H H -->|reload| L["internal/profile loader"]Sub-issues
Sub-issues will be linked below as they're filed.