feat(process): one confirmation runs a set to its end, within what its card showed; no card for a change the person may not make #113
Open
james.maes
wants to merge 6 commits from
feat/one-card-for-a-set into develop
pull from: feat/one-card-for-a-set
merge into: QRun-IO:develop
QRun-IO:develop
QRun-IO:feat/compact-answers-and-output-ceiling
QRun-IO:fix/render-widget-follows-data-access
QRun-IO:release/0.1
QRun-IO:rc/develop-into-release-0.1-registry
QRun-IO:feat/process-tools
QRun-IO:feat/writes-follow-the-person
QRun-IO:fix/atomic-confirm-and-closed-surface
QRun-IO:fix/tool-service-owns-policy-and-identity
QRun-IO:fix/tool-call-service-enforces-its-checks
QRun-IO:feat/tool-registry
QRun-IO:docs/actions-and-mcp-design
QRun-IO:rc/develop-into-release-0.1-everyone
QRun-IO:feat/store-reads-as-trusted-code
QRun-IO:rc/develop-into-release-0.1-weekly
QRun-IO:feat/weekly-budget
QRun-IO:rc/develop-into-release-0.1-save
QRun-IO:feat/save-and-schedule-analysis
QRun-IO:rc/develop-into-release-0.1-analyze
QRun-IO:feat/analyze-records
QRun-IO:fix/turn-watchdog-never-hangs-develop
QRun-IO:fix/turn-watchdog-never-hangs
QRun-IO:fix/live-thread-placeholders
QRun-IO:merge/develop-into-release-0.1
QRun-IO:automation/qbit-rc-pending
QRun-IO:fix/transcript-stored-before-message-end-develop
QRun-IO:fix/transcript-stored-before-message-end
QRun-IO:main
QRun-IO:archive/qrun-github-cutover-20261101/ca9212731dc2/develop
QRun-IO:feat/openai-compatible-provider
QRun-IO:dependabot/maven/develop/maven-minor-and-patch-634f43d868
QRun-IO:dependabot/github_actions/develop/github-actions-0fdda1077f
QRun-IO:feature/orb-0.8-track
QRun-IO:feature/orb-0.7.18
QRun-IO:feature/orb-0.7.17
QRun-IO:feature/orb-standardize-release-0.1
QRun-IO:feature/orb-main-standardization
QRun-IO:feature/shared-codeql
QRun-IO:feature/orb-0712-stable-gate
QRun-IO:feature/orb-rc-worker
QRun-IO:feature/orb-0.7.11
QRun-IO:feature/central-ci
QRun-IO:feature/conversation-management
QRun-IO:feature/starter-prompts-from-access
QRun-IO:feature/turns-not-jobs
QRun-IO:feature/assistant-attachments
QRun-IO:feature/assistant-optional-provider-health
QRun-IO:fix/assistant-health-tile-wording
QRun-IO:feature/fail-soft-renders
QRun-IO:fix/records-render-and-stream-context
QRun-IO:ci/release-rc-secrets-inherit
QRun-IO:feature/ui-api-1.6
QRun-IO:fix/shutdown-hook-weak-runtime
QRun-IO:fix/help-bundle-version
QRun-IO:feature/health-checks
QRun-IO:feature/jobs-tray
QRun-IO:feature/help-bundle
QRun-IO:feature/transcript-redaction
QRun-IO:feature/foreign-keys
QRun-IO:feature/schema-indexes
QRun-IO:fix/assistant-defaults-rollback
QRun-IO:feature/durable-turns
QRun-IO:fix/assistant-defaults-guards
QRun-IO:feature/tables-populated-defaults
QRun-IO:feature/provider-spi-package
QRun-IO:feature/email-api
QRun-IO:feature/orb-0.6.9
QRun-IO:feature/write-mode
QRun-IO:feature/x1-y1-channel-wall
QRun-IO:feature/email-qbit
QRun-IO:feature/spec-endpoints-core-invoker
QRun-IO:feature/provider-api-module
QRun-IO:feature/p7-scheduled-tasks
QRun-IO:feature/bulk-load-tools
QRun-IO:feature/p6-rag
QRun-IO:feature/presentation-demo-shots
QRun-IO:feature/answer-presentation
QRun-IO:fix/core-alerts-rc5
QRun-IO:feature/p5-routing-fallback
QRun-IO:feature/p4-budgets
QRun-IO:feature/p3-hipaa-routing
QRun-IO:feature/p2-bedrock-vertex
QRun-IO:feature/p1-provider-registry
QRun-IO:feature/spec-providers-write-mode-wall
QRun-IO:feature/demo-pending-card
QRun-IO:feature/release-rc-automation
QRun-IO:feature/demo-screens
QRun-IO:feature/profiles-skills-access
QRun-IO:feature/ui-api-tools
QRun-IO:feature/strict-tools-grammar-fix
QRun-IO:feature/app-home-settings
QRun-IO:feature/fix-rename-version-labels
QRun-IO:feature/note-burned-rc
QRun-IO:feature/assistant-record-screens
QRun-IO:feature/robustness-test-flake
QRun-IO:feature/ga-only-release-tags
QRun-IO:feature/snake-case-table-names
QRun-IO:chore/qrun-repo-standard
QRun-IO:feature/pom-revision-comment
QRun-IO:feature/phase-0-1-assistant
No Reviewers
Labels
Clear labels
architecture
bug
dependencies
documentation
duplicate
enhancement
github_actions
good first issue
help wanted
invalid
java
question
release:rc
secuurity
ux
wontfix
Architecture review: coupling, cohesion, UI API
Something isn't working
Improvements or additions to documentation
This issue or pull request already exists
New feature or request
Pull requests that update GitHub Actions code
Good for newcomers
Extra attention is needed
This doesn't seem right
Pull requests that update java code
Further information is requested
Merging this develop PR cuts the next release candidate
Admin UX / information architecture
This will not be worked on
No labels
Milestone
No items
No Milestone
Projects
Clear projects
No projects
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: QRun-IO/qbit-assistant#113
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
What
A person who asks for the same change to a set of records now sees ONE card and confirms once; the run goes to its end. And nobody is offered a card for a change they may not make.
Design note and safety argument:
docs/one-card-for-a-set.md(read that first; sections 3 and 4 are this pull request, section 5 is the next one in the stack).Stacked on #112 (
fix/render-widget-follows-data-access): merge that one first; until then this diff shows its commits too.Part A: one confirmation for a set
records).initandstepoperations as the person (what the person's own screen calls, so a host's filters on a person's process requests apply). A screen is passed for the person only when it shows nothing their card did not:assistantMaxActiveJobs.recordsBefore); the outcome carries counts (ok, failed, warnings) beside the process's own lines.Part B: no card for what cannot happen
create_record,update_record,delete_recordand a table's bulk edit and bulk delete ask the application, as the person, what it tells their own screens about the table (GET /metaData/table/{tableName}). A person who may not make that kind of change is told so and gets no card. The check only refuses; the confirmed change is still decided by the UI API.What a reviewer should look at
ProcessTools.screenDiffersandreviewDiffers: the only two places that decide a screen is passed for the person.ProcessTools.start: the stored proposal must say what its card showed (covers), carry the digest, and match it;guardstill refuses a name the process keeps for itself.ProcessTools.job: reads a job, cancels one that waits; never starts one.init"). The design note, section 3.4, says what stands in its place.UiApiToolsSecurityTest,WritesFollowThePersonTest(a person the application refuses is now refused before a card; the confirm-time refusal keeps its test with a permission revoked after the card),ProcessToolsTest(a table's bulk edit runs on one confirmation; a later screen that only says something is on the card),chat-tools-before-registry.txt(one description).Build
Full gated build of this branch's head
18e893b(./mvnw verify: Checkstyle, SpotBugs, PMD, tests, coverage; no gate skipped): BUILD SUCCESS, 737 tests (614 inqbit-assistant), 0 failures, every coverage check met.What a host must change
Nothing on core's defaults. A host whose application hands runs of 500 records or fewer to a background job sets
DurableJobsMetaData.withAssistantAutoStartMaxRows(seeUPGRADE.md); without it such a run ends as "did not run".Not delivered
get_run_statusreads how it ended.records(the data is sent; a released panel draws the card's lines).🤖 Generated with Claude Code
Note on hosted CI: the first run of this branch failed, and its rerun (the same commit, alone on the runner) passed.
The first run shared the runner with the build of the next pull request in the stack. Four existing tests that send several tool calls in one reply (
TurnEngineTest.testParallelToolResultsInOneMessage,GoldenEvalTest.golden[7],RedTeamTest.testNoPermissionNoLeak,PresentResultsToolTest.testPersistenceAndReplay) each waited 61 seconds and failed. That is reproducible ondevelopwithout this change, with two processors:Cause, read in code:
ToolCallService.executeholdssynchronized(admission)while the first offer of a scope waits for a task it submitted to the runtime's virtual-thread executor; a virtual thread that blocks holding or entering a monitor is pinned to its carrier, so with two carriers the task never runs and every call of the batch waits fortoolCallTimeoutSeconds. It is not changed here (it is the lock of the tool-call service and deserves its own review); it is written up as a follow-up.View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.