Skip to content

Prepare the v1.11.4 release candidate - #949

Draft
Y1fe1Zh0u wants to merge 82 commits into
mainfrom
v1.11.4
Draft

Prepare the v1.11.4 release candidate#949
Y1fe1Zh0u wants to merge 82 commits into
mainfrom
v1.11.4

Conversation

@Y1fe1Zh0u

Copy link
Copy Markdown
Collaborator

What changed

This release-candidate branch integrates and validates the currently planned v1.11.4 repairs against main:

  • keep Vercel deployments pending until the exact deployment reaches an authoritative terminal state
  • make Trigger timezone, Cron occurrence, dispatch, idempotency, persistence, and Runtime intake share one scheduled occurrence
  • preserve one-time default Agent initialization after deletion, stopping, or renaming
  • keep every group mention candidate reachable and preserve visible human mentions without waking a Runtime
  • scope Direct Chat controls and delayed events to the selected Session
  • stabilize accepted Tool execution across recovery with persisted contracts, repair budgets, deadlines, cancellation, leases, and compatibility boundaries
  • converge the release-only timezone and Tool Runtime migrations onto one Alembic head
  • make fresh-database enterprise metadata migration replay idempotent
  • add the consolidated v1.11.4 regression and release-gate document

Why

These changes assemble the pending Runtime, scheduling, Agent lifecycle, chat isolation, mention, and migration repairs into one branch so their interactions can be reviewed and validated as a release candidate instead of relying on isolated PR evidence.

Impact

The branch changes backend Runtime and Tool execution behavior, Trigger scheduling semantics, default Agent bootstrap behavior, group and Direct Chat UI behavior, and the Alembic migration graph. It intentionally keeps existing public APIs and reuses the current Runtime scheduling and settlement paths.

Validation recorded on this branch

  • latest combined Runtime, Tool, finish-protocol, and migration scope: 867 tests passed
  • scoped Ruff critical checks passed
  • Architecture Guard P0 passed
  • Alembic reports one head
  • Drone feat(tools): truncate large tool results with workspace spill #489 fresh PostgreSQL migration passed
  • prior combined frontend node tests and Vite production build passed
  • git diff --check upstream/main...HEAD passed

Remaining release gates

  • upgrade from a populated v1.11.3 database snapshot has not been validated
  • live Vercel, mixed-mention, Direct Chat/WebSocket, OAuth/SSO, and channel-provider E2E remain pending
  • backend/VERSION and frontend/VERSION still report 1.11.3; the version update strategy must be completed before release
  • full candidate backend regression should be rerun against the final PR head

See V1.11.4_REGRESSION_TEST_CASES.md for the detailed release matrix.

Vercel deployment acceptance is not terminal success. Declare non-terminal deployments as durable async operations, poll the exact deployment ID through the existing Runtime, and settle only on authoritative terminal provider states. The accompanying Spec Kit artifacts preserve the decision and regression contract.

Constraint: Reuse the existing Runtime scheduler and settlement path without generic Runtime changes

Rejected: Treat accepted or BUILDING deployments as success | loses the authoritative provider result

Rejected: Poll deployment lists | cannot prove which deployment owns the operation

Confidence: high

Scope-risk: narrow

Reversibility: clean

Directive: Do not reclassify Vercel acceptance as terminal success or replay launch writes from poll continuations

Tested: 102 scoped Vercel and Runtime tests; 172 deploy and Tool contract regression tests; scoped Ruff critical rules

Not-tested: Live Vercel deployment and long-duration retry termination policy
Tenant and Agent timezone values now enter the scheduler through one IANA validation boundary, while new tenants receive the confirmed Beijing default.

Constraint: Agent timezone remains nullable to preserve tenant inheritance.

Rejected: Validate against COMMON_TIMEZONES | it is a UI shortlist, not the complete IANA set.

Confidence: high

Scope-risk: narrow

Directive: Do not reintroduce silent UTC fallback for configured Trigger timezones.

Tested: backend/tests/test_timezone_validation.py (14 passed); Alembic single-head check.

Not-tested: Migration execution against a production-sized tenants table.
The evaluator now owns Cron occurrence calculation in the Agent effective timezone. The daemon, dispatch key, queue record, and Runtime source all consume that same planned instant, with a bounded 30-second grace and creation-time lower bound.

Constraint: Keep cooldown_seconds and non-Cron Trigger behavior compatible.

