Commit Graph

110 Commits

Author SHA1 Message Date
Carlos Florêncio e077658a61 refactor: centralize runtime feature flag bindings (#2142) 2026-08-02 15:36:21 +01:00
Carlos Florêncio 190eeddbc4 fix: default new workspaces to host GitHub access (#2156) 2026-08-02 14:13:04 +01:00
Carlos Florêncio 72f01e6c35 docs: simplify public documentation for scanning (#2139) 2026-08-01 22:02:54 +01:00
Carlos Florêncio 1d70a0df6d feat: enforce task title length limit (#2134) 2026-08-01 19:42:23 +01:00
Carlos Florêncio 1bccadf8f9 fix: validate MCP tool arguments (#2123) (#2128) 2026-08-01 18:18:08 +01:00
Carlos Florêncio 65b0e249ec docs: clarify subscription usage surfaces (#2122) 2026-08-01 12:04:15 +01:00
Carlos Florêncio e466bda55f fix: preserve service identity and resume credentials (#2121) 2026-08-01 11:19:24 +01:00
Carlos Florêncio 01beeb3753 fix: handle same-version agent runtime updates (#2120) 2026-08-01 11:18:37 +01:00
José Almeida 03e179c4d3 feat: add last task startup preference (#2102) 2026-08-01 09:58:05 +01:00
José Almeida f8c363f726 feat(layout): add layout-owned PR Details panel (#2094) 2026-07-31 19:45:32 +01:00
Carlos Florêncio aeb7c62e49 feat(github): unify workspace GitHub access (#2084) 2026-07-31 19:20:49 +01:00
Carlos Florêncio 9f2b5f92c3 refactor(settings): centralize portable user-setting defaults (#2107) 2026-07-31 18:41:49 +01:00
Jelloeater's Agent 26db9fc260 feat(agents): add Hermes ACP agent integration (#2089) 2026-07-31 16:32:19 +01:00
João Salavisa eb72f53c1b fix(web): phone navigation for plugin pages (#2093)
Co-authored-by: Kandev Agent <agent@kandev.dev>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-31 14:57:40 +01:00
Clément Fiere 59d1cc7277 feat: add Slack-style unread divider to session transcript (#1922) 2026-07-31 14:42:14 +01:00
Carlos Florêncio 7ad1599b70 feat(web): show WebSocket connectivity warnings (#2083) 2026-07-31 14:23:16 +01:00
João Salavisa 9be979827d fix: sync quick chats and their names across devices (#2085)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-31 09:01:22 +01:00
João Salavisa 6b31479ec2 feat(web): open the IDE at a file tree node's path (#2074)
Co-authored-by: Kandev Agent <agent@kandev.dev>
2026-07-31 09:00:31 +01:00
João Salavisa 1a3c134f1a feat(plugins): ship the plugin system without a feature flag (#2086)
Co-authored-by: Kandev Agent <agent@kandev.dev>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-31 08:59:34 +01:00
Carlos Florêncio 3760f12939 feat(editors): scope embedded VS Code by executor (#2059) 2026-07-30 22:24:16 +01:00
Carlos Florêncio 167ab6b778 feat(mcp): add session attachment diagnostics (#2061) 2026-07-30 20:49:07 +01:00
José Almeida d4e8f0a62a fix(web): make review ordering and navigation safe (#2067) 2026-07-30 20:07:36 +01:00
Clément Fiere 3eb8e4a59c feat: add transcript last prompt navigation (#1999) 2026-07-30 12:35:26 +01:00
Carlos Florêncio 6ba9f1b0fd feat: add quarantine retention lifecycle (#2049) 2026-07-30 10:44:51 +01:00
Carlos Florêncio b4c537fa11 feat(web): hide embedded VS Code on Windows hosts (#2045) 2026-07-29 22:10:19 +01:00
Luan Martins 04a5c4e4ee feat(github): add task PR lifecycle notifications (#2038) 2026-07-29 18:13:02 +01:00
João Salavisa 6868410d80 fix(plugins): match per-session-suffixed event subjects in plugin delivery (#2029)
Per-session events are published on a suffixed bus subject
("shell.output.<sessionId>") but stamped with the bare event-type constant
("shell.output"). The plugin deliverer subscribed with the manifest pattern and
then re-checked that pattern against event.Type, which made every suffixed
subject undeliverable: a 3-segment pattern matched the bus subscription but
failed the re-check on segment count, while a 2-segment pattern passed the
re-check but never subscribed to the 3-segment subject.

Carry the concrete publish subject on bus.Event (stamped in place by Publish in
both the memory and NATS implementations; the NATS receive side prefers the
delivering msg.Subject) and re-check the manifest pattern against it via a new
Event.EffectiveSubject helper that falls back to Type. The concrete subject is
also what plugins receive as pluginsdk.Event.EventType -- already documented in
the proto as "bus subject" -- so a plugin subscribed to "shell.output.*" can
read the session id off it.

Audited all 109 EventBus.Publish call sites: 17 subject families were affected;
office.run.event_appended, the office tree-hold subjects and the cross-plugin
plugin.<id>.<name> already stamped Type with the full subject. Three git.ws
sites in the orchestrator publish on git.ws.<sessionId> while stamping
events.GitEvent, so the subject there is not a suffixed form of its own type at
all -- left as-is, since the gateway routes off the subject and never reads
event.Type. Unsuffixed subjects publish with subject == type, so existing
2-segment subscriptions are unaffected, and the re-check still enforces manifest
segment-count strictness over the bus's looser NATS ">" semantics.
2026-07-29 13:30:30 +01:00
José Almeida 7ec82dcaec feat(search): add task workspace search palette (#2006) 2026-07-29 09:50:29 +01:00
Carlos Florêncio e8d4b7d69e fix: restore coarse running busy signal (#2023) 2026-07-29 08:11:51 +01:00
Carlos Florêncio a65087e062 fix: pull unstarted feeder tasks into available WIP steps (#2003) 2026-07-28 21:26:05 +01:00
Carlos Florêncio 09b5c4df7a feat: propagate managed git environment to terminals (#2010) 2026-07-28 21:19:27 +01:00
Carlos Florêncio adecad7f30 fix(github): honor executor clone transport (#1998) 2026-07-28 15:46:28 +01:00
Carlos Florêncio f501346d15 feat: add visible WIP overflow queues (#2001) 2026-07-28 15:46:16 +01:00
Carlos Florêncio 7250cdbf61 feat: explain busy storage cleanup and allow override (#1993) 2026-07-28 09:23:42 +01:00
Carlos Florêncio 35d1a85d74 fix: recover failed agent resumes and managed runtimes (#1991) 2026-07-28 09:23:30 +01:00
João Salavisa 16495a6dcc fix(terminal): expose executor-profile env vars to terminal shells (#1992)
* fix(terminal): expose executor-profile env vars to terminal shells

PR #1971 got the profile env into the agent subprocess and the repository
setup script, but the terminal panel was still a gap: the local user shell
was started with `InteractiveStartRequest.Env` unset, so it inherited only
the backend process environment, and agentctl's per-terminal shells were
started from `shell.DefaultConfig` with no env overrides at all.

Local/worktree path: resolve the task environment's executor profile at
terminal start (revealing secret-backed entries) and pass it through
UserShellOptions.Env into the deferred PTY start. Resolution happens per
terminal rather than being cached at launch, so a terminal opened before
the agent ever runs still gets the vars.

Remote path (Docker/Sprites/SSH): StartTerminalShell now folds the agent
instance's env into the shell config, so a terminal inside the workspace
sees what the agent sees. SSH is unchanged in scope — its instance env is
still only the credential allowlist, not arbitrary profile variables.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(terminal): resolve terminal env from the session's executor profile

Address PR review. The resolver read executor_profile_id off the
task_environments row, but persistTaskEnvironment's reuse branch never
refreshes that column — it keeps whatever the first session stamped on it.
buildLaunchAgentRequest resolves the agent's env from
session.ExecutorProfileID instead, so a task environment reused by a later
session that picked a different profile of the same executor type would give
the terminal stale secrets and omit the ones the agent just received.

Prefer the session's profile and fall back to the environment row only when
the session recorded none. Also document why mergeAgentEnvIntoShellConfig
needs no defensive copy and why StartEnvForTesting is exported.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* test(terminal): give env-row fallback subtests distinct session IDs

Address PR review nit: both subtests shared the hardcoded "session-3" at
the call site, so the error-path case read as a repeat of the first.
Move the session ID into the table as session-no-profile / session-error.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Kandev Agent <agent@kandev.dev>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-28 00:08:57 +01:00
Carlos Florêncio d705b3c2f3 fix(mcp): restore live add-branch worktrees (#1990)
* fix(mcp): restore live add-branch worktrees

* fix(mcp): reject deferred live branch additions

* docs(mcp): clarify live branch response contract
2026-07-27 22:08:18 +01:00
Carlos Florêncio 2bd2bae2ea feat: improve agent runtime update flow (#1982) 2026-07-27 19:34:13 +01:00
Carlos Florêncio b39a668e99 feat(github): add task git credential policy (#1985) 2026-07-27 18:10:12 +01:00
Carlos Florêncio 06d72a1215 fix: enforce workflow-step WIP limits on task creation (#1980) 2026-07-27 16:14:13 +01:00
Carlos Florêncio fdd915b946 fix: guard Office launches without runtime context (#1974) 2026-07-27 14:01:19 +01:00
Carlos Florêncio d0d084bdc6 feat(agents): add user-managed runtime updates (#1950) 2026-07-27 12:21:47 +01:00
João Salavisa 37b56ba11c feat(automations): reliable cron scheduling and webhook-driven push/CI triggers (#1972)
* feat(automations): reliable cron scheduling and webhook-driven push/CI triggers

Automations were "wounded": cron schedules mishandled timezones and some
never fired, and the GitHub push/CI trigger types were coming-soon stubs.

Cron (fix):
- The scheduler reduced every cron expression to a fixed interval derived
  only from a */N step in the minute/hour field, so any pinned schedule
  (0 9 * * *, 30 14 * * *, weekday ranges, day-of-month) never fired, and
  the configured timezone was parsed but never used.
- Replace the interval approximation with robfig/cron/v3: shouldFire now
  computes the true next fire time in the configured timezone (DST-aware,
  defaulting to UTC for host-independence), anchored to last-evaluated or
  creation time. Dead interval-parsing helpers and shorthand constants
  removed.

GitHub push + CI triggers (feat):
- Implement push and CI-failure triggers end to end via the existing
  per-workspace GitHub App webhook plumbing (#1810): the HMAC-verified
  webhook service now parses push and completed check_run events, resolves
  the installation to its workspaces, and publishes normalized bus events.
- A new automation subscriber matches enabled github_push / github_ci
  triggers by workspace + repo + branch/conclusion/check-name filters and
  fires them (deduped by commit SHA / check-run id). The old poll-based
  stub evaluators are removed; the PR poll path is unchanged.
- Subscribe the App manifest to push/check_run and enable both trigger
  types in the registry (CI defaults to the failure conclusion).

Docs:
- Update docs/public/feature-status.md and automation-and-mcp.md so the
  cron and push/CI rows reflect shipped reality.

Tests: regression tests pin the previously-never-firing cron shapes,
timezone/DST behavior, and host-independence; backend tests cover the
webhook parse->publish and subscriber match/fire/dedup flows for both
push and CI-failure.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(automations): populate push.message and ci.url placeholders in fired trigger data

Address PR review blockers: the default push and CI automation prompts
reference {{push.message}} and {{ci.url}}, which the interpolator maps to
data["message"] / data["html_url"] — but the webhook subscriber never
populated those fields, so both always rendered empty.

- Parse head_commit.message (push) and check_run.html_url (CI) in the
  GitHub webhook service and carry them on the published bus payloads.
- Include "message" / "html_url" in the fired trigger data so the
  placeholders resolve; extend the webhook and subscriber tests to assert
  both flow through end to end.

Non-blocking review cleanups:
- Replace the misleading reuse of matchesAuthors for CI conclusions/check
  names with a clearly-named matchesFilterValue helper.
- Drop dead context.Background() line and its unused import from the cron
  regression test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(automations): scope webhook triggers to active installs and per-branch dedup

Address CodeRabbit review on the push/CI webhook triggers:

- Security: resolveWorkspaceIDs now only returns connections whose status is
  active, so a suspended or revoked GitHub App installation can no longer fire
  push/CI automations.
- Correctness: include the branch in the push dedup key
  (push:owner/name@branch@sha) so the same commit pushed to two matching
  branches fires once per branch instead of being suppressed.
- Correctness: add an optional head-branch filter to github_ci triggers and
  gate CI matching on it, matching the push trigger's branch-scoping.
- Stability: make the webhook subscriber's Start retryable — a subscription
  failure rolls back partial subscriptions and leaves the subscriber
  un-started so a later Start re-attempts, instead of permanently disabling
  push/CI processing.
- Tests: cover multi-connection workspace resolution (dedup + inactive
  filtering), per-branch push dedup, and CI branch filtering.
- Docs: note the CI branch filter and per-branch push dedup.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(automations): cover webhook subscriber Start retry-after-failure path

Add TestGitHubWebhookSubscriberStartRetryableAfterFailure with a minimal
flaky bus whose second Subscribe fails, pinning the retry contract: a
subscription failure rolls back the partial subscription and leaves the
subscriber un-started, and a later Start re-attempts and succeeds.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Kandev Agent <agent@kandev.dev>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-27 10:24:57 +01:00
Carlos Florêncio 49e00447a5 fix: restore legacy GitHub launch compatibility (#1962) 2026-07-26 19:07:46 +01:00
João Salavisa b20047b3eb feat(plugins): add auth capability for plugin-provided OIDC/SAML login (#1964)
* feat(plugins): add auth capability for plugin-provided OIDC/SAML login

Plugins can now authenticate a visitor against an external IdP (OIDC/SAML)
and contribute a login button to the pre-auth screen:

- new `auth` manifest capability + a capability-gated X-Kandev-Auth-Login
  webhook-response directive; the host mints the kandev_session (ADR 0050),
  the plugin never receives the raw token. Plugin-set Set-Cookie is dropped.
- auth.Service.AuthenticateExternal: existing-identity / link-by-email / JIT
  member provisioning; refuses to auto-link to an admin; verified-email is
  the plugin's contract.
- auth_providers manifest block + plugins.SSOProviders() populate the
  anonymous boot payload (auth.ssoProviders); the login page renders a
  "Continue with <provider>" button per provider.
- ADR 0050 + plugin-manifest / plugin-authoring / auth spec docs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs: exclude publish_review_findings_kandev from public-docs coverage

The native code-review agent (#1957) added the publish_review_findings_kandev
MCP tool but did not update docs/public/coverage.json; that PR did not touch
docs/public so the path-filtered validator never ran. It's an internal review
reporting tool, not a user-facing feature, so record it as an exclusion.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(plugins,auth): address review on SSO directive and JIT provisioning

- takeAuthLoginDirective strips every case variant of X-Kandev-Auth-Login and
  rejects (403) when a plugin sends more than one, so no variant leaks to the
  browser and login never uses a nondeterministically-picked assertion.
- provisionExternalUser rolls back the just-created user when the identity
  insert fails (transient error or a lost UNIQUE(provider,subject) race) and
  resolves to the winning identity, so no account is left without a login and
  no email is reserved by an unusable row. Adds userstore.DeleteUser.
- auth spec: mark the login-page SSO buttons + provider discovery as landed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs: drop redundant coverage exclusion; main now covers publish_review_findings_kandev

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Kandev Agent <agent@kandev.dev>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-26 18:20:39 +01:00
Carlos Florêncio 45974b513a fix(acp): deliver follow-ups after foreground handoff (#1959) 2026-07-26 17:29:41 +01:00
Carlos Florêncio 6ffb23c187 fix: harden background work lifecycle tracking (#1955) 2026-07-26 14:18:35 +01:00
Carlos Florêncio 75abf779ed feat(github): support per-workspace GitHub App registrations (#1810) 2026-07-26 10:39:08 +01:00
Carlos Florêncio bc218dfbbe feat: add workspace sources from files panel (#1900)
* feat: add workspace sources from files panel

* fix: preserve worktree identity during recovery

* feat: unify workspace source actions

* fix: validate recovered workspace repositories

* fix: harden workspace source filesystem boundaries

* test: split workspace repository chip coverage

* fix: restrict repository rescan recovery paths

* fix: stabilize workspace source CI checks

* test: canonicalize workspace source paths

* test: align workspace source container paths

* fix: populate direct workspace repository names

* test: preserve git fixture rewrites across restarts

* test: isolate backend git fixture config

* fix: resume remote workspace executions before creation

* fix: preserve ssh agent identity during resume

* fix: preserve SSH workspace across backend restart

* fix: simplify workspace actions trigger

* fix: refine add workspace repositories UX

* docs: narrow workspace source UX updates

* fix: avoid phantom turn on session resume

* test(web): normalize workspace source request headers

* feat(web): streamline workspace source picker

* docs: remove trailing spaces from workspace source plan

* fix: prevent resume status from creating phantom turns

* fix(web): stabilize workspace source attachment

* refactor(web): extract workspace source store contract

* fix: avoid phantom turns on idle agent resume

* fix: address backend static analysis findings

* fix: preserve agentctl readiness status value

* fix: preserve resume messages without active turns

* fix: resume agents from promoted workspace root

* chore: merge origin/main into feature/add-new-repo-folder-d97

* feat(web): explain workspace source consequences

* test(websocket): count session activity subscription
2026-07-25 21:29:53 +01:00
Carlos Florêncio a4d53bdf42 feat(web): remember task listing display preferences (#1944) 2026-07-25 19:30:52 +01:00