feat(tools): save and schedule an analysis with one confirmation; decided actions reach the conversation; ask before guessing #98

Merged
james.maes merged 1 commits from feat/save-and-schedule-analysis into develop 2026-11-11 13:47:55 +00:00
Owner

What

  1. save_analysis: keeps an analyze_records question as a saved analysis the user owns (data_analysis_saved) and, when the user asked for it to be sent regularly, a daily schedule emailed to them (data_analysis_schedule: DAILY, a local time, an IANA time zone, the confirming user as the recipient). The target sentence: "create a report of the documents printed in the last day, grouped by type, and email it to me each morning at 9am".
  2. One confirmation, nothing before it. The tool only proposes: ONE pending-action card lists the saved analysis, what it shows, the filter, the schedule, who is emailed and the numbers as they are now. It is never auto-confirmed, also where the policy turns confirmation off for record writes. On confirmation both records are created through the tables' own insert operations with the confirming user's session.
  3. A schedule that could never run is refused, with the reason, when it is proposed and again at confirmation. The assistant reads the instance (a schedule table; a scheduler on data_analysis_run_schedules) and asks the host through the new AssistantQBitConfig.withScheduledDeliveryCheck(Supplier<List<String>>) for what only the host knows (a service identity and its credentials, mail delivery). The model is told to offer saving without the schedule.
  4. A decided action reaches the conversation. Confirming a pending action (any tool) adds a message of the assistant ("Done. ..." or "That did not work. ...", with links to the records) that the panel shows and the model reads as history. Each earlier proposal also carries what became of it in the next request: done, failed, cancelled by the user, or expired. Before, the model only ever saw "waiting for confirmation", so work after a confirmation stalled.
  5. Ask before guessing (rule 14). When a request can reasonably mean more than one thing and the choice changes the result (which table, which field, a clock time with no time zone), the model asks ONE short question naming the options it found, then waits; it never proposes a change while such a question is open. The user's browser time zone is now stated in the per-user context, so "9am" needs no question when it is known; save_analysis refuses a schedule without a valid IANA zone and tells the model to ask.

Inside the user's access

  • Offered only where the data-analysis extension is registered and an administrator set data access READ_WRITE on data_analysis_saved; a schedule also needs it on data_analysis_schedule.
  • The user's own permission to create the records is read from GET /metaData before a card is shown; the preview is the same pivot call as analyze_records (table read, analyze permission, field access); the inserts run as the confirming user, so owner locks and the qbit's validation decide.
  • If the schedule's insert is refused after the analysis was saved, the outcome says exactly that.

Panel

