feat(orchestrator): create_skill action + wire per-project watchers (§14.3)

- domain: OrchestratorCommand::CreateSkill with optional scope field
  (defaults to Project, case-insensitive, UnknownScope on bad value)
- application: dispatch CreateSkill through the CreateSkill use case
- app-tauri: build OrchestratorService and start/stop per-project request
  watchers on open/create/close_project (ensure/stop_orchestrator_watch)
- tests: domain validation, service dispatch, infra watcher e2e,
  app-tauri wiring lifecycle (idempotent, isolated, stop)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-07 13:06:41 +02:00
parent b9fd2fb925
commit d11eaaa8c0
13 changed files with 619 additions and 52 deletions

View File

@ -68,12 +68,15 @@ pub async fn create_project(
request: CreateProjectRequestDto,
state: State<'_, AppState>,
) -> Result<ProjectDto, ErrorDto> {
state
let output = state
.create_project
.execute(request.into())
.await
.map(ProjectDto::from)
.map_err(ErrorDto::from)
.map_err(ErrorDto::from)?;
// Start tailing this project's `.ideai/requests/` tree so an orchestrator
// agent can delegate agent/skill creation to IdeA (§14.3).
state.ensure_orchestrator_watch(&output.project);
Ok(ProjectDto::from(output))
}
/// `open_project` — load a project and its `.ideai/` meta/manifest.
@ -87,12 +90,14 @@ pub async fn open_project(
state: State<'_, AppState>,
) -> Result<ProjectDto, ErrorDto> {
let id = parse_project_id(&project_id)?;
state
let output = state
.open_project
.execute(OpenProjectInput { project_id: id })
.await
.map(ProjectDto::from)
.map_err(ErrorDto::from)
.map_err(ErrorDto::from)?;
// (Re)start the orchestrator watcher for this project (idempotent, §14.3).
state.ensure_orchestrator_watch(&output.project);
Ok(ProjectDto::from(output))
}
/// `close_project` — persist state and release resources for a project.
@ -105,6 +110,8 @@ pub async fn close_project(
state: State<'_, AppState>,
) -> Result<(), ErrorDto> {
let id = parse_project_id(&project_id)?;
// Stop tailing this project's `.ideai/requests/` tree (§14.3).
state.stop_orchestrator_watch(&id);
state
.close_project
.execute(CloseProjectInput {