Rejected: Persist next_run_at or schedule_effective_from | the accepted design uses current rules plus a bounded grace without new schedule state.

Confidence: high

Scope-risk: moderate

Directive: Do not derive Cron occurrences from last_fired_at or recompute them below evaluator.

Tested: 22 scheduling, queue, intake, completion, and A2A tests; scoped Ruff.

Not-tested: DST edge behavior and second-level Cron expressions are out of scope.
Scheduled Trigger intake failures now roll back the occurrence instead of persisting a failed receipt that blocks the next daemon scan. Structured logs retain the failure evidence, while webhook receipts preserve their existing synchronous failure contract.

Constraint: Retry is only the ordinary 15-second scan while the occurrence remains inside the 30-second grace.

Rejected: Add retry counters, backoff jobs, or new schedule fields | outside the confirmed minimal repair.

Confidence: high

Scope-risk: narrow

Directive: A failed scheduled intake must not consume its occurrence identity.

Tested: 40 timezone, scheduling, queue, Runtime, A2A, and webhook tests; scoped Ruff.

Not-tested: Process termination during the database commit syscall.
Cron creation already rejected malformed expressions, but both existing update boundaries could persist them. Validate before mutation and commit while preserving REST replacement and Agent-tool patch semantics.

Constraint: Preserve current Trigger APIs and config compatibility
Rejected: Introduce a shared Trigger config abstraction | interface unification remains deferred
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Trigger config timezone may remain stored for compatibility but must not define occurrence timezone
Tested: Full backend pytest 2162 passed; focused Trigger tests 18 passed; scoped Ruff and git diff checks passed
Not-tested: DST-specific and second-level Cron behavior remain out of scope
The scheduler already falls back through Agent and Tenant to Asia/Shanghai, but the Agent detail response still advertised UTC when both stored values were absent. Reuse the platform default so the visible configuration describes the runtime behavior.

Constraint: Preserve the existing Agent detail response shape
Rejected: Add a new frontend timezone resolution path | the backend already owns effective timezone resolution
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Any displayed effective timezone must follow the same Agent to Tenant to platform-default order as scheduling
Tested: Full backend pytest 2163 passed; timezone tests 15 passed; scoped Ruff and git diff checks passed
Not-tested: Frontend visual regression was unnecessary because the response field shape is unchanged
Current main routes Trigger persistence through query_dao and has advanced the Alembic chain. Preserve those boundaries while replaying the scheduling repair, move Cron imports to the module boundary, and adapt tests to the DAO session contract.

Constraint: Publish without rebasing the user's dirty working tree
Constraint: New migrations must follow the current single-head and DDL-only rules
Rejected: Rebase the checked-out fix branch | unrelated concurrent work makes worktree mutation unsafe
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep the PR branch based on current upstream main and retain query_dao session ownership
Tested: Focused timezone and Trigger regression 33 passed; scoped Ruff passed; Alembic reports one f061 head
Not-tested: Full backend suite was interrupted before completion
Persist tenant-scoped bootstrap identity so Morty and Meeseeks are initialized once, while surviving Agent storage remains repairable. Existing deployments lazily backfill stable IDs from the legacy marker or historical rows.

Constraint: Existing deployments have no database bootstrap marker and docs are ignored by default.

Rejected: Restore the legacy marker early return | it would disable storage drift repair and remains unsafe when storage changes.

Confidence: high

Scope-risk: moderate

Reversibility: clean

Directive: Do not use Agent name or runtime status as the default-Agent initialization fact.

Tested: 38 scoped pytest cases; Ruff; git diff --check.

Not-tested: Real PostgreSQL container startup because the local Docker daemon is unavailable.
The mention picker stopped at eight results and keyboard navigation could move the active candidate outside the visible popup. Keep all filtered members in the bounded list and synchronize its local scroll position with the highlighted option.

Constraint: Preserve existing structured mention identity and IME behavior.

Rejected: Keep the eight-candidate cap | members beyond the cap would remain unreachable by scrolling.

Confidence: high

Scope-risk: narrow

Reversibility: clean

Directive: Keep keyboard highlight changes synchronized with the mention popup scroll position.

Tested: Frontend npm test (89 passed); npm run build; Playwright with 12 mocked members, mouse wheel and keyboard scrolling.

Not-tested: Live backend WebSocket behavior; unrelated to the local candidate picker.
Bring Draft PR #827 into the local validation branch so its exact provider-settlement path can be tested with the other release candidates.

