Skip to main content

Config reference

Fairway reads .fairway/config.toml from the repo root by default. Override with --config <path> or FAIRWAY_CONFIG=<path>.

Track memory does not add provider configuration. fairway memory stores curated resume summaries and source fact references in the Fairway DB. It does not store provider credentials, raw prompts, transcripts, cookies, tokens, or private provider state.

Legacy tmp-ux/*memory*.md files are non-authoritative migration inputs. Memory import is preview-first and does not store the source file or raw body. The configured Fairway database remains the only durable working-memory authority.

Agent-contract compatibility is intentionally not inferred from project config or binary SemVer. .fairway/AGENTS.md carries its own schema, revision, generating binary, and managed-content hash. Use fairway agent-contract status|plan|apply to inspect or update it.

Repository-specific instructions belong in .fairway/AGENTS.local.md. fairway init --refresh-agent-contract and fairway agent-contract apply use the same safe managed-contract update path; locally modified managed content is never overwritten automatically.

Engineering knowledge is project-owned Markdown. Configure its project-relative root when the conventional location is unsuitable:

[knowledge]
root = "doc/agent-wiki"

Knowledge lifecycle commands use command-local bounds rather than hidden provider settings. knowledge query --budget-bytes and memory cold-start --knowledge-budget-bytes cap optional knowledge context separately from execution memory. Ingest and promotion remain preview-first and write only with explicit --apply; the configured root grants no canonical documentation or review authority. knowledge lint fails on errors; knowledge lint --fail-on-warning also fails on overdue review and other warning findings when a project deliberately chooses that stricter CI policy.

Supply-chain provenance exports are derived from existing task, evidence, review, session, checkpoint, batch, usage, and release records. There is no provenance-specific credential, provider, or content-capture setting in the current config. See supply-chain-provenance.md for the privacy boundary and future export model.

Tamper-evident evidence manifests are also config-free. Use fairway provenance manifest --path <file> on selected exported provenance bundles or redacted artifacts. The command hashes files and records path/hash metadata only; it does not store artifact contents, secrets, or credentials in Fairway.

Full schema

[fairway]
project_name = "myrepo" # default: basename of repo root; must be unique in registry
db_path = ".fairway/state.db" # relative to repo root
queue_source = "inline" # "inline" | "yaml:<path>" | "json:<path>"
main_branch = "main" # base branch worktrees branch off of
task_id_pattern = "^[A-Z]+-[0-9]+$" # regex enforced by add/import/update
local_artifact_paths = ["dist/fairway"] # optional local evidence artifact dirs

[runtime]
profile = "standard" # standard | sovereign-offline

[dashboard]
listen = "127.0.0.1:7878"
auto_open = true # open browser when `fairway dashboard` starts

[server]
enabled = false
listen = "127.0.0.1:7880"
mode = "disabled" # disabled | read_only
read_only = true
write_enabled = false # write-capable server mode is not implemented
identity_mode = "no_edge_local" # no_edge_local | trusted_proxy_read_only | api_token | service_account | mtls_service_account | sovereign_signed
allowed_roles = ["viewer"] # command-scoped roles allowed by the read-only API
api_token_env = "" # env var containing token for identity_mode = "api_token"
api_token_role = "viewer"
trusted_proxy_verified = false # must be true before proxy identity can authorize reads
trusted_proxy_identity_header = "X-Fairway-User"
trusted_proxy_proof_header = "X-Fairway-Proxy-Verified"
trusted_proxy_issuer = ""
trusted_proxy_issuer_header = "X-Fairway-Proxy-Issuer"
trusted_proxy_audience = ""
trusted_proxy_audience_header = "X-Fairway-Proxy-Audience"
sovereign_public_key_env = "" # base64 Ed25519 public key; required for sovereign_signed
sovereign_key_id = ""
sovereign_issuer = ""
sovereign_audience = ""
sovereign_revocation_file = "" # absolute private local fairway.sovereign-revocations.v1 JSON
sovereign_session_max_seconds = 900
sovereign_clock_skew_seconds = 30
sovereign_break_glass_max_seconds = 300
sovereign_dual_control_commands = ["set:status", "record:review"]

[worktrees]
root = "../worktrees"
naming = "{repo}-{role}"
review_branch_naming = "review/{role}"

[sessions]
default_backend = "shell" # shell | tmux | zellij
stale_after = "12h"

[coordinator]
max_primary_tracks = 1
max_sidecar_tracks = 1
max_review_tracks = 1
checkpoint_stale_after = "24h"
notification_ack_timeout = "24h"

[consumer_readiness]
minimum_version = "0.1.12"
minimum_schema_version = 13
pinned_binary_path = "/Users/operator/Library/Caches/fairway/binaries/versions/0.1.12-abc123/fairway"
required_capabilities = ["managed-binary-cache", "track-memory-lifecycle"]
required_commands = ["binary status", "memory disposition"]
required_features = ["managed_binary_cache", "track_memory_lifecycle"]

[[control_effectiveness.path_exclusions]]
pattern = "dist/**"
category = "generated" # generated | high_churn
rationale = "Release build output is generated from reviewed source."

[[roles]]
name = "backend"
branch = "agent/backend"
provider = "claude" # informational; not enforced

[[roles]]
name = "ui"
branch = "agent/ui"
provider = "codex"

[review_domain_aliases]
security = "arch"

[[review_routes]]
match = "doc/api/**"
reviewer = "arch"

[[review_routes]]
match = "doc/governance/**"
reviewer = "governance"

[[provider_targets]]
domain = "security"
provider = "codex"
type = "thread"
target = "codex-thread-id-or-adapter-target"

[[advisory_provider_adapters]]
name = "local-rules"
provider = "ollama"
type = "local_ollama" # noop | rules-only | local_ollama | local_llamacpp | openai-compatible | codex | claude | gemini
mode = "advisory" # advisory | report_only | disabled
trust = "low" # low | medium | high
model = "llama3.1"
endpoint_env = "FAIRWAY_OLLAMA_ENDPOINT"
capabilities = ["summarize_evidence", "rank_ready_tasks", "explain_code_narrative"]
allowed_actions = ["inspect_task", "render_packet"]

[[external_notifiers]]
name = "control-log"
type = "log" # noop | log
mode = "dry_run" # dry_run | disabled
target_env = "FAIRWAY_NOTIFY_LOG"
domains = ["coordinator", "ops"]
template_name = "control_room_handoff"

[[workstream_profiles]]
name = "platform-foundation"
task_kinds = ["architecture-map", "boundary-guard", "facade"]
dashboard_groups = ["architecture maps", "boundary guards", "facades"]
review_domains = ["architecture", "security"]
route_samples = ["doc/api/openapi.yaml", "cmd/api/routes.go"]

[[review_profiles]]
name = "micro-slice"
mode = "advisory" # advisory | blocking; default blocking
match_kinds = ["task"]
match_risk_levels = ["low"]
match_tags = ["review:micro"]
required_review_domains = ["governance"]
waive_review_domains = ["backend"]
defer_review_domains = ["ops"]
safe_iteration_zone = true
safe_iteration_defect_class = "harness"
safe_iteration_control = "non-live disposable boundary"
extra_reviewer_rationale = "governance catches evidence contract drift"
process_hypothesis = "one governance review catches evidence drift without full matrix overhead"
outcome_metrics = ["defects_caught", "cycle_time", "avoided_unsafe_actions"]

[[workstream_profiles.gates]]
name = "security-review"
group = "security gates"
mode = "advisory" # advisory | blocking | report_only
task_kinds = ["facade"] # optional; omit to apply to all profile task kinds
evidence_type = "security-review"
required_evidence_count = 1
accepted_results = ["pass", "partial"]
artifact_required = true
owner_signoff_required = false
expires_after = "720h"
description = "Security review evidence should be attached before release readiness."

[[packet_templates]]
profiles = ["platform-foundation"]
name = "architecture-map"
required_fields = ["scope", "current_owner", "target_owner", "migration_risk", "acceptance"]
optional_fields = ["source_doc"]

[states]
allowed = ["todo", "in_progress", "blocked", "done"]
terminal = ["done"]
# transitions = [["todo","in_progress"], ...] # optional; permissive if omitted

[gates]
require_evidence_before_done = false
require_review_before_done = false
require_handoff_before_merge_ready = false
require_blocked_reason = true
allow_force_without_reason = false

[task_kinds]
allowed = ["epic", "story", "task", "bug", "spike"] # optional; free-text if omitted
default = "task"

[task_priorities]
default = 2
levels = [
{ rank = 0, label = "P0", description = "drop everything" },
{ rank = 1, label = "P1", description = "this sprint" },
{ rank = 2, label = "P2", description = "soon" },
{ rank = 3, label = "P3", description = "eventually" },
]

Section reference

Assurance profiles are versioned local YAML or JSON inputs, not a Fairway configuration section. Keep them under a reviewed project directory and pass their paths explicitly to fairway assurance .... See the starter catalog, authoring guide, and compatibility policy. Fairway does not fetch or silently update profiles from framework URLs.

For a project-neutral starting point, copy examples/fairway-config.toml and adjust the roles, routes, and profile samples. Consumer compatibility fixtures under examples/ are regression inputs, not Fairway defaults.

[fairway]

KeyTypeDefaultDescription
project_namestringbasename of repo rootLabel used by the multi-project dashboard. Must be unique across ~/.fairway/registry.toml; multiple registry entries may share one repo path only when their names and DB/config identities differ.
db_pathstring.fairway/state.dbSQLite DB path. Relative to repo root unless absolute. Fairway opens SQLite with WAL mode and a bounded 5s busy timeout so short local write bursts can wait for the current writer instead of failing immediately with SQLITE_BUSY.
queue_sourcestringinlineinline (DB-only task definitions), yaml:<path> or json:<path> (active backlog definition for import/reconciliation; runtime execution state still lives in the DB).
main_branchstringmainBase branch new worktree branches are created from.
task_id_patternstring^[A-Z]+-[0-9]+$Regex enforced for task IDs. Compatibility fixtures may use a wider pattern for legacy IDs such as A-DEMO-UAT-001; standalone projects should choose the narrowest pattern that fits their versioned backlog.
local_artifact_paths[]string[]Optional repo-relative directories or files that may appear as untracked local evidence artifacts without making merge-ready, workflow check, or workflow closeout dirty. The dashboard evidence artifact viewer also uses this list as its allow-list: it only renders recorded evidence artifacts inside these roots, rejects traversal and symlink escapes, applies redaction before display truncation, and keeps raw path readback visible for local operators. Tracked source changes and arbitrary untracked files remain dirty.

[runtime]

KeyTypeDefaultDescription
profilestringstandardRuntime network boundary. sovereign-offline fails config loading when an active non-loopback dashboard/server listener, trusted-proxy identity edge, remote provider target, remote advisory adapter, webhook notifier, remote rule source, proxy environment variable, or Plane tracker environment dependency is present.

sovereign-offline permits numeric loopback HTTP endpoints and explicitly local surfaces such as SQLite, local files, local process boundaries, tmux, shell, local log notifiers, and disabled or dry-run remote definitions. Local model adapters must use an endpoint environment variable containing a numeric loopback http:// URL; hostnames are rejected so operation does not require DNS. Fairway loopback HTTP clients ignore proxy environment variables and reject redirects and non-loopback resolution. fairway doctor --format json and fairway readiness capabilities return the redacted dependency inventory.

This profile constrains Fairway-owned network and adapter surfaces. It does not sandbox arbitrary commands started by an operator or provide host firewalling; the disconnected rehearsal and customer deployment must still enforce OS or network-level egress denial. The profile adds no certification, approval, release, deploy, live-operation, or dashboard mutation authority.

[dashboard]

KeyTypeDefaultDescription
listenstring127.0.0.1:7878HTTP listen address. Bind to 127.0.0.1 unless you understand the auth implications.
auto_openbooltrueOpen the system browser when fairway dashboard starts.
read_onlyboolfalseDisable dashboard mutation endpoints and hide mutation controls. Use for shared dashboard views behind an identity-aware proxy.
trusted_proxystringnoneDeployment note for trusted proxy mode. Supported values: none, cloudflare_access, identity_aware_proxy. Fairway does not trust identity headers unless the origin is exclusively reachable through that proxy and JWT/header verification is handled. See Trusted Proxy Identity Verification for the planned verifier model.

Fairway has one dashboard. / serves the wall view, /board serves the operator board, /board?tab=diagnostics serves diagnostics, /reports serves retrospectives, and /tasks/<id> serves task detail. There is no dashboard version selector; [dashboard] surface is not part of the active config contract.

For shared read-only viewing, keep listen = "127.0.0.1:7878", set read_only = true, and expose the origin only through a trusted tunnel/proxy. See dashboard-sharing.md. For a single-host small-team lab with explicit binary, DB, pid, log, backup, restore, dashboard, and read-only API paths, use the small-team lab deployment runbook.

[server]

KeyTypeDefaultDescription
enabledboolfalseAdvisory switch for shared-team server configuration. When true, mode must be read_only or the FW-271 api-write-pilot.
listenstring127.0.0.1:7880HTTP listen address for fairway server --read-only or fairway server --mode api-write-pilot --write. Current server modes accept loopback binds only. Non-loopback addresses such as 0.0.0.0, LAN/private, Tailscale, or public interfaces fail closed until a reviewed deployment/public-exposure task authorizes them.
modestringdisabledSupported values are disabled, read_only/api-read-only, and api-write-pilot. The write pilot exposes evidence/checkpoint append endpoints plus FW-272 guarded status/review endpoints.
read_onlybooltrueMust be true for read-only mode and false for api-write-pilot. The dashboard remains read-only when the server write pilot is enabled.
write_enabledboolfalseMust be true with mode = "api-write-pilot" and false otherwise. It enables the FW-271 append-only evidence/checkpoint API pilot and FW-272 guarded status/review write pilot.
identity_modestringno_edge_localIdentity source for the shared API. Supported values are no_edge_local, trusted_proxy_read_only, api_token, service_account, mtls_service_account, and sovereign_signed. Service-account and mTLS modes remain fail-closed placeholders. sovereign_signed verifies customer-signed Ed25519 session proofs and is required for any active server under [runtime] profile = "sovereign-offline"; it has no anonymous, proxy-header, API-token, or identity fallback.
allowed_roles[]string["viewer"]Command-scoped roles accepted by the server guard. Supported role strings are viewer, operator, reviewer:<domain>, coordinator, adapter:<name>, and admin; the FW-270 read API authorizes only viewer and admin for read:api.
api_token_envstring""Environment variable containing the API token for identity_mode = "api_token". Raw token values must not be committed or recorded as evidence. Runtime proof uses bounded error responses and constant-time comparison for equal-length bearer values.
api_token_rolestringviewerRole assigned to accepted API-token requests. It must be a supported server role and must also appear in allowed_roles, so misconfigured token roles fail closed. Use viewer for the FW-270 read-only API. Use operator, coordinator, admin, or adapter:<name> for the FW-271 append-only write pilot. Use operator, coordinator, or admin for guarded status writes; use reviewer:<domain> or admin for guarded review writes.
trusted_proxy_verifiedboolfalseMust be true before trusted proxy headers can authorize read API requests. Without verified proof, proxy identity is advisory only.
trusted_proxy_identity_headerstringX-Fairway-UserHeader carrying proxy identity after proof verification. Error output does not echo raw header values.
trusted_proxy_proof_headerstringX-Fairway-Proxy-VerifiedHeader that must equal true for the FW-270 placeholder trusted proxy guard. This is not a JWT verifier; cryptographic verification remains future work.
trusted_proxy_issuerstring""Optional expected issuer for trusted proxy read-only mode.
trusted_proxy_issuer_headerstringX-Fairway-Proxy-IssuerHeader containing the issuer value checked against trusted_proxy_issuer.
trusted_proxy_audiencestring""Optional expected audience for trusted proxy read-only mode.
trusted_proxy_audience_headerstringX-Fairway-Proxy-AudienceHeader containing the audience value checked against trusted_proxy_audience.
sovereign_public_key_envstring""Environment variable containing the customer's base64-encoded 32-byte Ed25519 public verification key. The private key is never configured in Fairway. Active sovereign_signed mode fails config validation if this variable is absent or invalid.
sovereign_key_idstring""Exact customer key identifier required in the signed proof header. Key substitution fails closed. Rotation and overlap must be handled as an explicit customer change; this first profile accepts one active verification key.
sovereign_issuerstring""Exact issuer required in every signed proof.
sovereign_audiencestring""Exact audience required in every signed proof.
sovereign_revocation_filestring""Absolute path to a bounded private regular JSON file using schema fairway.sovereign-revocations.v1. It can revoke proof IDs, subjects, or key IDs and is read for every request. Missing, malformed, symlinked, group-readable, or world-readable state fails closed.
sovereign_session_max_secondsinteger900Maximum signed session lifetime, from 60 through 86400 seconds. Proofs also require bounded iat, nbf, and exp claims.
sovereign_clock_skew_secondsinteger30Allowed clock skew from 0 through 300 seconds. It does not extend the configured maximum session lifetime.
sovereign_break_glass_max_secondsinteger300Maximum break_glass proof lifetime, from 30 through 900 seconds and no longer than the normal session maximum. Break-glass requires an admin role and reason and does not bypass dual control or any deployment, release, credential, public-exposure, or live-operation boundary.
sovereign_dual_control_commandsstring array["set:status", "record:review"]Machine-readable consequential-command policy. Sovereign write mode requires both commands and an authorizer role. A distinct signed authorizer proof must be bound to command, task, canonical payload SHA-256, primary proof ID, and Idempotency-Key; exact replay returns the existing idempotent result and rebinding fails closed.

Sovereign cryptography boundaries

[[sovereign_crypto_boundaries]] records metadata and local evidence references for the five required names: in_transit, at_rest, backup, evidence_export, and signing. fairway readiness crypto reports and fails on missing boundaries or proof. The configuration stores no keys or secrets.

FieldValuesPurpose
nameone required boundary nameStable boundary identity. Duplicate or unknown names fail config validation.
ownercustomer, product, sharedAccountable control owner; this is not a transfer of certification or authorization responsibility.
custodianbounded metadata stringCustomer or platform key custodian reference.
key_referencebounded metadata referenceIdentifier such as a PKCS#11/HSM/TPM/OS-keystore reference. Never put key material, credentials, or tokens here.
algorithmbounded metadata stringExact configured algorithm or protection mechanism.
module_name, module_versionbounded metadata stringsExact cryptographic module and version used at this boundary.
module_assurancecustomer_approved, fips_140_3_validated, not_assessedfips_140_3_validated applies only to the named externally validated module/configuration and requires certificate/configuration proof. It never means Fairway itself is validated.
approval_evidencelocal file referenceCustomer approval or external module-assurance decision.
validation_certificate, validated_configurationlocal file referencesRequired only for fips_140_3_validated; must identify the exact certificate and approved configuration.
custody_evidence, rotation_evidence, recovery_evidencelocal file referencesRequired proof that key custody, rotation, loss/recovery, and responsible owner have been exercised or reviewed.

All evidence references must resolve to non-symlink regular files inside the project root. URLs, URNs, traversal, absent files, and symlinks remain gaps so a remote assertion cannot silently satisfy sovereign readiness.

fairway server --read-only serves a read-only JSON API skeleton at /api/v1/status, /api/v1/tasks, /api/v1/tasks/<task-id>, and /api/v1/reports/summary. It reuses the existing Fairway store and read models. It does not create a second store and does not add review approval, merge, deploy, provider-send, dashboard write, release, public exposure, or live-operation authority. Proxy/public/shared exposure requires FW-270 or a later reviewed identity/proxy/deployment task; FW-269 itself is loopback-only. FW-270 adds a read API identity and command-authorization guard. It does not make trusted proxy identity authoritative unless trusted_proxy_verified = true and the configured proof checks pass, and it still does not add any server write API. FW-271 adds the first write pilot only when [server] mode = "api-write-pilot" and write_enabled = true: POST /api/v1/tasks/<task-id>/evidence and POST /api/v1/tasks/<task-id>/checkpoints. FW-272 adds guarded POST /api/v1/tasks/<task-id>/status and POST /api/v1/tasks/<task-id>/reviews to the same pilot. All write endpoints require JSON, Idempotency-Key, API-token identity with a command-scoped role, project scope matching, unsafe private-data marker rejection, and audit/idempotency metadata. Status writes require expected_status and return a structured conflict when the task moved. Review writes require admin or a matching reviewer:<domain> role; reviewer-domain tokens cannot override the stored reviewer identity, while admin may explicitly record an override and the audit row still records the authenticated admin actor. They do not add dashboard writes, provider sends, merge/deploy/release/live-operation authority, raw prompt or transcript storage, raw tool body storage, arbitrary artifact upload, or generic SQL/row patching.

[worktrees]

KeyTypeDefaultDescription
rootstring../worktreesParent directory for per-role worktrees. Relative to repo root.
namingstring{repo}-{role}Worktree directory name template. {repo} is the basename of the primary checkout, {role} is the role name.
review_branch_namingstringreview/{role}Local branch template used by fairway review checkout.

[sessions]

KeyTypeDefaultDescription
default_backendstringshellDefault backend for optional fairway session launch. Core queue operations do not require launch adapters.
stale_afterduration12hSession reconciliation threshold for missing PID/backend sessions.

Provider runtime watchers do not need provider API configuration in Fairway core. Keep provider credentials, polling, and API-specific state outside the Fairway config; adapters should write generic session upsert, checkpoint record, record evidence, and record handoff events using provider labels such as codex, claude, gemini, or shell.

[[review_profiles]]

Review profiles define risk-scaled review policy. They are deterministic rules used by merge-ready, task-detail, review-waits, and coordinator plan output. They do not approve reviews, waive safety gates, or authorize live execution by themselves.

Profiles are evaluated in file order. The first matching profile can add required review domains, waive or defer domains for the current slice, inherit domains from an approved parent/group packet, and explain why extra reviewers improve risk control.

Fairway also provides built-in default profiles named prototype-first, reversible, irreversible, live-boundary, and release-boundary. These defaults cover the common small-team policy: uncertain reversible product/UX work can run as prototype-first, reversible non-live work is advisory and evidence-led, while irreversible, live, and release boundaries remain blocking. A configured [[review_profiles]] entry with the same name replaces the built-in default for that name.

For prototype-first work, use evidence artifact types prototype-artifact, owner-usage-proof, prototype-gap-list, and stabilization-decision to show the build-use-learn loop before stabilizing contracts or moving to a stricter profile.

Key fields:

KeyTypeDescription
namestringProfile name, such as micro-slice, grouped-slice, epic, launch, live-window, deploy, or production-readiness.
modestringadvisory or blocking. New process rules should usually start advisory with a stated hypothesis before becoming blocking defaults.
match_kinds, match_risk_levels, match_tags, match_authoring_domains, match_owning_domains, match_paths[]stringMatch task metadata and source/target paths. Empty lists do not restrict matching.
required_review_domains[]stringReview domains added by the profile. Task-level review_domains still apply unless waived or deferred.
inherit_from_parent, inherit_review_domainsbool, []stringAllow child domains to be covered by matching approved parent reviews.
waive_review_domains, defer_review_domains[]stringMark domains as waived for this slice or deferred to parent/epic/release review.
safe_iteration_zoneboolMarks approved non-live/disposable boundaries where setup, readback, harness, classifier, or provider-shape fixes can iterate with lightweight review.
safe_iteration_defect_class, safe_iteration_controlstringExplain the expected defect class and risk-control value for this profile.
extra_reviewer_rationalestringExplains why any extra reviewers reduce risk or cycle time.
process_hypothesisstringStates the speed, quality, or safety hypothesis for a new review/gate process pilot.
outcome_metrics[]stringNames outcomes to review in fairway review-policy report, such as defects_caught, rework_reduced, blocked_time, cycle_time, and avoided_unsafe_actions.
no_inheritance_kinds, no_inheritance_risk_levels, no_inheritance_tags, no_inheritance_paths[]stringTriggers that force direct review instead of inherited/grouped review. Use these for authority expansion, environment mutation, credentials, safety-gate weakening, live/deploy/public exposure, compliance, or enforcement boundaries.
group_reviewboolLets coordinator plan recommend grouped review for related ready tasks that match this profile.

[[provider_targets]]

Provider targets map review or work domains to notification destinations. They are routing metadata only. They do not store provider credentials and they do not grant review approval, task completion, merge, push, deploy, or release authority.

[[provider_targets]]
domain = "security"
provider = "codex"
type = "thread" # generic | thread | tmux | cli | webhook
target = "019e..."

[[provider_targets]]
domain = "ops"
provider = "tmux"
type = "tmux"
target = "ops:0.1"

Notification adapters may use these targets to send a provider-specific prompt or event, then record the result with fairway record notification. Fairway keeps the durable state machine separate: a delivered notification is only proof that the target was contacted, not proof that review happened.

type = "thread" is routing metadata unless a host-specific adapter or desktop thread tool is actually available and invoked. Recording a Fairway notification or handoff does not by itself send a prompt into an existing Codex Desktop thread. Agents must distinguish "Fairway handoff/notification recorded" from "thread steered" and should fall back to a manual relay block when the host does not expose a thread messaging tool. See agent-guide.md.

KeyTypeDefaultDescription
domainstringReview domain or target role, such as architecture, security, governance, backend, frontend, or ops.
providerstringProvider/adapter label, such as codex, claude, tmux, shell, or webhook.
typestringgenericDestination type: generic, thread, tmux, cli, or webhook.
targetstringProvider-local target id. Do not put secrets or bearer URLs here.

fairway advisory validate uses provider targets only to warn when a wake_provider recommendation is not routable. The warning does not grant send authority, dashboard mutation authority, review approval, merge, deploy, or live-operation permission.

Wake surfaces also use provider targets for static routability checks. Review wait wakes, generic wait wakes, completion-handback wakes, live-operation closeout wakes, and provider-session handoff wakes must have a configured target for the next owner/domain before Fairway can claim delivery. If the mapping is missing, dry-run output names mapping_required; --send records notification_failed evidence instead of silently parking the wait or claiming thread delivery.

[[advisory_provider_adapters]]

Advisory provider adapters declare optional recommendation sources for fairway advisory validate and future bounded coordinator surfaces. They are configuration metadata only. They do not store prompts, transcripts, raw tool bodies, provider-private data, auth tokens, cookies, or credentials; they also do not grant approval, review, wake, merge, deploy, release, or live-operation authority.

[[advisory_provider_adapters]]
name = "local-rules"
provider = "ollama"
type = "local_ollama"
mode = "advisory"
trust = "low"
model = "llama3.1"
endpoint_env = "FAIRWAY_OLLAMA_ENDPOINT"
capabilities = ["summarize_evidence", "rank_ready_tasks", "explain_code_narrative"]
allowed_actions = ["inspect_task", "render_packet", "wake_provider"]

Use fairway advisory adapters to inspect configured adapters. Disabled adapters are hidden by default; use --include-disabled for an operator audit. Use fairway advisory validate --provider <name> to validate a recommendation against the adapter's mode and allowed_actions. The validated recommendation may be recorded as advisory-recommendation evidence only; Fairway does not apply the recommendation automatically.

KeyTypeDefaultDescription
namestringStable adapter name used by --provider.
providerstringProvider label, such as ollama, codex, claude, or gemini.
typestringnoopAdapter type: noop, rules-only, local_ollama, local_llamacpp, openai-compatible, codex, claude, or gemini.
modestringadvisoryadvisory, report_only, or disabled. Disabled adapters cannot validate recommendations.
truststringlowTrust label: low, medium, or high. Low-trust output with risk flags must stay human-reviewed.
modelstringOptional model label for operator visibility.
endpoint_envstringOptional environment variable name for an endpoint URL. This is an env var name, not the endpoint value and not a credential.
capabilities[]stringTokenized advisory capabilities for reporting and review.
allowed_actions[]stringall bounded advisory actionsOptional subset of the advisory action enum accepted from this adapter.

explain code --narrative-provider <name> implements the first provider-backed advisory surface only for type = "local_ollama". The adapter must declare capabilities = ["explain_code_narrative"], allow render_packet, and name an endpoint_env whose runtime value is a loopback-only HTTP base URL. Fairway posts the already-redacted grounded packet to /api/generate; redirects, non-loopback endpoints, unsupported response schemas, unknown citations, privacy-rejected text, and responses over 64 KiB fail closed. The endpoint value and generated provider exchange are not persisted. Credentialed remote providers are not implemented by this slice.

[[external_notifiers]]

External notifiers declare optional notification sinks for operator-controlled notification workflows. noop notifiers remain dry-run only. log and webhook notifiers can be enabled for real delivery only with mode = "send". Destinations and credentials are read from environment variables at send time; Fairway records only the env var name or safe target label, never webhook URLs, tokens, arbitrary prompts, transcripts, or raw tool bodies. The dashboard never calls notifier send paths and does not gain send authority.

[[external_notifiers]]
name = "control-log"
type = "log"
mode = "dry_run"
target_env = "FAIRWAY_NOTIFY_LOG"
domains = ["coordinator", "ops"]
template_name = "control_room_handoff"

[[external_notifiers]]
name = "control-webhook"
type = "webhook"
mode = "send"
target_env = "FAIRWAY_NOTIFY_WEBHOOK_URL"
token_env = "FAIRWAY_NOTIFY_WEBHOOK_TOKEN"
domains = ["coordinator", "ops"]
template_name = "control_room_handoff"
rate_limit_per_minute = 30

Use fairway notify notifiers to inspect configured notifiers. Use fairway notify dry-run --notifier <name> --task <task-id> --domain <domain> to render a bounded notification request from the configured fixed template, or pass --template <name> to choose another fixed template label. With --record-intent, Fairway records a record notification row with state intent only. That is a durable coordination fact, not proof that an external system or provider thread was contacted. Fairway stores the template label in the notification reason, not arbitrary prompt text for later replay.

Use fairway notify send --notifier <name> --task <task-id> --domain <domain> only for explicitly configured mode = "send" notifiers. Send records a sent notification row before delivery and then records either notification_delivered or notification_failed. Webhook send uses HTTP POST with a fixed JSON body rendered from current task/domain/template metadata. If token_env is configured and set, the value is sent as a bearer token but is not printed or recorded. The optional --target value is only a safe display label and is restricted to letters, digits, dots, dashes, and underscores. Rate limiting is per notifier send attempt and degrades to notification_failed evidence instead of silent loss.

KeyTypeDefaultDescription
namestringStable notifier name used by fairway notify dry-run --notifier and fairway notify send --notifier.
typestringnoopNotifier type: noop, log, or webhook. noop cannot use mode = "send".
modestringdry_rundry_run, send, or disabled. Disabled notifiers fail closed.
target_envstringEnvironment variable name for the destination, such as a log path or webhook URL. Required for mode = "send". This is an env var name, not a secret or URL value.
token_envstringOptional environment variable name for a webhook bearer token. The value is used only at send time and is not recorded.
domains[]stringall domainsOptional allowed notification domains/roles.
template_namestringOptional fixed-template label for operator review.
rate_limit_per_minuteint30 for send modeMaximum sends per notifier per minute. 0 uses the send-mode default.

[[provider_model_prices]]

Provider model prices are advisory calculator inputs for fairway usage cost-report. They convert already-recorded provider usage counts into planning estimates. They do not configure provider credentials, do not poll provider APIs, and do not create budget, approval, merge, completion, or release gates.

Prices are expressed in dollars per million tokens. Use model = "*" for a provider default, provider = "*" for a model default, or both as a global fallback.

[[provider_model_prices]]
provider = "codex"
model = "gpt-5-codex"
input_per_million = 1.25
cached_input_per_million = 0.125
output_per_million = 10.0
reasoning_per_million = 10.0

[[provider_model_prices]]
provider = "codex"
model = "snapshot-only-model"
total_per_million = 2.0
KeyTypeDefaultDescription
providerstringProvider label matching record usage --provider, or * for a fallback.
modelstringModel label matching record usage --model, or * for a fallback.
input_per_millionfloatUncached input-token price. When cached tokens are known, Fairway charges input - cached here.
cached_input_per_millionfloatCached input-token price.
output_per_millionfloatOutput-token price.
reasoning_per_millionfloatReasoning-token price when providers report it separately.
total_per_millionfloatFallback total-token price for records that only have total_tokens or derived snapshots.

Each row must include provider, model, and at least one non-negative price field. Missing token counts or missing matching prices stay unknown in cost reports rather than being treated as zero.

[coordinator]

KeyTypeDefaultDescription
max_primary_tracksint1Advisory limit for active primary work in fairway coordinator preflight.
max_sidecar_tracksint1Advisory limit for active side tracks/checkpoints.
max_review_tracksint1Advisory limit for active review/verification tracks.
checkpoint_stale_afterduration24hCheckpoints older than this are stale unless the checkpoint state is awaiting_input, done, parked, or abandoned.
notification_ack_timeoutduration24hHow long a sent provider/thread notification may wait without acknowledgement, review_recorded, or a real matching review before coordinator plan escalates it as stale-sent.

[consumer_readiness]

Optional, non-mutating requirements consumed by fairway readiness capabilities.

KeyTypeDefaultDescription
minimum_versionversionMinimum invoked and pinned Fairway version in MAJOR.MINOR.PATCH form.
minimum_schema_versionint0Minimum applied SQLite migration version. The report also names the latest schema supported by the invoked binary.
pinned_binary_pathpathOptional consumer-selected binary whose fairway version readback is reported; relative paths resolve from the project root.
required_capabilities[]stringNamed Fairway bundles such as managed-binary-cache, task-decision-memory, track-memory-lifecycle, work-common-path, or wait-hygiene.
required_commands[]stringExact command paths required by the consumer, for example binary status.
required_features[]stringExact feature tokens required by the consumer, for example managed_binary_cache.

The report is advisory/readiness-only but returns non-zero when configured requirements are missing. It never downloads, installs, upgrades, migrates, restarts, or mutates task/dashboard/server state. A pinned path is explicit trusted local operator input; Fairway executes only its version subcommand and does not store output beyond the bounded version readback.

[[roles]]

KeyTypeDefaultDescription
namestringRole identifier. Must be unique. Referenced by task role and handoffs.
branchstringagent/<name>Long-lived branch for this role.
providerstringInformational tag (e.g. claude, codex, gemini). Not enforced.

[[review_routes]]

Ordered list. The first matching glob wins.

KeyTypeDefaultDescription
matchstringGlob matched against paths touched in the task's commits.
reviewerstringRole name to route the review to. Must match a configured role.

[review_domain_aliases]

Maps a review domain that has no same-named role to one configured reviewer role. For example, security = "arch" makes the security domain routable through the arch lane while preserving security as the required review domain in task and review records. Alias targets must be configured roles; self-aliases, empty targets, and alias-to-alias chains fail validation.

Aliases are routing metadata only. They do not let the mapped role self-approve, waive the original domain, or create a review verdict. Use fairway route review-preflight to distinguish exact roles, configured aliases, review-route patterns, explicit provider targets, and missing mappings before a task enters review wait.

[[workstream_profiles]]

Named coordination profiles for architecture-aware work. These are advisory configuration today: validation accepts them, fairway adoption artifact uses route_samples, reports named profile gates, and evaluates those gates against matching task evidence rows. Future dashboard/packet work can consume the same metadata without changing the file shape.

KeyTypeDefaultDescription
namestringStable profile name, for example platform-foundation, release-readiness, or sdk-readiness. Must be unique.
task_kinds[]stringTask kinds associated with this profile. If [task_kinds].allowed is configured, every profile kind must appear there.
dashboard_groups[]stringHuman-facing groups a dashboard can use to cluster tasks for this profile.
rule_groups[]stringRule groups bound to this profile, using <rule-source-name>.<rules-subdirectory> names such as fairway-platform.core.
tag_groups[]tableOptional recommended tag display groups for dashboards/reports. These are advisory; task tags remain generic task metadata.
review_domains[]stringReview domains that may be required for readiness, distinct from first-match assignment routes.
route_samples[]stringPaths sampled by fairway adoption artifact when no --route flags are provided.

[[workstream_profiles.tag_groups]]

Recommended tag groups under the preceding profile. They document common cross-cutting tags without making those tags core Fairway grammar.

KeyTypeDefaultDescription
namestringHuman-facing group name, for example release environments or security programs. Must be unique within the profile.
tags[]stringRecommended tags in display order. Supports simple and key:value tags.
descriptionstringOptional explanation for operators and profile authors.

[[workstream_profiles.gates]]

Named readiness gates under the preceding profile.

KeyTypeDefaultDescription
namestringGate name, for example security-review, uat-evidence, release-risk, or sdk-readiness. Must be unique within the profile.
groupstringderived from task kind or evidence typeOptional dashboard/report grouping label, for example boundary guards, release evidence, security gates, or SDK readiness. Use it when a profile has many gates and the default gate-by-gate view would be noisy.
modestringadvisory, blocking, or report_only. Missing blocking gates fail merge-ready; missing advisory and report_only gates are warnings.
task_kinds[]stringOptional task-kind filter for this gate. Omit to apply the gate to every task kind in the profile.
evidence_typestringOptional evidence type this gate expects.
required_evidence_countint0Minimum count expected for this evidence type in adoption gate evaluation. If omitted but other evidence requirements are present, evaluation treats the gate as needing at least one matching row.
accepted_results[]stringAccepted task_evidence.result values: pass, fail, partial, skipped, or blocked. Rows with other results do not count.
artifact_requiredboolfalseWhether each counted evidence row must include an artifact path or URL.
owner_signoff_requiredboolfalseWhether each counted evidence row's notes must contain signoff or sign-off.
expires_afterdurationDuration after which an evidence row is considered stale and no longer counted, for example 720h.
descriptionstringOptional human-readable description.

[[packet_templates]]

Declarative packet template metadata. fairway packet template <name> <task-id> validates required fields and renders a packet with task detail, evidence, and review context. The current built-in packet commands still render their specific packet shapes, but templates let projects add profile-specific packets without Fairway code changes.

For deploy handoffs, use a reusable template such as environment-deploy-preflight; see environment-deploy-preflight.md for the recommended fields, evidence types, and readiness gates.

KeyTypeDefaultDescription
profiles[]stringOptional list of workstream profile names this packet template belongs to. If profiles are configured, references must match a configured profile.
namestringPacket template name. Must be unique.
required_fields[]stringRequired field names for template validation/rendering.
optional_fields[]stringOptional field names. A field cannot appear in both required and optional lists.

Render a configured template with repeated --field key=value arguments:

fairway packet template architecture-map T-010 \
--field scope="route ownership" \
--field current_owner=mixed \
--field target_owner=D-arch \
--field migration_risk="route moves can hide auth regressions" \
--field acceptance="owners and review routes are explicit"

[[rule_sources]]

Rule sources configure reusable operating rule packs. They are documented in Rule packs. The first implementation is local-first: enabled sources must use path: or file:.

The examples below show possible shapes, not automatic adoption. A source is live only when the active project config points at a local path that exists and the project has completed the adoption checklist in Rule packs. Keep optional or future remote sources disabled until fetch/cache policy exists.

[[rule_sources]]
name = "fairway-platform"
source = "path:../fairway-rules-platform"
mode = "advisory"

[[rule_sources]]
name = "service-platform"
source = "path:../fairway-rules-service-platform"
mode = "disabled" # enable only after local path and vocabulary validation

[[rule_sources]]
name = "codeguard"
source = "github:fairway-run/fairway-rules-codeguard"
mode = "disabled"
commit_sha = "0123456789abcdef0123456789abcdef01234567"
checksum = "sha256:..."
KeyTypeDefaultDescription
namestringUnique source name. Group names are derived from this value plus the pack rules/ subdirectory.
sourcestringSource reference. Initial enabled support is local path: or file: only. Remote schemes are represented but not fetched.
modestringadvisoryadvisory, blocking, or disabled.
commit_shastringFuture immutable remote pin metadata. Required for represented github: sources.
checksumstringFuture remote content checksum metadata. Required for represented github: sources.

Modes:

  • advisory: recommend rules and evidence without blocking closeout.
  • blocking: missing required evidence blocks configured readiness checks.
  • disabled: keep the source configured but do not evaluate it.

Missing or unreadable local sources are mode-sensitive. Advisory sources become error-severity load findings in rule CLI JSON/human output while other valid sources still load. Blocking sources fail closed and stop the command.

Remote github: sources must remain disabled until safe fetch/cache support lands. They must include both commit_sha and checksum so mutable branch/tag references do not become blocking authority by accident.

[states]

KeyTypeDefaultDescription
allowed[]string["todo","in_progress","blocked","done"]All states tasks may occupy.
terminal[]string["done"]Subset of allowed considered terminal. Tasks in terminal states do not move without --reopen.
transitions[][2]stringOptional whitelist of allowed transitions. ["*", "x"] means any state may transition to x. Omit for permissive mode.

[gates]

KeyTypeDefaultDescription
require_evidence_before_doneboolfalseIf true, a task cannot transition to a terminal state without at least one task_evidence row.
require_review_before_doneboolfalseIf true, a task cannot transition to a terminal state without at least one task_reviews row with verdict = "approve".
require_handoff_before_merge_readyboolfalseIf true, fairway merge-ready requires at least one handoff row. Useful for coordinated PR handoff workflows.
require_blocked_reasonbooltrueIf true, transitions into blocked require --reason so timing and health reports can explain the blocker.
allow_force_without_reasonboolfalseIf false, forced transitions still require a reason so overrides remain auditable.

[task_kinds]

KeyTypeDefaultDescription
allowed[]stringOptional whitelist for task_definitions.kind. Omit for free-text.
defaultstringtaskKind assigned when fairway add or fairway spawn omits --kind.

See docs/design/hierarchy.md for the hierarchy model and the fairway spawn command.

[task_priorities]

KeyTypeDefaultDescription
defaultintPriority assigned when fairway add / fairway spawn omits --priority.
levels[]{rank,label,description?}Optional label table. The stored value is always the integer rank; labels are display-time only. Omit [task_priorities] entirely to leave priority as a free integer with no labels.

Lower rank is more urgent. Priority is cross-cutting — it overrides epic boundaries in fairway ready and dashboard backlog sort.

Task metadata

Tasks may carry profile-aware metadata in YAML/JSON imports and through fairway add, fairway spawn, and fairway update flags:

Field / flagTypeDescription
profile / --profilestringWorkstream profile name. Validated when [[workstream_profiles]] exists.
owning_domain / --owning-domainstringArchitecture or product domain that owns the task.
owning_layer / --owning-layerstringLayer such as api, service, frontend, guard, or release.
source_paths / --source-paths[]string / CSVCurrent paths, inputs, or surfaces affected by the task.
target_paths / --target-paths[]string / CSVTarget paths, outputs, or artifacts expected from the task.
review_domains / --review-domains[]string / CSVReview domains expected for the task.
tags / --tag[]string / CSVGeneric cross-cutting tags. Supports simple tags and key:value tags such as environment:staging.
risk_level / --risk-levelstringLightweight risk label. Fairway does not hardcode allowed values.
migration_type / --migration-typestringShape of the work, such as facade, boundary-guard, or ownership-map.

This metadata is intentionally generic. It powers architecture-aware coordination without making Fairway specific to any one consumer repository. It also drives fairway audit work-coverage: changed files are matched against task source_paths and target_paths, and done tasks with review_domains are checked for matching approved review rows.

[[control_effectiveness.path_exclusions]]

Control-effectiveness path exclusions are reviewed, versioned project configuration. Each entry requires a project-relative pattern, a category of generated or high_churn, and a single-line rationale. The work-coverage report exposes every active exclusion and reports observed, eligible, covered, and excluded denominators. Exclusions are not accepted as command-line report arguments, so a caller cannot silently remove unfavorable files from a cohort.

The optional [control_effectiveness] table also configures the advisory classification boundary:

[control_effectiveness]
revision = "2026-08-02"
minimum_sample_size = 5
minimum_coverage_ratio = 0.8
material_outcome_delta = 0.1
high_friction_p90_seconds = 900
mandatory_control_ids = ["review:security"]
KeyTypeDefaultMeaning
revisionstringunversioned in report outputHuman-reviewed configuration revision retained with every report.
minimum_sample_sizeint5Minimum mature, outcome-known tasks required independently in both the observed and bypassed cohorts of one profile/risk/size/horizon stratum.
minimum_coverage_ratiofloat0.8Minimum known observed-or-explicitly-bypassed control states among applicable tasks.
material_outcome_deltafloat0.1Minimum lower observed outcome rate required for discriminating.
high_friction_p90_secondsint900Attributable evidence-duration p90 used for high_friction; unavailable duration is never treated as zero.
mandatory_control_ids[]string[]Reviewed controls that analytics must classify as mandatory_invariant regardless of sparse outcomes.

Fairway includes the normalized table digest in fairway control report, so results from different revisions are not silently combined. Zero-valued thresholds use the defaults above. Stable discovered control IDs currently use review:<domain> and gate:<profile>:<gate-name>.

Validation

fairway init writes a default config. fairway config validate checks an existing one. Errors are reported with file path and line number.

fairway init defaults

fairway init writes the concrete defaults shown above, not a commented sample. The initial config has permissive completion gates but requires a reason when a task enters blocked:

  • task_id_pattern = "^[A-Z]+-[0-9]+$"
  • require_evidence_before_done = false
  • require_review_before_done = false
  • require_handoff_before_merge_ready = false
  • require_blocked_reason = true
  • allow_force_without_reason = false

This keeps first-run friction low while ensuring blocked work is explainable.