chantier: durcissement reprise headless inter-projets + persistance profils Opencode

- Implémentation reprise de session Opencode headless (conversational_recovery)
- Persistance des profils IA Opencode dans .ideai/memory avec JSON Schema
- Gestion des permissions MCP pour agents externes
- Tests QA verts : structured_launch_d3, conversation_log, tickets_missing_carnet, agents, ProfilesSettings
This commit is contained in:
2026-07-28 12:23:34 +02:00
parent 78f7c8fe2d
commit 045e0984cc
15 changed files with 782 additions and 49 deletions

View File

@ -72,8 +72,18 @@ impl TicketToolProvider for AppTicketToolProvider {
.await
.map_err(ticket_error)?
.issue;
let fallback_carnet = issue.carnet.as_str().to_owned();
let carnet = if include_carnet {
Some(read_carnet_body(&*self.read_carnet, project, issue_ref).await?)
Some(
read_ticket_carnet_body_best_effort(
&*self.read_carnet,
project,
issue_ref,
fallback_carnet,
)
.await
.map_err(ticket_error)?,
)
} else {
None
};
@ -287,17 +297,17 @@ pub async fn ticket_read(
.await
.map_err(ErrorDto::from)?
.issue;
let fallback_carnet = issue.carnet.as_str().to_owned();
let carnet = if request.include_carnet.unwrap_or(false) {
Some(
state
.read_issue_carnet
.execute(ReadIssueCarnetInput { project, issue_ref })
.await
.map_err(ErrorDto::from)?
.carnet
.carnet
.as_str()
.to_owned(),
read_ticket_carnet_body_best_effort(
&state.read_issue_carnet,
&project,
issue_ref,
fallback_carnet,
)
.await
.map_err(ErrorDto::from)?,
)
} else {
None
@ -680,6 +690,25 @@ async fn read_carnet_body(
.map_err(ticket_error)
}
async fn read_ticket_carnet_body_best_effort(
read_carnet: &application::ReadIssueCarnet,
project: &Project,
issue_ref: IssueRef,
fallback_carnet: String,
) -> Result<String, AppError> {
match read_carnet
.execute(ReadIssueCarnetInput {
project: project.clone(),
issue_ref,
})
.await
{
Ok(out) => Ok(out.carnet.carnet.as_str().to_owned()),
Err(AppError::NotFound(_)) => Ok(fallback_carnet),
Err(err) => Err(err),
}
}
fn ticket_error(err: AppError) -> TicketToolError {
let message = err.to_string();
let code = if message.contains("issue version conflict") {