Constraint: Preserve the Draft PR head unchanged inside the merge.

Confidence: high

Scope-risk: moderate

Reversibility: clean

Related: #827

Tested: Merge completed without conflicts.

Not-tested: Combined branch tests run after all Draft PRs are assembled.
Bring Draft PR #833 into the local validation branch alongside the Vercel settlement repair, preserving both Tool surfaces for combined testing.

Constraint: Resolve overlapping agent_tools changes without dropping either Draft PR contract.

Confidence: medium

Scope-risk: broad

Reversibility: clean

Related: #833

Tested: Combined tests run after conflict resolution and remaining Draft PR merges.

Not-tested: Merge compatibility until conflicts are resolved.

# Conflicts:
#	backend/app/schemas/schemas.py
Bring Draft PR #837 into the local validation branch so bootstrap identity and storage repair behavior can be tested with the other release candidates.

Constraint: Preserve the Draft PR head unchanged inside the merge.

Confidence: high

Scope-risk: moderate

Reversibility: clean

Related: #837

Tested: Merge completed without conflicts.

Not-tested: Combined branch tests run after all Draft PRs are assembled.
Bring Draft PR #927 into the local validation branch so the complete mention picker is included in the release-candidate frontend test pass.

Constraint: Preserve structured mention identity and existing IME behavior.

Confidence: high

Scope-risk: narrow

Reversibility: clean

Related: #927

Tested: Merge completed without conflicts.

Not-tested: Combined branch tests run after all Draft PRs are assembled.
Direct Chat kept both per-session runtime caches and component-wide active
state. Project controls through the selected session identity and keep delayed
background sends from mutating the visible conversation.

Constraint: Preserve background Session execution and WebSocket delivery
Rejected: Close the previous Session socket on navigation | long-running Sessions must continue after the user switches away
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Never let background Session events update the visible composer without matching Agent and Session identities
Tested: Frontend node tests 90 passed; TypeScript and Vite production build passed
Not-tested: Live backend-connected multi-Session browser flow
Merge the latest authenticated channel, browser-bound SSO, and image timeout
reconciliation fixes from main while preserving the accumulated release
candidate repairs.

Constraint: Preserve the existing v1.11.4 candidate commit history
Rejected: Rebase the release candidate | rewriting the accumulated candidate history would weaken the release audit trail
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Re-run release candidate regressions whenever main advances again
Tested: 75 focused backend tests passed; frontend node tests 91 passed; TypeScript and Vite production build passed
Not-tested: Full backend suite, Docker upgrade paths, or live provider and browser flows
Record the current main baseline, Direct Chat Session isolation scenarios,
and the newly merged OAuth, channel authentication, and image timeout
reconciliation paths in one executable release-candidate checklist.

Constraint: Historical PR evidence cannot replace candidate or live validation
Rejected: Keep the previous four-feature checklist | it would omit the latest main security and reconciliation changes
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Refresh the baseline SHA, candidate evidence, and affected cases whenever main advances
Tested: Markdown structure, referenced paths, 75 focused backend tests, 91 frontend tests, and production frontend build
Not-tested: Full backend suite, Docker upgrade paths, and live provider or browser cases
Record the two active Alembic heads and Drone fresh-database duplicate-column
failure so the synchronized release candidate cannot be treated as publishable
until the main migration graph is repaired and revalidated.

Constraint: The Direct Chat PR changes only frontend files and must not absorb an unrelated migration repair
Rejected: Ignore the failed check as unrelated | v1.11.4 now contains the same main migration state
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Clear this blocker only with fresh and upgrade database evidence on the repaired candidate
Tested: Alembic heads inspected; Drone build 486 clone, image build, and migration logs read
Not-tested: Repaired fresh or upgrade database path because no repair is present yet
Freeze the model-visible Workset and accepted execution binding in checkpoint state, separate Provider correlation from Runtime identity, and give repairable failures a sanitized model-visible result. Add independent 10/20 repair budgets, operation-specific deadline/cancel/lease controls, and an incremental RegisteredTool compatibility boundary.