No frontend change is needed: the card is the existing pending_action render (toolName stays create_record for the panel's verb and icon; the new actionKind is extra). After a confirmation the panel's existing refetch shows the assistant's "Done." message with both links.

Tests

  • AnalysisSaveTest (released data-analysis 0.3.0-RC.2 served by the real UI API): one confirmation creates both records owned by and addressed to the confirming user and the stored definition runs; always a proposal; a schedule that could not run is refused at proposal and at confirmation with the host's words; refusals (no permission, no analyze, no or bad time zone, hidden field, READ data access); a whole conversation where the confirmed outcome is stored as a message and told to the model; cancelled and expired proposals are told too. The two conversation tests fail with the feedback switched off (checked).
  • ClarifyingRulesTest: the rule is in every request; the user's time zone is stated only when known.
  • Golden task clarify-ambiguous-field (scripted in every build). Its live variant against a real model was NOT run here (no API key in this environment).

Local: ./mvnw -B verify (whole reactor, no skip flags): BUILD SUCCESS; qbit-assistant 408 tests, 0 failures.

🤖 Generated with Claude Code

## What 1. **`save_analysis`**: keeps an `analyze_records` question as a saved analysis the user owns (`data_analysis_saved`) and, when the user asked for it to be sent regularly, a daily schedule emailed to them (`data_analysis_schedule`: DAILY, a local time, an IANA time zone, the confirming user as the recipient). The target sentence: "create a report of the documents printed in the last day, grouped by type, and email it to me each morning at 9am". 2. **One confirmation, nothing before it.** The tool only proposes: ONE pending-action card lists the saved analysis, what it shows, the filter, the schedule, who is emailed and the numbers as they are now. It is never auto-confirmed, also where the policy turns confirmation off for record writes. On confirmation both records are created through the tables' own insert operations with the confirming user's session. 3. **A schedule that could never run is refused, with the reason**, when it is proposed and again at confirmation. The assistant reads the instance (a schedule table; a scheduler on `data_analysis_run_schedules`) and asks the host through the new `AssistantQBitConfig.withScheduledDeliveryCheck(Supplier<List<String>>)` for what only the host knows (a service identity and its credentials, mail delivery). The model is told to offer saving without the schedule. 4. **A decided action reaches the conversation.** Confirming a pending action (any tool) adds a message of the assistant ("Done. ..." or "That did not work. ...", with links to the records) that the panel shows and the model reads as history. Each earlier proposal also carries what became of it in the next request: done, failed, cancelled by the user, or expired. Before, the model only ever saw "waiting for confirmation", so work after a confirmation stalled. 5. **Ask before guessing (rule 14).** When a request can reasonably mean more than one thing and the choice changes the result (which table, which field, a clock time with no time zone), the model asks ONE short question naming the options it found, then waits; it never proposes a change while such a question is open. The user's browser time zone is now stated in the per-user context, so "9am" needs no question when it is known; `save_analysis` refuses a schedule without a valid IANA zone and tells the model to ask. ## Inside the user's access - Offered only where the data-analysis extension is registered and an administrator set data access READ_WRITE on `data_analysis_saved`; a schedule also needs it on `data_analysis_schedule`. - The user's own permission to create the records is read from `GET /metaData` before a card is shown; the preview is the same pivot call as `analyze_records` (table read, analyze permission, field access); the inserts run as the confirming user, so owner locks and the qbit's validation decide. - If the schedule's insert is refused after the analysis was saved, the outcome says exactly that. ## Panel No frontend change is needed: the card is the existing `pending_action` render (`toolName` stays `create_record` for the panel's verb and icon; the new `actionKind` is extra). After a confirmation the panel's existing refetch shows the assistant's "Done." message with both links. ## Tests - `AnalysisSaveTest` (released data-analysis 0.3.0-RC.2 served by the real UI API): one confirmation creates both records owned by and addressed to the confirming user and the stored definition runs; always a proposal; a schedule that could not run is refused at proposal and at confirmation with the host's words; refusals (no permission, no analyze, no or bad time zone, hidden field, READ data access); a whole conversation where the confirmed outcome is stored as a message and told to the model; cancelled and expired proposals are told too. The two conversation tests fail with the feedback switched off (checked). - `ClarifyingRulesTest`: the rule is in every request; the user's time zone is stated only when known. - Golden task `clarify-ambiguous-field` (scripted in every build). Its live variant against a real model was NOT run here (no API key in this environment). Local: `./mvnw -B verify` (whole reactor, no skip flags): BUILD SUCCESS; qbit-assistant 408 tests, 0 failures. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
james.maes added 1 commit 2026-11-11 13:35:23 +00:00
save_analysis proposes keeping an analyze_records question as a saved analysis the user owns
and, when asked, a daily schedule emailed to them. One pending action lists everything that
will be created with the numbers as they are now; nothing exists until the user confirms it
(never auto-confirmed). On confirmation both records are created through the data-analysis
tables' own insert operations with the confirming user's session. Offered only with the
data-analysis extension and data access READ_WRITE on data_analysis_saved (a schedule also
needs it on data_analysis_schedule); the user's own insert permission is read from
GET /metaData first.

A schedule that could never run is refused when proposed and again at confirmation, with
what is missing: the instance is read (a schedule table, a scheduler on
data_analysis_run_schedules) and the host is asked through
AssistantQBitConfig.withScheduledDeliveryCheck.

Confirming any pending action now adds a message of the assistant to the conversation
(what was done, links to the records), and each earlier proposal carries what became of it
in the next request (done, failed, cancelled, expired). Before, the model only ever saw
'waiting for confirmation'.

Rule 14 for every model: ask one short question when a request is ambiguous in a way that
changes the result (table, field, time zone); the user's browser time zone is stated in the
per-user context. Golden task clarify-ambiguous-field.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
james.maes merged commit 7d4014d79f into develop 2026-11-11 13:47:55 +00:00
Sign in to join this conversation.