feat(context): transition guards — addons can veto context switches #386

Open
opened 2026-03-03 23:02:59 +00:00 by forbes · 0 comments
Owner

Summary

Allow addons to register guard callbacks that can prevent context transitions. Critical for addons managing locks or unsaved state (e.g., silo preventing a context switch while a document has uncommitted changes).

Current state (MISSING)

EditingContextResolver resolves and applies unconditionally. No guard/veto callbacks. No canTransitionTo() hook. Addons cannot prevent or delay context switches.

Proposed API

import kindred_sdk as sdk

def my_guard(from_ctx, to_ctx):
    if from_ctx["id"] == "silo.editing" and has_unsaved_changes():
        return False, "Unsaved changes — save or discard before switching"
    return True, None

sdk.add_transition_guard(my_guard)
sdk.remove_transition_guard(my_guard)
  • Guards run in registration order; first rejection cancels the transition
  • Rejection reason string is surfaced to the user via a warning dialog
  • Return value is (allowed: bool, reason: str | None)

Implementation notes

  • Add addTransitionGuard() / removeTransitionGuard() to EditingContextResolver
  • Guards stored as a list of std::function<std::pair<bool, QString>(EditingContext, EditingContext)>
  • Called in applyContext() before any toolbar/breadcrumb changes
  • On rejection: emit a signal or show QMessageBox::warning with the reason
  • Python SDK: add_transition_guard(), remove_transition_guard() in kindred_sdk/context.py

Roadmap

v0.2.0 — Context System

## Summary Allow addons to register guard callbacks that can prevent context transitions. Critical for addons managing locks or unsaved state (e.g., silo preventing a context switch while a document has uncommitted changes). ## Current state (MISSING) `EditingContextResolver` resolves and applies unconditionally. No guard/veto callbacks. No `canTransitionTo()` hook. Addons cannot prevent or delay context switches. ## Proposed API ```python import kindred_sdk as sdk def my_guard(from_ctx, to_ctx): if from_ctx["id"] == "silo.editing" and has_unsaved_changes(): return False, "Unsaved changes — save or discard before switching" return True, None sdk.add_transition_guard(my_guard) sdk.remove_transition_guard(my_guard) ``` - Guards run in registration order; first rejection cancels the transition - Rejection `reason` string is surfaced to the user via a warning dialog - Return value is `(allowed: bool, reason: str | None)` ## Implementation notes - Add `addTransitionGuard()` / `removeTransitionGuard()` to `EditingContextResolver` - Guards stored as a list of `std::function<std::pair<bool, QString>(EditingContext, EditingContext)>` - Called in `applyContext()` before any toolbar/breadcrumb changes - On rejection: emit a signal or show `QMessageBox::warning` with the reason - Python SDK: `add_transition_guard()`, `remove_transition_guard()` in `kindred_sdk/context.py` ## Roadmap v0.2.0 — Context System
forbes added the enhancement label 2026-03-03 23:02:59 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: kindred/create#386