Constraint: Existing checkpoints and nullable Receipt rows must remain recoverable during mixed-version rollout
Rejected: Re-resolve enabled assignments in Tool Step | changes an already accepted model decision
Rejected: Reuse Provider-local call IDs as Runtime identity | IDs repeat across Assistant turns
Confidence: high
Scope-risk: broad
Reversibility: clean
Directive: Do not remove the legacy resolver until its zero-usage release and rollback-window gate is satisfied
Tested: 834 Runtime/Tool pytest cases; 9 migration/contract cases; Alembic f061-f062 offline upgrade and downgrade; scoped Ruff; Architecture Guard; git diff check
Not-tested: Live Provider credentials and online migration against an isolated PostgreSQL database
Integrate the checkpoint-stable Tool Runtime repair while preserving the release branch's established SpecKit constitution and trigger fixes. Join the release timezone migration and main-based Tool identity migration with a no-op Alembic merge revision.

Constraint: v1.11.4 already carries a sibling f061 timezone migration that is absent from upstream main
Rejected: Retarget the feature migration to the release-only head | would make PR #945 diverge from main migration history
Rejected: Leave two Alembic heads | release startup and migration gates require one head
Confidence: high
Scope-risk: broad
Reversibility: clean
Directive: Keep f063_merge_v1_11_4_heads when rebasing or publishing the release candidate
Tested: v1.11.4 import path verified; 834 Runtime/Tool pytest cases; 5 release migration cases; single Alembic head; fatal Ruff; Architecture Guard; git diff check
Not-tested: Live Provider credentials and online migration against an isolated PostgreSQL database
Drone clones only the target repository before checking out the fork PR SHA. Publish this no-op descendant to both repositories so the synchronize build can resolve the commit without changing the reviewed tree.

Constraint: Drone build 487 failed in clone before any test because the fork-only SHA was absent from dataelement/Clawith
Rejected: Ignore the failed required check | would leave PR health ambiguous
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: This empty commit carries no release behavior and need not be merged separately into v1.11.4
Tested: Underlying tree is identical to 1dbad6d
Not-tested: Drone rerun until remote status is observed
Fresh installs create the enterprise_info target shape from current ORM metadata before Alembic replays f061. Inspecting the live schema keeps that replay idempotent while preserving the legacy upgrade path, and the unified-schema assertion now leaves f062-owned Tool identity columns to their dedicated migration contract.

Constraint: Fresh bootstrap derives tables from current ORM metadata before replaying historical revisions

Rejected: Skip the failing CI migration lane | would leave a documented v1.11.4 P0 release blocker unresolved

Confidence: high

Scope-risk: narrow

Directive: Keep provider_call_id and contract_version owned by f062 rather than backporting them into the unified baseline revision

Tested: 836 Runtime, Tool, and migration tests; scoped Ruff; py_compile

Not-tested: Fresh PostgreSQL bootstrap locally because Docker is unavailable; Drone will provide that evidence
Merge the CI-proven f061 idempotence repair into the release candidate while retaining the release-only f063 revision that joins the timezone and Tool Runtime migration chains. The regression record now distinguishes the passing fresh path from the still-unverified v1.11.3 upgrade path.

Constraint: v1.11.4 must retain one Alembic head across both release migration branches

Rejected: Mark the entire database P0 complete | the previous-version upgrade path still lacks real database evidence

Confidence: high

Scope-risk: moderate

Directive: Do not remove f063 or mark A4 passed until a v1.11.3 database snapshot upgrades successfully

Tested: 836 Runtime, Tool, and migration tests; scoped Ruff; Alembic single-head check; Architecture Guard P0; Drone #489 fresh PostgreSQL migration

Not-tested: Upgrade from a populated v1.11.3 database snapshot
Native group replies already persist human mentions without dispatching work, but the Runtime at preflight rejected every non-Agent participant. Split public mention validation from Agent handoff validation so mixed human and Agent targets remain atomic while child Runs are created only for wakeable Agents.

Constraint: Human mentions must remain visible without creating child Runs.

Rejected: Strip human IDs during model repair | loses structured mention metadata and contradicts group message behavior.

Confidence: high

Scope-risk: narrow

Directive: Keep public mention targets distinct from wakeable Agent targets.

Tested: 232 scoped Runtime and group delivery tests; Ruff check on changed files.

Not-tested: Browser rendering and live 3010 mixed-mention E2E pending deployment.
Merge the standalone main-based mention repair into the release candidate so mixed human and Agent targets preserve public message metadata while only wakeable Agents receive child Runs. The automatic merge retains the Tool Runtime contract work already integrated into model_step_service.

Constraint: Human participants are valid visible mention targets but are never Runtime handoff targets

Rejected: Continue carrying the fix only on the Feishu reimbursement branch | obscures ownership and release ancestry

