/**
 * Canonical task-ownership axis (D0064).
 *
 * `ownership` is a deliberately binary, system-managed field on `ailf.task`:
 *
 *   - `"studio"` — authored in Studio, fully editable.
 *   - `"repo"`   — synced from an external repository, read-only in Studio.
 *
 * It is NOT a team and NOT an "ecosystem" tier. The Studio field's
 * `options.list` is studio/repo only, `hidden`, and "managed by system
 * actions, not manually edited", so a value outside this set (`"ecosystem"`,
 * `null`) is bad data that leaked in through a non-Studio write that bypassed
 * the constraint — never a missing ownership tier. Widening the enum would
 * corrupt the editability semantics: the Studio `readOnly` predicate and the
 * dashboard row adapter both treat any value `!== "repo"` as editable/studio.
 *
 * Unlike the free-form owner-team slug (see `./owner-teams.ts`, an open enum),
 * this is a closed set — out-of-set values are coerced to a caller-chosen
 * fallback, not passed through.
 *
 * @see docs/decisions/D0064-default-local-run-to-repo-tasks.md
 * @see docs/work-items/W-normalize-task-ownership.json
 */
export const TASK_OWNERSHIP_VALUES = ["studio", "repo"];
/** Narrow an unknown value to a canonical {@link TaskOwnership}. */
export function isTaskOwnership(value) {
    return value === "studio" || value === "repo";
}
/**
 * Coerce any persisted `ownership` into the binary axis.
 *
 * A conforming value passes through untouched. A non-conforming value
 * (`null`, `undefined`, legacy `"ecosystem"`, anything else) collapses to
 * `options.fallback` and fires `options.onCoerce`. Callers pick the fallback
 * for their context:
 *
 *   - Read / display (dashboard) → `"studio"`, the editable default that
 *     mirrors the Studio `readOnly` rule (any value `!== "repo"` is editable)
 *     and keeps every task in a filter bucket rather than absent from both.
 *   - Repo-sync write seam → `"repo"`, the synced/read-only default, with a
 *     logged warning so the leak is observable.
 */
export function normalizeTaskOwnership(value, options) {
    if (isTaskOwnership(value))
        return value;
    options.onCoerce?.({ received: value, coercedTo: options.fallback });
    return options.fallback;
}
