Skip to content
Draft
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
123 commits
Select commit Hold shift + click to select a range
4e4f88e
plans
senigami Apr 8, 2026
60abd15
refine plans
senigami Apr 8, 2026
8257648
focused plans
senigami Apr 8, 2026
a15426c
adding missing items
senigami Apr 8, 2026
fc62bdd
updated structure and implementation plans
senigami Apr 8, 2026
c51a753
Fix: Track total render groups on queue resume so percentage reflects…
senigami Apr 8, 2026
24664ea
breakout plan into stages
senigami Apr 8, 2026
9abb8e8
phase 0
senigami Apr 8, 2026
1944a01
Studio2/phase 1 (#89)
senigami Apr 8, 2026
48e7041
Studio2/phase 2: domain contracts (#91)
senigami Apr 9, 2026
bb5de4e
Phase 3: Voice Interface, Preview/Test Flows, and Bridge Integration …
senigami Apr 9, 2026
912b587
Studio2/phase 4 (#100)
senigami Apr 14, 2026
4db3432
Add Studio 2.0 orchestration, progress, and domain service foundation…
senigami Apr 14, 2026
14f42d5
Studio2/phase 6: frontend foundations, queue hydration, and visible n…
senigami Apr 21, 2026
f7c8360
Studio2/phase 7 (#104)
senigami Apr 24, 2026
be76b50
Studio2/phase 8 (#105)
senigami Apr 25, 2026
838a19f
Studio2/phase 9.1 (#107)
senigami Apr 27, 2026
c82eb47
Studio2/phase 10 (#108)
senigami Apr 30, 2026
b426256
Merge branch 'main' into studio-2.0
senigami Apr 30, 2026
bb2bb02
Studio2/phase 11 (#114)
senigami May 14, 2026
d2b64ac
Studio2/Phase 12: Polish And Cleanup (#118)
senigami Jun 5, 2026
f20f8bd
docs: Studio 2.0 Handbook — outline + navigable static scaffold (#121)
senigami Jun 5, 2026
fdf0b04
Add CLAUDE.md documenting Studio 2.0 architecture and workflows (#119)
senigami Jun 5, 2026
07add60
Studio2/phase 12.2 polish and cleanup (#123)
senigami Jun 11, 2026
1e475d5
Studio2/phase 12.3 polish and cleanup (#124)
senigami Jun 12, 2026
2bed61c
Studio 2: Phase 12.4 polish and cleanup (#125)
senigami Jun 20, 2026
b87e189
Studio 2.0 Phase 12.5 — Quiet Studio redesign + foundation cleanup (#…
senigami Jul 11, 2026
86e8409
Studio2/phase 12.6 fix up (#127)
senigami Jul 11, 2026
2603421
Phase 12.7: North Star Screen Parity, bookmark theming fix, and plugi…
senigami Jul 16, 2026
85252cd
Security hardening, correctness fixes, and dead-code cleanup (fable a…
senigami Jul 16, 2026
6043b82
final prs
senigami Jul 16, 2026
4ee9fdb
Fix ReDoS in demo token parser (CodeQL js/redos #806) (#130)
senigami Jul 17, 2026
6227a6f
Reconcile North Star demo to the shipping app (PR09 demo parity) (#135)
senigami Jul 17, 2026
8e2d27d
W-PERF: safe foundation only (Workloads 1-3) (#136)
senigami Jul 17, 2026
6a81d1b
StatusOrb: distinct preparing tier + live segment arc (#133)
senigami Jul 17, 2026
7bd3f14
TTS gateway API: verify, fix queued-download flow, add POC (#134)
senigami Jul 17, 2026
d469dea
Add chapter sample video export (real MP4) (#132)
senigami Jul 17, 2026
f2d4a7c
P5 Sub-task B: rename --accent to --action-primary at all call sites …
senigami Jul 17, 2026
eeb17d8
Close out simplification-005: split plugin_loader, document PL-6, rem…
senigami Jul 17, 2026
b78f643
Fix pre-existing red CI on studio-2.0 (backend collection + hardcoded…
senigami Jul 17, 2026
324f4b1
Backend namespace rename: plugins/ -> tts_engines/ (006) (#139)
senigami Jul 17, 2026
6bf6c23
010: Repo-ready plugin folders + real studio_plugin_sdk package (#140)
senigami Jul 17, 2026
4bff914
Merge branch 'studio-2.0' of https://github.com/senigami/audiobook-st…
senigami Jul 17, 2026
ffa8cc8
docs: close DC-1b as will-not-delete after re-verification (#141)
senigami Jul 17, 2026
740b3c0
Fix XTTS permanently gated needs_setup (BUG 1) (#142)
senigami Jul 17, 2026
744d3d3
Fix stale XTTS app-adapter health check and dead-end Install Deps cop…
senigami Jul 17, 2026
d4a3989
Fix API gateway voice-profile resolution in ApiSynthesisTask (#144)
senigami Jul 17, 2026
0c56bc2
Word-boundary snapping for sub-sentence speaker assignment (#143)
senigami Jul 17, 2026
17dccf4
Expand recording cue & persona samples: mad-lib composer, 103-charact…
senigami Jul 17, 2026
4bff01d
Add funding options (GitHub Sponsors, Ko-fi, Buy Me a Coffee) (#147)
senigami Jul 17, 2026
ebf484b
Add synced player-piano reader with chapter timing sidecar (#148)
senigami Jul 17, 2026
58b7bec
Add memory-queue mechanism for worktrees, fix worktree.baseRef defaul…
senigami Jul 18, 2026
f2274e4
Consolidate code-map queue backlog, backfill flow schema fields (#149)
senigami Jul 18, 2026
3ddf5be
Grant orchestrator identity & director mandate; add session-closeout …
senigami Jul 18, 2026
2164dd3
Expand mandate: push and PR-open/draft-vs-ready are now do-then-report
senigami Jul 18, 2026
44f050b
Hire runtime-verifier; add reciprocal Team Boundaries to the roster (…
senigami Jul 18, 2026
9d88736
Record naming-ceremony results: Ledger (engineer), Floor (designer)
senigami Jul 18, 2026
55c8c5d
Correct designer's self-chosen name: Floor was quoted, not built
senigami Jul 18, 2026
c30a8c9
docs: catch up wiki and changelog to shipped Studio 2.0 work (#152)
senigami Jul 18, 2026
2dd721a
docs: consolidate and clean up design-docs/plans for release (#153)
senigami Jul 18, 2026
b5cdb90
Clean up leftover plugins/ cruft from the tts_engines rename (#155)
senigami Jul 18, 2026
2d46bdd
Record Plumb naming, document model-inherit, fix designer boundary in…
senigami Jul 18, 2026
aee5085
docs: sync master_fix_plan status banners with REMAINING_TASKS/COMPLE…
senigami Jul 18, 2026
8dff499
chore: reorganize repo structure — public docs vs internal docs vs hi…
senigami Jul 18, 2026
28f41d1
docs: consolidate muddied plan/workflow docs (#158)
senigami Jul 19, 2026
6ed0e9c
docs: add plain-language operator's manual for the owner (#159)
senigami Jul 19, 2026
afe3e1d
agents: add Fable-reviewable candidate pool (nameless primers) (#160)
senigami Jul 19, 2026
2d476ed
agents: add reasoning-analyst candidate (Opus/max, twin-converge) (#161)
senigami Jul 19, 2026
c55a6ad
agents: record Fable priming output; clarify Fable-approval rule (#162)
senigami Jul 19, 2026
d2176c3
agents: hire the reasoning twins (Constance & Petra) + calibration sc…
senigami Jul 19, 2026
ca8aae6
calibration: Phase-1 Fable references + findings + plan-review method…
senigami Jul 19, 2026
984bc07
calibration: RC-1 plan + Phase-3 twins-vs-Fable review comparison (#165)
senigami Jul 19, 2026
556c44e
calibration: RC-1 plan v2, round-2 twin review, and corrections (#166)
senigami Jul 19, 2026
d05253a
calibration: complete Phase 3 for all 6 scenarios (#167)
senigami Jul 19, 2026
6046a9b
calibration: second scenario round -- remaining 6 menu candidates (#168)
senigami Jul 19, 2026
1c4851b
feat: RC-1 Task 1 (align_segments) + Phase 4 code-review comparison (…
senigami Jul 19, 2026
a3986be
feat: RC-1 Task 4 (wire sync_chapter_segments) + review-gap fixes (#170)
senigami Jul 19, 2026
a9581f5
feat: RC-1 Tasks 5+6 (wire preview, surface loss count) + review-gap …
senigami Jul 19, 2026
f091013
docs: update RC-1 plan roadmap with real completion status (#172)
senigami Jul 19, 2026
70f6d96
docs: add Adversarial-Execution Gate to the code-review checklist (#173)
senigami Jul 19, 2026
4448e0b
orchestration: bias-neutral roster renaming + partnership mandate (ne…
senigami Jul 30, 2026
6484a18
orchestration: retrofit the layer onto a decision log, shared doctrin…
senigami Jul 30, 2026
4c36920
docs: record the 2026-07-29 branch reconciliation (#177)
senigami Jul 30, 2026
b620f82
docs: merge authority stays with the owner (OD-0020); record the unfi…
senigami Aug 4, 2026
aa43987
Upgrade orchestration layer to skill-arsenal's current conventions
senigami Aug 12, 2026
87e2b94
Rename agent roster to Harry Potter characters (OD-0028) (#186)
senigami Aug 16, 2026
b6d5953
code-map: refresh stale map, stop tracking it in git (OD-0027) (#184)
senigami Aug 16, 2026
f55c139
Add .claude/agents/ folders for the 46 renamed personas (#185)
senigami Aug 16, 2026
714adca
chore: remove local AI-assistant configuration from the repo, keep th…
senigami Aug 16, 2026
2d1c807
Upgrade to skill-arsenal Release 1.1.0: tracked git hooks and a relea…
senigami Aug 23, 2026
00f8fd2
fix(scheduler): release resources using the admission mode captured a…
senigami Aug 24, 2026
9d4408e
Route XTTS plugin through the SDK and make the import gate real (#200…
senigami Aug 25, 2026
be4ba06
ci: run CI on studio-2.0 branches and PRs (#210)
senigami Aug 25, 2026
1709b44
Add a plugin registration Protocol and free XTTS from app imports (#2…
senigami Aug 25, 2026
a536ac5
ci: fix the three failures the studio-2.0 trigger exposed (#212)
senigami Aug 25, 2026
24414e0
Fix the two CI failures on studio-2.0: skip the XTTS-only tests, and …
senigami Aug 26, 2026
b00b221
Close a storage-path escape, plugin-upload ceilings, and error-body p…
senigami Aug 26, 2026
16296c0
Sync spec index versions with each spec's own front-matter (#223)
senigami Aug 26, 2026
31a7a50
Add missing 1.3.0 changelog row to engines-and-plugins.md (#226)
senigami Aug 26, 2026
d9ef3ce
Fix chapter renders bypassing the parallel-cap setting (#228) (#229)
senigami Aug 26, 2026
d2c7884
Fix per-engine concurrency cap hidden for XTTS, and stale restart cop…
senigami Aug 26, 2026
e0175a6
Fix chapter-progress display to use real render-batch counts (#231)
senigami Aug 26, 2026
e0219f5
Add preliminary plan: segment/render-block redesign (issue #232)
senigami Aug 26, 2026
2e44121
Note today's code moves in two active plan docs (closeout stale-doc-s…
senigami Aug 26, 2026
44649b6
Fix chapter progress showing raw sentence count for parallel chapter …
senigami Aug 27, 2026
20834b0
Fix chapters admitted out of submission order at the admission semaphore
senigami Aug 27, 2026
0c6166b
Add regression coverage for the Segment detail <details> click toggle
senigami Aug 27, 2026
a35331e
Replace native <details> toggle with explicit button in SegmentAccess…
senigami Aug 27, 2026
f3beecc
Fix durable job-row write missing render-batch counts (third fix, sam…
senigami Aug 27, 2026
c1c7e72
Fix segment-peek-strip block row overflowing its card at high segment…
senigami Aug 27, 2026
7738838
Make the segment render monitor batch-granular, never sentence-granular
senigami Aug 27, 2026
46fbfc6
Fix synthetic batch children never recording calibration samples
senigami Aug 27, 2026
bb9beea
Fix recovery crash: engine_id missing from recovered synthesis payloa…
senigami Aug 28, 2026
69facf9
Add versioned, transactional schema-migration runner (#233) (#244)
senigami Aug 28, 2026
a84f02d
Fix WAL-unsound migration backup (#246) (#256)
senigami Aug 31, 2026
7485d46
Run schema migrations before startup recovery, not after (#257)
senigami Aug 31, 2026
b45dda5
Bump react-router and transitive deps to close 18 open Dependabot ale…
senigami Sep 1, 2026
17b055b
Add engine-id allowlist to tts_engine_caps settings endpoint (#235) (…
senigami Sep 1, 2026
cab4bc7
Carry project_id/chapter_id through crash recovery (#261) (#262)
senigami Sep 2, 2026
9a47717
Redesign chapter_segments to render-block grain, char-weighted progre…
senigami Sep 3, 2026
60ddd37
Stop calling a partially-rendered batch "Preparing" (#237) (#265)
senigami Sep 3, 2026
033736f
Name the two job-status sets for the questions they answer (#236) (#267)
senigami Sep 3, 2026
9bd2695
Await the first assertion after fireEvent (#213) (#268)
senigami Sep 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
9 changes: 9 additions & 0 deletions .agent/notes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Agent Notes

This file is for durable repo-specific learnings that help future work but do not yet belong as hard rules.

## Usage

- Put normative, repo-level guidance in `.agent/rules.md` or `.agent/rules/`.
- Put useful learnings, reminders, heuristics, and recurring gotchas here when they are worth remembering but are not yet stable enough to be promoted into rules.
- When a note becomes clearly normative or repeatedly important, move it into the relevant rules file.
67 changes: 34 additions & 33 deletions .agent/rules.md
Original file line number Diff line number Diff line change
@@ -1,35 +1,36 @@
# Agent Rules

This is the canonical entry point for repository rules.

Use this file as the quick-reference summary, then consult the focused rule files in `.agent/rules/` for the details that match the task.

## Read First

- Verify all changes with the appropriate test and lint commands before considering a task done.
- Use the local `./venv` for backend commands.
- Update tests when logic changes; do not weaken tests to fit broken behavior.
- Keep wiki docs and `wiki/Changelog.md` aligned with shipped behavior.
- Prefer manual verification by the user for UI changes unless they explicitly ask for browser-driven verification.
- Treat filesystem paths as a security surface; follow the backend security/path rules.
- Push back when the requested implementation is weaker than the better pattern already available in the repo.

## Rule Map

- [`verification.md`](/Users/stevendunn/GitHub-Steven/audiobook-factory/.agent/rules/verification.md)
Test-first expectations, verification commands, and definition of done.
- [`workflow.md`](/Users/stevendunn/GitHub-Steven/audiobook-factory/.agent/rules/workflow.md)
Ownership, pushback, documentation, and manual verification expectations.
- [`backend.md`](/Users/stevendunn/GitHub-Steven/audiobook-factory/.agent/rules/backend.md)
Progress/state consistency, worker sync, path safety, and backend structural guidance.
- [`frontend.md`](/Users/stevendunn/GitHub-Steven/audiobook-factory/.agent/rules/frontend.md)
UI consistency, accessibility, responsiveness, and frontend quality guidance.

## Priority Order

When rules overlap, follow them in this order:

1. Verification and correctness
2. Security and data safety
3. User-visible behavior and documentation accuracy
4. Maintainability and consistency
This is the router for repository rules.

## Task Map

Use the smallest rule set that matches the task.

1. Always read [`verification.md`](/Users/stevendunn/GitHub-Steven/audiobook-factory/.agent/rules/verification.md) before calling code work complete.
1. For frontend UI or UI-state work, read [`frontend.md`](/Users/stevendunn/GitHub-Steven/audiobook-factory/.agent/rules/frontend.md), the relevant frontend subfile(s), and [`modular_architecture.md`](/Users/stevendunn/GitHub-Steven/audiobook-factory/.agent/rules/modular_architecture.md).
1. For frontend state ownership or overlays, read [`frontend-state.md`](/Users/stevendunn/GitHub-Steven/audiobook-factory/.agent/rules/frontend-state.md) plus [`modular_architecture.md`](/Users/stevendunn/GitHub-Steven/audiobook-factory/.agent/rules/modular_architecture.md).
1. For frontend UX, recovery, waiting, or editor-flow work, read [`frontend-ux.md`](/Users/stevendunn/GitHub-Steven/audiobook-factory/.agent/rules/frontend-ux.md) plus [`frontend-state.md`](/Users/stevendunn/GitHub-Steven/audiobook-factory/.agent/rules/frontend-state.md) when state ownership is involved.
1. For frontend interaction, styling, semantics, or responsive layout work, read [`frontend-interactions.md`](/Users/stevendunn/GitHub-Steven/audiobook-factory/.agent/rules/frontend-interactions.md).
1. For backend progress or ETA work, read [`backend.md`](/Users/stevendunn/GitHub-Steven/audiobook-factory/.agent/rules/backend.md), [`backend-progress.md`](/Users/stevendunn/GitHub-Steven/audiobook-factory/.agent/rules/backend-progress.md), and usually [`modular_architecture.md`](/Users/stevendunn/GitHub-Steven/audiobook-factory/.agent/rules/modular_architecture.md).
1. For artifact publication or recovery work, read [`backend.md`](/Users/stevendunn/GitHub-Steven/audiobook-factory/.agent/rules/backend.md), [`backend-artifacts.md`](/Users/stevendunn/GitHub-Steven/audiobook-factory/.agent/rules/backend-artifacts.md), and usually [`modular_architecture.md`](/Users/stevendunn/GitHub-Steven/audiobook-factory/.agent/rules/modular_architecture.md).
1. For backend path handling, read [`backend.md`](/Users/stevendunn/GitHub-Steven/audiobook-factory/.agent/rules/backend.md) and [`backend-paths.md`](/Users/stevendunn/GitHub-Steven/audiobook-factory/.agent/rules/backend-paths.md).
1. For routing, service boundaries, queue policy, or migration shape, read [`backend.md`](/Users/stevendunn/GitHub-Steven/audiobook-factory/.agent/rules/backend.md), [`backend-boundaries.md`](/Users/stevendunn/GitHub-Steven/audiobook-factory/.agent/rules/backend-boundaries.md), and [`modular_architecture.md`](/Users/stevendunn/GitHub-Steven/audiobook-factory/.agent/rules/modular_architecture.md).
1. For large-file refactors or files over the architecture thresholds, read [`modular_architecture.md`](/Users/stevendunn/GitHub-Steven/audiobook-factory/.agent/rules/modular_architecture.md) plus the relevant frontend/backend rule files.
1. For plan, rollout, or documentation changes, read [`workflow.md`](/Users/stevendunn/GitHub-Steven/audiobook-factory/.agent/rules/workflow.md) and usually [`modular_architecture.md`](/Users/stevendunn/GitHub-Steven/audiobook-factory/.agent/rules/modular_architecture.md).

## What Matters Most

- Verify changes with the relevant tests and linting before calling work complete.
- Use the local `./venv` for backend tooling.
- Update tests when behavior or logic changes.
- Fix concrete bugs or regression risks in the same pass.
- Keep implementation docs, wiki pages, and `wiki/Changelog.md` aligned with shipped behavior.
- Treat paths, assets, and output publication as security-sensitive.
- Prefer the better long-term boundary when a quick fix would deepen worker-centric or UI-state coupling.

## Rule Ownership

- The agent owns the organization and maintainability of `.agent/rules.md`, `.agent/rules/`, and related agent guidance files.
- The agent may restructure, split, rename, cross-link, and refine these rule files without asking for additional permission when doing so improves discoverability, routing, or long-term usability.
- Normative, repo-level guidance should live in the rules files.
- Durable repo learnings, heuristics, and reminders that are useful to the agent but are not yet normative rules may be stored in [`notes.md`](/Users/stevendunn/GitHub-Steven/audiobook-factory/.agent/notes.md).
12 changes: 12 additions & 0 deletions .agent/rules/backend-artifacts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Backend Artifacts

Use this file for completion checks, artifact publication, recovery, and cache safety.

## Core Rules

- Raw file existence alone is never enough to mark render work complete.
- Validated artifact manifests plus canonical persistence state determine whether output is reusable.
- Publish generated outputs atomically: temp file first, validate, write manifest, then promote into the final artifact location.
- Shared cached artifacts must be immutable once published.
- When job state is re-queued, recovered, or invalidated, clear stale runtime metadata and recalculate status from canonical state.
- If a revision changes, mark prior artifacts stale explicitly rather than silently treating them as valid.
13 changes: 13 additions & 0 deletions .agent/rules/backend-boundaries.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Backend Boundaries

Use this file for routing, service layers, queue policy, and legacy migration boundaries.

## Core Rules

- Route handlers should call domain services and orchestrator services, not engine-specific or worker-specific code directly.
- Engine wrappers must not decide scheduling policy.
- Queue tasks must declare resource needs; they must not acquire ad-hoc locks scattered through task code.
- Keep domain logic, orchestration logic, engine integration, and infrastructure concerns in separate modules.
- Prefer explicit repositories and services over ad-hoc data access from route handlers and workers.
- During migration, compatibility adapters are acceptable, but they should live in explicit legacy or adapter layers.
- Do not let temporary migration code redefine the long-term architecture.
47 changes: 47 additions & 0 deletions .agent/rules/backend-paths.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Backend Paths

Use this file for request-derived filesystem paths, scanned directories, and containment checks.

## Core Rules

- Treat any filesystem path derived from request data, DB values, uploaded filenames, or user-editable names as untrusted.
- For existing files or directories, prefer enumerating a trusted root and matching by `entry.name`.
- For new paths, use the explicit containment pattern that CodeQL recognizes well:
1. validate with a strict regex
2. build with `os.path.join(...)`
3. normalize with `os.path.normpath(...)`
4. absolutize with `os.path.abspath(...)`
5. verify the result stays under the trusted root before reading or writing
- Reject traversal-style input instead of silently “fixing” it.
- Do not hide security-critical path creation in vague helpers.

## CodeQL Lessons Learned

- If CodeQL traces a route parameter into a filesystem sink, repeat the validation and containment proof in the same function as the sink. A shared helper may be safe at runtime but opaque to the scanner.
- For each filesystem sink argument (`open`, `shutil.move`, `shutil.copy*`, `Path.exists`, `rmtree`, etc.), make the value passed to the sink a locally checked string:
1. derive it from a trusted root with `os.path.join(...)`
2. normalize with `os.path.normpath(...)`
3. absolutize with `os.path.abspath(...)`
4. compare against a trusted-root prefix before the sink
- For moves/copies, prove both sides independently. The source and destination can produce separate CodeQL findings even when they appear on the same line.
- When migrating legacy files named from DB values, prefer enumerating the trusted directory and matching `entry.name`; then normalize and contain-check the matched `entry` before using it.
- If a destination filename does not need to preserve a user/DB identifier, generate a deterministic safe filename such as `seg_{index}.wav` and persist that mapping instead of embedding the untrusted ID in the path.
- For speaker-profile resolution and metadata files, prove the profile root locally in the same function, then use trusted `os.scandir(...)` results or direct string-based `open(...)` on the proved path instead of `Path.exists()`, `Path.read_text()`, or `Path.write_text()`.
- For storage-version probes, scan the trusted root first and match `entry.name` rather than scanning a derived child directory built from the user-supplied name, even if the child path is validated.
- For voice bundle export/import helpers, resolve the voice root by scanning the trusted voices directory and matching `entry.name`, then prove the manifest path relative to that discovered root before calling `os.path.isdir()`, `os.path.exists()`, or `open()`.
- For profile metadata reads and repairs, scan the parent directory and match the exact metadata filename by `entry.name` before opening it; do not rely on `os.path.exists()` on a derived metadata path when CodeQL is tracing the source.
- If CodeQL still traces a metadata or discovery scan, prefer a direct `try/except os.scandir(validated_parent)` block over a separate `os.path.isdir()` guard on the same derived path, so the root proof and sink stay in the same control-flow block.
- **Extreme Hardening for Sinks**: Standard `Path` object methods like `.exists()`, `.is_dir()`, and `.mkdir()` are treated as sinks. CodeQL often ignores containment proofs on the parent `Path` object if the child path is derived and then checked via these methods.
- **Solution**: Convert all `Path` sinks to string-based `os.path` sinks (`os.path.exists`, `os.path.isdir`, `os.makedirs`).
- **Pattern**: Resolve the final string using `os.path.abspath(os.path.realpath(os.fspath(path)))` and perform the `startswith(trusted_prefix)` check immediately before the sink in the same local block.
- **Source Sanitization is King**: While sink-level proofs are required for completeness, sanitizing user-provided strings (e.g., validating UUIDs or using strict regex) at the **API entry point** is the most effective way to break the taint chain early.
- **Pattern**: Use a public helper like `config.canonical_chapter_id(id)` that raises `ValueError` on anything except a valid UUID before passing the ID to any domain logic.
- **Unrolled Proofs for Linear Path Analysis**: CodeQL's path-sensitive analysis frequently fails to follow containment proofs through loops (e.g., `for root in trusted_roots:`).
- **Solution**: Explicitly "unroll" these checks into `if/elif` blocks for each trusted root. This provides a clear, linear path for the scanner to follow from the proof to the sink.
- **Taint Persistence in Objects**: CodeQL often tracks taint through `pathlib.Path` objects even after a containment check.
- **Pattern**: For high-risk sinks, convert the `Path` to a string (`os.fspath`), resolve it fully (`abspath/realpath`), and perform a fresh `startswith()` check immediately before the sink in the same local block.
- **Test-Mode Database Safety**: When running tests, a safety guard should prevent connecting to non-test databases.
- **Pattern**: Resolve the `DB_PATH` and the system temp roots (including symlinks like `/tmp` -> `/private/tmp` on macOS) fully before comparison. Use `Path(path).resolve()` on both sides to ensure consistent behavior across platforms.
- **Temp Dir Containment Traps**: Be careful when allowing `tempfile.gettempdir()` in containment proofs to support tests.
- **Risk**: Allowing the entire temp root can permit "traversal" between unrelated test directories (e.g., from `tmp/project_a` to `tmp/project_b`), which security tests correctly identify as a vulnerability.
- **Solution**: Instead of allowing the broad temp root, ensure that tests correctly patch the `PROJECTS_DIR` and `XTTS_OUT_DIR` to their specific temp workspaces. The standard `startswith(p_root)` check will then naturally allow the test paths without compromising security.
10 changes: 10 additions & 0 deletions .agent/rules/backend-progress.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Backend Progress

Use this file for ETA, progress, and WebSocket state consistency rules.

## Core Rules

- WebSocket progress values must be rounded to exactly 2 decimal places.
- Only broadcast progress updates when the value advances meaningfully, the status changes, or the event carries important new context.
- Queue and progress services own progress math. Do not duplicate ETA or completion logic inside engine wrappers or route handlers.
- Parent-child job behavior should be modeled explicitly rather than inferred from filenames or loose naming conventions.
39 changes: 14 additions & 25 deletions .agent/rules/backend.md
Original file line number Diff line number Diff line change
@@ -1,33 +1,22 @@
# Backend Rules

## Progress And State Consistency
Use this file when the task touches backend orchestration, queueing, progress, artifact publication, or filesystem path handling.

- WebSocket progress values must be rounded to exactly 2 decimal places.
- Only broadcast progress updates when the value advances by at least 1%.
- When a job is re-queued, reset, or recovered, clear stale metadata such as logs, timestamps, progress, and warnings.
- Disk state is the source of truth when UI status and actual files disagree.
## Read The Right Subfile

## Technical Environment
- [`backend-artifacts.md`](/Users/stevendunn/GitHub-Steven/audiobook-factory/.agent/rules/backend-artifacts.md) for manifest validation, publish flow, cache immutability, and recovery safety.
- [`backend-progress.md`](/Users/stevendunn/GitHub-Steven/audiobook-factory/.agent/rules/backend-progress.md) for progress math, ETA rules, rounding, and update throttling.
- [`backend-boundaries.md`](/Users/stevendunn/GitHub-Steven/audiobook-factory/.agent/rules/backend-boundaries.md) for route/service/engine boundaries and migration discipline.
- [`backend-paths.md`](/Users/stevendunn/GitHub-Steven/audiobook-factory/.agent/rules/backend-paths.md) for request-derived paths and containment checks.

- Always use the local `./venv` for backend tooling.
- When worker threads update `j` objects, follow up with `update_job` so the WebSocket bridge receives the change.
## Load Order

## Path Safety And Code Scanning
1. [`backend-progress.md`](/Users/stevendunn/GitHub-Steven/audiobook-factory/.agent/rules/backend-progress.md) for ETA, rounding, and progress consistency.
1. [`backend-artifacts.md`](/Users/stevendunn/GitHub-Steven/audiobook-factory/.agent/rules/backend-artifacts.md) for publish/recovery/immutability.
1. [`backend-paths.md`](/Users/stevendunn/GitHub-Steven/audiobook-factory/.agent/rules/backend-paths.md) for any request-derived path handling.
1. [`backend-boundaries.md`](/Users/stevendunn/GitHub-Steven/audiobook-factory/.agent/rules/backend-boundaries.md) for routing, orchestration, queue policy, and migration shape.

- Treat any filesystem path derived from request data, DB values, uploaded filenames, or user-editable names as untrusted.
- For existing files or directories, prefer enumerating a trusted root and matching by `entry.name`.
- For new paths, use the explicit containment pattern that CodeQL recognizes well:
1. validate with a strict regex
2. build with `os.path.join(...)`
3. normalize with `os.path.normpath(...)`
4. absolutize with `os.path.abspath(...)`
5. verify the result stays under the trusted root before reading or writing
- For filenames and profile names, require flat single-segment names unless nested paths are truly intentional.
- Reject traversal-style input instead of silently “fixing” it.
- Avoid hiding security-critical path creation in generic helpers unless the helper exactly mirrors the accepted containment shape and has already been proven scanner-safe.
- When code scanning regresses, export the latest `code-scanning-alerts.json`, group by rule and file, and fix the current highest-concentration sink lines directly before broad refactors.
## Pair With

## Structural Guidance

- If a file exceeds 500 lines, consider splitting it along real logical boundaries.
- Refactor carefully to avoid circular dependencies or scattering tightly coupled logic across too many files.
- [`modular_architecture.md`](/Users/stevendunn/GitHub-Steven/audiobook-factory/.agent/rules/modular_architecture.md) for Studio 2.0 boundary rules.
- [`verification.md`](/Users/stevendunn/GitHub-Steven/audiobook-factory/.agent/rules/verification.md) for the required backend test and lint verification.
Loading
Loading