Confidence: high

Scope-risk: moderate

Directive: Keep visible mention validation separate from wakeable Agent handoff validation

Tested: 867 Runtime, Tool, finish-protocol, and migration tests; fatal Ruff; Architecture Guard P0; Alembic single-head check

Not-tested: Live mixed-mention E2E on deployed port 3010
Add typed Feishu approval definition, attachment upload, and create tools while binding provider submission to the exact tenant, Run, Tool Ledger receipt, applicant, and in-chat confirmation.

Constraint: Approval creation must not depend on a new frontend or legacy ApprovalRequest flow
Constraint: Existing user worktree changes remain outside this commit
Rejected: Bare yes/no confirmation | stale replies could authorize another request
Rejected: Raw approver and CC open IDs | bypasses tenant roster authorization
Rejected: Reusable bearer proof | could replay an identical provider write
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Do not expose feishu_approval_create outside the receipt-bound Durable Runtime conversation gate
Tested: 335 relevant backend tests; scoped Ruff; compileall; diff check; independent code review and verification
Not-tested: Live Feishu Provider create and 3010 deployment
Preserve a bounded, sanitized Provider receipt in the Tool outcome and surface HTTP status, business code, message, and response body to the model. Approval reads and writes retain their existing retry classification, while attachment inputs are rejected before confirmation unless they contain stable file-code strings.

Constraint: External approval writes must never be replayed after an ambiguous Provider outcome

Constraint: Provider response metadata must pass through the Tool Ledger sanitizer before model visibility

Rejected: Return only a generic rejection string | leaves the model unable to repair invalid form controls or permissions

Rejected: Accept attachment objects in form_data | confirmation would bind an unstable provider payload shape

Confidence: high

Scope-risk: moderate

Directive: Preserve provider receipt bounds and redaction whenever adding new Feishu failure fields

Tested: 804 Runtime and Tool tests; 201 approval-focused tests; fatal Ruff; Architecture Guard P0; diff check

Not-tested: Live Feishu Provider create and deployed 3010 approval flow
Merge the standalone Feishu approval tools into the release Runtime while retaining stable Tool Call identity, validation, deadlines, cancellation, lease renewal, and repair budgeting. Approval creation now issues its single-use authorization inside the controlled application execution path, after the exact call has been confirmed and reserved.

Constraint: Approval writes must remain bound to the tenant, actor, Run, call instance, execution receipt, lease owner, and exact arguments

Rejected: Restore the approval branch's direct executor call | would bypass v1.11.4 deadline, cancellation, lease, and Tool contract controls

Confidence: high

Scope-risk: broad

Directive: Keep approval authorization issuance inside _execute_application_with_controls and preserve call_instance_id as the Runtime identity

Tested: 941 Runtime, Tool, approval, finish-protocol, and migration tests; fatal Ruff; Architecture Guard P0; Alembic single-head check

Not-tested: Live Feishu approval creation and deployed 3010 confirmation flow
Set the existing protocol repair, safe-read replay, and model-visible Tool episode limits to ten while preserving their current independent state and execution semantics. Update focused tests and planning artifacts to make the off-by-one behavior explicit.

Constraint: Tool-related retry and repair limits must be ten without restructuring the existing counters

Rejected: Unify protocol, Receipt, and model-visible repair state now | counter redesign is intentionally deferred

Confidence: high

Scope-risk: moderate

Directive: Keep the independent counters until the planned repair-control refactor; do not infer identical attempt semantics from the shared numeric limit

Tested: 911 Runtime and Tool pytest cases; scoped Ruff; fatal-level caller Ruff; py_compile; git diff --check

Not-tested: Live Provider credentials
Merge the main-based Tool Runtime follow-up so the release candidate uses ten for protocol repair, safe-read replay, and model-visible Tool episode limits without restructuring their independent counters.

Constraint: v1.11.4 must remain aligned with PR 945 while retaining its release-only approval and mention fixes

Rejected: Cherry-pick individual files | merging the reviewed main-based commit preserves its tests and planning evidence

Confidence: high

Scope-risk: moderate

Directive: Keep protocol, Receipt, and model-visible repair state separate until the planned counter refactor

Tested: 928 release-combination pytest cases with release PYTHONPATH; scoped Ruff; fatal-level caller Ruff; py_compile; staged diff check

Not-tested: Live Provider credentials
Gemini reuses provider call identifiers across assistant turns, so a history-wide lookup allowed later calls to overwrite earlier tool names. Scope name resolution to the active assistant exchange while preserving provider wire identifiers.

