Imported from gaelic-ghost/TextForSpeech (
AGENTS.md). Install upstream withnpx skills add gaelic-ghost/TextForSpeech. Copyright stays with the author.
AGENTS.md
Use this file for durable repo-local guidance that Codex should follow before changing code, docs, or project workflow surfaces in this Swift Package Manager repository.
Repository Scope
What This File Covers
This root guidance covers the retired TextForSpeech Swift package, its frozen public API, normalization model, runtime profile persistence, tests, maintainer docs, and repo-owned maintenance scripts.
TextForSpeech is a plain Swift Package Manager repository. Treat Package.swift as the source of truth for package structure, products, targets, platforms, and language mode.
Where To Look First
- Start with
Package.swiftfor package structure, platform floors, products, targets, and Swift language mode. - Read
Sources/TextForSpeech/API,Sources/TextForSpeech/Models,Sources/TextForSpeech/Normalization, andSources/TextForSpeech/Runtimeaccording to the surface being changed. - Use
Tests/TextForSpeechTestsfor nearby behavior coverage when normalization or runtime behavior changes. - Keep
README.md,ROADMAP.md, anddocs/maintainers/aligned with public API, runtime model, ownership boundaries, and source layout changes. - Keep release notes under
docs/releases/factual, scoped to the tagged change, and explicit about behavior or API shifts.
Working Rules
Change Scope
- Treat
v0.23.0as the final standalone release and preserve this repository as historical source and migration reference. - Treat
SpeakSwiftlyv12.0.0and newer as the active source of truth for speech-safe normalization, summarization, text profiles, and persistence. - Do not add standalone features, public API, compatibility shims, dependencies, or releases here. Limit future changes to retirement guidance or an explicitly requested critical correction for pinned legacy consumers.
- Preserve the frozen namespace-first public surface centered on
TextForSpeech.NormalizeandTextForSpeech.Runtimefor historical reference. - Prefer complete cleanup passes over incremental compatibility layers. Do not leave legacy shims, duplicate codepaths, or transitional wrappers behind unless Gale explicitly approves that compromise.
- Keep source files role-focused and avoid letting catch-all files grow back.
- If a file starts collecting unrelated responsibilities, split it by role before adding more behavior.
Source of Truth
- Keep structural parsing, routing, markdown handling, format detection, and normalization pipeline control in
Sources/TextForSpeech/Normalization. - Keep durable built-in lexical policy in the built-in profile layers and related model definitions under
Sources/TextForSpeech/Models. - Keep stored-profile ownership, active-profile identity, persistence, and runtime state repair in
Sources/TextForSpeech/Runtime. - Keep parsing helpers in normalization only when they materially support the production normalization pipeline. Do not reintroduce a separate forensic surface unless the package regains a real analysis use case that earns its own API.
- Prefer explicit, stable, source-of-truth naming across models, runtime state, and public APIs when the meaning has not changed.
Communication and Escalation
- Before adding a new abstraction, wrapper, helper type, dependency, DTO layer, domain conversion layer, coordinator type, or protocol surface, confirm that it removes a real maintenance or modeling problem in this package.
- If scope needs to widen beyond the requested normalization, runtime, docs, or maintenance surface, say so before editing.
- If Apple or SwiftPM documentation and current repo guidance disagree, stop and surface the conflict before continuing.
- Keep operator-facing errors, warnings, and log messages concrete, descriptive, and human-readable.
Commands
Setup
No special bootstrap command is required for normal local package work beyond having a Swift 6.2-capable toolchain available.
Use Swift Package Manager from the repository root:
swift package describe
Validation
Run SwiftPM validation serially from the repository root:
swift build
swift test
Run repo-maintenance validation when retirement guidance, tooling, or maintainer workflow files change:
sh scripts/repo-maintenance/validate-all.sh
Optional Project Commands
The repo-owned sync entrypoint remains available for maintenance guidance. The release entrypoint is historical and must not be run for this frozen package:
sh scripts/repo-maintenance/sync-shared.sh
Use swift package subcommands for structural package work when they cover the change. Keep manual Package.swift edits minimal and intentional when the CLI does not cover the needed configuration.
Review and Delivery
Review Expectations
- Use Swift Testing (
import Testing) as the default test framework. Do not introduce XCTest unless an external constraint requires it. - When touching normalization or runtime behavior, add or update focused tests in
Tests/TextForSpeechTestsin the same pass. - Keep formatting and linting choices consistent with the existing repository direction. If formatter or linter config is added or changed, prefer clear maintainable rule intent over style churn.
- Preserve checklist-style structure in
ROADMAP.md.
Definition of Done
Work is not done until the relevant docs and maintainer guidance agree that the package is retired and frozen.
For an explicitly requested critical legacy package correction, run swift build and swift test. For retirement guidance or maintenance-tooling changes, run sh scripts/repo-maintenance/validate-all.sh.
Safety Boundaries
Never Do
- Never run multiple SwiftPM or Xcode build or test commands concurrently.
- Never hand-edit
Package.resolvedor other package-manager generated outputs. - Never introduce machine-local dependency declarations, lockfile entries, scripts, docs, examples, generated project files, or CI config that point at
/Users/...,~/...,../..., local worktrees, or private checkout paths. - Never reintroduce a separate forensic surface unless the package regains a real analysis use case that earns its own API.
- Never leave legacy compatibility shims, stringly typed fallback surfaces, transitional wrappers, or duplicate codepaths behind after cleanup unless Gale explicitly approves that compromise.
Ask Before
- Ask before changing the frozen public API shape, runtime persistence format, or built-in profile semantics. Do not change release behavior or create another standalone release without a new explicit decision from Gale.
- Ask before widening a narrow normalization fix into an architectural pivot.
- Ask before using
xcodebuild; prefer SwiftPM unless the task truly depends on Apple SDK or Xcode-managed behavior that SwiftPM alone does not cover.
Local Overrides
There are no nested AGENTS.md files in this repository today. If a deeper guidance file is added later, that closer file refines this root guidance for work inside its subtree.
Swift Package Workflow
- Use
swift buildandswift testas the default first-pass validation commands for this package. - Use
bootstrap-swift-packagewhen a new Swift package repo still needs to be created from scratch. - Use
sync-swift-package-guidancewhen the repo guidance for this package drifts and needs to be refreshed or merged forward. - Re-run
sync-swift-package-guidanceafter substantial package-workflow or plugin updates so local guidance stays aligned. - Use
swift-package-build-run-workflowfor manifest, dependency, plugin, resource, Metal-distribution, build, and run work whenPackage.swiftis the source of truth. - Use
swift-package-testing-workflowfor Swift Testing, XCTest holdouts,.xctestplan, fixtures, and package test diagnosis. - Use
scripts/repo-maintenance/validate-all.shfor local maintainer validation andscripts/repo-maintenance/sync-shared.shfor repo-local sync steps. - Do not run
scripts/repo-maintenance/release.sh;v0.23.0is the final standalone release. A future release requires a new explicit decision from Gale that reverses the retirement policy first. - Treat
scripts/repo-maintenance/config/profile.envas the installedmaintain-project-repoprofile marker, and keep it on theswift-packageprofile for plain package repos. - Read relevant SwiftPM, Swift, and Apple documentation before proposing package-structure, dependency, manifest, concurrency, or architecture changes.
- Prefer Dash or local Swift docs first, then official Swift or Apple docs when local docs are insufficient.
- When SwiftPM behavior, manifest syntax, package plugins, resources, products, targets, or dependency rules matter, prefer the Dash.app docset workflow with the
swiftlang/swift-package-managerdocset first; fall back to the canonicalswiftlang/swift-package-managerGitHub repository only when the local docset is unavailable or insufficient. - Prefer the simplest correct Swift that is easiest to read and reason about.
- Prefer synthesized and framework-provided behavior over extra wrappers and boilerplate.
- For public Swift APIs, treat streamlined, compact, ergonomic call sites as the only acceptable default; prefer optional parameters with explicit default values over additional methods or overloads when the difference is optional behavior on the same operation.
- When a public function, initializer, or method reaches four or more arguments or parameters, strongly prefer a named typed
structrequest, options, or configuration value so call sites stay readable and future additions do not multiply overloads. - Prefer enums, enum cases with associated values, and narrow typed values over strings, booleans, sentinel values, or parallel parameters whenever the domain has a closed or meaningful set of choices.
- Keep data flow straight and dependency direction unidirectional.
- Treat
Package.swiftas the source of truth for package structure, targets, products, and dependencies. - Prefer
swift packagesubcommands for structural package edits before manually editingPackage.swift. - Edit
Package.swiftintentionally and keep it readable; agents may modify it when package structure, targets, products, or dependencies need to change, and should try to keep package graph updates consolidated in one change when possible. - Keep
Package.swiftexplicit about its package-wide Swift language mode. On current Swift 6-era manifests, preferswiftLanguageModes: [.v6]as the default declaration, treatswiftLanguageVersionsas a legacy alias used only when an older manifest surface requires it, and keep the supported Swift toolchain window focused on the latest minor and previous minor. As of this guidance, that window is Swift6.3.xand6.2.x; do not lower// swift-tools-version:below6.2without an explicit repo policy and a matching guidance update. - Keep
swift-configurationas the default configuration dependency for Swift packages unless the package has a concrete reason to remove it. The preferred manifest shape depends onhttps://github.com/apple/swift-configurationfrom1.2.0, enables the.defaults,Reloading,YAML, andCommandLineArgumentspackage traits, and adds theConfigurationproduct to the primary target. Add thePropertyListtrait when the package should parse property-list configuration, and add theLoggingtrait when configuration access should integrate withSwiftLog.Logger. - Keep dependency provenance concise but explicit enough for another contributor to fetch the same package: use package-manager, package-registry, GitHub URL, or other real remote repository requirements, and do not commit machine-local dependency paths such as
/Users/...,~/...,../..., local worktrees, or private checkout paths. Avoid branch- or revision-based requirements unless the user explicitly asks for that level of control. - Treat
Package.resolvedand similar package-manager outputs as generated files; do not hand-edit them. - Prefer Swift Testing by default unless an external constraint requires XCTest.
- Use
apple-ui-accessibility-workflowwhen the package work crosses into SwiftUI accessibility semantics, Apple UI accessibility review, or UIKit/AppKit accessibility bridge behavior. - Keep package resources under the owning target tree, declare them intentionally with
Resource.process(...),Resource.copy(...),Resource.embedInCode(...), and load them throughBundle.module. - Keep test fixtures as test-target resources instead of relying on the working directory.
- Bundle precompiled Metal artifacts such as
.metallibfiles as explicit resources when they ship with the package, and preferxcode-build-run-workflowwhen shader compilation or Apple-managed Metal toolchain behavior matters. - Prefer normal SwiftPM parallel test execution for ordinary Swift Testing and XCTest runs. Do not serialize regular package tests just because they use Swift, XCTest, async tests, fixtures, or test plans.
- Treat tests that load large local AI or ML models, especially models over 500 million parameters, as heavy system-resource tests. Run those tests sequentially, one at a time, and call
unload_modelson Gale's live TTS service before the heavy run andreload_modelsafter it ends, even when the run fails or is interrupted. - Validate both Debug and Release paths when optimization or packaging differences matter, and treat tagged releases as a cue to verify the Release artifact path before publishing.
- Prefer
xcode-build-run-workfloworxcode-testing-workflowonly when package work needs Xcode-managed SDK, toolchain, or test behavior. - Keep runtime UI accessibility verification and XCUITest follow-through in
xcode-testing-workflowrather than treating package-side testing as a substitute for live UI verification.