Commit Graph

13 Commits

Author SHA1 Message Date
João Salavisa 2a1f7c2edf feat: sync workflows from a configured github repo (#1721)
* feat: sync workflows from a configured github repo

Per-workspace setting pointing at a GitHub repo directory of portable
workflow export files. A background poller fetches it on an interval and
creates, updates, or deletes the matching workflows; a force-sync endpoint
bypasses the content-hash check. Synced workflows carry source/source_path
provenance and coexist with manual ones; changes that cannot be applied
safely (steps or workflows that still hold tasks, ambiguous step names,
unparseable files) surface as warnings in the new settings section.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(web): fill workflow sync form from a pasted github link

A new Repository link field parses plain repo URLs, SSH remotes, and
tree/blob links (which also carry branch and directory) into the
structured owner/repo/branch/path fields.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(web): simplify workflow sync form to link, branch, and interval

The repository link is now the only repo input: owner, repo, and
directory resolve from the pasted URL (echoed as a summary under the
field), and a stored config renders back into a canonical tree link via
buildGitHubRepoUrl. Branch and poll interval stay individually editable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(web): collapse workflow sync into a button, dialog, and status card

The Workflows settings page now shows only a GitHub Sync button by
default; the link/branch/interval form lives in a dialog that closes on
successful save or removal. Once configured, a compact status card
(mirroring the GitHub connection-status card) shows the synced repo,
branch, directory, last result, warnings, and a Sync now action.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(web): move github sync button into the workflows page header

The GitHub Sync trigger now stacks under the Workspace settings button
on the top right, and the extra separator around the sync area is gone —
unconfigured workspaces show no sync chrome at all, configured ones show
just the status card above the workflow list.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(web): move github sync button next to the workflow actions

GitHub Sync now sits in the Workflows section toolbar alongside
Export All, Import, and Add Workflow; the status card renders inside the
section above the workflow list. The toolbar moved to its own component
to keep the page under the file-size limit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(web): separate sync status card from the workflow list

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(web): align sync status card with the workflow list gutter

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix: repair local edits to synced workflows on periodic sync

Periodic syncs previously skipped applying when the repo content hash
was unchanged, so local UI edits to a synced workflow were only reverted
by a manual Sync now. Every sync now reconciles against the repo; the
applier compares each step against its definition and only writes (and
broadcasts) actual differences, so a no-drift sync stays silent.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat: make github-synced workflows read-only

Workflows with source=github reject UI mutations: workflow rename,
description, agent-profile, and delete return 409 from the task-domain
handlers; step create/update/delete/reorder and template application are
guarded in the workflow controller. The sync applier writes through the
service/repo layer and stays exempt. The frontend disables the card's
inputs, save/delete, and the step pipeline editor for synced workflows,
with a tooltip pointing at the synced repository. Drift repair on sync
remains as the backstop.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat: optional workflow sync polling and repo-derived branch picker

A per-workspace auto-sync toggle (poll_enabled, default on) controls
the background polling loop; when off the workspace only syncs via Sync
now. The dialog's branch field becomes a select fed by the repository's
actual branches (same loader the task-create dialog uses), falling back
to free text until branches load. Existing dev databases gain the new
column via an idempotent ALTER.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat: release synced workflows when the sync config is removed

Deleting a workspace's workflow sync configuration converts its
GitHub-sourced workflows back to manual ownership (source=manual), so
they become editable instead of being stranded read-only. Release runs
before the config row is deleted so a failure keeps the config for
retry. The settings page reloads after removal (and after syncs that
changed workflows) so cards unlock without a manual refresh.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(web): drop branch selector and compact the auto-sync row

The pasted link already carries the branch (main by default), so the
dialog no longer needs a branch field — the resolved summary echoes it.
The auto-sync toggle is now one compact row with the interval inline and
a single short helper line.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix: address PR review feedback

Backend: fail-open read-only guard on workflow lookup errors (fixes MCP
step handler CI failures); poller Stop holds its mutex through drain;
per-workspace lock serializes syncs against config delete/replace;
rollback workflow creation when provenance stamping fails; idiomatic
duplicate-column migration via db.IsDuplicateColumnError; branch-name
validation and a 30-day interval cap; generic 500s with logged detail;
WS read-only rejections use CONFLICT with the real reason; e2e reset
aborts when sync-config cleanup fails; test hygiene (t.Cleanup,
SetMaxOpenConns).

Frontend: malformed percent escapes parse as invalid instead of
throwing; save disabled during initial load and for invalid intervals;
Remove disabled while saving; stale async config responses discarded;
delete-dialog confirms re-check read-only; focusable Synced badge;
explicit button types; failed polls labeled 'last attempt'; unique
warning list keys; test cleanup via afterEach.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix: guard workflow sync test fake against concurrent poller access

The poller invokes the fake applier from its own goroutine while the
synctest test asserts on call counts; -race caught the unguarded reads.
Also documents that the per-workspace lock is deliberately held across
the GitHub fetch.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Kandev Agent <agent@kandev.dev>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 08:31:20 +01:00
Carlos Florêncio 248e8bf48e feat: add workflow WIP pull system (#1613) 2026-07-13 12:18:57 +01:00
Carlos Florêncio 6118201c20 fix: enforce single workflow start step (#1507) 2026-06-26 13:59:55 +01:00
João Salavisa 97c1f689e4 feat(workflow): explicit step-completion signal for auto-advance (#1276)
* feat(workflow): explicit step-completion signal for auto-advance

Adds `step_complete_kandev` MCP tool + `WorkflowStep.auto_advance_requires_signal`
column so workflow steps can gate their `on_turn_complete` transitions on an
agent-emitted completion signal instead of inferring "done" from any turn-end.
See docs/decisions/0015-explicit-completion-signal-for-auto-advance.md for the
motivation, alternatives considered, and trade-offs.

* fix(workflow): address PR review feedback for explicit completion signal

- Dedup `LoadPendingStepSignal` into `internal/task/models` so the MCP
  handler (write site) and the orchestrator (read site) share one decoder.
- Gate the out-of-band subscriber on `WorkflowStep.AutoAdvanceRequiresSignal`
  so `step_complete_kandev` is not an unintended manual-advance path for
  signalless steps.
- Fail closed on step-load errors in `processOnTurnCompleteViaEngine`: a
  loader hiccup must block the transition rather than silently bypass the
  gate.
- Reject `step_complete_kandev` for terminal sessions
  (Completed / Failed / Cancelled) so the agent gets a clear error instead
  of `accepted: true` followed by a no-op.
- Surface bus-publish failures back to the agent instead of swallowing
  them — the idempotency guard makes the retry safe and prevents the
  session from getting stuck.
- New `TestOnStepCompletionSignaled` covers the subscriber paths
  (RUNNING / WAITING+match / stale step / not signal-gated).
- ADR doc fixes: payload field list now matches the wire shape, writer
  ownership is documented, the unsubstantiated 250ms-debounce claim is
  removed, and the late-signal re-close race is recorded as a deferred
  open question.
- Drop the new toggle's HelpTip in favour of an inline description — the
  shadcn tooltip portal was intercepting clicks on the agent-profile
  dropdown options in the workflow settings E2E.

* fix(workflow): round-2 review fixes for explicit completion signal

- Split `handleStepComplete` into `resolveStepCompleteTarget` +
  `publishStepCompletionEvent` helpers so the entrypoint clears funlen
  (88 → under 80 lines) and the two halves are independently testable.
- Classify session/task load errors instead of returning `NotFound` for
  every failure: use the exported `taskrepo.ErrTaskNotFound` sentinel for
  task lookups, substring-match for the session repo (no sentinel today),
  and surface anything else as `InternalError` with the raw error logged
  but not leaked to the agent — so a transient DB hiccup triggers a retry
  rather than session abandonment.
- Pin `step_complete_kandev` explicitly in the mode-specific tool-count
  tests: `Contains` in `ModeTask`, `NotContains` in `ModeConfig` and
  `ModeOffice`, so accidental dereg or cross-mode registration is caught
  by the diff instead of by a still-equal count.

* fix(workflow): round-3 review fixes + defer pipeline-editor toggle

- Defer the "Wait for agent completion signal" sub-toggle to a follow-up
  PR. Adding it to the step config card shifts the layout enough that the
  agent profile select's Radix popper opens into a sibling tooltip's hover
  path, breaking workflow-agent-profile.spec.ts on shard 7. The backend
  column ships in this PR — workflows can opt in via the YAML import or
  the MCP `update_workflow_step_kandev` tool — and the UI affordance gets
  its own iteration where the test interference can be investigated
  without blocking the rest of the change.
- Re-publish the bus event on the `already_signaled` short-circuit when
  the session is WAITING_FOR_INPUT. Without this, an agent's retry after
  the first call's publish failed would short-circuit on the persisted
  bag, never fire the subscriber, and leave the session stuck.
- handleStepComplete docstring: drop the non-existent feature-flag claim
  and the "audit entry" wording — gating is purely
  `WorkflowStep.AutoAdvanceRequiresSignal` and the bag is cleared on the
  next turn start with no separate audit trail.
- `step_complete_kandev` tool description: same fix — clarify that the
  call succeeds for non-gated steps but the signal is discarded on the
  next turn start (no audit history to query later).

* test(workflow): cover handleStepComplete + reword defer-comment

- Add `TestHandleStepComplete_*` (6 subtests, all passing) covering the
  uncovered handler paths flagged by Claude/cubic on round 3:
  missing-fields validation, session-does-not-belong-to-task ownership
  guard, terminal-session rejection (Completed/Failed/Cancelled),
  first-call happy path (bag persisted + bus payload shape pinned), dedup
  while RUNNING (no re-publish), and dedup while WAITING_FOR_INPUT (the
  retry-after-publish-failure path — must re-publish so the subscriber
  fires).
- Reword the deferred-toggle comment to drop the YAML-export claim:
  the workflow export model doesn't yet serialize
  `auto_advance_requires_signal`, so MCP `update_workflow_step_kandev`
  is the only configuration path that round-trips today. Note the
  follow-up needs to extend the export schema alongside the UI toggle.

* test(workflow): pin signaled_at + drop redundant GetTaskSession on bag-clear

- Assert `signaled_at` is present and parses as RFC3339Nano in
  `TestHandleStepComplete_FirstCallAccepted`. The field is part of the
  handler's documented response contract; pinning it catches accidental
  drop/rename regressions.
- Add `clearPendingStepSignalByID(ctx, sessionID)` as a thin DB-only
  variant of `clearPendingStepSignal` and use it from
  `executeStepTransition`, where the session struct isn't read after the
  clear. Avoids an extra `GetTaskSession` round-trip per transition.
  `clearPendingStepSignal(session)` still exists for the
  in-memory-mutation case (subscriber's stale-step path).

* fix(workflow): subscriber stale-clear guard + ADR/comment drift fixes

- onStepCompletionSignaled's stale-step path now reads the bag and only
  clears it when its current StepID matches the (stale) event's stepID.
  Previously the unconditional clear could destroy a valid signal that
  the new step's agent had just written when sessions are reused across
  steps without auto_start_agent. (Greptile P1.)
- Drop the "feature flag" phrase from WorkflowStep.AutoAdvanceRequiresSignal
  docstring — leftover from an earlier draft. The gating is purely the
  boolean field; the global flag was removed two rounds ago.
- Merge the two adjacent `if triggerOnEnter` blocks in
  executeStepTransition so the full triggerOnEnter=true path reads top-
  to-bottom in one place. (CodeRabbit + cubic.)
- ADR 0015 Mechanism section: re-label the SessionStepHistory.Metadata
  audit annotation, the `step_complete_signaled` system message, and the
  expvar telemetry counters as deferred. They're planned shapes, not
  current behaviour — calling them "Audit" / "Chat visibility" /
  "Telemetry" in present tense was misleading for future readers.

* fix(workflow): drop subscriber complexity + reload session on stale-clear

- Extract `parseStepCompletionEvent` and `stepIsSignalGated` helpers from
  `onStepCompletionSignaled`. Cyclomatic complexity goes 17 → under 15
  (cyclop on new code, CI lint regression after the round-6
  stale-clear guard).
- The stale-step branch now re-loads the session from the DB before
  deciding whether to clear the bag. The previous round-6 fix checked
  the local `session.Metadata` snapshot, which can be older than a
  concurrent write from the new step's agent — that check could see a
  stale signal that had since been overwritten with a valid one and
  erase the new bag entry. The narrower load-on-clear is cheap and
  closes the cubic P1 hole. (The broader race in
  `processOnTurnCompleteViaEngine` reading session.Metadata is the
  monotonic-marker open question in ADR 0015; out of scope here.)

* test(workflow): pin stale-event guard's preserve-current-bag side + dedup StringFromAny

- Add `TestOnStepCompletionSignaled` subtest "stale event → valid bag
  for CURRENT step is preserved" — fires a stale step-A event while
  the bag holds a valid step-B signal, asserts the bag still contains
  StepID=step_b after the subscriber runs. Pins the negative side of
  the round-6 `existing.StepID == stepID` guard, so a regression that
  drops or inverts the guard (and would silently leave signal-gated
  steps stuck) fails the test instead of slipping through.
- Promote `pendingSignalString` to exported `models.StringFromAny`
  and reuse it from the orchestrator subscriber's
  `parseStepCompletionEvent`. Eliminates the byte-for-byte duplicate
  helper across the two packages; the bag-shape decoder and the bus-
  event decoder now share one source of truth for "missing string".

---------

Co-authored-by: Kandev Agent <agent@kandev.dev>
2026-06-05 18:32:27 +01:00
Carlos Florêncio 5e4fc9c1dd fix(workflow): exclude office workflows from settings export (#1184) 2026-05-31 11:47:25 +01:00
Carlos Florêncio a222854422 feat: associate agent profiles with workflows and steps (#597) 2026-04-16 10:14:45 +01:00
José Almeida 74a8d7563e feat: split file search from command panel, add inline task search & configurable shortcuts (#383)
* feat(web): split file search from command panel and add inline task search

Separate the command panel (Cmd+K) from file search (Cmd+Shift+K) to
prevent file results from overpowering commands. Add inline task search
directly in the command panel — tasks appear in a "Tasks" group when
typing ≥2 characters, with workflow step badges and archived state
indicators. Archived tasks are sorted last with reduced opacity.

- Add "search-files" mode to CommandPanelMode
- Add FILE_SEARCH shortcut (Cmd/Ctrl+Shift+K)
- Move file search to dedicated mode, remove from commands mode
- Add useInlineTaskSearchEffect for commands mode task search
- Remove "Search Tasks" sub-mode entry point (now inline)
- Show file search shortcut hint in command panel footer

* feat(web): add configurable keyboard shortcuts in general settings

Add localStorage-based shortcut override system for the command panel
and file search keybindings. Users can record new key combos via the
settings UI and reset to defaults.

- Add shortcut-overrides module (get/set/reset via localStorage)
- Add KeyboardShortcutsCard with shortcut recorder UI
- Add "Keyboard Shortcuts" section to general settings page

* test(web): add e2e tests for command panel and file search split

Cover the key use cases: Cmd+K opens commands without files,
Cmd+Shift+K opens file search, inline task search with workflow step
badges, escape/backspace navigation, and panel toggle behavior.

* fix(test): remove unused seedData variable in command panel e2e test

* feat(settings): persist keyboard shortcuts to user settings API

Replace localStorage-based shortcut overrides with server-persisted
storage via the user settings API. Adds keyboard_shortcuts field to
the backend model, DTO, store, service, and controller. Frontend
reads overrides from Zustand store (hydrated from SSR/WS) and saves
via PATCH /api/v1/user/settings.

* fix(ui): prioritize tasks over commands, add step colors, fix shortcut display

- Move task results above command results in cmd+K for faster task switching
- Replace magnifier icon with task icon (IconSubtask) for task results
- Apply workflow step color to task badges
- Fix formatShortcut early return bug that dropped Shift modifier
  when ctrlOrCmd was set (e.g. Cmd+Shift+K showed as Cmd+K)
- Fix same bug in shortcutToCodeMirrorKeybinding

* fix(ui): use clipboard icon for task results in command panel

* style: format command panel footer

* fix(ui): use hammer icon and map step colors to hex for task badges

* feat(ui): show repo directory and agent name on task results

Display secondary details (repository directory, agent name, last
updated) on the right side of task results in the command panel.

* fix: avoid inline selector closure to prevent getServerSnapshot loop

Select the raw repositories map from the store instead of using an
inline selector that closes over workspaceId and returns new array
references, which triggers React's getServerSnapshot infinite loop.

* feat(task): expose agent name and working directory in task DTO

Add primary_agent_name (from AgentProfileSnapshot) and
primary_working_directory (from RepositorySnapshot) to TaskDTO.
Extend the primary session info query to fetch agent_profile_snapshot
and repository_snapshot columns, and extract the new fields in the
handler layer.

* feat(ui): show agent name and working directory on command panel tasks

Replace executor name with agent name from the primary session and
display the working directory (with repository path fallback) in the
task result details.

* fix(ui): add Commands heading to separate tasks from commands in search

* fix(task): use profile display name instead of agent slug

* feat(workflow): add show_in_command_panel per-step configuration

Add a configurable boolean to each workflow step that controls whether
tasks in that step appear in the command panel (Cmd+K). Default
templates mark backlog/done steps as hidden, active steps as visible.

- Add show_in_command_panel to WorkflowStep, StepDefinition, StepPortable
- Add column with idempotent migration (DEFAULT 1 for backwards compat)
- Include field in DTO serialization and export/import round-trip
- Update all default templates (Plan & Build, Architecture, Kanban, PR Review)
- Add tests for export preservation and import round-trip

* feat(ui): wire show_in_command_panel through frontend and settings

- Add field to HTTP types (WorkflowStep, WorkflowStepDTO, StepDefinition)
- Add to kanban state types and KanbanUpdatePayload
- Map in SSR snapshot mapper and WS kanban handler
- Add "Show in command panel" checkbox to workflow step settings
- Extract StepCheckboxRow component to stay within lint limits

* feat(ui): filter command panel tasks by show_in_command_panel flag

Replace position-based heuristic (resolveExcludedStepIds) with the
per-step show_in_command_panel configuration. Tasks in steps where
the flag is false are hidden from the default Cmd+K view but still
accessible via search.

- Replace resolveExcludedStepIds with resolveVisibleStepIds
- Consolidate useInlineTaskSearchEffect params into options object

* fix(ui): differentiate task sections in command panel

Rename the inline task results heading to "Active Tasks" when showing
the default view, distinguishing it from the "Tasks" command group
that contains "Create New Task".

* fix(ui): keep auto-archive checkbox inline with other step options

* fix(ui): include show_in_command_panel in step update action

The server action was missing show_in_command_panel from its Pick type
and body builder, so the checkbox change was silently dropped.

* fix(ui): pass is_start_step and show_in_command_panel from template steps

Both normalizeWorkflowTemplate mappers (workflow-api.ts and
workspaces.ts) were only picking name/position/color/prompt/events
from backend template steps, dropping is_start_step and
show_in_command_panel. This caused all template steps to appear
with show_in_command_panel checked when creating a new workflow.

* fix(ui): fix command panel empty tasks and step update losing checkbox state

Two fixes:
- Command panel: when kanban steps haven't loaded yet, don't filter
  tasks by visibility (resolveVisibleStepIds returns null for empty
  steps instead of an empty Set that rejects everything)
- Workflow settings: BackendWorkflowStep type and transformWorkflowStep
  were missing show_in_command_panel, so refreshing steps after an
  update dropped the field and the checkbox always reverted

* fix(ui): prevent back button from stealing focus in command panel

The back button was focusable and appeared before CommandInput, so
opening file search mode focused the button instead of the input.
Add tabIndex={-1} to keep focus on the search input.

* feat(web): show archive icon for archived tasks in command panel

Replace the text badge (e.g. "COMPLETED") with an IconArchive for
archived tasks in the command panel search results. Active tasks
keep the existing IconHammer icon.

* style: fix Prettier formatting and extract useStepMaps hook

Fix Prettier formatting issues in command-panel.tsx and
workflow-pipeline-editor-panels.tsx. Extract useStepMaps hook
from useInlineTaskSearchEffect to stay within the 100-line
function limit.

* fix: address PR review feedback

- Validate keyboard shortcut payload shape before persisting (service.go)
- Normalize KeyboardShortcuts to {} on read path for legacy rows (sqlite.go)
- Deduplicate getRepoDir into getFileName (command-panel-footer.tsx)
- Show toast on shortcut persistence failure instead of swallowing (keyboard-shortcuts-card.tsx)
- Reset keyboard_shortcuts in E2E test fixture for deterministic tests (test-base.ts)
2026-03-07 03:59:01 +00:00
Carlos Florêncio 6e4d22cae0 feat: improve sql queries (#260) 2026-02-21 23:02:52 +00:00
Carlos Florêncio 61ef224ec7 style: fix format issues (#255) 2026-02-19 22:18:01 +00:00
Carlos Florêncio 5a871af788 feat: import export workflows (#244) 2026-02-17 23:01:54 +00:00
Carlos Florêncio 3af7a692bf feat: archive tasks (#232) 2026-02-16 21:46:25 +00:00
Carlos Florêncio 658bd349b5 feat: improve workflows (#228) 2026-02-16 13:48:58 +00:00
João Salavisa 0b573bbdda feat(workflow): implement workflow system with steps terminology (#102) 2026-01-27 01:21:47 +00:00