Constraint: Gemini provider call IDs are not globally unique across turns

Rejected: Persist globally unique provider IDs | would alter provider wire identity and conflict with existing Runtime correlation

Confidence: high

Scope-risk: narrow

Directive: Keep Tool Result name resolution exchange-local when modifying Gemini history lowering

Tested: backend/tests/test_llm_single_step.py; LLM scoped tests; Ruff

Not-tested: Live Gemini API
Y1fe1Zh0u and others added 30 commits August 14, 2026 15:06
…ion-scope

fix(runtime): authorize native group sandbox execution
A depleted Tool repair budget previously parked the Run in waiting_user, leaving users with an apparently active task and only a plain assistant message. Treat the exhausted budget as a structured terminal failure so the existing run_failed delivery and frontend error paths are used.

Constraint: Historical waiting_user checkpoints for repair exhaustion must remain resumable.

Rejected: Add a special frontend waiting card | the exhausted repair budget is not recoverable without starting a new turn and should release the Run lane.

Confidence: high

Scope-risk: narrow

Directive: Keep repair-budget exhaustion terminal unless a bounded automatic recovery mechanism is introduced.

Tested: 62 Runtime node, checkpoint, chat stream, and repair budget tests; scoped Ruff; git diff --check.

Not-tested: Live WebSocket rendering against the deployed frontend.
Fail runs when tool repair budget is exhausted
Replace the product-style base prompt with a concise execution contract and add an independent semantic completion gate after deterministic Tool ledger verification. Explicit repair decisions re-enter the Agent loop up to ten times; gate infrastructure failures fail open, and exhausted semantic repairs deliver the latest candidate with internal diagnostics.

Constraint: Completion checking must not suppress a usable model answer when the judge is unavailable or repeatedly disagrees.

Rejected: Treat semantic judge failures like Tool ledger failures | semantic evaluation is probabilistic and must not block normal output.

Confidence: high

Scope-risk: moderate

Directive: Keep Tool ledger verification fail-closed and semantic completion infrastructure fail-open.

Tested: 78 scoped backend tests; scoped Ruff; git diff --check

Not-tested: Live provider completion-gate call and 3010 end-to-end Run
Tool-call chat rows written after the tenant backfill omitted tenant ownership, so request-scoped ORM filtering hid them from session history even though execution data remained in PostgreSQL. Resolve the Agent tenant on write and repair existing null-owned tool rows by Agent or Session ownership.

Constraint: ChatMessage is globally tenant-scoped and nullable legacy rows are intentionally invisible in request context.
Rejected: Bypass tenant filtering in the history endpoint | would weaken cross-tenant isolation.
Confidence: high
Scope-risk: narrow
Directive: Every new ChatMessage writer must persist tenant_id before commit.
Tested: 24 chat session service/API tests; scoped Ruff; live DB/API diagnosis on 3010.
Not-tested: Browser rendering until the updated backend is deployed.
Direct Chat previously rebuilt Tool cards from the final checkpoint, so context compaction reduced a 170-call Run to 51 visible calls. Project settled Tool activity from the durable Run event ledger and lazily repair completed sessions on read.

Constraint: Tool history must remain tenant-scoped and idempotent across refresh and checkpoint replay

Rejected: Count only agent_tool_executions | excludes validation and protocol failures that still reached the model-visible Tool loop

Confidence: high

Scope-risk: moderate

Reversibility: clean

Directive: Keep Chat Tool history derived from durable call IDs, not compactable checkpoint message windows

Tested: 102 scoped backend tests; scoped Ruff; git diff --check

Not-tested: Full backend suite and 3010 live repair before deployment
Ignore repository-root temporary, generated output, and internal documentation directories so routine release commits remain focused on deployable source.

Constraint: Existing local artifacts must remain untouched

Confidence: high

Scope-risk: narrow

Reversibility: clean

Tested: git check-ignore for all four directories; git diff --check

Not-tested: None
Merge the latest upstream sandbox path normalization while preserving the two local candidate commits for Tool history and artifact hygiene.

Constraint: Local candidate contains two commits not yet present on upstream/v1.11.4

Confidence: high

Scope-risk: narrow

Tested: Merge completed without conflicts; repository status and commit graph inspected

