Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 3 additions & 28 deletions .github/workflows/mockup-sprint-pentest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
push:
branches:
- main
# Dev pushes run the full mockup pentest catalog before integration.
# Dev pushes run the rapid orchestration lane before integration.
- dev
workflow_dispatch:

Expand Down Expand Up @@ -40,30 +40,5 @@ jobs:
- name: Install dependencies
run: pnpm install --frozen-lockfile --ignore-scripts

- name: Build
run: pnpm run build

- name: Verify Docker availability
run: |
if ! docker version; then
echo "::error::Docker is required for the mockup sprint pentest Docker lane."
exit 1
fi

- name: Run mockup sprint pentest
run: |
if [ "${GITHUB_REF_NAME}" = "dev" ]; then
node scripts/e2e/run-mockup-sprint-pentest.mjs --scenario pentest --timeout-ms 3600000
else
pnpm run test:e2e:mockup-sprint-pentest
fi

- name: Upload mockup sprint pentest artifacts
if: ${{ failure() || hashFiles('.cache/e2e-mockup-sprint-pentest/**') != '' }}
uses: actions/upload-artifact@v4
with:
name: mockup-sprint-pentest-artifacts
path: .cache/e2e-mockup-sprint-pentest/
if-no-files-found: ignore
include-hidden-files: true
retention-days: 5
- name: Run rapid orchestration validation
run: pnpm run test:orchestration:rapid
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,43 @@ export const SettingsModelsPanel: FunctionComponent<{ state: SettingsPageState }
}));
};

const clearRouteProviderOverrideField = (
routeId: InvocationRoutingId,
providerConfigId: ProviderConfigId,
field: keyof ProjectSettings["aiProvider"]["invocationRouting"][InvocationRoutingId]["providers"][ProviderConfigId],
): void => {
updateEditableSettings((current) => {
const route = current.aiProvider.invocationRouting[routeId];
const currentOverride = route.providers[providerConfigId];
if (!currentOverride || !(field in currentOverride)) {
return current;
}

const nextOverride = { ...currentOverride };
delete nextOverride[field];
const nextProviders = { ...route.providers };
if (Object.keys(nextOverride).length > 0) {
nextProviders[providerConfigId] = nextOverride;
} else {
delete nextProviders[providerConfigId];
}

return {
...current,
aiProvider: {
...current.aiProvider,
invocationRouting: {
...current.aiProvider.invocationRouting,
[routeId]: {
...route,
providers: nextProviders,
},
},
},
};
});
};

