Skip to content

v0.7.38: mothership improvements, clickup, rocketlane integrations, gitlab tools, deployment state machine#5712

Open
waleedlatif1 wants to merge 24 commits into
mainfrom
staging
Open

v0.7.38: mothership improvements, clickup, rocketlane integrations, gitlab tools, deployment state machine#5712
waleedlatif1 wants to merge 24 commits into
mainfrom
staging

Conversation

@waleedlatif1

@waleedlatif1 waleedlatif1 commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

TheodoreSpeaks and others added 14 commits July 15, 2026 20:28
…5697)

* chore(pii): remove GLiNER/GPU image + add spaCy-skip fast path to CPU server

* feat(pii): restrict block-output redaction to regex-only entities

* fix(pii): derive spaCy-NER set from registry + skip fast path when score_threshold set

* fix(pii): include ORGANIZATION in app-side NER set (align with server)
… sub management (#5680)

* improvement(webhooks): external subscription management

* ui/ux

* remove test file

* fix tests

* address comments

* address comments

* update to grain v2 api

* improvement(grain): hide auto-registered webhook URL on v2 triggers

* Revert "improvement(grain): hide auto-registered webhook URL on v2 triggers"

This reverts commit c89660c.

* address comments

* address comments

* address rollback

* fix grain v2

* fix more comments
* improvement(ci): decouple image builds from the test gate

- build-amd64 now starts immediately and pushes only sha tags (ECR :sha,
  GHCR :sha-amd64). The EventBridge deploy triggers filter on exactly the
  latest/staging/dev ECR tags, so nothing deploys from these pushes.
- New promote-images job retags sha -> latest/staging (and GHCR
  latest-amd64/version-amd64) via buildx imagetools once tests and
  migrations pass — a seconds-long manifest copy instead of rebuilding
  after the gate. Cuts push-to-deploy from ~13.5 to ~7 minutes.
- Split the Next.js production build out of test-build into a parallel
  Build App job with its own sticky-disk keys, cutting PR feedback from
  ~5.5 to ~3.5 minutes.
- create-ghcr-manifests and process-docs now gate on promote-images.

* improvement(ci): harden promotion — atomic retag, stale-run guards, gate all mutable GHCR tags

Review follow-ups:
- promote-images is a single job (not a matrix): verifies all four :sha
  manifests exist before moving any deploy tag, so a missing image can't
  cause a partial mixed-version deploy
- stale-run guard on promote-images and create-ghcr-manifests: re-running
  an old run no longer retags latest/staging back to stale code (a
  one-click prod rollback); superseded runs skip mutable tags with a
  warning while immutable sha/version tags still publish
- ARM64 build now pushes only the immutable :sha-arm64 tag; latest-arm64
  and version tags moved behind the gate into create-ghcr-manifests
  (closes the pre-existing hole where a failing run moved latest-arm64)
- dropped dead detect-version needs from both build jobs
- sticky-disk comment corrected (clone + last-writer-wins, not exclusive
  mounts); build job shares warm bun/node_modules disks, keeps its own
  turbo cache key so test/build entries don't evict each other
…ew loop (#5695)

* fix(babysit): resolve merge conflicts against staging during the review loop

* fix(babysit): trim merge-conflict handling to essentials

* fix(babysit): gate conflict-resolution pushes and handle UNKNOWN mergeable

* fix(babysit): bound persistent UNKNOWN mergeable state and clarify step skip

* fix(babysit): merge instead of rebase to resolve conflicts, drop force-with-lease

* fix(babysit): don't skip pending review findings when resolving a merge conflict

* fix(babysit): spot-check commit hygiene before a merge-conflict push

* fix(babysit): commit merge-conflict fixes before pushing, bound UNKNOWN before waiting

* fix(babysit): run pre-push checks before committing the merge-conflict fix

* fix(babysit): bound persistent CONFLICTING state and fix pre-push check order

* fix(babysit): reconcile hard rule with step 2's merge-conflict sync exception

* fix(babysit): page all review threads before branching on mergeable state

* fix(babysit): cut merge-conflict handling down to the essentials

* fix(babysit): simplify merge-conflict handling to a minimal step
…, attachment upload (#5702)

* feat(clickup): add ClickUp integration with OAuth + API-token auth, 23 tools, block, and attachment upload

- 23 tools covering tasks (create/get/update/delete/list/search), comments
  (create/get/update/delete), attachment upload, tags, members, custom
  fields, and the workspace/space/folder/list hierarchy
- OAuth provider wiring (authorization-code flow, non-expiring tokens) plus
  clickup-service-account token-paste credential (personal pk_ API tokens),
  with a shared clickupAuthorizationHeader helper (pk_ tokens sent bare,
  OAuth tokens as Bearer)
- File upload follows the internal-route pattern: contract-validated
  /api/tools/clickup/upload-attachment builds the multipart form and
  returns UserFiles
- ClickUp block with per-operation subBlocks, canonical file param,
  BlockMeta templates/skills, and gradient brand icon
- Generated integration docs page + hand-written service-account guide

* fix(clickup): apply validation-audit fixes across tools, block, and upload route

- Map documented task fields that were dropped: markdown_description,
  subtasks, watchers, custom_fields, time_spent, folder, space — making
  the include_subtasks / include_markdown_description options observable
- Expand verified filters: assignees/tags/due-date ranges on get_tasks and
  search_tasks, include_closed on search_tasks; add due_date_time /
  start_date_time flags and update-task assignee add/remove
- Guard update_comment against an empty body and require comment text in
  the block; prefer markdown_content over content on create_list and make
  markdown reachable for lists in the UI
- Drop the unverified 'required' field from custom-field outputs; read
  both err and error keys from ClickUp error bodies; correct notify_all
  wording
- Upload route: 100MB size cap, shared attachment mapper with full
  documented response fields (version, thumbnails), base-URL constant

* fix(docs): restore clickup-service-account guide and shield it from doc generation

The generator prunes integration pages it does not derive from blocks;
add the hand-written ClickUp API-token guide to
HANDWRITTEN_INTEGRATION_DOCS so regeneration cannot delete it.

* fix(clickup): address review findings — dedupe catalog entries, config-time list parent validation, upload memory cap, unique icon gradient ids

- Remove duplicated clickup entries in docs meta.json and integrations.json
  introduced by a double docs regeneration
- Add a Location dropdown for Get Lists / Create List so the folder ID or
  space ID is conditionally required at configuration time instead of
  failing at run time
- Pass the 100MB cap into downloadServableFileFromStorage so oversized
  files abort during download instead of after full buffering
- Use useId()-derived SVG gradient ids for ClickUpIcon in both icon files

* chore(clickup): format integrations.json entry per biome

* improvement(clickup): final validation-pass refinements across tools and block

- create_task: add doc-backed sprint points param (parity with update)
- get_tasks/search_tasks: expose include_markdown_description
- update_task legacy numeric priority in list responses mapped instead of
  dropped; create_comment omits absent response fields instead of
  emitting sentinel ''/0 values
- order_by only sent when explicitly chosen (Default sentinel); comment
  text no longer UI-required for update_comment (resolve-only and
  assignee-only updates are valid per the tool contract, which still
  rejects an empty body)
- add_tag_to_task sends no request body per docs; upload tool tolerates
  non-JSON error responses

* fix(clickup): tolerate nested user wrapper in member mapping

The task/list member endpoints document a flat member object; accept the
workspace-members-style nested { user: {...} } wrapper as well so both
shapes map correctly.

* fix(clickup): map size-limit errors from download/compile to a 400 upload-size response

downloadServableFileFromStorage enforces maxBytes on both the raw download
and the resolved (compiled) artifact via PayloadSizeLimitError; catch it in
the route so oversized content returns the intended 400 instead of
bubbling to the generic 500 handler.

* feat(clickup): add custom field values, checklists, and time tracking (15 tools, 38 total)

- Set/remove custom field values on tasks (PUT/DELETE /task/{id}/field/{field_id});
  block value input parses JSON for structured field types, plain values pass through
- Checklist CRUD: create/rename/reorder/delete checklists and create/update/
  delete checklist items (assign, resolve, nest), mapped from the documented
  {checklist} response shape
- Time tracking: list entries in a date range (assignee/location filters,
  task-tag and location-name includes), create/update/delete entries, start/
  stop timers, and read the currently running timer; entries mapped from the
  documented data envelope with negative-duration running semantics
- Block gains 15 operations with conditionally-required fields, timestamp
  wand configs, tri-state billable/resolved dropdowns, and a single-location
  filter selector matching the API's one-location-filter rule

* fix(clickup): new-tools audit fixes — POST for set custom field value, tolerant time-entry envelopes, richer mappings

- Set Custom Field Value uses POST per the live reference OpenAPI (the
  llms mirror shows PUT; the reference console spec is authoritative)
- delete_time_entry maps the documented array envelope; create_time_entry
  tolerates both data-wrapped and flat echo bodies
- Time entries surface task_tags and task_location so the include switches
  are observable; checklists carry date_created
- Custom field value input parses any JSON literal (numbers, booleans,
  arrays, objects) and passes plain text through
- Update Time Entry supports duration edits; single-assignee time ops get
  their own field so a comma-separated list can't silently NaN out

* fix(clickup): send explicit date-time flags whenever a date is set

The due/start date-time switches previously only transmitted true; a
timed date could never be flipped back to date-only. The flag is now sent
as an explicit boolean whenever the corresponding date is provided and
omitted otherwise.

* improvement(clickup): final per-tool audit polish — checklist item children, tolerant comment date

- Checklist items surface the documented children array of nested item IDs
- create_comment tolerates a string-typed date in the response

* fix(clickup): reject empty update_task bodies with a clear local error, matching sibling update tools
…alesforce + Pipedrive API tokens (#5690)

Second service-account kind (follow-up to #5682): client-credential pairs
(client ID + secret + org identifier) that mint short-lived tokens at
execution — in-memory cache with ciphertext-fingerprint validation
(rotation-correct across instances), single-flight coalescing, 30s failure
memo, no refresh-token storage.

- Zoom Server-to-Server OAuth, Box Client Credentials Grant, and Salesforce
  client-credentials (integration user) are the first minters; Salesforce's
  live instance_url rides the existing instanceUrl plumbing so all 40 tools
  work unchanged
- Pipedrive lands as a token-paste provider with explicit authStyle
  threading: descriptor declares x-api-token, one shared header helper drives
  all 18 tools + both selector routes, OAuth Bearer behavior untouched
- SSRF-allowlisted Salesforce My Domain host (production/sandbox/developer
  partitioned domains); ENOTFOUND maps to site_not_found, EAI_AGAIN stays
  provider_unavailable; 408/429 from token endpoints never blamed on creds
- Create route forwards clientId/clientSecret/orgId to the builder, pinned by
  a route-level regression test
- Zoom user-scoped tools document that server-to-server tokens don't support
  'me'
- 4 setup-guide docs pages verified against current vendor flows (incl.
  Salesforce External Client Apps — the classic Connected App wizard is
  disabled by default since Spring '26); integrations sidebar gains a Service
  Accounts & API Keys section
…ta> outputs (#5700)

* feat(start-block): add run metadata toggle with trusted <start.metadata> outputs

* fix(start-block): fail-soft email lookup, consistent nested metadata propagation, toggle parsing parity

* improvement(start-block): enumerate metadata fields in toggle description for agent schema

* fix(start-block): carry metadata chain through toggle-off children, preserve fail-soft null email

* fix(start-block): recover metadata chain from seeded start output after resume
…, phases, fields, time tracking, spaces, and invoices (#5709)

* feat(rocketlane): Rocketlane integration — 64 tools across projects, tasks, phases, fields, time tracking, spaces, and invoices

* fix(rocketlane): allow clearing optional fields on update, require a user reference for time-off and placeholder assignment

* chore(rocketlane): trigger fresh review round

* fix(rocketlane): require an owner reference when creating a project, matching the API contract
…dge-base connector (#5708)

* feat(clickup): webhook triggers with auto-managed subscriptions + hierarchy selectors

* feat(clickup): KB connector (Docs v3), selector-route hardening, subblock migrations, registry-check regex fix

* test(clickup): webhook provider handler tests + redact create-response secret in error logs

* fix(clickup-connector): trim final page to maxDocs cap with precise listingCapped semantics

* chore(clickup): lint formatting

* fix(clickup): restore list-op location requiredness, split listSpaceId migration target, surface failed webhook rollback

* fix(clickup): clickup.lists selector accepts listSpaceId context like clickup.folders

* fix(clickup): integer-only maxDocs and location filters, depth-aware doc headings, most-specific-location hints
…ts, fork chat, inline questions (mothership v0.8) (#5410)

* feat(scout): add scout agent

* fix(contracts): update contracts to include scout agent

* feat(copilot): search agent (research+scout merge) + read-only table/KB tool handlers

Mirrors mothership dev f90f9b05:
- regenerated tool-catalog/tool-schemas mirrors (search trigger replaces
  research + scout; QueryUserTable / SearchKnowledgeBase entries)
- queryUserTableServerTool / searchKnowledgeBaseServerTool: read-only
  wrappers delegating to the full user_table / knowledge_base handlers with
  hard operation allowlists (and outputPath export rejection on
  query_user_table)
- display maps: 'search' agent label/title/icon added; research + scout
  entries retained so historical transcripts keep rendering
- Search.id replaces Research.id in LONG_RUNNING_TOOL_IDS (it inherits
  research's long crawls)

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

* feat(copilot): run_code compute-only handler; docs lint fix

Mirrors mothership dev db60da94: run_code is the compute-only variant of
function_execute for the search agent — same sandbox and inputs, no
outputs.files / outputTable, so it cannot create or overwrite workspace
resources. Wrapper handler hard-rejects the write vectors and delegates to
executeFunctionExecute; run_code is deliberately absent from
OUTPUT_PATH_TOOLS and the table output post-processor, so the name gating
blocks writes even for leaked args. Added to LONG_RUNNING_TOOL_IDS,
display title/icon maps, and the regenerated catalog/schema mirrors.

Also removes two ineffective biome suppression comments in the docs
workflow-preview (the rule doesn't fire in the docs app config).

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

* fix(copilot): failed tool calls must surface their error in terminal data

A failed handler result that carried a defined-but-empty output (the
app-tool executor's 'Tool not found' ships output: {}) won the priority
race in getToolCallTerminalData, so the resume payload's data — the only
thing the model reads — was a bare {} with the error text dropped. The
search agent retried run_code 20+ times blind against a stale server
because every failure rendered as empty instead of 'Tool not found'.

Failed calls now always carry error in their terminal data: merged into
object outputs, wrapped alongside non-object outputs, preserved when the
output already has an error field.

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

* feat(chat): render inline question tags from the agent in chat

* fix(chat): let inert multi-step questions browse all prompts

* improvement(chat): guard question answer formatting against sparse arrays

* chore(copilot): drop user_memory from generated contracts and tool display

Companion to mothership 8ae32e97 (user_memory tool removed — the feature no
longer exists). Regenerates the mothership contract mirrors via
generate-mship-contracts.ts, which also picks up the pending telemetry
contract additions (gen_ai.agent.name labels, llm.client.context_tokens,
llm.client.compactions, llm.request.compaction_trigger, llm.compaction.pause,
gen_ai.usage.context_tokens), and removes the user_memory display title.

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

* improvement(chat): answered question card becomes the user turn; two select types only

UI ordering: answering a question card no longer echoes a duplicate user
bubble. The combined answer still goes on the wire as a user message, but the
chat pairs it back to its card (strict 'Prompt — Answer' match, now uniform
for single questions too) and renders the card as the answered recap — the
card IS the user turn, and the next assistant message streams below it. The
pairing is derived from the transcript, so live and reloaded renders are
identical; a dismissed card followed by an unrelated typed message does not
match and renders normally. Messages ending with a question card also drop
the copy/thumbs actions row — the card is an input surface, not a reactable
assistant turn.

Question types are now single_select and multi_select only: text is removed
(the free-text 'Something else' row covers it) and confirm collapses into
single_select with Yes/No options. multi_select rows toggle with a check and
the free-text row's arrow submits the step; answers are comma-joined labels
plus any typed entry. Agent-supplied catch-all options ('Other', 'Something
else', 'None of the above') are stripped at parse — the card always provides
its own free-text row; a question left with no real options is invalid.

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

* improvement(chat): question cards are single_select only

Removes multi_select (and its toggle/check UI). The card is one shape: pick
one option or type into the always-present 'Something else' row. Catch-all
stripping and the transcript pairing/recap behavior are unchanged.

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

* improvement(chat): bring back multi_select question cards

Re-adds multi_select with a reworked interaction: option rows carry real
checkboxes (emcn Checkbox chrome) instead of numbers and arrows, an
option-styled Submit row confirms the step, and the "Something else" row
reads as a plain option until clicked — then it becomes the focused text
box, auto-checks, and can be unchecked without losing the typed text
(blur with nothing typed reverts it). single_select behavior, catch-all
stripping, and the transcript pairing/recap format are unchanged;
multi_select answers are the checked labels comma-joined.

* chore(copilot): regenerate mothership contract mirror (chat blob span attrs)

* chore(copilot): regenerate mothership contract mirror (chat blob metrics)

* feat(secrets): make output of generate api key a secret

* feat(cli): add mkdir, mv, cp to mship tool set

* feat(fork-chat): add fork chat to mothership

* fix(fork-chat): fix messageid handling in fork chat

* feat(credentials): agent-initiated oauth credential reconnect (#5488)

* feat(credentials): agent-initiated oauth credential reconnect

* fix(credentials): address reconnect review findings

* improvement(credentials): log when connect draft name lookups degrade

* fix(conflicts): remove migration

* fix(conflicts): fix conflicts

* fix(fork-chat): add migrations back

* fix(ci): fix lint

* fix(ci): fix bad import

* fix(vfs): fix 500 char limit in vfs for skills and custom tools

* feat(copilot): gate user skills to explicit slash-attach (#5536)

Stop the mothership from adopting a workspace user-skill on its own:

- Remove the load_user_skill tool and its three payload callers (chat
  payload, mothership execute route, inbox executor); delete
  lib/mothership/skills.ts + its test. Skills no longer autoload as the
  agent's own instructions.
- Rename the workspace "## Skills" inventory to "## Agent Block Skills
  — NOT FOR YOU" with a one-line guardrail so a skill's description
  (e.g. "respond like a pirate") is not treated as an instruction.
  Skills reach the model as behavior only via explicit /-attach.

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

* feat(lots-of-things): lots of things

* feat(subagents): add persistent subagents

* fix(copilot): let edit_workflow set knowledge-base tag filters, and stop it clearing them (#5546)

* fix(copilot): persist KB tag subblocks as JSON strings from edit_workflow

The edit_workflow tool normalizes array-with-id subblocks (via
normalizeArrayWithIds) but only re-stringifies the keys listed in
JSON_STRING_SUBBLOCK_KEYS. `tagFilters` (knowledge-tag-filters) and
`documentTags` (document-tag-entry) were missing, so agent-authored tag
filters were stored as raw JSON arrays while those UI components read
their value with JSON.parse (expecting a string). The result: an agent
edit to a Knowledge block's tag filter persisted correctly but rendered
as an empty filter in the editor (JSON.parse on an array throws -> []).

- Add `tagFilters` and `documentTags` to JSON_STRING_SUBBLOCK_KEYS so
  edit_workflow stores them in the same shape the UI writes.
- Make both components' parsers tolerate an already-parsed array on read,
  self-healing values already persisted in the broken (array) shape.

Search execution was unaffected (parseTagFilters accepts arrays), so the
value was never lost — only the editor render and round-trip were broken.

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

* feat(copilot): expose KB tag definitions in VFS meta.json

Surface each knowledge base's defined tags (displayName -> tagSlot) inline in
its meta.json via serializeKBMeta, loaded in one batched query
(loadKbTagDefinitions), so the agent can bind a knowledge-tag filter to a real
tag slot instead of guessing a tag name it cannot otherwise see.

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

* fix(copilot): stringify KB tag subblocks on the nested-node edit path

The nested-node merge path normalized array-with-id subblocks but never
re-serialized the JSON_STRING_SUBBLOCK_KEYS, so editing a block nested in a
loop/parallel container still persisted tagFilters/documentTags (and
conditions/routes) as raw arrays -- the exact shape the subblock components
cannot JSON.parse.

Route all four write paths through a single normalizeSubblockValue helper so
the normalize and re-stringify steps cannot drift apart again, and extract the
duplicated string-or-array read logic into parseJsonArrayValue.

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

* refactor(copilot): tighten subblock serialization helpers

Derive KbTagDefinitionSummary from the canonical TagDefinition instead of
restating its fields, make parseJsonArrayValue generic so callers drop their
`as T[]` casts, and unexport the three builders helpers that no longer have
consumers outside the module now that normalizeSubblockValue fronts them.

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

* fix(copilot): stop stripping tagFilters/documentTags from the agent's workflow view

sanitizeForCopilot dropped `tagFilters` and `documentTags` from the workflow state the
agent reads (workflows/{name}/state.json), while edit_workflow is allowed to write both.
The field was therefore write-only: on a follow-up edit the agent read back an absent
field, concluded no filter was set, and cleared the user's tag filter.

The redaction was introduced for workflow *export* (#1628) and is already enforced there
by sanitizeWorkflowForSharing's key list. The duplicate in the copilot-only
sanitizeSubBlocks was redundant for export and destructive for the agent. Removes it and
pins the contract with a regression test.

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

* fix(copilot): reject malformed KB tag values instead of clearing the filter

`knowledge-tag-filters` and `document-tag-entry` had no arm in the
`edit_workflow` input validator, so they fell through to the pass-through
default. Any non-array value the agent supplied -- a double-encoded JSON
string, an object, an unparseable string -- reached `normalizeSubblockValue`,
where `normalizeArrayWithIds` coerces unparseable input to `[]`. The write
path then persisted `"[]"` over the tag filter the user had configured.

`condition-input` and `router-input` already guard against exactly this and
return an actionable error to the model. Extend that arm to cover the two KB
subblock types. It keys on subblock type, so the unrelated `tagFilters`
short-input on the Algolia block is unaffected. `null`/`undefined` and empty
arrays still clear the field, so intentional clears keep working.

Also wrap `loadKbTagDefinitions` in try/catch. Tag definitions are an optional
meta.json enrichment, but the query ran inside the top-level `Promise.all`, so
a transient failure would reject the entire workspace VFS materialize and
leave the agent unable to read any file. Now it degrades to a meta.json
without tag definitions, matching the sibling materializers.

Adds regression tests for both, plus the first tests for
`parseJsonArrayValue`, the helper that keeps pre-fix raw-array rows readable.

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

* refactor(copilot): collapse duplicate JSON-array parsing in edit-workflow builders

`normalizeArrayWithIds` and `normalizeConditionRouterIds` each hand-rolled the
same "accept a raw array or the JSON string these subblocks persist" parse.
Extract `parseJsonArray`, which returns null when the value is neither, so each
caller keeps its own distinct fallback: `[]` for the former, the untouched
original value for the latter.

Behavior-preserving. An empty array is truthy, so `[]` and `"[]"` still parse
through rather than hitting either fallback.

`validation.ts` has a third copy, but `builders.ts` already imports from it, so
sharing the helper across the two would introduce an import cycle. Left as is.

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

* feat(copilot): specify tag name and legal operators in KB meta.json

`tagDefinitions` exposed `displayName`, but a `tagFilters` entry must carry the
key `tagName`. An entry written with `displayName` passes validation and
persists, then filters nothing -- a silent failure. Rename the field at the
serializer boundary; the DB column is untouched.

Also emit the operators legal for each tag's `fieldType`, reusing
`getOperatorsForFieldType`. `between` is valid for number and date but not for
text or boolean, and the agent has no way to infer that. An unrecognized
fieldType yields an empty list rather than throwing.

Still unspecified, and deliberately out of scope: a filter entry's value key is
`tagValue` (but `value` on documentTags), and `between` needs `valueTo`. Those
describe the subblock entry shape, not the knowledge base, so meta.json is the
wrong place for them.

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

* fix(copilot): pass a nullish subblock clear through instead of serializing "[]"

`validateValueForSubBlockType` accepts null as an explicit clear, but
`normalizeSubblockValue` then ran it through `normalizeArrayWithIds`, which
coerces any non-array to `[]`, and persisted the string "[]".

No data is lost either way -- "[]" and an absent field both mean "no filters".
But it left the field present when the caller asked for it to be unset, so
`sanitizeForCopilot` showed the agent an empty filter rather than an absent
one, contradicting the absent-means-unset invariant the sanitizer documents.
It also made Algolia's `if (params.tagFilters)` see a set value, since "[]" is
truthy.

An explicitly empty array still serializes to "[]" -- clearing with a value is
distinct from clearing by omission.

Reported by Cursor Bugbot on #5546.

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

---------

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

* feat(changes): huge changes

* fix(subagents): lanes

* fix(mship): transcript stuff

* fix(subagents): thinking lanes

* fix(superagent): fix superagent tools and checkpoints

* fix(scope): scope subagent tools

* fix(lint): fix lint

* chore(db): regenerate workspace_files.message_id migration as 0260 on staging base

* fix(superagent): fix superagent integration tools

* improvement(questions): make something else a placeholder

* chore(copilot): regenerate mothership contract mirror after staging rebase

* feat(mship): add external mcps to mship

* fix(ci): fix dev build

* fix(stream): show thinking text

* fix(ci): force redeploy

* fix(mothership): keep chat forks outside workspace storage billing

Preserve the product invariant that Mothership chat files are not charged as workspace file storage after the billing storage merge.

* fix(uploads): restore listWorkspaceFiles throwOnError option dropped in rebase

* fix(subagent-streaming): remove italics

* fix(mothership): treat subagent lanes closed by subagent_end as settled so the between-steps thinking indicator isn't suppressed

* fix(ui): thinking loader and rool names

* fix(ui): add file

* fix(thinking): show thinking during subagents

* fix(chat): drop dead thinking-channel ternary after lanes skip thinking blocks

* fix(thinking): remove thinking text

* improvement(function execute): add timeout to function execute and stop showing text in subagents

* fix(subagents): hide thinking text

* fix(ff): move ff to go

* improvement(superagent): nuke superagent

* feat(main-agent): superagent into main agent

* chore(db): regenerate workspace_files.message_id migration as 0262 on staging base

* fix(credentials): restore reconnect params on shared createConnectDraft

* fix(migrations): rebase with staging

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Emir Karabeg <emirkarabeg@berkeley.edu>
Co-authored-by: Justin Blumencranz <96924014+j15z@users.noreply.github.com>
Co-authored-by: Vikhyath Mondreti <vikhyath@simstudio.ai>
* feat(gitlab): add access, membership, and user-admin tools

Adds member, invitation, access-request, SAML group link, and user
administration tools to the GitLab integration. Resource-scoped ops work
against projects or groups; user-admin ops require an admin token. All tools
reuse the existing host/SSRF guard via getGitLabApiBase and add a shared
getGitLabResourcePath helper.

* feat(gitlab): wire access operations into the GitLab block

Adds the new operations to the block dropdown and tools access list, with a
named access-level dropdown (enum in, integer out), first-class expires_at,
a /members/all default (direct-only opt-in), resource-type selector, and
member_role_id passthrough.

* test(gitlab): cover access operations

Covers the access_level enum-to-integer coercion, the /members/all default vs
direct-only, the 409-duplicate-add soft success, invitation per-email error
handling, user-status-action response parsing, and getGitLabResourcePath.

* docs(gitlab): document access and membership operations

* Update apps/sim/blocks/blocks/gitlab.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* fix(gitlab): address review findings

- update_user now sends admin:false so the Administrator switch can demote
  (an untouched switch stays undefined and leaves the flag unchanged)
- expose the access-level dropdown for Update Invitation
- normalize comma-separated invite emails so spaced multi-email input works

* fix(gitlab): make update-invitation access level optional

Update Invitation now uses a dedicated dropdown that defaults to 'Leave
unchanged', so updating only the expiration no longer silently resets the
invitation's access level to Developer. The level is sent only when explicitly
chosen.

* fix(gitlab): validation pass — SAML provider param, member/invitation query filter, moderation user guard, registry order

* fix(gitlab): apply 10-agent validation findings across all 62 tools

- MR draft flag now applied via Draft: title prefix (GitLab has no draft body param)
- update_user only sends admin when a real boolean (untouched switch serialized null and could demote admins)
- add_member 409 soft-success now verified against the conflict body
- auto_merge sent alongside deprecated merge_when_pipeline_succeeds
- job log capped at 200k chars, file content at 1M chars, with truncated outputs
- MR diffs signal hasMore beyond 100 files
- wire dropped params: update_issue milestoneId, MR milestone/squash/removeSourceBranch, pipelines ref, tree ref, branches search, commits since/until/path/author, update_file lastCommitId, jobs includeRetried, create_user forceRandomPassword
- complete pipeline/job status enums, access-level enums, widen stale type unions
- guards: update_invitation requires a change; create_user requires a password strategy
- fix double-encoding trap in path descriptions; doc-accuracy touch-ups

* fix(gitlab): review round 1 — dedicated no-default access level for update member, expiration clearing via explicit empty string

* fix(gitlab): explicit Clear Expiration toggle for update member/invitation

* feat(gitlab): expose full documented API surface across tools and block

- membership: add-by-username, remove-member cleanup flags, list-member filters (user_ids/state/seat info), invite_source
- listings: search/visibility/owned/membership, assignee/milestone filters, source/target branch filters, per-domain order-by + sort direction
- CI: pipeline variables + spec:inputs, manual-job variables
- repo: commit authoring (start branch, author, execute flag), release tag message + asset links, cross-fork compare + unidiff, internal notes
- catalog: access-governance template + member-provisioning and access-request-audit skills
- hardening from 3-agent validation: declared release params, tolerate single-object asset links, NaN guard on assignee filter, null/scalar JSON rejection

* fix(gitlab): tri-state controls for update-op booleans (executable flag, MR squash/remove-source-branch)

---------

Co-authored-by: Marcus Chandra <mzxchandra@gmail.com>
Co-authored-by: mzxchandra <129460234+mzxchandra@users.noreply.github.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
@waleedlatif1
waleedlatif1 requested a review from a team as a code owner July 16, 2026 19:36
@greptile-apps

greptile-apps Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Too many files changed for review. (670 files found, 100 file limit)

@vercel

vercel Bot commented Jul 16, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Jul 17, 2026 2:16am

Request Review

@cursor

cursor Bot commented Jul 16, 2026

Copy link
Copy Markdown

PR Summary

High Risk
Changes to when ECR/GHCR deploy tags move directly affect what CodePipeline ships to production/staging; a mis-gated promotion could block deploys or, without the stale-head guard, retag old images. The rest is mostly docs and agent playbooks (lower runtime risk).

Overview
CI/CD no longer moves latest/staging ECR tags (or public GHCR latest tags) during image build. AMD64/ARM64 builds push commit-SHA tags only in parallel with tests; a new promote-images job retags all four ECR repos after migrations + builds succeed, with a branch-head guard so re-running an old workflow cannot roll production back. GHCR mutable tags and multi-arch manifests are published only after that gate; test-build splits into parallel Lint and Test vs Build App jobs.

Babysit agent/command docs now check gh pr view --json mergeable, resolve CONFLICTING PRs against origin/staging before review triage, and treat stuck merge conflicts like stuck review findings.

Docs / integrations (in diff): full ClickUp block reference (actions + webhook triggers), ClickUp API token and Box service account setup guides, expanded GitLab docs (membership, invitations, SAML links, instance user admin, truncation flags on file/log outputs), Airtable typecast on write operations, and new doc icons (ClickUp, Rocketlane, NVIDIA, Z.ai, grain_v2).

Reviewed by Cursor Bugbot for commit 8adeaab. Configure here.

@github-actions github-actions Bot added the requires-mothership-merge Has a companion PR on the mothership/copilot side — merge in lockstep label Jul 16, 2026
@github-actions

github-actions Bot commented Jul 16, 2026

Copy link
Copy Markdown

⚠️ Cross-repo companion check

One or more companion PRs aren't merged into main yet (aggregated across the feature PRs in this release). Merging this without them will leave copilot and sim out of sync — merge them in lockstep.

  • ⚠️ simstudioai/mothership#343 — merged into staging (this PR targets main) — feat(mothership): mixture of models, search agent, persistent subagents, fork ch
  • ⚠️ simstudioai/mothership#344 — merged into dev (this PR targets main) — feat(tools): reconnect support for oauth_get_auth_link via credentialId

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 8adeaab. Configure here.

Comment thread .github/workflows/ci.yml
waleedlatif1 added a commit that referenced this pull request Jul 16, 2026
The stale-promotion guard skipped any run whose commit was no longer the
branch head. If commit A passed its gate but was superseded mid-run by
commit B, and B then failed tests, A's promotion was skipped and the
deploy tags stayed on pre-A code with no automatic recovery (Cursor
finding on #5712).

A first-attempt run promoting an ancestor of the branch head is always a
forward deploy — runs on a ref are serialized by the concurrency group,
so nothing newer can have promoted first. Only re-runs of superseded
commits (a rollback attempt) and force-pushed-away commits are skipped.
Same semantics applied to the GHCR latest-tag guard.
* improvement(ci): promote superseded first-attempt runs forward

The stale-promotion guard skipped any run whose commit was no longer the
branch head. If commit A passed its gate but was superseded mid-run by
commit B, and B then failed tests, A's promotion was skipped and the
deploy tags stayed on pre-A code with no automatic recovery (Cursor
finding on #5712).

A first-attempt run promoting an ancestor of the branch head is always a
forward deploy — runs on a ref are serialized by the concurrency group,
so nothing newer can have promoted first. Only re-runs of superseded
commits (a rollback attempt) and force-pushed-away commits are skipped.
Same semantics applied to the GHCR latest-tag guard.

* fix(ci): grant contents:read to create-ghcr-manifests for the compare-API guard

Job-level permissions replace the workflow defaults, so packages:write
alone left the guard's compare call 403ing — STATUS=unknown would have
silently skipped the GHCR latest tags on every main push.
…ode pin; remove i18n workflow (#5714)

* improvement(ci): job timeouts everywhere, docs-only PR skip, event-scoped sticky disks, Node pin; drop dead i18n workflow

- timeout-minutes on every runnable job (defaults ran hung jobs to the
  6-hour cap — the i18n workflow burned three full 6-hour runs in Feb
  before its schedule was pulled)
- paths-ignore on the pull_request trigger: docs content and markdown
  don't affect the app build or images; push runs stay unfiltered
- sticky-disk keys scoped by event name so fork PR runs never share a
  disk with the push runs that feed production image builds
- node-version pinned to 22 (was 'latest', non-deterministic)
- delete i18n.yml: schedule already removed after repeated 6-hour hangs,
  workflow_dispatch-only since, comments stale

* improvement(ci): 45m migrate timeout (covers 30m lock wait), fork-namespaced PR sticky disks

- migrate.ts waits up to 30 minutes for the migration advisory lock
  (LOCK_ACQUIRE_DEADLINE_MS); the 15m job timeout would preempt that
  designed wait, so the bound is 45m
- fork PRs now get their own sticky-disk namespace so an untrusted fork
  run can't poison the disks that trusted internal-PR runs restore
* feat(providers): add Kimi (Moonshot AI) provider

* fix(providers): preserve reasoning_content in kimi tool loop
Comment thread packages/security/src/hash.ts Dismissed
Comment thread packages/security/src/hash.ts Dismissed
waleedlatif1 and others added 3 commits July 16, 2026 15:49
…5722)

* feat(library): add best AI agent platforms 2026 comparison article

* fix(library): count all eleven compared platforms and add Dust/Lindy table rows
…5720)

* feat(table): per-plan table dispatch concurrency with env overrides

* fix(table): enforce shared concurrencyKey cap on database batchEnqueueAndWait

* refactor(table): thread dispatch concurrency via invocation instead of persisting it

* improvement(table): collapse dispatch concurrency env vars to FREE/PAID
… block double-covered personal checkouts (#5715)

* improvement(checkout): enforce team/enterprise-only org subscriptions, block double-covered personal checkouts, and drop renewal-triggered workspace detach

* close race with personal pro / org inclusions

* address comments

* fix(billing): compute org coverage independently of the personal-sub lookup and fail closed on unverifiable plan writes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

requires-mothership-merge Has a companion PR on the mothership/copilot side — merge in lockstep

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants