/**
 * Type definitions, constants, and configuration shapes for SF preferences.
 *
 * All interfaces, type aliases, and static lookup tables live here so that
 * both the validation and runtime modules can import them without pulling
 * in filesystem or loading logic.
 */
/**
 * Resolve whether context-mode features (exec sandbox + compaction snapshot)
 * should be active. Default is ON: missing config or missing `enabled` is true.
 */
export function isContextModeEnabled(prefs) {
	return prefs?.context_mode?.enabled !== false;
}
/** Default preference values for each workflow mode. */
export const MODE_DEFAULTS = {
	solo: {
		git: {
			auto_push: true,
			push_branches: false,
			pre_merge_check: "auto",
			merge_strategy: "squash",
			isolation: "none",
		},
		unique_milestone_ids: false,
		context_compact_at: 20000,
		context_hard_limit: 35000,
		unit_timeout: 300,
		max_agents_by_phase: {
			research: 1,
			planning: 1,
			execution: 1,
			validation: 1,
		},
		turn_input_required: false,
		worktree_mode: "auto",
		tool_abort_grace: 5000,
		max_turns_per_attempt: 50,
		hot_cache_turns: 5,
	},
	team: {
		git: {
			auto_push: false,
			push_branches: true,
			pre_merge_check: true,
			merge_strategy: "squash",
			isolation: "none",
		},
		unique_milestone_ids: true,
		context_compact_at: 25000,
		context_hard_limit: 40000,
		unit_timeout: 300,
		max_agents_by_phase: {
			research: 2,
			planning: 1,
			execution: 4,
			validation: 2,
		},
		turn_input_required: true,
		worktree_mode: "manual",
		tool_abort_grace: 8000,
		max_turns_per_attempt: 60,
		hot_cache_turns: 10,
	},
};
/** All recognized top-level keys in SFPreferences. Used to detect typos / stale config. */
export const KNOWN_PREFERENCE_KEYS = new Set([
	"version",
	"last_synced_with_sf",
	"sf_template_state",
	"sf_template_hash",
	"mode",
	"always_use_skills",
	"prefer_skills",
	"avoid_skills",
	"skill_rules",
	"custom_instructions",
	"models",
	"persist_model_changes",
	"skill_discovery",
	"skill_staleness_days",
	"auto_supervisor",
	"uat_dispatch",
	"unique_milestone_ids",
	"budget_ceiling",
	"budget_enforcement",
	"context_pause_threshold",
	"notifications",
	"cmux",
	"remote_questions",
	"git",
	"post_unit_hooks",
	"pre_dispatch_hooks",
	"dynamic_routing",
	"uok",
	"token_profile",
	"phases",
	"auto_visualize",
	"auto_report",
	"parallel",
	"verification_commands",
	"verification_auto_fix",
	"verification_max_retries",
	"verification_auto_defer_threshold",
	"search_provider",
	"context_selection",
	"widget_mode",
	"reactive_execution",
	"gate_evaluation",
	"github",
	"service_tier",
	"allowed_providers",
	"advisor_allowed_providers",
	"blocked_providers",
	"provider_preference",
	"provider_model_allow",
	"provider_model_block",
	"forensics_dedup",
	"show_token_cost",
	"stale_commit_threshold_minutes",
	"context_management",
	"experimental",
	"codebase",
	"slice_parallel",
	"safety_harness",
	"enhanced_verification",
	"enhanced_verification_pre",
	"enhanced_verification_post",
	"enhanced_verification_strict",
	"discuss_preparation",
	"discuss_web_research",
	"discuss_depth",
	"flat_rate_providers",
	"shell_wrapper",
	"workspace",
	"subscription",
	"allow_flat_rate_providers",
	"planning_depth",
	"min_request_interval_ms",
	"context_compact_at",
	"context_hard_limit",
	"unit_timeout",
	"unit_timeout_by_phase",
	"max_agents_by_phase",
	"turn_input_required",
	"worktree_mode",
	"tool_abort_grace",
	"max_turns_per_attempt",
	"hot_cache_turns",
]);
/** Canonical list of all dispatch unit types. */
export const KNOWN_UNIT_TYPES = [
	"research-milestone",
	"roadmap-meeting",
	"plan-milestone",
	"research-slice",
	"plan-slice",
	"refine-slice",
	"execute-task",
	"reactive-execute",
	"gate-evaluate",
	"complete-slice",
	"replan-slice",
	"reassess-roadmap",
	"run-uat",
	"complete-milestone",
	"validate-milestone",
	"rewrite-docs",
	"discuss-milestone",
	"discuss-slice",
	"discuss-project",
	"discuss-requirements",
	"research-project",
	"workflow-preferences",
	"worktree-merge",
];
export const SKILL_ACTIONS = new Set(["use", "prefer", "avoid"]);
/**
 * Format a skill reference for the system prompt.
 * If resolved, shows the path so the agent knows exactly where to read.
 * If unresolved, marks it clearly.
 */
export function formatSkillRef(ref, resolutions) {
	const resolution = resolutions.get(ref);
	if (!resolution || resolution.method === "unresolved") {
		return `${ref} (⚠ not found — check skill name or path)`;
	}
	if (
		resolution.method === "absolute-path" ||
		resolution.method === "absolute-dir"
	) {
		return ref;
	}
	return `${ref} → \`${resolution.resolvedPath}\``;
}
