package router import "github.com/kami/maven/internal/lexicon" // ActHasEntityTarget reports whether an act names something that Nexus may be // asked to resolve. A local zero-argument tool may still be valid; this gate is // only about crossing into the ecosystem, where an entity is mandatory. // // A matched function carries its target in Args. An unmatched entity act is // the Hexis discovery lane, so it must at least contain a verb plus a subject. // A bare verb and a demonstrative-only tail carry no target evidence and stay // local/clarify instead of sending free ambiguity to Nexus. func ActHasEntityTarget(decision Decision) bool { if decision.Intent != IntentAct { return false } if decision.CapabilitySelection.Resolved { if len(decision.CapabilitySelection.Args) > 0 { return hasNamedEntityToken(decision.CapabilitySelection.Args) } // A resident-model act may name the accepted verb and its target in // Text while leaving Args empty. Resolved establishes that the first token // is the operation; only a meaningful tail can establish the entity. tokens := planTokens(decision.Slots.Text) return len(tokens) > 1 && hasNamedEntityToken(tokens[1:]) } tokens := planTokens(decision.Slots.Text) if len(tokens) < 2 { return false } return hasNamedEntityToken(tokens[1:]) } func hasNamedEntityToken(tokens []string) bool { references := lexicon.UnresolvedReferences() for _, token := range tokens { if lexicon.IsFillerParticle(token) || hasExactWord(references, token) { continue } return true } return false }