const clearRouteProviderOverride = (
routeId: InvocationRoutingId,
providerConfigId: ProviderConfigId,
Expand Down Expand Up @@ -863,6 +900,8 @@ export const SettingsModelsPanel: FunctionComponent<{ state: SettingsPageState }
const effectiveModel = getEffectiveProviderDisplayModel(providerConfigId, provider, override.model || provider.model);
const inheritedModel = getEffectiveProviderDisplayModel(providerConfigId, provider);
const effectiveThinking = getThinkingSelectValue(provider, override.thinkingMode);
const inheritedThinkingLabel = getProviderThinkingModeLabel(provider.provider, provider.thinkingMode);
const hasThinkingOverride = typeof override.thinkingMode === "string";
const effectiveWeight = override.weight ?? provider.weight;
const supportsModel = providerSupportsModelSelection(provider.provider);
return (
Expand Down Expand Up @@ -956,12 +995,21 @@ export const SettingsModelsPanel: FunctionComponent<{ state: SettingsPageState }
</Row>
) : null}
{providerSupportsThinkingMode(provider.provider) ? (
<Row label="Thinking override" description={`Inherited: ${getProviderThinkingModeLabel(provider.provider, provider.thinkingMode)}`}>
<Row label="Thinking override" description={`Inherited: ${inheritedThinkingLabel}`}>
<SelectInput
value={effectiveThinking}
value={hasThinkingOverride ? effectiveThinking : INHERIT_VALUE}
aria-label={`${provider.name} thinking override for ${activeRouteDefinition.label}`}
onChange={(value) => updateRouteProviderOverride(activeRouteDefinition.id, providerConfigId, { thinkingMode: value as ThinkingMode })}
options={getProviderThinkingModeOptions(provider.provider)}
onChange={(value) => {
if (value === INHERIT_VALUE) {
clearRouteProviderOverrideField(activeRouteDefinition.id, providerConfigId, "thinkingMode");
return;
}
updateRouteProviderOverride(activeRouteDefinition.id, providerConfigId, { thinkingMode: value as ThinkingMode });
}}
options={[
{ value: INHERIT_VALUE, label: `Inherit base thinking (${inheritedThinkingLabel})` },
...getProviderThinkingModeOptions(provider.provider),
]}
/>
</Row>
) : null}
Expand Down
26 changes: 18 additions & 8 deletions dashboard/src/v2/components/ui/AvantgardeSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,22 +128,32 @@ export const AvantgardeSelect: FunctionComponent<AvantgardeSelectProps> = ({
? boundary.getBoundingClientRect()
: { top: 0, left: 0, right: window.innerWidth, bottom: window.innerHeight };

const viewportBounds = {
top: Math.max(bounds.top, 0),
bottom: Math.min(bounds.bottom, window.innerHeight),
left: Math.max(bounds.left, 0),
right: Math.min(bounds.right, window.innerWidth),
};

// --- Vertical direction ---
const spaceBelow = bounds.bottom - triggerRect.bottom - GAP - EDGE_MARGIN;
const spaceAbove = triggerRect.top - bounds.top - GAP - EDGE_MARGIN;
const spaceBelow = viewportBounds.bottom - triggerRect.bottom - GAP - EDGE_MARGIN;
const spaceAbove = triggerRect.top - viewportBounds.top - GAP - EDGE_MARGIN;
const direction: "down" | "up" =
spaceBelow >= PANEL_MAX_H || spaceBelow >= spaceAbove ? "down" : "up";

const top =
const rawTop =
direction === "down"
? triggerRect.bottom + GAP
: triggerRect.top - GAP;
: triggerRect.top - GAP - PANEL_MAX_H;
const minTop = viewportBounds.top + EDGE_MARGIN;
const maxTop = Math.max(minTop, viewportBounds.bottom - PANEL_MAX_H - EDGE_MARGIN);
const top = Math.min(Math.max(rawTop, minTop), maxTop);

// --- Horizontal: keep panel within bounds ---
let left = triggerRect.left;
const panelRight = left + panelWidth;
const boundsRight = bounds.right;
const boundsLeft = bounds.left;
const boundsRight = viewportBounds.right;
const boundsLeft = viewportBounds.left;

if (panelRight > boundsRight - EDGE_MARGIN) {
// Align right edge of panel with right edge of trigger (or boundary)
Expand Down Expand Up @@ -189,8 +199,8 @@ export const AvantgardeSelect: FunctionComponent<AvantgardeSelectProps> = ({
const panel = panelRef.current;
let ctx = gsap.context(() => {
const isUp = position.direction === "up";
const initialY = isUp ? "calc(-100% + 10px)" : "-10px";
const targetY = isUp ? "-100%" : "0px";
const initialY = isUp ? "10px" : "-10px";
const targetY = "0px";

// Check if gsap is mocked or unavailable in test environment
if (typeof gsap.fromTo !== 'function' || typeof gsap.to !== 'function') {
Expand Down
6 changes: 3 additions & 3 deletions docs-web/content/docs/developer-orchestration-debugging.mdx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# Rapid orchestration debugging suite

Use this suite when a sprint stalls, local merges fail, worker-owned attention items churn, or memory usage needs extended observation after a fix.
Use this suite when a sprint stalls, local merges fail, worker-owned attention items churn, or memory usage needs extended observation after a fix. CI uses the rapid lane by default; full mockup pentest lanes are manual escalation tools for targeted investigations.

## Commands

| Lane | Command | Purpose |
| --- | --- | --- |
| Fast regressions | `pnpm run test:orchestration:rapid` | Watch-loop, feature merge, and local final-merge regressions without Docker or provider CLIs. |
| Mockup merge E2E | `pnpm run test:orchestration:merge-e2e` | Compiled runtime plus `mockup-cli` through a deterministic local merge-conflict DAG. |
| Full mockup pentest | `pnpm run test:orchestration:full` | All deterministic mockup scenarios: smoke, CI repair, merge conflict, parallel DAG, dirty checkout, multi-project overrides. |
| Full mockup pentest | `pnpm run test:orchestration:full` | Manual escalation for all deterministic mockup scenarios: smoke, CI repair, merge conflict, parallel DAG, dirty checkout, multi-project overrides. |
| Large DAG stress | `pnpm run test:orchestration:large-dag` | Heavy 129-task mockup DAG with wide fan-out and layered joins. |
| Full heavy pentest | `pnpm run test:orchestration:pentest` | Default mockup catalog plus heavy stress scenarios. |
| Backend broadening | `pnpm run test:backend` | Full backend suite after focused fixes. |
Expand All @@ -20,7 +20,7 @@ Start with `pnpm run test:orchestration:rapid`. It covers provider routing, watc

Run `pnpm run test:orchestration:merge-e2e` after a unit-level merge fix passes. It builds the compiled runtime and exercises the `merge-conflict-dag` mockup scenario through the local project runtime.

Run `pnpm run test:orchestration:full` before calling a scheduler, provider, CI, QA, or multi-project orchestration issue fixed. It executes every deterministic mockup scenario and writes artifacts under `.cache/e2e-mockup-sprint-pentest/<run-id>/`.
Run `pnpm run test:orchestration:full` manually when a scheduler, provider, CI, QA, or multi-project orchestration issue needs broader compiled-runtime evidence. It executes every deterministic mockup scenario and writes artifacts under `.cache/e2e-mockup-sprint-pentest/<run-id>/`.

Run `pnpm run test:orchestration:large-dag` for a heavy 129-task DAG with 96 leaf tasks, 24 batch joins, 6 group joins, one final manifest, and one validation task. Use `pnpm run test:orchestration:pentest` for the default catalog plus heavy stress scenarios.

Expand Down
8 changes: 6 additions & 2 deletions docs-web/content/docs/user-dashboard-settings.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -304,12 +304,16 @@ Related docs:

Defines each named provider instance's default eligibility, model, thinking depth, weight, and concurrency.

Project and sprint scopes store base provider cards as sparse field overrides. Editing a named instance's base model or thinking depth keeps inherited fields such as eligibility, weight, and max concurrency from the parent scope unless those fields are explicitly changed.

**What it controls:** Provider cards set default route participation, model, thinking mode, weighted routing weight, and max concurrent tasks.

**Recommended defaults:** Keep only healthy instances eligible and use weights to express preference rather than hard pinning every route.

**Risks and gotchas:** Incompatible model choices or high concurrency can cause repeated provider failures or quota pressure.

Base provider cards inherit field-by-field, but invocation route provider maps remain replace-on-write for that route's pool and overrides.

Related docs:

- [Provider Routing](/docs/user-providers-and-models)
Expand All @@ -322,11 +326,11 @@ Related docs:

Routes each invocation type to inherited, manual, weighted, or agent-selected provider pools.

**What it controls:** Each route chooses a profile, strategy, primary instance, allowed weighted pool, and per-provider overrides.
**What it controls:** Each route chooses a profile, strategy, primary instance, allowed weighted pool, and per-provider overrides. Thinking overrides can be reset to inherit the provider instance's base thinking setting.

**Recommended defaults:** Use inherited defaults first, then override high-risk routes such as planning, QA, CI repair, and remediation.

**Risks and gotchas:** Weighted pools with unavailable providers can spread failures across multiple task types.
**Risks and gotchas:** Weighted pools with unavailable providers can spread failures across multiple task types. Stale route thinking overrides can keep using an older thinking budget until reset to inherit.

Related docs:

Expand Down
2 changes: 2 additions & 0 deletions docs-web/content/docs/user-providers-and-models.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ CLI providers expose provider-specific **thinking** or **reasoning** selections.

Older saved values `SMALL`, `MEDIUM`, and `HIGH` continue to load and are migrated to the closest supported value for the selected provider.

Route-specific thinking overrides are optional. Selecting **Inherit base thinking** on a route removes that route's `thinkingMode` override, so later provider-level thinking budget changes apply to the route.

## Provider weights and strategies

In **Settings → AI providers** each provider has a `weight` (0–100). Weights are used by the routing strategy:
Expand Down
6 changes: 3 additions & 3 deletions docs-web/developer/orchestration-debugging.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# Rapid orchestration debugging suite

Use this suite when a sprint stalls, local merges fail, worker-owned attention items churn, or memory usage needs extended observation after a fix.
Use this suite when a sprint stalls, local merges fail, worker-owned attention items churn, or memory usage needs extended observation after a fix. CI uses the rapid lane by default; full mockup pentest lanes are manual escalation tools for targeted investigations.

## Commands

| Lane | Command | Purpose |
| --- | --- | --- |
| Fast regressions | `pnpm run test:orchestration:rapid` | Watch-loop, feature merge, and local final-merge regressions without Docker or provider CLIs. |
| Mockup merge E2E | `pnpm run test:orchestration:merge-e2e` | Compiled runtime plus `mockup-cli` through a deterministic local merge-conflict DAG. |
| Full mockup pentest | `pnpm run test:orchestration:full` | All deterministic mockup scenarios: smoke, CI repair, merge conflict, parallel DAG, dirty checkout, multi-project overrides. |
| Full mockup pentest | `pnpm run test:orchestration:full` | Manual escalation for all deterministic mockup scenarios: smoke, CI repair, merge conflict, parallel DAG, dirty checkout, multi-project overrides. |
| Large DAG stress | `pnpm run test:orchestration:large-dag` | Heavy 129-task mockup DAG with wide fan-out and layered joins. |
| Full heavy pentest | `pnpm run test:orchestration:pentest` | Default mockup catalog plus heavy stress scenarios. |
| Backend broadening | `pnpm run test:backend` | Full backend suite after focused fixes. |
Expand All @@ -20,7 +20,7 @@ Start with `pnpm run test:orchestration:rapid`. It covers provider routing, watc

Run `pnpm run test:orchestration:merge-e2e` after a unit-level merge fix passes. It builds the compiled runtime and exercises the `merge-conflict-dag` mockup scenario through the local project runtime.

Run `pnpm run test:orchestration:full` before calling a scheduler, provider, CI, QA, or multi-project orchestration issue fixed. It executes every deterministic mockup scenario and writes artifacts under `.cache/e2e-mockup-sprint-pentest/<run-id>/`.
Run `pnpm run test:orchestration:full` manually when a scheduler, provider, CI, QA, or multi-project orchestration issue needs broader compiled-runtime evidence. It executes every deterministic mockup scenario and writes artifacts under `.cache/e2e-mockup-sprint-pentest/<run-id>/`.

Run `pnpm run test:orchestration:large-dag` for a heavy 129-task DAG with 96 leaf tasks, 24 batch joins, 6 group joins, one final manifest, and one validation task. Use `pnpm run test:orchestration:pentest` for the default catalog plus heavy stress scenarios.

Expand Down
4 changes: 2 additions & 2 deletions docs-web/user/dashboard/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -322,11 +322,11 @@ Related docs:

Routes each invocation type to inherited, manual, weighted, or agent-selected provider pools.

**What it controls:** Each route chooses a profile, strategy, primary instance, allowed weighted pool, and per-provider overrides.
**What it controls:** Each route chooses a profile, strategy, primary instance, allowed weighted pool, and per-provider overrides. Thinking overrides can be reset to inherit the provider instance's base thinking setting.

**Recommended defaults:** Use inherited defaults first, then override high-risk routes such as planning, QA, CI repair, and remediation.

**Risks and gotchas:** Weighted pools with unavailable providers can spread failures across multiple task types.
**Risks and gotchas:** Weighted pools with unavailable providers can spread failures across multiple task types. Stale route thinking overrides can keep using an older thinking budget until reset to inherit.

Related docs:

Expand Down
2 changes: 2 additions & 0 deletions docs-web/user/providers-and-models.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ CLI providers expose provider-specific **thinking** or **reasoning** selections.

Older saved values `SMALL`, `MEDIUM`, and `HIGH` continue to load and are migrated to the closest supported value for the selected provider.

Route-specific thinking overrides are optional. Selecting **Inherit base thinking** on a route removes that route's `thinkingMode` override, so later provider-level thinking budget changes apply to the route.

## Provider weights and strategies

In **Settings → AI providers** each provider has a `weight` (0–100). Weights are used by the routing strategy:
Expand Down
Loading