Not-tested: Automated and live regression suites not yet run
The chat shell duplicated viewport sizing inside an already bounded layout, allowing the document to grow and receive wheel events at message boundaries. Let flex sizing own the remaining height and contain overscroll in the shared read-only and writable message viewport.

Constraint: Historical pagination fires only from the message container scroll handler

Rejected: Intercept wheel events globally | breaks nested Tool result scrolling and native input behavior

Confidence: high

Scope-risk: narrow

Reversibility: clean

Directive: Keep Direct Chat viewport height owned by the chat-page flex chain

Tested: 93 frontend contract tests; TypeScript production build; 41 backend Tool history tests; scoped Ruff; git diff --check

Not-tested: Browser interaction before deployment because no browser instance was connected
A scroll handler cannot fire when the message viewport is already at scrollTop zero or the first page is too short to overflow. Observe a top sentinel inside each history viewport so pagination runs whenever the load boundary is visible, while retaining the existing scroll handler as a fallback.

Constraint: Pagination must work for both writable and read-only Direct Chat sessions

Rejected: Trigger only from wheel events | excludes touch, keyboard, and non-overflowing first pages

Confidence: high

Scope-risk: narrow

Reversibility: clean

Directive: Keep history loading tied to the message viewport, not document scroll position

Tested: 93 frontend tests; TypeScript production build; git diff --check

Not-tested: Authenticated browser interaction before deployment because no browser instance is connected
The Analysis card derived its Tool count from the currently materialized frontend page, so a 170-call settled run initially appeared as roughly 18 calls. Aggregate Tool rows with the existing Session message-count query and use that authoritative total for settled single-turn histories.

Constraint: History detail remains paginated and must not be eagerly loaded just to compute a total

Rejected: Count tools from chatMessages | makes a factual total depend on viewport pagination

Confidence: high

Scope-risk: narrow

Reversibility: clean

Directive: Keep session-level Tool totals server-derived and tenant-scoped

Tested: 18 backend API tests; scoped Ruff; 94 frontend tests; TypeScript production build; git diff --check

Not-tested: Multi-run per-turn server totals because this change intentionally exposes only the authoritative Session total
Top-sentinel pagination could request the next page before requestAnimationFrame restored the prior viewport, making long Tool histories visibly jump. Capture scroll height and offset before prepending, then compensate synchronously after React commits the new rows.

Constraint: The first visible message must stay fixed across every paginated prepend

Rejected: Delay subsequent pages with timers | masks the race and makes loading latency-dependent

Confidence: high

Scope-risk: narrow

Reversibility: clean

Directive: Keep native overflow anchoring disabled while manual prepend anchoring owns scroll compensation

Tested: 94 frontend tests; TypeScript production build; git diff --check

Not-tested: Authenticated visual browser observation because no browser instance is connected
History prepends and live auto-follow both reacted to chatMessages mutations, so the anchor compensation and scroll-to-bottom observers alternated during multi-page Tool loading. Mark the prepend window explicitly, cancel queued follow jobs, and suppress every bottom-follow entry until the anchored frame settles.

Constraint: Realtime messages must retain normal near-bottom auto-follow outside history prepends

Rejected: Remove auto-follow observers | regresses live streaming and expanded Tool cards

Confidence: high

Scope-risk: narrow

Reversibility: clean

Directive: Any future history prepend path must enter the auto-follow suppression window

Tested: 94 frontend tests; TypeScript production build; git diff --check

Not-tested: Authenticated visual replay because browser automation could not safely reuse the live login state
Direct Chat accumulated sentinel loading, local anchor state, and auto-follow suppression while Group Chat kept a separate scroll-height implementation. Replace both paths with shared gesture gating and prepend anchoring so history advances only from explicit wheel, touch, pointer, keyboard, or button intent.

Constraint: One inertial gesture may request at most one page and session switches must reset pending anchors

Rejected: Keep an always-visible IntersectionObserver sentinel | collapsed long Tool traces make it auto-load every page

Confidence: high

Scope-risk: moderate

Reversibility: clean

Directive: New chat history surfaces must reuse useHistoryPaginationScroll instead of adding visibility-driven loaders

Tested: 95 frontend tests; TypeScript production build; git diff --check

Not-tested: Authenticated visual replay because the available browser session could not safely reuse production login state
Backend rows are not frontend visual units: a 20-row page can contain only part of one collapsed Tool trace and reveal no earlier bubble. Continue older Direct Chat requests while the visible boundary is inside tool_call rows, trim at the nearest user boundary, and publish the completed turn once.

