Files
WeiCHEN d019388f37 feat(intent): wire production QueryOwner and confirm dispatcher
Replace FakeActionOwner with QueryOwner+QueryGuard at the composition
root; DispatchEligible reuses claim/execute/recover so confirm stays
zero-write before dispatch and default tier remains legacy.
2026-09-22 21:44:56 +08:00

76 lines
1.8 KiB
Go

package intentflow
import (
"context"
"chat-agent-system/internal/app/uow"
)
// DispatchEligible is the production step dispatcher. It reuses ClaimStep,
// ExecuteClaimed, and RecoverReceipt on the existing intent_plan_steps ledger.
// It must not introduce a second decision queue or step state machine.
//
// After a crash between domain receipt and plan write-back, RecoverReceipt
// replays the owner receipt without re-executing the side effect.
func (p *Plans) DispatchEligible(ctx context.Context, workerID, planID string) (*PlanView, error) {
if workerID == "" || planID == "" {
return nil, ErrPlanDependencyInvalid
}
var prin Principal
var ids []string
err := p.withTx(ctx, func(ctx context.Context, scope uow.TxScope) error {
plan, err := p.store.GetPlan(ctx, scope, planID)
if err != nil {
return err
}
if plan == nil {
return ErrPlanNotFoundOrHidden
}
prin = plan.Principal
for _, s := range plan.Steps {
if s.Status == StepEligible || s.Status == StepPending || s.Status == StepRunning {
ids = append(ids, s.StepID)
}
}
return nil
})
if err != nil {
return nil, err
}
var last *PlanView
var firstErr error
for _, id := range ids {
claimed, claimErr := p.ClaimStep(ctx, workerID, planID, id)
if claimErr != nil {
if firstErr == nil {
firstErr = claimErr
}
continue
}
if claimed == nil {
continue
}
got, execErr := p.ExecuteClaimed(ctx, claimed)
if execErr != nil {
recovered, recErr := p.RecoverReceipt(ctx, claimed)
if recErr == nil && recovered != nil {
last = recovered
continue
}
if firstErr == nil {
firstErr = execErr
}
continue
}
last = got
}
if last == nil {
view, getErr := p.GetPlan(ctx, prin, planID)
if firstErr != nil {
return view, firstErr
}
return view, getErr
}
return last, firstErr
}