Profiles
booktx translation profiles let one source book support multiple translation
efforts without mixing mutable state.
Examples:
PROFILE_APROFILE_Bfr_gpt5_5
Why profiles exist
Without profiles, all mutable translation state lands in one shared store. That mixes different languages, different model experiments, and different context decisions.
Profiles prevent that by moving mutable translation state under
translations/<profile>/.
Commands
booktx profile create ./book PROFILE_A --target de --target-locale de-DE
booktx profile list ./book
booktx profile show ./book PROFILE_A
booktx profile compare ./book --profiles PROFILE_A,PROFILE_B --record 0001-000001
booktx profile migrate-current ./book PROFILE_A
Resolution rules
Explicit
--profilewins.Otherwise the explicit profile from
.booktx/profile stateis used.Otherwise exactly one existing profile is auto-resolved.
Otherwise target-dependent commands fail until a profile is chosen explicitly.
Access modes
Profiles own mutable translation state, but visibility of sibling profiles depends on how the harness starts:
Collaborative project-root mode
Start the harness at the book project root when you need:
profile administration
profile comparison
cross-profile reference work
migration and debugging
In this mode, project-relative paths and explicit cross-profile commands are expected and allowed.
Isolated profile-root mode
Start the harness inside translations/<profile>/ when you want unbiased model
or context evaluation for one target profile.
This is booktx-mediated isolation, not OS sandboxing. It assumes:
the harness blocks parent paths, absolute paths, sibling profile paths, shell globs, and arbitrary filesystem inspection snippets;
the agent uses only profile-local
booktx ... .commands;booktxitself never requires or prints parent/sibling paths for the normal isolated workflow.
Use:
booktx mode .
booktx doctor isolation .
booktx source status .
booktx profile list . # shows current profile only, no sibling names
booktx profile show . . # defaults to current profile
booktx context status .
booktx translate next . --unit batch --max-words 800 --format block
booktx translate insert . --task-id TASK --file ingest/TASK.block.txt --format block
booktx validate .
booktx build .
profile list in isolated mode shows only the current profile (no sibling profile names, no absolute paths, no ../). Cross-profile commands like profile compare, profile create, and profile migrate-current remain blocked.
If a command in profile-root mode suggests ../, prints an absolute path, or
reveals another profile, stop and report a booktx isolation bug.
Before starting the harness inside a profile, prepare the matching harness instructions so the agent does not have to rediscover them:
booktx agents write . --mode isolated --profile PROFILE
This writes a profile-local AGENTS.md (safe to read from inside the profile
root: no parent paths, absolute paths, sibling profile names, or --profile)
and removes project-root/collaborative generated instructions. From inside the
profile root, booktx agents write . --mode isolated refreshes the local file
without printing parent paths. booktx agents status . reports ownership and
staleness for the local file only.
What is isolated?
Each profile owns its own copy of all mutable translation state under
translations/<profile>/:
Path |
Meaning |
|---|---|
|
Profile-root runtime marker |
|
Profile config (target, output name) |
|
Live actor/harness/model identity |
|
Translation context and rendered form |
|
Primary record-level translations |
|
Version tracks and subversions |
|
Durable translation task files |
|
Submission templates (agent edits) |
|
Generated compatibility export |
|
Validation/build reports |
|
Final rebuilt document |
Two profiles never share any of the above. Translations accepted into one profile are invisible to another.
When to create a new profile?
Create a new profile whenever you want a hard isolation boundary:
Different target language:
PROFILE_A,fr_gpt5_5,es_gpt5_5.Different model experiment:
PROFILE_AvsPROFILE_Bfor the same language, so the two outputs never contaminate each other.Different context decisions: a re-translation under revised glossary or style rules, kept separate from a previous accepted run.
Do not create a new profile for a routine re-translation of the same language/model/context; that is a version, not a profile.
Pass-through profiles
A pass-through profile is a generated validation fixture, not a translation. Its target language equals the source language, and every translated record’s target is set to the source text. Use it to verify that extraction and EPUB reconstruction include all content before involving a translator.
Pass-through profiles are generated fixtures; they must not be used for human or LLM translation.
They use the source language as the target language.
They are isolated under
translations/<profile>/, just like any profile, so they cannot contaminate real translation profiles.booktx pass-throughrequires an explicit--profileand refuses to run against a profile whosekindis notpass-through.
A non-empty translation store can silently override generated chunks, so
pass-through refuses a profile with store records unless you pass
--clear-store (which rewrites only translation-store.json).
Selection profiles
A selection profile is a normal buildable profile whose accepted output is assembled from cross-profile judge decisions.
kind = "selection"intranslations/<profile>/config.tomlit keeps its own
context.json,translation-store.json, and output filesaccepted judge output is written into the normal translation store so
booktx validateandbooktx buildwork without special build rulesprovenance is stored separately in
translation-selection-ledger.jsondurable judge task artifacts live under
judge-tasks/andjudge-ingest/
Create one with:
booktx judge create-profile ./book JUDGE_PROFILE \
--target de \
--target-locale de-DE \
--sources PROFILE_A,PROFILE_B \
--context-from PROFILE_A \
--model gpt-5.5 \
--context-from copies approved style, global rules, glossary, and reusable
approved answers from a ready source profile into the new selection profile and
marks the judge context ready when that imported policy satisfies all required
questions. Without it, initialize the selection profile context explicitly and
sync policy from a compatible source profile before judging.
booktx context init ./book --profile JUDGE_PROFILE --non-interactive
booktx context sync ./book \
--from PROFILE_A \
--to JUDGE_PROFILE \
--section glossary \
--section style \
--section global-rules \
--write
booktx context mark-ready ./book --profile JUDGE_PROFILE
Judge profile creation and snapshot preparation are project-root workflows.
After snapshot preparation, a selection profile may run judge status,
judge next, judge insert, judge show, judge continue, and
judge accept-identical from its own profile root:
booktx judge status ./book --profile JUDGE_PROFILE --sources PROFILE_A,PROFILE_B
booktx judge accept-identical ./book --profile JUDGE_PROFILE --sources PROFILE_A,PROFILE_B --unit chapter --chapter 0001 --max-records 100 --write
booktx judge next ./book --profile JUDGE_PROFILE --sources PROFILE_A,PROFILE_B --unit chapter --chapter 0001 --max-records 8 --format decisions
booktx judge insert ./book --profile JUDGE_PROFILE --judge-task-id TASK --file translations/JUDGE_PROFILE/judge-ingest/TASK.decisions.txt --format decisions
Judge task record ids are chunk-based, so a task for a logical chapter can
still contain ids prefixed with another chunk such as 0001-....
Single-source judge revision profiles
Use --purpose revise when one translation source is clearly best and you
want an isolated final profile where an LLM must explicitly proofread every
record.
Revision profiles are judge profiles, not review passes. Their effective output is valid only while each active target has matching judge-decision provenance.
Do not run accept-identical, sweep-identical, or
prefill-policy-fixes in a revision profile. Do not modify effective output
through translation or review revision commands; use judge record for later
corrections.
Create a revision profile with exactly one source:
booktx judge create-profile ./book PROFILE_REVISED \
--target de \
--target-locale de-DE \
--sources PROFILE_B \
--context-from PROFILE_B \
--model gpt-5.5 \
--purpose revise
booktx judge prepare-isolation ./book \
--profile PROFILE_REVISED \
--write
Inside the isolated profile root, judge every record explicitly. For each
record choose copy (keep the base target) or edited (write the complete
corrected target). Later corrections use booktx judge record, not
translation or review revision commands:
cd translations/PROFILE_REVISED
booktx judge status .
booktx judge next . --unit chapter --chapter 0008 --max-records 20 --format decisions
booktx judge insert . --judge-task-id TASK --file judge-ingest/TASK.decisions.txt --format decisions
booktx judge continue . --max-records 20
booktx judge record . --record RECORD_ID --format decisions
booktx validate . --fail-on-warnings
booktx build . --require-complete
In selection.purpose=compare, prefer accept-identical and
sweep-identical for true multi-source identical candidates.
In selection.purpose=revise, never use deterministic selection commands.
Every record requires an explicit copy or edited judge decision.
What stays a version?
Versions live inside a profile. Two profiles may both contain version 1.1;
they are unrelated.
A model/actor/harness identity change creates or selects a major track (e.g.
1).A baseline policy change creates or selects a subversion inside that track (e.g.
1.2).A chapter-note append changes the next task’s composed context view but does not create a new dotted version on its own.
Use:
booktx version current . --profile PROFILE
booktx version list . --profile PROFILE
booktx translation compare . --profile PROFILE RECORD --versions 1.1,1.2
booktx translation activate . --profile PROFILE RECORD 1.2
Migration from legacy layout
A legacy single-layout project keeps all state under .booktx/. Migrate it
into the profile layout:
booktx profile migrate-current ./book PROFILE
Before:
book/.booktx/{config.toml, translation-store.json, tasks/, ingest/, ...}
After:
book/.booktx/{source-config.toml, source-manifest.json, chunks/, ...}
book/translations/PROFILE/{identity.json, translation-store.json, tasks/, ingest/, ...}
CLI identity overrides (--model, --actor, --harness) are honored over any
legacy .booktx/identity.json. Migration is staged: mutable files move
first, then the final profile config/identity/state are written, and the
legacy config.toml is removed only after all moves succeed.
Failure modes
multiple_profiles_ambiguous: more than one profile exists and no--profilewas given for a target-state command. Pass--profile.profile_root_marker_missing: the profile-root marker is missing. Recreate or backfill the profile marker before using isolated mode.profile_root_marker_mismatch: the marker no longer matches the profile directory, project root, or profile config. Regenerate or repair the marker.stale_profile_root_marker: the marker is bound to an older extracted source identity. Refresh the marker after source extraction changes.task_profile_mismatch: a submission’s profile header does not match the selected profile. Re-request the task in the correct profile.submission_profile_mismatch: a JSON submission’sprofilefield differs from the target profile. Fix the submission or switch profile.legacy_project_required: the project still uses the legacy layout. Runbooktx profile migrate-currentfirst.migration_target_exists: the destination profile directory already exists and is non-empty. Remove it or pick a new profile name.
Quality review configuration
Add or update quality review through the CLI (preferred) or by editing
the profile config.toml directly:
# Show current config
booktx review configure . --show
# Enable with one pass
booktx review configure . --enable --pass 1 --name "Flow review" \
--mode manual --enforce warn --base active_translation \
--before 2 --after 2 --batch-words 900 \
--instructions "Improve reading flow and pronoun continuity."
# Add a second pass
booktx review configure . --enable --pass 2 --name "Final polish" \
--base active_review --required-base-pass 1 --enforce error \
--instructions "Polish final prose. Prefer minimal edits."
# Disable quality review entirely
booktx review configure . --disable
Manual TOML equivalent (kept for reference):
Add a [quality_review] table to the profile config.toml:
[quality_review]
enabled = true
active_passes = [1]
require_all_active_passes = true
[[quality_review.passes]]
pass_number = 1
name = "Flow review"
enabled = true
mode = "after_chapter"
enforce = "warn"
base = "active_translation"
before_records = 2
after_records = 2
batch_words = 900
instructions = "Improve reading flow and pronoun continuity."
Two-pass example:
[quality_review]
enabled = true
active_passes = [1, 2]
[[quality_review.passes]]
pass_number = 1
name = "Flow review"
base = "active_translation"
enforce = "warn"
[[quality_review.passes]]
pass_number = 2
name = "Final polish"
base = "active_review"
required_base_pass = 1
enforce = "error"
instructions = "Polish final prose. Prefer minimal edits."
Fields:
enabled– enable or disable quality review for this profileactive_passes– which passes are currently active (reported byreview status)require_all_active_passes– when true, validation reports missing active passes
Per-pass fields:
pass_number– unique pass identifier (1, 2, …)name– human-readable labelenabled– enable or disable this specific passmode–manual,after_chapter, orbefore_buildenforce–off(no findings),warn(warning),error(blocking)base–active_translation(first-pass version) oractive_review(prior review)required_base_pass– pass that must be completed first (for chaining)before_records/after_records– neighbor context window sizebatch_words– maximum source words per review taskinstructions– prompt for the reviewing agent
Pass-through profiles must not set [quality_review].
Series continuation profiles
Use the same profile name for a new book only after creating it in the new project. Policy transfer is explicit through context packs and optional termbase import, not by copying profile directories. After project-root preparation, run booktx agents write BOOK --profile PROFILE --mode isolated and start translation inside translations/PROFILE.