feat(KIN-012): UI auto/review mode toggle, autopilot indicator, persist project mode in DB
- TaskDetail: hide Approve/Reject buttons in auto mode, show "Автопилот активен" badge
- TaskDetail: execution_mode persisted per-task via PATCH /api/tasks/{id}
- TaskDetail: loadMode reads DB value, falls back to localStorage per project
- TaskDetail: back navigation preserves status filter via ?back_status query param
- ProjectView: toggleMode now persists to DB via PATCH /api/projects/{id}
- ProjectView: loadMode reads project.execution_mode from DB first
- ProjectView: task list shows 🔓 badge for auto-mode tasks
- ProjectView: status filter synced to URL query param ?status=
- api.ts: add patchProject(), execution_mode field on Project interface
- core/db.py, core/models.py: execution_mode columns + migration for projects & tasks
- web/api.py: PATCH /api/projects/{id} and PATCH /api/tasks/{id} support execution_mode
- tests: 256 tests pass, new test_auto_mode.py with 60+ auto mode tests
- frontend: vitest config added for component tests
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
3cb516193b
commit
4a27bf0693
12 changed files with 2698 additions and 30 deletions
|
|
@ -51,14 +51,15 @@ def create_project(
|
|||
claude_md_path: str | None = None,
|
||||
forgejo_repo: str | None = None,
|
||||
language: str = "ru",
|
||||
execution_mode: str = "review",
|
||||
) -> dict:
|
||||
"""Create a new project and return it as dict."""
|
||||
conn.execute(
|
||||
"""INSERT INTO projects (id, name, path, tech_stack, status, priority,
|
||||
pm_prompt, claude_md_path, forgejo_repo, language)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
||||
pm_prompt, claude_md_path, forgejo_repo, language, execution_mode)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
||||
(id, name, path, _json_encode(tech_stack), status, priority,
|
||||
pm_prompt, claude_md_path, forgejo_repo, language),
|
||||
pm_prompt, claude_md_path, forgejo_repo, language, execution_mode),
|
||||
)
|
||||
conn.commit()
|
||||
return get_project(conn, id)
|
||||
|
|
@ -70,6 +71,20 @@ def get_project(conn: sqlite3.Connection, id: str) -> dict | None:
|
|||
return _row_to_dict(row)
|
||||
|
||||
|
||||
def get_effective_mode(conn: sqlite3.Connection, project_id: str, task_id: str) -> str:
|
||||
"""Return effective execution mode: 'auto' or 'review'.
|
||||
|
||||
Priority: task.execution_mode > project.execution_mode > 'review'
|
||||
"""
|
||||
task = get_task(conn, task_id)
|
||||
if task and task.get("execution_mode"):
|
||||
return task["execution_mode"]
|
||||
project = get_project(conn, project_id)
|
||||
if project:
|
||||
return project.get("execution_mode") or "review"
|
||||
return "review"
|
||||
|
||||
|
||||
def list_projects(conn: sqlite3.Connection, status: str | None = None) -> list[dict]:
|
||||
"""List projects, optionally filtered by status."""
|
||||
if status:
|
||||
|
|
@ -114,15 +129,17 @@ def create_task(
|
|||
brief: dict | None = None,
|
||||
spec: dict | None = None,
|
||||
forgejo_issue_id: int | None = None,
|
||||
execution_mode: str | None = None,
|
||||
) -> dict:
|
||||
"""Create a task linked to a project."""
|
||||
conn.execute(
|
||||
"""INSERT INTO tasks (id, project_id, title, status, priority,
|
||||
assigned_role, parent_task_id, brief, spec, forgejo_issue_id)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
||||
assigned_role, parent_task_id, brief, spec, forgejo_issue_id,
|
||||
execution_mode)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
||||
(id, project_id, title, status, priority, assigned_role,
|
||||
parent_task_id, _json_encode(brief), _json_encode(spec),
|
||||
forgejo_issue_id),
|
||||
forgejo_issue_id, execution_mode),
|
||||
)
|
||||
conn.commit()
|
||||
return get_task(conn, id)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue