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
2 changes: 1 addition & 1 deletion application/single_app/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@
EXECUTOR_TYPE = 'thread'
EXECUTOR_MAX_WORKERS = 30
SESSION_TYPE = 'filesystem'
VERSION = "0.261.317"
VERSION = "0.261.318"
IS_DEVELOPMENT = is_development_env_enabled()

# Opt-out for deployments where App Service Easy Auth is active but the platform
Expand Down
6 changes: 4 additions & 2 deletions application/v2_ui/src/lib/activityLanes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@
{
key: 'tabular',
title: 'Tabular analysis',
showsCard: true,
// Tool details stay under the reasoning toggle; durable export status has its own card.

Check warning on line 80 in application/v2_ui/src/lib/activityLanes.ts

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains AI, plugin, agent, or workspace boundary marker. Recommendation%3A Check whether prompts, chat history, uploaded documents, embeddings, citations, settings, or identity can cross a new boundary.
showsCard: false,
currentStepPrefix: 'Current tabular step',
initialStatus: 'Gathering workbook evidence',
completedStatus: 'Workbook evidence ready',
Expand Down Expand Up @@ -133,7 +134,8 @@
{
key: 'agent',
title: 'Agent progress',
showsCard: true,
// The reasoning toggle already exposes the agent's activity without a duplicate summary.

Check warning on line 137 in application/v2_ui/src/lib/activityLanes.ts

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains AI, plugin, agent, or workspace boundary marker. Recommendation%3A Check whether prompts, chat history, uploaded documents, embeddings, citations, settings, or identity can cross a new boundary.
showsCard: false,
currentStepPrefix: 'Current tool',
initialStatus: 'Connecting to the selected agent',
completedStatus: 'Response ready',
Expand Down
35 changes: 25 additions & 10 deletions docs/explanation/features/V2_TABULAR_ANALYSIS.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
This change closes that gap and five smaller ones around it. Implemented in version
**0.261.057**.

Thought-summary progress cards were removed in version **0.261.318**, tracked in
`application/single_app/config.py`. Activity details remain in the reasoning dropdown;
background-export status and its run controls remain available on the generated-file card.

### Dependencies

None added. Every route and payload this uses already existed and is unchanged; the work is
Expand Down Expand Up @@ -163,9 +167,14 @@
more specific lane supersedes the general agent one — otherwise a workbook run would be
labelled "Agent progress".

A lane can claim steps without drawing a card. Orchestration's lane has `showsCard: false`.
Its entry still keeps planner and run steps out of the agent and tabular lanes, but the plan
card and the reasoning toggle already show that progress, and a third display repeated them.
A lane can claim steps without drawing a card. Since **0.261.318**, agent, tabular, and

Check warning on line 170 in docs/explanation/features/V2_TABULAR_ANALYSIS.md

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains AI, plugin, agent, or workspace boundary marker. Recommendation%3A Check whether prompts, chat history, uploaded documents, embeddings, citations, settings, or identity can cross a new boundary.
orchestration lanes all use `showsCard: false`. Their classification remains intact, but
thought-summary headings, percentages, bars, and repeated status text no longer appear
above the reasoning dropdown or inside a finished answer's expanded reasoning.

The dropdown still exposes the activity details when opened. Orchestration's plan card
reports its run status, and the separate generated-file card reports durable export
progress with Continue/Cancel controls. Neither operational surface is removed.

Every activity is emitted at least twice, running then completed, keyed by `activity_key`.
They are folded into a map so a tool call is counted once rather than once per frame.
Expand Down Expand Up @@ -233,8 +242,9 @@
offers Continue or Cancel where the server allows them. It replaces itself with the finished
files.

**A run being analysed.** The reasoning panel shows a progress card above the steps while the
run is live, without needing to be expanded.
**A run being analysed.** Expand **N reasoning steps** to read the agent's tool activity or

Check warning on line 245 in docs/explanation/features/V2_TABULAR_ANALYSIS.md

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains AI, plugin, agent, or workspace boundary marker. Recommendation%3A Check whether prompts, chat history, uploaded documents, embeddings, citations, settings, or identity can cross a new boundary.
workbook-analysis details. The dropdown starts collapsed, with no extra thought-summary
progress card. Details remain available on the finished response.

**An uploaded spreadsheet.** Click its name in the thread to see it as a table, with
**Download original** when the original file is still in storage. The name is inert in a
Expand All @@ -251,9 +261,14 @@
|---|---|
| `functional_tests/test_v2_tabular_parity.py` | The client reads the metadata keys the server writes; every requested route is registered; the run-control routes carry their decorators; the confirmation thresholds survive sanitization; the thought frame fields are carried; every component is mounted; the confirmation precedes the send; run members are read from the key the server sends; a withheld file offers no download; the upload preview is gated on what the endpoint supports; no remote assets |
| `functional_tests/test_v2_tabular_parity_logic.ts` | 70 behavioural checks: normalising and de-duplication, download target selection, the compact-layout rule, preview table construction, run progress and polling, artifact set completion and member ordering, approval states, lane detection and counting, the completion rule, the progress ratchet, the confirmation heuristic, row banding, CSV parsing |
| `functional_tests/test_v2_agent_tabular_progress_cards.mjs` | Agent and tabular markers still claim their lanes without cards during running, completed, and failed activity; agent-to-tabular precedence and thought content remain intact |

Check warning on line 264 in docs/explanation/features/V2_TABULAR_ANALYSIS.md

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains AI, plugin, agent, or workspace boundary marker. Recommendation%3A Check whether prompts, chat history, uploaded documents, embeddings, citations, settings, or identity can cross a new boundary.
| `ui_tests/test_v2_orchestration_streaming_bubble.py` | Agent/tabular summary cards remain absent on desktop and mobile while mouse/keyboard access to live, finished, and remounted reasoning stays available; orchestration status is unchanged |

Check warning on line 265 in docs/explanation/features/V2_TABULAR_ANALYSIS.md

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains AI, plugin, agent, or workspace boundary marker. Recommendation%3A Check whether prompts, chat history, uploaded documents, embeddings, citations, settings, or identity can cross a new boundary.

Both are run by executing the Python file, which bundles the TypeScript with esbuild and runs
it under node, skipping that half when `application/v2_ui/node_modules` is absent.
The tabular parity checks are run by executing the Python file, which bundles the TypeScript
with esbuild and runs it under node, skipping that half when

Check warning on line 268 in docs/explanation/features/V2_TABULAR_ANALYSIS.md

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains security control, sanitization, or audit marker. Recommendation%3A Confirm the change does not weaken auth, CSRF, CSP, XSS defenses, settings sanitization, redaction, audit logging, or tests.
`application/v2_ui/node_modules` is absent. Run the focused card-policy checks with `node`

Check warning on line 269 in docs/explanation/features/V2_TABULAR_ANALYSIS.md

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains security control, sanitization, or audit marker. Recommendation%3A Confirm the change does not weaken auth, CSRF, CSP, XSS defenses, settings sanitization, redaction, audit logging, or tests.
and the browser checks with `pytest`; their commands and current validation results are in
the [duplicate progress card fix](../fixes/V2_AGENT_TABULAR_DUPLICATE_PROGRESS_CARD_FIX.md).

Check warning on line 271 in docs/explanation/features/V2_TABULAR_ANALYSIS.md

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains AI, plugin, agent, or workspace boundary marker. Recommendation%3A Check whether prompts, chat history, uploaded documents, embeddings, citations, settings, or identity can cross a new boundary.

### Known limitations

Expand All @@ -269,9 +284,9 @@
- **Non-boolean tabular admin settings are still not editable in V2.** That is the general
"admin settings edits boolean capabilities only" limitation rather than anything specific to
tabular, and is unchanged by this work.
- **Progress cards cover tabular and agent work only.** Orchestration has a lane so its steps
are claimed, but it draws no card, because the plan card shows a run's progress. Workflow
activity emits compatible payloads but is not yet wired end to end, so it has no lane entry.
- **Thought-summary progress cards are intentionally absent.** Agent and tabular activity

Check warning on line 287 in docs/explanation/features/V2_TABULAR_ANALYSIS.md

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains AI, plugin, agent, or workspace boundary marker. Recommendation%3A Check whether prompts, chat history, uploaded documents, embeddings, citations, settings, or identity can cross a new boundary.
is read through the reasoning dropdown rather than an additional top-level card. This
does not remove the separate progress and recovery controls for a background export.

## See also

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# V2 Agent and Tabular Duplicate Progress Card Fix (v0.261.318)

## Issue

When a selected agent responded in V2, an **Agent progress** card appeared above the
collapsed reasoning dropdown. It repeated activity that was already available by expanding
the dropdown: the current tool, latest status sentence, counts, and a progress percentage.
Workbook analysis displayed a similar **Tabular analysis** card. These summaries distracted
from the response and made activity details visible even when the user had not opened them.

Fixed in version: **0.261.318**, tracked by the `VERSION` update in
`application/single_app/config.py`.

## Root cause

`activityLanes.ts` classifies thought events as agent, tabular, or orchestration work.
Its agent and tabular entries set `showsCard: true`. The shared `ThoughtsProgressCard`
renderer therefore drew their summaries above live reasoning and inside a finished answer's
expanded reasoning.

Orchestration already used `showsCard: false` to avoid a duplicate summary beside its plan
and reasoning details. Agent and tabular activity needed the same presentation policy,
without removing the events or changing how tools execute.

## Technical details

### Files modified

- `application/v2_ui/src/lib/activityLanes.ts`: agent and tabular entries now set
`showsCard: false`. Lane matching, precedence, status counting, and completion handling
remain unchanged.
- `application/single_app/config.py`: application version incremented to `0.261.318`.
- `functional_tests/test_v2_agent_tabular_progress_cards.mjs`: exercises real lane
classification for hand-off text, step types, activity kinds, lane keys, and plugins.
- `functional_tests/test_v2_orchestration_progress_lane.mjs`: updates agent/tabular
expectations while retaining orchestration classification coverage.
- `ui_tests/test_v2_orchestration_streaming_bubble.py`: verifies hidden agent/tabular
summaries and usable reasoning details with production components and CSS.
- `docs/explanation/features/V2_TABULAR_ANALYSIS.md`: describes the current distinction
between reasoning activity and background-export status.

The renderer already returns nothing when `showsCard` is false. No component rewrite,
CSS visibility workaround, new setting, route change, or dependency is required.

### User-facing behavior

Both thought-summary cards are removed completely, including their headings, badges,
percentages, progress bars, counters, current-tool summaries, and repeated status sentences.
Their underlying thought records remain available.

The **N reasoning steps** dropdown keeps its existing label and starts collapsed. It still
opens with mouse or keyboard during generation and on finished responses. Tool failures
remain readable there; suppressing the summary does not discard their details.

V1 is unchanged. V2's lightweight **Thinking**/**Planning** indicator, streamed answer,
connection notices, error handling, and orchestration plan/run status are also unchanged.

The separate background-export card is intentionally preserved. `TabularRunStatus.tsx`
still reports durable file generation, polls the server, offers **Continue**/**Cancel** when
allowed, and yields to the finished downloads. That operational status is not the
thought-summary card above the reasoning dropdown.

## Validation

Before the fix, the new lane checks failed because `showsCard` was true, and the desktop-agent
browser case found one progress bar where none was expected. After the fix:

| Check | Result |
|---|---|
| `node --test .\functional_tests\test_v2_orchestration_progress_lane.mjs .\functional_tests\test_v2_agent_tabular_progress_cards.mjs` | 20 passed |
| `npm --prefix .\application\v2_ui run build -- --outDir ..\..\ui_tests\artifacts\orchestration-plan-editor --logLevel error` | Passed, including TypeScript checking |
| `python -m pytest .\ui_tests\test_v2_orchestration_streaming_bubble.py -q` | 8 passed in local Chromium |
| `python .\functional_tests\test_v2_tabular_parity.py` | 13 of 14 checks passed, including all 70 TypeScript logic checks; existing confirmation-handler lookup failure |

Browser coverage includes desktop and mobile agent/tabular turns, collapsed and expanded
reasoning, Enter/Space activation, failed activity, finished answers, and remounted saved
responses. It checks that the whole summary card is absent rather than hiding only its bar.
The existing orchestration planning/running cases also pass.

The wider tabular parity script has an unrelated assertion, **Could not locate the composer
submit handler**. Re-running that check against the unchanged `HEAD` version of `Composer.tsx`
reproduces the same failure. Neither the composer nor that assertion is modified by this fix.

## Related

- [V2 Tabular Analysis](../features/V2_TABULAR_ANALYSIS.md)
- [Orchestration Duplicate Progress Card Fix](ORCHESTRATION_DUPLICATE_PROGRESS_CARD_FIX.md)
83 changes: 83 additions & 0 deletions functional_tests/test_v2_agent_tabular_progress_cards.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// test_v2_agent_tabular_progress_cards.mjs
// Version: 0.261.318
// Implemented in: 0.261.318
// Agent and tabular activity stays classified and available as reasoning, but neither lane
// draws a duplicate progress card in live or saved V2 responses.

import assert from 'node:assert/strict';
import test from 'node:test';
import './test_support/tsResolve.mjs';

// Register the repository resolver before loading TypeScript application modules.
const { buildLaneProgress } = await import('../application/v2_ui/src/lib/activityLanes.ts');

const markers = [
['agent hand-off text', 'agent', { content: 'Sending to agent researcher' }],
['agent step type', 'agent', { step_type: 'agent_tool_call', content: 'Calling search.' }],
['agent activity lane', 'agent', {
content: 'Calling search.',
activity: { lane_key: 'agent', activity_key: 'search', title: 'Search', status: 'running' },
}],
['tabular step type', 'tabular', { step_type: 'tabular_analysis', content: 'Reading a workbook.' }],
['tabular tool kind', 'tabular', {
activity: { kind: 'tabular_tool_invocation', activity_key: 'read', status: 'running' },
}],
['tabular post-processing kind', 'tabular', {
activity: { kind: 'tabular_post_processing', activity_key: 'export', status: 'running' },
}],
['tabular activity lane', 'tabular', { activity: { lane_key: 'tabular', status: 'running' } }],
['tabular plugin', 'tabular', {
activity: { plugin_name: 'TabularProcessingPlugin', status: 'running' },
}],
];

for (const [name, lane, thought] of markers) {
test(`${name} claims its lane without drawing a live or saved card`, () => {
for (const live of [true, false]) {
const thoughts = [structuredClone(thought)];
const original = structuredClone(thoughts);
const progress = buildLaneProgress(thoughts, { live });
assert.ok(progress);
assert.equal(progress.lane.key, lane);
assert.equal(progress.lane.showsCard, false);
assert.deepEqual(thoughts, original, 'Reasoning content must not be removed or mutated.');
}
});
}

for (const lane of ['agent', 'tabular']) {
for (const status of ['running', 'completed', 'failed']) {
test(`${lane} ${status} activity never brings back a progress card`, () => {
const thoughts = [
{ step_type: 'agent_tool_call', content: 'Sending to agent analyst' },
{
step_type: lane === 'agent' ? 'agent_tool_call' : 'tabular_analysis',
content: status === 'failed' ? 'The tool could not finish.' : 'Reading evidence.',
activity: {
activity_key: 'read',
lane_key: lane,
kind: lane === 'tabular' ? 'tabular_tool_invocation' : 'agent_tool_invocation',
title: 'Read evidence',
status,
},
},
];
for (const live of [true, false]) {
const progress = buildLaneProgress(thoughts, { live });
assert.ok(progress);
assert.equal(progress.lane.key, lane, 'Tabular must still supersede the agent hand-off.');
assert.equal(progress.lane.showsCard, false);
assert.equal(progress.failedCount, status === 'failed' ? 1 : 0);
}

const answered = buildLaneProgress([
...thoughts,
{ step_type: 'generation', content: 'Agent responded with the answer.' },
]);
assert.ok(answered);
assert.equal(answered.lane.key, lane);
assert.equal(answered.completed, true);
assert.equal(answered.lane.showsCard, false);
});
}
}
13 changes: 7 additions & 6 deletions functional_tests/test_v2_orchestration_progress_lane.mjs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
// test_v2_orchestration_progress_lane.mjs
// Version: 0.261.204
// Version: 0.261.318
// Implemented in: 0.261.204
// Agent and tabular cards removed in: 0.261.318
// Executes the real activity-lane fold (lib/activityLanes.ts) over the reasoning steps an
// orchestrated turn produces. The orchestration lane still claims those steps, so they are never
// counted as agent or tabular work, but it draws no progress card: the plan card and the reasoning
// toggle already show that progress. Tabular and agent work keep their cards.
// toggle already show that progress. Agent and tabular details also stay under the toggle.

import assert from 'node:assert/strict';
import test from 'node:test';
Expand Down Expand Up @@ -93,24 +94,24 @@ test('an agent hand-off inside an orchestrated turn does not bring back a card',
assert.equal(progress.lane.showsCard, false);
});

test('tabular and agent work keep their progress cards', () => {
test('tabular and agent work keep their lanes without progress cards', () => {
const tabular = buildLaneProgress([tabularThought()], { live: true });
assert.equal(tabular?.lane.key, 'tabular');
assert.equal(tabular.lane.showsCard, true);
assert.equal(tabular.lane.showsCard, false);

const handedOff = buildLaneProgress([
{ step_type: 'agent_tool_call', content: 'Sending to agent analyst' },
tabularThought('completed'),
]);
assert.equal(handedOff?.lane.key, 'tabular');
assert.equal(handedOff.lane.showsCard, true);
assert.equal(handedOff.lane.showsCard, false);

const agent = buildLaneProgress(
[{ step_type: 'agent_tool_call', content: 'Sending to agent researcher' }],
{ live: true },
);
assert.equal(agent?.lane.key, 'agent');
assert.equal(agent.lane.showsCard, true);
assert.equal(agent.lane.showsCard, false);
});

test('ordinary reasoning still forms no lane at all', () => {
Expand Down
Loading
Loading