feat(wave): #119/#122/#131/#132 verts + sprint plugins ESM/persistance #135/#136/#139

État d'intégration confiné à la branche batch. Les tickets #119 (skills →
capacités agent découvrables), #122 (override permissions par défaut), #131
(effort par agent/presets) et #132 (outil MCP d'édition du contexte projet)
sont verts en périmètre. Le sprint plugins multi-fichiers ESM / persistance
plugin-owned (#135/#136/#139) est co-implémenté dans les MÊMES fichiers de
câblage (frontend/src/ports/index.ts, backend/src/lib.rs, domain/ports.rs,
backend/dto.rs), inséparable sans staging interactif (indisponible ici).

Commit unique volontaire : préserve l'état vert QA sans découpe hunk risquée.
NON mergé vers develop tant que #137 (QA e2e plugins) n'est pas vert.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-08-03 11:06:23 +02:00
parent 22c6bd803d
commit 171c6c923c
59 changed files with 3654 additions and 291 deletions

View File

@ -52,10 +52,11 @@ use application::{
ResolveAgentSystemPermissionsInput, ResolveMemoryLinksInput, RevokeDeviceInput,
RotateConversationLogInput, StopLiveAgentInput, SyncAgentWithTemplateInput, TouchDeviceInput,
UnassignSkillFromAgentInput, UnassignTicketFromSprintInput, UnlinkIssuesInput,
UpdateAgentContextInput, UpdateAgentMcpToolPermissionsInput, UpdateAgentPermissionsInput,
UpdateAgentSystemPermissionsInput, UpdateIssueCarnetInput, UpdateMemoryInput,
UpdateProjectContextInput, UpdateProjectMcpToolPermissionsInput, UpdateProjectPermissionsInput,
UpdateProjectSystemPermissionsInput, UpdateSkillInput, WriteToTerminalInput,
UpdateAgentContextInput, UpdateAgentEffortInput, UpdateAgentMcpToolPermissionsInput,
UpdateAgentPermissionsInput, UpdateAgentSystemPermissionsInput, UpdateIssueCarnetInput,
UpdateMemoryInput, UpdateProjectContextInput, UpdateProjectMcpToolPermissionsInput,
UpdateProjectPermissionsInput, UpdateProjectSystemPermissionsInput, UpdateSkillInput,
WriteToTerminalInput,
};
use domain::ports::PtyHandle;
use domain::IssueActor;
@ -74,16 +75,16 @@ use backend::dto::{
ChangeAgentProfileRequestDto, CloneOpenCodeProfileFromSeedRequestDto,
ConfigureProfilesRequestDto, ConversationDetailsDto, CreateAgentFromTemplateRequestDto,
CreateAgentRequestDto, CreateMemoryRequestDto, CreateSkillRequestDto, CreateTemplateRequestDto,
DetectProfilesRequestDto, DetectProfilesResponseDto, EffectivePermissionsDto,
EmbedderEnginesDto, EmbedderProfileDto, EmbedderProfileListDto, ErrorDto, FirstRunStateDto,
GitBranchesDto, GitCheckoutRequestDto, GitCommitDto, GitCommitListDto, GitCommitRequestDto,
GitStageRequestDto, GitStatusListDto, GraphCommitListDto, HealthRequestDto, HealthResponseDto,
InspectConversationRequestDto, LaunchAgentRequestDto, LiveAgentListDto, MemoryDto,
MemoryIndexDto, MemoryLinksDto, MemoryListDto, OpenCodeProviderListDto, OpenTerminalRequestDto,
ProfileDto, ProfileListDto, ProfileModelCatalogDto, ProjectDto, ProjectListDto,
ProjectMcpToolPermissionsDto, ProjectPermissionsDto, ProjectSystemPermissionsDto,
ProjectWorkStateDto, ReadAgentContextResponseDto, ReadConversationPageRequestDto,
RecallMemoryRequestDto, ResolveAgentPermissionsRequestDto,
DetectProfilesRequestDto, DetectProfilesResponseDto, EmbedderEnginesDto, EmbedderProfileDto,
EmbedderProfileListDto, ErrorDto, FirstRunStateDto, GitBranchesDto, GitCheckoutRequestDto,
GitCommitDto, GitCommitListDto, GitCommitRequestDto, GitStageRequestDto, GitStatusListDto,
GraphCommitListDto, HealthRequestDto, HealthResponseDto, InspectConversationRequestDto,
LaunchAgentRequestDto, LiveAgentListDto, MemoryDto, MemoryIndexDto, MemoryLinksDto,
MemoryListDto, OpenCodeProviderListDto, OpenTerminalRequestDto, ProfileDto, ProfileListDto,
ProfileModelCatalogDto, ProjectDto, ProjectListDto, ProjectMcpToolPermissionsDto,
ProjectPermissionsDto, ProjectSystemPermissionsDto, ProjectWorkStateDto,
ReadAgentContextResponseDto, ReadConversationPageRequestDto, RecallMemoryRequestDto,
ResolveAgentPermissionsRequestDto, ResolveAgentPermissionsResponseDto,
ResolveAgentSystemPermissionsRequestDto, ResolvedAgentSystemPermissionsDto,
ResumableAgentListDto, SaveEmbedderProfileRequestDto, SaveOpenCodeProviderProfileRequestDto,
SaveProfileRequestDto, SkillDto, SkillListDto, SprintCreateRequestDto, SprintDeleteRequestDto,
@ -97,8 +98,9 @@ use backend::dto::{
TicketListRequestDto, TicketReadRequestDto, TicketSprintAssignRequestDto,
TicketSprintUnassignRequestDto, TicketUnlinkCommandRequestDto, TicketUpdateCarnetRequestDto,
TicketUpdateRequestDto, TurnPageDto, UnassignSkillRequestDto, UpdateAgentContextRequestDto,
UpdateAgentMcpToolPermissionsRequestDto, UpdateAgentPermissionsRequestDto,
UpdateAgentSystemPermissionsRequestDto, UpdateMemoryRequestDto, UpdateProjectContextRequestDto,
UpdateAgentEffortRequestDto, UpdateAgentMcpToolPermissionsRequestDto,
UpdateAgentPermissionsRequestDto, UpdateAgentSystemPermissionsRequestDto,
UpdateMemoryRequestDto, UpdateProjectContextRequestDto,
UpdateProjectMcpToolPermissionsRequestDto, UpdateProjectPermissionsRequestDto,
UpdateProjectSystemPermissionsRequestDto, UpdateSkillRequestDto, UpdateTemplateRequestDto,
};
@ -2426,6 +2428,7 @@ async fn invoke(
"update_agent_permissions" => {
invoke_update_agent_permissions(&request.args, &state.app).await
}
"update_agent_effort" => invoke_update_agent_effort(&request.args, &state.app).await,
"resolve_agent_permissions" => {
invoke_resolve_agent_permissions(&request.args, &state.app).await
}
@ -3482,9 +3485,10 @@ async fn invoke_create_skill(args: &Value, state: &BackendCore) -> Result<Value,
.create_skill
.execute(CreateSkillInput {
name: request.name,
description: None,
description: request.description,
content: request.content,
scope: request.scope,
kind: request.kind,
project_root: project.root,
})
.await
@ -3620,6 +3624,22 @@ async fn invoke_update_agent_permissions(
serde_json::to_value(output).map_err(serialization_error)
}
async fn invoke_update_agent_effort(args: &Value, state: &BackendCore) -> Result<Value, ErrorDto> {
let request = required_request::<UpdateAgentEffortRequestDto>("update_agent_effort", args)?;
let project = resolve_project_readonly(&request.project_id, state).await?;
let output = state
.update_agent_effort
.execute(UpdateAgentEffortInput {
project,
agent_id: parse_agent_id(&request.agent_id)?,
effort: request.effort,
})
.await
.map(|out| AgentDto::from_agent(out.agent))
.map_err(ErrorDto::from)?;
serde_json::to_value(output).map_err(serialization_error)
}
async fn invoke_resolve_agent_permissions(
args: &Value,
state: &BackendCore,
@ -3634,7 +3654,7 @@ async fn invoke_resolve_agent_permissions(
agent_id: parse_agent_id(&request.agent_id)?,
})
.await
.map(|out| out.effective.map(EffectivePermissionsDto))
.map(ResolveAgentPermissionsResponseDto::from)
.map_err(ErrorDto::from)?;
serde_json::to_value(output).map_err(serialization_error)
}
@ -7895,6 +7915,7 @@ mod tests {
"get_project_permissions",
"update_project_permissions",
"update_agent_permissions",
"update_agent_effort",
"resolve_agent_permissions",
"get_project_system_permissions",
"update_project_system_permissions",