Files
weichenandCursor 0611b1f24f feat(intentflow): wire U9–U12 ports and gated OwnerMux
Register dry-run adapters via BuildOwnerMux when independent flags are on;
U9 stub fail-closes on malformed/timeout/out-of-bounds without raising PlanTier.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-16 15:42:49 +00:00

84 lines
1.9 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package intentflow
import "context"
// OwnerMux routes generate keys to Task, optional U10–U12 owners when their
// flags are on, and everything else to Query.
type OwnerMux struct {
Query ActionOwner
Task ActionOwner
Mutate ActionOwner
DocGov ActionOwner
RunControl ActionOwner
}
func (m OwnerMux) pick(actionKey string) ActionOwner {
switch actionKey {
case "task.run", "task.run.adhoc":
return m.Task
}
f := CurrentFeatureFlags()
if _, ok := mutateActionKeys[actionKey]; ok {
if f.U10Mutate {
return m.Mutate
}
return m.Query
}
if _, ok := docGovActionKeys[actionKey]; ok {
if f.U11DocGov {
return m.DocGov
}
return m.Query
}
if _, ok := runControlActionKeys[actionKey]; ok {
if f.U12RunControl {
return m.RunControl
}
return m.Query
}
return m.Query
}
func (m OwnerMux) Authorize(ctx context.Context, exec StepExec) error {
owner := m.pick(exec.ActionKey)
if owner == nil {
return ErrPlanActionForbidden
}
if a, ok := owner.(StepAuthorizer); ok {
return a.Authorize(ctx, exec)
}
return nil
}
func (m OwnerMux) Execute(ctx context.Context, exec StepExec) (Receipt, error) {
if err := m.Authorize(ctx, exec); err != nil {
return Receipt{}, err
}
owner := m.pick(exec.ActionKey)
if owner == nil {
return Receipt{}, ErrPlanActionForbidden
}
return owner.Execute(ctx, exec)
}
func (m OwnerMux) LookupReceipt(ctx context.Context, idempotencyKey string) (Receipt, bool, error) {
owners := []ActionOwner{m.Task, m.Mutate, m.DocGov, m.RunControl, m.Query}
for _, o := range owners {
if o == nil {
continue
}
if rec, ok, err := o.LookupReceipt(ctx, idempotencyKey); err != nil || ok {
return rec, ok, err
}
}
return Receipt{}, false, nil
}
func (m OwnerMux) ObserveFence(stepID string, token int64) {
for _, o := range []ActionOwner{m.Query, m.Task, m.Mutate, m.DocGov, m.RunControl} {
if obs, ok := o.(FenceObserver); ok {
obs.ObserveFence(stepID, token)
}
}
}