package router

// Source — where the answer to a query lives. It is the second half of a
// routing decision and it used to be made outside the router entirely (V-655).
//
// The cascade sorted an utterance into one of seven intents with stage 0 rules,
// the resident model and the classifier behind it, a fixture measuring it and
// the decision trace recording it. Then IntentQuery handed the turn to
// querySources in the daemon, a chain of twenty-two branches deciding by seed
// similarity in a fixed order, with none of that. So the careful sorter did the
// easy half and the sloppy one did the hard half: on 2026-08-07 weather claimed
// "что такое TCP?" and answered "для какого города?", because weather read one
// percent closer to the turn than the pile of leftover seeds did, and one
// percent was enough. Search would have answered it and search was never asked.
//
// "query" is not a destination. It is a shrug. This is the field that says
// where to look.
//
// # Why twelve and not twenty-two
//
// A destination is what a decider can plausibly name from the utterance alone,
// not one entry per source. Three of the daemon's sources are successive passes
// over his own words and a fourth reads the facts by key: which of them lands
// the hit is an ordering detail inside the chain, and no utterance says. They
// are SourceRecall together. The same goes for the metasearch, the offline
// encyclopedia and a page he named by URL, which are SourceWorld.
//
// # Empty is a real value and it is the floor
//
// SourceUnknown means nobody decided. The daemon then walks the whole chain in
// its original order, which is the behaviour that shipped before this field
// existed. So the classifier arm sets nothing and costs nothing, and a box
// whose model is down routes queries exactly as it did.
type Source string

const (
	// SourceUnknown — no decider named a destination. Walk the chain.
	SourceUnknown Source = ""

	// His own data.
	SourceRecall   Source = "recall"   // notes, facts and what he has said before
	SourceCalendar Source = "calendar" // events, and the only date-aware destination
	SourceTasks    Source = "tasks"    // the task list
	SourceList     Source = "list"     // the shopping and other named lists
	SourceMoney    Source = "money"    // the spending facts the poller writes

	// The surroundings.
	SourceWeather   Source = "weather"   // the forecast for a place
	SourceHome      Source = "home"      // lights, devices, the house
	SourceNetwork   Source = "network"   // the LAN and what is on it
	SourceFeeds     Source = "feeds"     // the RSS she reads
	SourceAttention Source = "attention" // what Praxis says needs looking at

	// Everything else.
	SourceSelf  Source = "self"  // a question about Maven herself
	SourceWorld Source = "world" // search, the ZIMs, a page he named
)

// Sources — every destination a decider may name, in a fixed order so a prompt,
// a grammar table and a test all read the same list. SourceUnknown is not a
// member: it is the absence of a choice, not one of the choices.
var Sources = []Source{
	SourceRecall, SourceCalendar, SourceTasks, SourceList, SourceMoney,
	SourceWeather, SourceHome, SourceNetwork, SourceFeeds, SourceAttention,
	SourceSelf, SourceWorld,
}

// ValidSource reports whether s is one a decider may name. Anything else,
// including a destination invented by a model, is dropped back to
// SourceUnknown by the caller rather than trusted.
func ValidSource(s Source) bool {
	for _, known := range Sources {
		if s == known {
			return true
		}
	}
	return false
}