Constraint: Initial history remains 20 rows and Group Chat keeps ordinary message paging

Rejected: Increase the global page size | still splits larger Tool turns and over-fetches normal conversations

Confidence: high

Scope-risk: moderate

Reversibility: clean

Directive: Keep collapsed trace completion separate from backend row-page size

Tested: 99 frontend tests including a 170-call folded turn; TypeScript production build; git diff --check

Not-tested: Authenticated visual replay because the production browser login state was unavailable to automation
Sandbox and direct file mutations now preserve execution-scoped candidates, verify base/candidate/current state, and converge safe retries before asking a human. Direct and native Group chats reuse their existing two-button confirmation surfaces, while all current human group members may settle the first decision and resume the exact durable Run.

Constraint: Shared Workspace mode remains the default and unknown side effects must never replay execute_code.

Rejected: Add Workspace tools to the old applied/not-applied allowlist without candidate bytes | the button would not actually apply Agent output after sandbox cleanup

Rejected: Last-write-wins publication | it can overwrite a concurrent human or Session update

Confidence: high

Scope-risk: moderate

Reversibility: clean

Directive: Preserve tenant-scoped candidate refs, write-before-delete ordering, and RuntimeCommandIntake resume boundaries.

Tested: Backend pytest 2431 passed; frontend node tests 104 passed; frontend production build; scoped Ruff; arch-guard P0; git diff --check

Not-tested: Real Provider conflict generation before 3010 browser E2E
Direct Chat now takes the maximum of the persisted session total and the Tool rows already loaded in the browser, so stale zero metadata cannot hide a real execution.

Confidence: high

Scope-risk: narrow

Directive: Never let cached Tool totals undercount rows already present in the canonical message stream.

Tested: Frontend node tests 105 passed; TypeScript and Vite production build passed; git diff --check

Not-tested: Browser refresh on 3010 until this frontend follow-up is deployed
Users may now choose a Run-scoped all-accept policy after a real Workspace conflict. Later conflicts in that Run apply preserved Agent candidates automatically, while unreadable storage and protected paths remain fail-closed. This commit also closes final concurrency and cleanup findings from review.

Constraint: All-accept expires with the Run and never becomes an Agent-wide default.

Rejected: Permanent Agent-level last-write-wins | it would silently affect unrelated future tasks

Confidence: high

Scope-risk: moderate

Directive: Keep auto-accept Run-scoped, candidate-backed, audited, and disabled for unverified storage.

Tested: Backend pytest 2431 passed; frontend node tests 105 passed; TypeScript and Vite production build passed

Not-tested: 3010 browser all-accept follow-up until deployed
Workspace decisions now settle through a dedicated Runtime resume type and terminate the waiting Run directly. A Run-scoped all-accept choice applies later preserved candidates automatically without turning into an Agent-wide policy.

Confidence: high

Scope-risk: moderate

Directive: Human Workspace decisions must apply candidates in backend control flow and must not be re-prompted to the model.

Tested: Backend targeted 65 passed and full 2431 passed before control-flow delta; frontend 105 passed and production build passed

Not-tested: 3010 all-accept browser follow-up until deployed
A source-preserving decision now publishes independent safe writes, skips unsafe deletes, and resumes the pending Tool batch instead of terminalizing the Run.

Constraint: Conflicted or unreadable paths must retain the current Workspace bytes.

Rejected: End the Run after reconciliation | abandons remaining files and pending Tool Calls

Confidence: high

Scope-risk: moderate

Directive: Preserve decisions must remain CAS-protected and must not delete a possible move source when any path is unsafe.

Tested: 115 targeted backend tests; 2432 full backend tests passed; arch-guard P0 passed

Not-tested: 2 unrelated html-to-pdf tests require missing local WeasyPrint system libraries
A resumed reconciliation now carries a structured Workspace decision into Runtime history, and the semantic completion gate treats that authenticated decision as an authoritative amendment to the original goal.

Constraint: A keep-source decision must not be undone by completion repair.

Rejected: Disable the completion gate after reconciliation | unrelated task requirements still need verification

Confidence: high

Scope-risk: moderate

Directive: Later human reconciliation decisions override conflicting initial file-content requirements, but not unrelated completion requirements.

Tested: 141 targeted backend tests; 2433 full backend tests passed; arch-guard P0 passed

Not-tested: 2 unrelated html-to-pdf tests require missing local WeasyPrint system libraries
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants