Šķîþ ţö ḿàîñ çöñţéñţ

É-03: Ţĥé ţööļ šýšţéḿ

Šüḿḿàŕý​

À ţööļ îš à šîñĝļé šţàĝé îñ à þŕöçéššîñĝ þîþéļîñé. Îţ ŕéàđš Þàŕţš ƒŕöḿ àñ îñþüţ çĥàññéļ àñđ ŵŕîţéš Þàŕţš ţö àñ öüţþüţ çĥàññéļ. Ţööļš çöḿþöšé îñţö ƒļöŵš; ƒļöŵš àŕé éẋéçüţéđ ƃý ţĥé þîþéļîñé éñĝîñé (É-01). Ţĥé BaseTool šţŕüçţ ŵîţĥ öþţîöñàļ ĥàñđļéŕ ƒîéļđš (à çàþàƃîļîţý-ţýþéđ ƃļöçķ ĥàñđļéŕ, Annotate / Produce / Transform, þļüš üñţýþéđ ĥàñđļéŕš ƒöŕ öţĥéŕ Þàŕţ ţýþéš) ļéţš ḿöšţ ţööļš îḿþļéḿéñţ öñļý ţĥé ĥàñđļéŕ ƒöŕ ţĥé Þàŕţ ţýþé ţĥéý çàŕé àƃöüţ; éṽéŕýţĥîñĝ éļšé þàššéš ţĥŕöüĝĥ üñçĥàñĝéđ. Ţĥé ƃļöçķ ĥàñđļéŕ à ţööļ šéţš àļšö đéçļàŕéš ŵĥàţ îţ ḿàý ŵŕîţé. Ţööļš đéçļàŕé þàŕàḿéţéŕ šçĥéḿàš ṽîà SchemaProvider, ŵĥîçĥ đŕîṽéš ÇĻÎ ƒļàĝ ĝéñéŕàţîöñ, ƒļöŵ-éđîţöŕ çöñƒîĝ þàñéļš, àñđ ṽàļîđàţîöñ. Àñ ÎÖ çöñţŕàçţ öñ ToolMeta đéçļàŕéš ļöçàļé çàŕđîñàļîţý, ţĥé šţàñđ-öƒƒ ļàýéŕš à ţööļ þŕöđüçéš, àñđ îţš šîđé 郃éçţš, šö ţĥé ŕüññéŕ çàñ îñƒéŕ ļöçàļé îţéŕàţîöñ àñđ ţĥé ƒļöŵ éđîţöŕ çàñ šĥöŵ đàţà ƒļöŵ. À ţööļ ŵĥöšé ƃéĥàṽîöüŕ çöḿéš ƒŕöḿ öñé öƒ šéṽéŕàļ îñţéŕçĥàñĝéàƃļé ƃàçķéñđš îš à ţööļ ĝŕöüþ: îţ ŕéĝîšţéŕš šéļƒ-đéšçŕîƃîñĝ ḿéḿƃéŕš ŵîţĥ à đéƒàüļţ, àñđ ţĥé üšéŕ šéļéçţš àñđ çöñƒîĝüŕéš öñé ḿéḿƃéŕ àţ à ţîḿé.

Çöñţéẋţ​

Ḿöšţ ţööļš öñļý çàŕé àƃöüţ öñé öŕ ţŵö Þàŕţ ţýþéš. À ţŕàñšļàţîöñ ţööļ þŕöçéššéš Ƃļöçķš; à ŵöŕđ çöüñţéŕ ŕéàđš Ƃļöçķš; à ƃîñàŕý éẋţŕàçţöŕ ĥàñđļéš Ḿéđîà. Ŕéǫüîŕîñĝ éṽéŕý ţööļ ţö îḿþļéḿéñţ ţĥé ƒüļļ Process(ctx, in, out) ḿéţĥöđ ŵîţĥ à ţýþé šŵîţçĥ öṽéŕ àļļ Þàŕţ ţýþéš þŕöđüçéš ŕéþéţîţîṽé ƃöîļéŕþļàţé àñđ çŕéàţéš à ŕîšķ öƒ àççîđéñţàļļý đŕöþþîñĝ Þàŕţš.

Ƃéýöñđ šţŕüçţüŕàļ đîšþàţçĥ, à ţööļ šýšţéḿ ñééđš ţö àñšŵéŕ šéṽéŕàļ ǫüéšţîöñš üñîƒöŕḿļý ƒöŕ ţĥé ÇĻÎ, ţĥé ƒļöŵ éđîţöŕ, àñđ þļüĝîñ çöñšüḿéŕš:

  • Ŵĥàţ þàŕàḿéţéŕš đöéš ţĥîš ţööļ àççéþţ, àñđ ŵĥàţ àŕé ţĥéîŕ ţýþéš?
  • Ĥöŵ ḿàñý ļöçàļéš đöéš îţ öþéŕàţé öñ? Ŵĥîçĥ öñéš?
  • Ŵĥàţ šţàñđ-öƒƒ ļàýéŕš đöéš îţ þŕöđüçé? Ŵĥîçĥ đöéš îţ çöñšüḿé?
  • Ŵĥàţ éẋţéŕñàļ šýšţéḿš đöéš îţ ţöüçĥ (çöñţéñţ ḿéḿöŕý, ţéŕḿš, ŕéḿöţé ÀÞΚ)?

Đéçîšîöñ​

Ţööļ îñţéŕƒàçé àñđ ƂàšéŢööļ đîšþàţçĥ​

Ţĥé çöŕé îñţéŕƒàçé îš ḿîñîḿàļ:

type Tool interface {
Process(ctx context.Context, in <-chan *Part, out chan<- *Part) error
}

BaseTool þŕöṽîđéš à šţàñđàŕđ đîšþàţçĥ šĥéļļ. Ţĥé ƃļöçķ ĥàñđļéŕ îš öñé öƒ ţĥŕéé çàþàƃîļîţý-ţýþéđ ƒîéļđš; ţĥé ţööļ šéţš éẋàçţļý öñé, àñđ ţĥé þàŕàḿéţéŕ ţýþé ƃöüñđš ŵĥàţ îţ ḿàý ŵŕîţé:

type BaseTool struct {
Annotate func(BlockView) error // read-only: overlays/annotations/properties
Produce func(VariantView) error // writes target
Transform func(BlockView) (EditPlan, error) // read-only producer; the applier rewrites source

HandleDataFn PartHandler
HandleMediaFn PartHandler
HandleLayerStartFn PartHandler

SchemaFn func() *schema.ComponentSchema
}

BaseTool.Process ŕéàđš Þàŕţš ƒŕöḿ ţĥé îñþüţ çĥàññéļ, đîšþàţçĥéš Ƃļöçķš ţö ŵĥîçĥéṽéŕ çàþàƃîļîţý-ţýþéđ ĥàñđļéŕ îš šéţ (àñđ öţĥéŕ Þàŕţ ţýþéš ţö ţĥéîŕ Handle*Fn), àñđ þàššéš üñĥàñđļéđ Þàŕţ ţýþéš ţĥŕöüĝĥ üñçĥàñĝéđ. Çöñçŕéţé ţööļš éḿƃéđ BaseTool àñđ šéţ öñļý ţĥé ĥàñđļéŕš ţĥéý ñééđ. À ţööļ ţĥàţ ñééđš ţĥé ƒüļļ šţŕéàḿ (ƃàţçĥîñĝ, 1→Ñ ƒàñ-öüţ, çŕöšš-ƃļöçķ šţàţé) öṽéŕŕîđéš Process đîŕéçţļý; îţ ŵŕîţéš à ĥéļđ ƃļöçķ ţĥŕöüĝĥ tool.WriteAs, ŵĥîçĥ ĥàñđš à ţýþéđ ĥàñđļéŕ à ṽîéŵ öƒ ţĥé ƃļöçķ àñđ ŕéţüŕñš àñý ŵŕîţé ţĥé ṽîéŵ çöüļđ ñöţ àþþļý.

Ţĥé çàļļéŕ öŵñš ƃöţĥ çĥàññéļš. À ţööļ öƃšéŕṽéš ctx öñ éṽéŕý ŕéçéîṽé àñđ šéñđ, ŕéţüŕñš öñçé îţš îñþüţ îš éẋĥàüšţéđ öŕ ţĥé çöñţéẋţ îš çàñçéļļéđ, ĵöîñš àñý ĝöŕöüţîñé îţ šţàŕţéđ ƃéƒöŕé ŕéţüŕñîñĝ, àñđ ļéàṽéš çļöšîñĝ ţĥé öüţþüţ ţö ţĥé çàļļéŕ. À ƃļöçķ ĥàñđļéŕ ţĥàţ çàļļš Drop() öñ îţš ṽîéŵ, öŕ à Handle*Fn ţĥàţ ŕéţüŕñš ñîļ, ŕéḿöṽéš ţĥàţ Þàŕţ ƒŕöḿ ţĥé šţŕéàḿ, àñđ ñöţĥîñĝ îš éḿîţţéđ îñ îţš þļàçé.

tool.RetryTool ŕéţŕîéš à BaseTool'š çàþàƃîļîţý-ţýþéđ ƃļöçķ ĥàñđļéŕ, ŵîţĥ ƃàçķöƒƒ, öñ ţĥé éŕŕöŕš îţš çöñƒîĝüŕàţîöñ ñàḿéš àš ŕéţŕýàƃļé (éṽéŕý éŕŕöŕ ŵĥéñ îţ ñàḿéš ñöñé). Îţ ŵŕàþš ţĥé ĥàñđļéŕ öñ à þŕîṽàţé çöþý öƒ ţĥé BaseTool, šö ţĥé çàļļéŕ'š ţööļ ķééþš îţš öŵñ ĥàñđļéŕš, àñđ à ŕéţŕîéđ ĥàñđļéŕ ḿüšţ ƃé îđéḿþöţéñţ: à ŕéţŕý ķééþš ţĥé ƃļöçķ ŵŕîţéš àñđ éẋţéŕñàļ 郃éçţš öƒ ţĥé àţţéḿþţ ƃéƒöŕé îţ. À ţööļ ţĥàţ öṽéŕŕîđéš Process, öŕ šéţš ñö ţýþéđ ƃļöçķ ĥàñđļéŕ, ŕüñš öñçé, šîñçé îţš îñþüţ çĥàññéļ çàññöţ ƃé ŕéŵöüñđ àñđ îţš éàŕļîéŕ öüţþüţ ḿàý àļŕéàđý ƃé đöŵñšţŕéàḿ. Çàñçéļļàţîöñ àñđ đéàđļîñé éŕŕöŕš ŕéţüŕñ àţ öñçé, àñđ SessionProcess þàššéš ţö à ŵŕàþþéđ SessionTool, ŵĥîçĥ öŵñš àñý ŕéţŕý îñšîđé îţš šéššîöñ.

ŠéššîöñŢööļ éẋţéñšîöñ​

Ţĥé çĥàññéļ-ƃàšéđ Tool.Process îš à ƒöŕŵàŕđ-öñļý ţŕàñšƒöŕḿ. Šöḿé ţööļš ñééđ ŕàñđöḿ àççéšš ţö ţĥé þŕöĵéçţ'š ƃļöçķ šţàţé: ļööķüþ ƃý çöñţéñţ ĥàšĥ, ŕéàđîñĝ þŕîöŕ öṽéŕļàýš (ḿéḿöŕý ḿàţçĥéš, çĥéçķ ƒîñđîñĝš, ţàŕĝéţš àñ éàŕļîéŕ ŕüñ þŕöđüçéđ) ţö šķîþ ŵöŕķ ţĥàţ îš àļŕéàđý đöñé, öŕ ŵŕîţîñĝ àññöţàţîöñš ţĥàţ đöŵñšţŕéàḿ ţööļš îñ ţĥé šàḿé öŕ à ļàţéŕ ŕüñ ŵîļļ çöñšüļţ. Ţĥöšé ţööļš öþţ îñţö ţĥé SessionTool îñţéŕƒàçé àļöñĝšîđé Tool:

type SessionTool interface {
Tool

SessionProcess(
ctx context.Context,
sess blockstore.Session,
in <-chan *Part,
out chan<- *Part,
) error
}

Ļîƒéçýçļé îš öŵñéđ ƃý ţĥé éẋéçüţöŕ, ñöţ ţĥé ţööļ:

  1. Àţ ƒļöŵ šţàŕţ ţĥé éẋéçüţöŕ öþéñš à blockstore.Session àĝàîñšţ ţĥé þŕöĵéçţ'š đéçļàŕéđ šţöŕé ƃàçķéñđ (Ç-01).
  2. Ƒöŕ éàçĥ ţööļ ţĥé éẋéçüţöŕ çàļļš SessionProcess ŵĥéñ ţĥé ţööļ îḿþļéḿéñţš SessionTool àñđ ţĥé šţöŕé ŕéþöŕţš îţšéļƒ þéŕšîšţéñţ, öţĥéŕŵîšé ţĥé þļàîñ šţŕéàḿîñĝ Process, ŵĥîçĥ îš ŵĥàţ éṽéŕý ţööļ ĝéţš öṽéŕ àñ éþĥéḿéŕàļ šţöŕé. Ĥýƃŕîđ îḿþļéḿéñţàţîöñš àŕé àļļöŵéđ: SessionProcess çàñ ŕéàđ ƒŕöḿ in, éñŕîçĥ ṽîà ţĥé šéššîöñ, àñđ éḿîţ ţö out.
  3. Ţĥé éẋéçüţöŕ çöḿḿîţš ţĥé šéššîöñ öñ šüççéšš öŕ ŕöļļš ƃàçķ öñ éŕŕöŕ. Ţööļš ḿüšţ ñöţ çàļļ Commit öŕ Rollback ţĥéḿšéļṽéš.

Éṽéŕý SessionTool àļšö îḿþļéḿéñţš Tool, šö ƒļöŵ çöḿþöšîţîöñ ķééþš ŵöŕķîñĝ ŵĥéţĥéŕ öŕ ñöţ à šţéþ üšéš ţĥé šéššîöñ. Šéé ţĥé ŠéššîöñŢööļ àüţĥöŕîñĝ ĝüîđé ƒöŕ îđîöḿàţîç þàţţéŕñš.

Ţööļ çàţéĝöŕîéš​

Éṽéŕý ţööļ đéçļàŕéš öñé öƒ šîẋ çàñöñîçàļ çàţéĝöŕîéš, ŵĥîçĥ šéţ éẋþéçţàţîöñš ƒöŕ îđéḿþöţéñçý àñđ öŕđéŕîñĝ àñđ đŕîṽé ţĥé ĝŕöüþîñĝ îñ ţĥé ŕéƒéŕéñçé àñđ ţĥé çöñƒîĝ ÜÎ:

ÇàţéĝöŕýÇöñšţàñţŔéšþöñšîƃîļîţý
translationschema.CategoryTranslationþŕöđüçéš ţàŕĝéţ çöñţéñţ
qualityschema.CategoryQualityṽàļîđàţéš à ţàŕĝéţ; þŕöđüçéš çĥéçķ öŕ ţéŕḿ ƒîñđîñĝš
analysisschema.CategoryAnalysisŕéàđ-öñļý ḿéţŕîçš àñđ ŕéþöŕţš
text-processingschema.CategoryTextProcessingŕéŵŕîţéš, šéĝḿéñţš, öŕ ŕéđàçţš šöüŕçé
convertschema.CategoryConvertƒöŕḿàţ çöñṽéŕšîöñ
pipelineschema.CategoryPipelineçöḿþöšîţé öŕ šüƃ-þîþéļîñé

ÎÖ ḿöđéļ​

Éàçĥ ţööļ đéçļàŕéš àñ ÎÖ çöñţŕàçţ îñ îţš ToolMeta (þàçķàĝé core/schema). Ţĥé çöñţŕàçţ îš éẋþŕéššéđ öṽéŕ IOPortš (ţýþéđ šţàñđ-öƒƒ ļàýéŕš öƒ à Ƃļöçķ, Ƒ-02) ŕàţĥéŕ ţĥàñ öṽéŕ çöàŕšé þàŕţ-ţýþé ñàḿéš: Consumes ļîšţš ţĥé þöŕţš à ţööļ ŕéàđš üþšţŕéàḿ àñđ Produces ţĥé þöŕţš îţ ŵŕîţéš. Àñ IOPort'š Type ñàḿéš àñ öṽéŕļàý ţýþé (term, qa, …), à ƃļöçķ-àññöţàţîöñ ţýþé (voice, …), öŕ à þšéüđö-þöŕţ (PortTarget / PortSource); îţš Side šàýš ŵĥîçĥ šîđé îţ þéŕţàîñš ţö; àñđ Optional ḿàŕķš à çöñšüḿéđ þöŕţ àš đéĝŕàđàƃļé ŕàţĥéŕ ţĥàñ ŕéǫüîŕéđ.

// core/schema/schema.go
type IOPort struct {
Type string // overlay type, annotation type, or "target"/"source"
Side model.Side // source | target
Optional bool // consumed: degrades without it, does more with it
Layer string // segmentation granularity; "" = primary
}

// PortTarget is the committed Target; PortSource is a rewritten source.
const (
PortTarget = "target"
PortSource = "source"
)

type ToolMeta struct {
ID string
Category string // one of the six canonical categories above
DisplayName string
Description string
Tags []string

// Requires declares external resources the tool needs at runtime:
// "target-language", "source-language", "memory", "terms", "credentials",
// "retryable". A tool that declares one and does not get it cannot run.
Requires []string

// Accepts declares optional resources the tool uses when the run has them
// ("memory", "target-language", "source-language"). A tool that declares
// one and does not get it still runs.
Accepts []string

// Cardinality declares how many locales the tool operates on per execution.
Cardinality LocaleCardinality

// DefaultLocale is an optional default for monolingual and bilingual tools.
DefaultLocale model.LocaleID

// Consumes / Produces are the IO contract. Non-Optional consumed
// ports are hard requirements the flow validator enforces.
Consumes []IOPort
Produces []IOPort

// SideEffects lists external systems this tool reads from or writes to.
SideEffects []SideEffect

// Recoverable marks a transformer that vaults the originals it removes
// and restores them later (redaction); the placement pass holds it to
// the remote-egress rule.
Recoverable bool

WritesOutput bool // CLI adds -o/--output when true
DefaultParallelBlocks int // concurrency for IO-bound tools
Aliases []string // alternative CLI command names
Internal bool // withheld from kapi exec, kapi tools and MCP; still a flow step
}

Ƒöŕ éẋàḿþļé recycle öþţîöñàļļý çöñšüḿéš šöüŕçé šéĝḿéñţàţîöñ àñđ þŕöđüçéš à ḿéḿöŕý-ḿàţçĥ àññöţàţîöñ, àñ àļţéŕñàţîṽé ţŕàñšļàţîöñ, àñđ target; qa ŕéǫüîŕéš à target àñđ þŕöđüçéš ţĥé qa öṽéŕļàý. Ţĥé ƒļöŵ ļöàđéŕ üšéš ţĥéšé çöñţŕàçţš ƒöŕ đàţà-ƒļöŵ ṽàļîđàţîöñ: à ƒļöŵ ŵĥöšé ţööļ ñééđš à þöŕţ ţĥàţ ñö üþšţŕéàḿ ţööļ öŕ ţĥé šöüŕçé ƃîñđîñĝ šüþþļîéš îš ŕéĵéçţéđ àţ ƃüîļđ (É-04).

Requires îš àļšö à çöñšţŕüçţîöñ ĥööķ. Ŵĥéñ à ţööļ đéçļàŕéš terms, ţĥé ŕüññéŕ öþéñš ţĥé þŕöĵéçţ'š ţéŕḿš šţöŕé àñđ ƃŕàçķéţš ţĥé ţööļ ŵîţĥ ţĥé ţéŕḿ šţàĝéš: term-lookup (þàçķàĝé terms) ŕüñš terms.Locate, ţĥé öñé þàšš öṽéŕ ţĥé ţéŕḿš šţöŕé àñđ ţĥé ŕéçîþé'š term_rules:, àñđ ŕéçöŕđš ŵĥéŕé đéçļàŕéđ ţéŕḿš àŕé üšéđ ŵîţĥöüţ ĝŕàđîñĝ ţĥéḿ; éñƒöŕçéḿéñţ ţĥéñ ĝŕàđéš ţĥé üšéš ƃý ţĥé ĝàţé'š öŵñ þöļîçý. Ŵĥéñ à ţööļ đéçļàŕéš memory, à çöñţéñţ-ḿéḿöŕý þŕöṽîđéŕ îš îñĵéçţéđ ƒŕöḿ --memory öŕ ţĥé þŕöĵéçţ'š öŵñ šţöŕé; Accepts: memory àšķš ƒöŕ ţĥé šàḿé þŕöṽîđéŕ ŵîţĥöüţ ƒàîļîñĝ ŵĥéñ ţĥéŕé îš ñöñé. Ţĥéšé šţàĝéš àŕé ƃüîļţ ƃý ţĥé ŕüññéŕ ŕàţĥéŕ ţĥàñ ŕéĝîšţéŕéđ, šö ţĥéý đö ñöţ àþþéàŕ îñ kapi tools; ţĥéý àŕé ĥöŵ à đéçļàŕàţîöñ îš ĥöñöüŕéđ.

Éṽéŕý ĝöṽéŕñéđ šţéþ ţàķéš îţš ţéŕḿîñöļöĝý üñđéŕ öñé ŕéçîþé ķéý, term_rules:, àš à ļîšţ öƒ profile.TermRule: öñé ţéŕḿ, ŵĥàţ ţö üšé îñšţéàđ, ĥöŵ ĥàŕđ îţ ƃîţéš, àñđ àñ öþţîöñàļ çöñçéþţ îđ ţĥàţ ţîéš îţ ţö ţĥé ţéŕḿš šţöŕé àñđ ţĥé ĝŕàþĥ. profile.TermRuleMap îš ţĥé šîñĝļé þŕöĵéçţîöñ îñţö ţĥé ḿàþ à þŕöḿþţ öŕ à çĥéçķ çöñšüḿéš, àñđ ţĥàţ ḿàþ ƒééđš ţĥé çöñţéẋţ ƒîñĝéŕþŕîñţ à ţàŕĝéţ'š Origin ŕéçöŕđš (Ƒ-02).

Ļöçàļé çàŕđîñàļîţý​

Ţööļš đéçļàŕé ĥöŵ ḿàñý ļöçàļéš ţĥéý öþéŕàţé öñ þéŕ éẋéçüţîöñ:

type LocaleCardinality string

const (
// Monolingual: operates on a single locale.
Monolingual LocaleCardinality = "monolingual"

// Bilingual: operates on exactly two locales, provided as a pair.
Bilingual LocaleCardinality = "bilingual"

// Multilingual: operates on N locales simultaneously.
Multilingual LocaleCardinality = "multilingual"
)

Çàŕđîñàļîţý đéšçŕîƃéš ĥöŵ ḿàñý ļöçàļéš à ţööļ ñééđš. Ŵĥîçĥ ļöçàļéš àŕé þŕöṽîđéđ àţ ŕüñţîḿé ƃý ţĥé ŕüññéŕ öŕ ƒļöŵ çöñƒîĝüŕàţîöñ, ñéṽéŕ ĥàŕđçöđéđ îñ ţĥé ţööļ.

Çàŕđîñàļîţý, ţöĝéţĥéŕ ŵîţĥ ţĥé target-language éñţŕý îñ Requires àñđ Accepts, àļšö đéçîđéš ŵĥéţĥéŕ à ŕüñ çàñ ñàḿé à ţàŕĝéţ ļàñĝüàĝé ƒöŕ ţĥé ţööļ. ToolMeta.TakesTargetLanguage ĥöļđš ƒöŕ à ƃîļîñĝüàļ öŕ ḿüļţîļîñĝüàļ ţööļ, àñđ ƒöŕ à ḿöñöļîñĝüàļ öñé ţĥàţ ŕéǫüîŕéš öŕ àççéþţš target-language öŕ ñàḿéš à DefaultLocale. À ţööļ ŵîţĥ ñö đéçļàŕéđ çàŕđîñàļîţý ţàķéš öñé. search-replace àñđ xml-validation àççéþţ îţ, ƃéçàüšé ţĥéý ŵöŕķ öñ ţĥé šöüŕçé àñđ, ŵĥéñ ţĥé ŕüñ ñàḿéš öñé, öñ ţĥàţ ţàŕĝéţ àš ŵéļļ. Ţĥàţ ţàŕĝéţ îš öñé ţĥé îñþüţ çàŕŕîéš, àš à ƃîļîñĝüàļ ƒîļé đöéš. À ḿöñöļîñĝüàļ îñþüţ çàŕŕîéš ñöñé, šö kapi exec case-transform app.json --target-lang fr ŵŕîţéš ţĥé ţŕàñšƒöŕḿéđ šöüŕçé ţö fr/app.json, öṽéŕ àñý ƒîļé àļŕéàđý ţĥéŕé. kapi exec <tool> đéçļàŕéš --target-lang ƒŕöḿ ţĥîš àñšŵéŕ, šö à ţööļ ţĥàţ ŵöŕķš öñ ţĥé šöüŕçé àļöñé, šüçĥ àš redact öŕ encoding-detect, öƒƒéŕš ñöñé. TestToolsDeclareTheTargetLanguageTheyRead îñ core/tools ĥöļđš ţĥé đéçļàŕàţîöñš ţö ŵĥàţ éàçĥ ţööļ'š çöñƒîĝ ƒàçţöŕý ŕéàđš.

Éṽéŕý kapi exec çöḿḿàñđ öƒƒéŕš --source-lang ƃéšîđé --format àñđ --encoding, ƃéçàüšé éṽéŕý ŕüñ þàššéš ţĥé šöüŕçé ļàñĝüàĝé ţö ţĥé ƒöŕḿàţ ŕéàđéŕ. Ţĥé ŕéàđéŕ ļàƃéļš éàçĥ ƃļöçķ ŵîţĥ îţ, àñđ þîçķš ƃý îţ ţĥé šöüŕçé ṽàŕîàñţ öƒ à ḿüļţîļîñĝüàļ ƒîļé ţĥàţ ñàḿéš ñöñé. À ḿöñöļîñĝüàļ ţööļ ŵĥöšé ŕéšüļţ àļšö đéþéñđš öñ ţĥé šöüŕçé ļàñĝüàĝé, àš šéĝḿéñţàţîöñ þîçķš îţš ŕüļéš ƃý îţ, đéçļàŕéš source-language îñ Accepts.

Üñîƒöŕḿ ļöçàļé àççéšš​

À ƃļöçķ ĥöļđš îţš çöñţéñţ àš þééŕ éđîţîöñš (Ƒ-02). Ţĥé éđîţîöñ ţĥé ƃļöçķ ŵàš ŕéàđ îñ, îñ ţĥé ļàñĝüàĝé SourceLocale ñàḿéš, àñçĥöŕš ţĥé đöçüḿéñţ šķéļéţöñ àñđ îñļîñé çöđé þöšîţîöñš, ƃüţ ţööļš šĥöüļđ ñöţ ñééđ ţö ķñöŵ ŵĥéţĥéŕ à ļöçàļé ñàḿéš ţĥàţ éđîţîöñ öŕ à ţŕàñšļàţîöñ; ţĥéý ĵüšţ ñééđ ţéẋţ ƒöŕ à ĝîṽéñ ļöçàļé:

// Text returns the plain text for a locale: the source text if the
// locale matches the Block's source locale, otherwise the target text.
func (b *Block) Text(locale LocaleID) string

// SetText writes text for a locale (source if it matches the source
// locale, otherwise a target).
func (b *Block) SetText(locale LocaleID, text string)

// HasLocale reports whether the Block has content for the locale.
func (b *Block) HasLocale(locale LocaleID) bool

À ƃîļîñĝüàļ ţööļ çöḿþàŕîñĝ [fr, de] çàļļš block.Text("fr") àñđ block.Text("de"): îđéñţîçàļ çöđé ŵĥéţĥéŕ fr îš šöüŕçé öŕ ţàŕĝéţ. SourceText() àñđ TargetText(locale) àŕé àṽàîļàƃļé ŵĥéñ à ţööļ šþéçîƒîçàļļý ñééđš ţĥé éđîţîöñ ţĥé ƃļöçķ ŵàš ŕéàđ îñ öŕ öñé ţŕàñšļàţîöñ, àñđ ţĥé ṽîéŵ'š SetEdition àñđ RemoveEdition ŵŕîţé àñý đéŕîṽéđ éđîţîöñ ƃý îţš ƒüļļ ķéý (model.EditionKey: ļöçàļé, ţöñé àñđ çĥàññéļ).

Šéĝḿéñţš: öñé îţéŕàţöŕ öṽéŕ šéĝḿéñţéđ àñđ üñšéĝḿéñţéđ ƃļöçķš​

À šéĝḿéñţ îš à šþàñ îñ ţĥé šéĝḿéñţàţîöñ öṽéŕļàý ŕàţĥéŕ ţĥàñ à šţŕüçţüŕàļ ţýþé (Ƒ-02), šö à ţööļ ţĥàţ ŵöŕķš þéŕ šéĝḿéñţ ŵöüļđ öţĥéŕŵîšé ŕéþéàţ ţĥé šàḿé ƃŕàñçĥ: îţéŕàţé ţĥé šþàñš ŵĥéñ à šéĝḿéñţàţîöñ öṽéŕļàý éẋîšţš, ţŕéàţ ţĥé ŵĥöļé ƃļöçķ àš öñé šéĝḿéñţ ŵĥéñ ñöñé đöéš, àñđ ḿàþ éàçĥ þéŕ-šéĝḿéñţ ŵŕîţé ƃàçķ îñţö ţĥé ŕîĝĥţ ŕüñ ŕàñĝé. Ţĥé ţööļ ṽîéŵš (core/tool/view.go) çàŕŕý ţĥàţ ƃŕàñçĥ öñçé:

type BlockView interface {
// SourceSegments yields the source segments of the given segmentation
// layer (LayerPrimary = primary), or one whole-block segment when none is
// present.
SourceSegments(layer string) iter.Seq[Segment]
}

type VariantView interface {
BlockView
// TargetSegments yields writable per-segment target production over the
// source segmentation of the given layer, splicing each segment's runs back
// into the block at the segment's range and preserving ignorable spans
// verbatim.
TargetSegments(loc model.LocaleID, layer string) iter.Seq[WritableSegment]
}

Ŕéàđš ŕéüšé Anchor.ExtractRuns; ŵŕîţéš üšé ţĥé îñṽéŕšé šþļîçé, ŵĥîçĥ ŕéšþéçţš ĥàļƒ-öþéñ ŕàñĝéš àñđ Span.Ignorable(). À šéĝḿéñţ ŕéàđš à ţŕàñšļàţîöñ'š ţéẋţ ţĥŕöüĝĥ ţĥàţ ţŕàñšļàţîöñ'š öŵñ šéĝḿéñţàţîöñ (Block.TargetSegmentation), ñéṽéŕ ţĥé šöüŕçé'š. À ţööļ ţĥàţ ŵàñţš ţĥé ŵĥöļé ƃļöçķ ķééþš üšîñĝ SourceRuns(); à ţööļ ţĥàţ ŵàñţš šéĝḿéñţš öþţš îñţö SourceSegments(""), öñ àñý šîđé àñđ àñý ñàḿéđ ļàýéŕ, àñđ þàîŕš ñàţüŕàļļý ŵîţĥ ţĥé alignment öṽéŕļàý ƒöŕ šöüŕçé-ţö-ţàŕĝéţ šéĝḿéñţ çöŕŕéšþöñđéñçé.

Šţàñđ-öƒƒ ţýþéš àñđ ţĥé þàýļöàđ ŕéĝîšţŕý​

Ţĥé šţàñđ-öƒƒ ţýþéš à ţööļ çöñšüḿéš àñđ þŕöđüçéš àŕé ţýþéđ šţŕîñĝ çöñšţàñţš (Ƒ-02). Þöšîţîöñàļ, ŕüñ-àñçĥöŕéđ ļàýéŕš üšé ţĥé OverlayType çöñšţàñţš; ƃļöçķ-šçöþéđ ḿéţàđàţà üšéš ţĥé àññöţàţîöñ-ķéý çöñšţàñţš. Ƃöţĥ àñ öṽéŕļàý šþàñ'š Value àñđ àñ àññöţàţîöñ ṽàļüé àŕé ţýþéđ þàýļöàđš; ţĥé ƒŕàḿéŵöŕķ ŕéĝîšţéŕš ţĥé ŵéļļ-ķñöŵñ çöñţéñţ þàýļöàđš, àñđ ƒöŕḿàţš àñđ þļüĝîñš ŕéĝîšţéŕ àđđîţîöñàļ ţýþéš àñđ ţĥéîŕ çöñšţŕüçţöŕš ṽîà öñé þàýļöàđ ŕéĝîšţŕý (model.RegisterPayload / model.NewPayload):

// Positional layers (Block.Overlays): core/model/overlay.go
const (
OverlaySegmentation OverlayType = "segmentation"
OverlayTerm OverlayType = "term"
OverlayEntity OverlayType = "entity"
OverlayCheck OverlayType = "qa"
OverlayAlignment OverlayType = "alignment"
OverlayTermCandidate OverlayType = "term-candidate"
)

// Block-scoped metadata (Block.Annotations): core/model/annotation_access.go
const (
AnnoNote = "note"
AnnoAltTranslation = "alt-translation"
AnnoMemoryMatch = "tm-match"
AnnoWordCount = "word-count"
AnnoVoice = "voice"
// …char-count, seg-count, comparison, repetition, entity-mapping,
// term-enforcement, scoping-report
)

À ĥàñđƒüļ öƒ ţĥéšé šţŕîñĝ ṽàļüéš ("tm-match" àƃöṽé, àñđ ţĥé ḿéḿöŕý àñđ ţéŕḿš šîđé 郃éçţš ƃéļöŵ) ķééþ šþéļļîñĝš ţĥé þŕöšé ĥàš ŕéţîŕéđ. Àññöţàţîöñ ķéýš àñđ šîđé-郃éçţ îđš àŕé à ŵîŕé àñđ šţöŕàĝé ƃöüñđàŕý, ŵĥéŕé ŕéñàḿîñĝ à ṽàļüé šþļîţš à ŕéçöŕđ ŕàţĥéŕ ţĥàñ ḿöṽîñĝ îţ. Ţĥé Ĝö îđéñţîƒîéŕš çàŕŕý ţĥé çüŕŕéñţ ṽöçàƃüļàŕý; ţĥé šţŕîñĝš ƃéĥîñđ ţĥéḿ đö ñöţ çĥàñĝé.

Éṽéŕý çĥéçķéŕ (ţéŕḿîñöļöĝý, đö-ñöţ-ţŕàñšļàţé, þļàçéĥöļđéŕ, ǫüàļîţý, ṽöîçé) ŵŕîţéš ţĥé šàḿé qa öṽéŕļàý (à core/check.FindingsAnnotation þàýļöàđ çàŕŕýîñĝ à []check.Finding þļüš à ŕöļļéđ-üþ šçöŕé), šö öñé šçöŕîñĝ, àññöţàţîöñ, àñđ ĝöṽéŕñàñçé þàţĥ šéŕṽéš ţĥéḿ àļļ.

À ţööļ'š Consumes/Produces ñàḿé ţĥéšé öṽéŕļàý àñđ àññöţàţîöñ ţýþéš, öŕ à þšéüđö-þöŕţ, šö ţĥé šàḿé ŕéĝîšţŕý ţĥàţ đîšçŕîḿîñàţéš à þàýļöàđ'š çöñçŕéţé ţýþé öñ ţĥé ŵîŕé îš ţĥé ṽöçàƃüļàŕý ţĥé ƒļöŵ ṽàļîđàţöŕ çĥéçķš ţĥé ÎÖ çöñţŕàçţ àĝàîñšţ.

Ţĥŕéé çöñšéǫüéñçéš ƒöļļöŵ ƒŕöḿ ṽàļîđàţîñĝ öñ ţĥé đéçļàŕéđ çöñţŕàçţ. À ŵŕöñĝ Consumes/Produces öñ à ƃüîļţ-îñ ţööļ ƃŕéàķš à ŕéàļ ƒļöŵ, šö éàçĥ ţööļ'š đéçļàŕàţîöñ îš àüđîţéđ àĝàîñšţ îţš àçţüàļ ŕéàđš àñđ ŵŕîţéš, ŵîţĥ àñ éñđ-ţö-éñđ ţéšţ þéŕ ƃüîļţ-îñ ƒļöŵ àš ţĥé ĝüàŕđŕàîļ. Ţĥé öṽéŕļàý àñđ àññöţàţîöñ ṽöçàƃüļàŕý îš öþéñ ţö þļüĝîñš (É-05) ţĥŕöüĝĥ model.RegisterPayload: à þļüĝîñ-đéƒîñéđ ţýþé çŕöššéš ţĥé þļüĝîñ ŵîŕé ƃý ţýþé ñàḿé àñđ ĴŠÖÑ, àñđ ŕéĥýđŕàţéš ţö îţš çöñçŕéţé ţýþé ŵĥéŕéṽéŕ ţĥé þàýļöàđ çöñšţŕüçţöŕ îš ŕéĝîšţéŕéđ. Àļîĝñḿéñţ îš ţĥé öñé ŕéļàţîöñàļ öṽéŕļàý: îţ ļîñķš à šöüŕçé šþàñ ţö à ţàŕĝéţ šþàñ, šö îţš þàýļöàđ çàŕŕîéš ţĥé çöüñţéŕþàŕţ ŕàñĝé ŵĥîļé ţĥé Overlay šĥàþé šţàýš šîñĝļé-šîđéđ.

Šîđé 郃éçţš​

Šîđé 郃éçţš àŕé à çļöšéđ šéţ öƒ ķñöŵñ éẋţéŕñàļ îñţéŕàçţîöñš:

type SideEffect string

const (
SideEffectMemoryRead SideEffect = "tm-read"
SideEffectMemoryWrite SideEffect = "tm-write"
SideEffectTermsRead SideEffect = "termbase-read"
SideEffectTermsWrite SideEffect = "termbase-write"
SideEffectAPICall SideEffect = "api-call"
SideEffectAnalytics SideEffect = "analytics"

// RemoteSourceEgress marks a tool that sends source content to a remote
// system, distinct from APICall: a local detector, terms, or
// content-memory lookup must not carry it, every cloud-provider call must.
SideEffectRemoteSourceEgress SideEffect = "remote-source-egress"

// ProcessExec marks a tool that hands block content to a program
// outside kapi (external-command), whatever that program does with it.
SideEffectProcessExec SideEffect = "process-exec"
)

Ḿöšţ šîđé-郃éçţ đéçļàŕàţîöñš àŕé îñƒöŕḿàţîöñàļ ḿéţàđàţà ƒöŕ ţĥé ƒļöŵ éđîţöŕ àñđ ţĥé đöçüḿéñţàţîöñ. Ţĥéý àŕé ñöţ éñƒöŕçéđ àţ ŕüñţîḿé: à ţööļ đéçļàŕîñĝ à ḿéḿöŕý ŵŕîţé šţîļļ ŕüñš ñöŕḿàļļý ŵîţĥ ñö çöñţéñţ ḿéḿöŕý çöñƒîĝüŕéđ; îţ šķîþš ţĥé ŵŕîţé. Ţĥîš ķééþš ţĥé ţööļ îñţéŕƒàçé šîḿþļé ŵĥîļé ĝîṽîñĝ ţĥé ÜÎ éñöüĝĥ îñƒöŕḿàţîöñ ţö ŵàŕñ ḿéàñîñĝƒüļļý. Ţĥé éẋçéþţîöñš àŕé RemoteSourceEgress àñđ ProcessExec. Ţĥé ţŕàñšƒöŕḿéŕ þļàçéḿéñţ þàšš àñđ ţĥé ŕéđàçţîöñ çöṽéŕàĝé çĥéçķ ķéý à ĥàŕđ ƃüîļđ éŕŕöŕ öƒƒ éàçĥ, àñđ à ţööļ ŵĥöšé ŕéḿöţéñéšš đéþéñđš öñ çöñƒîĝüŕàţîöñ (à ḿöđéļ ţööļ þöîñţéđ àţ à ļöçàļ ŕüñţîḿé öŕ ţĥé öƒƒļîñé đéḿö þŕöṽîđéŕ) ŕéƒîñéš RemoteSourceEgress àŵàý ţĥŕöüĝĥ îţš çöñţŕàçţ ŕéšöļṽéŕ. À šîñĝļé-ţööļ ŕüñ üñđéŕ à ŕéđàçţîöñ þöļîçý þļàçéš redact àĥéàđ öƒ à ţööļ ţĥàţ çàŕŕîéš ProcessExec öŕ APICall.

Ƒļöŵ ļöçàļé îñƒéŕéñçé​

Ţĥé ŕüññéŕ îñšþéçţš ţĥé ţööļ çĥàîñ'š çàŕđîñàļîţý đéçļàŕàţîöñš ţö đéţéŕḿîñé ŵĥîçĥ ļöçàļéš ţö þŕöçéšš. Ţĥîš îš ţĥé šîñĝļé àþþļîçàƃîļîţý-ƃàšéđ àñšŵéŕ ţö "ŵĥîçĥ ļöçàļéš đöéš ţĥîš ƒļöŵ ŕüñ ƒöŕ": ţĥé ÇĻÎ'š þŕöĵéçţ ƒļöŵ-ŕüñ àñđ ţĥé đéšķţöþ ŕüññéŕ ƃöţĥ ŕéšöļṽé ţĥéîŕ ļöçàļé þàššéš ţĥŕöüĝĥ îţ, šö ţĥé ţŵö šüŕƒàçéš çàññöţ đîšàĝŕéé. Çöñṽéŕĝéñçé (kapi up) îñţéñţîöñàļļý àñšŵéŕš à đéŕéñţ ǫüéšţîöñ ŵîţĥ à ñééđ-ƃàšéđ šéļéçţîöñ: öñļý ţĥé ļöçàļéš šţîļļ šĥöŕţ öƒ ţĥéîŕ šĥîþ ĝàţé ŕüñ à þàšš.

func ResolveFlowLocales(
spec *StepsSpec,
toolInfos map[registry.ToolID]registry.ToolInfo,
sourceLocale string,
projectTargets []string,
) [][]string

Ţĥé ŕüññéŕ þàššéš ţĥé ƒļöŵ'š *StepsSpec þļüš à ḿàþ ƒŕöḿ registry.ToolID ţö registry.ToolInfo, ŵĥîçĥ çàŕŕîéš éàçĥ ţööļ'š çàŕđîñàļîţý àñđ đéƒàüļţ-ļöçàļé ḿéţàđàţà.

Ŕéšöļüţîöñ ŕéţüŕñš à šļîçé öƒ ļöçàļé šéţš, öñé šéţ þéŕ éẋéçüţîöñ þàšš:

ƑļöŵŢööļšÞàššéš
çàšé-ţŕàñšƒöŕḿ[case-transform(mono)][[en]]
þšéüđö-ţŕàñšļàţé[pseudo-translate(bi, default:qps)][[en, qps]]
ţŕàñšļàţé[translate(bi)][[en, de], [en, fr], [en, ja], ...]
ţŕàñšļàţé+ǫà[translate(bi), qa(bi)][[en, de], [en, fr], ...]
çöḿþàŕé đé ṽš ƒŕ[comparison(bi)] ŵîţĥ çöñƒîĝ [de, fr][[de, fr]]
çŕöšš-ļöçàļé çĥéçķ[consistency-check(multi)][[en, de, fr, ja, nb, ar]]
ţŕàñšļàţé + þšéüđö[translate(bi), pseudo(bi, default:qps)][[en, de], [en, fr], ..., [en, qps]]

Ḿîẋéđ ƒļöŵš ŕéšöļṽé ţö ţĥé üñîöñ öƒ àļļ ñééđéđ þàššéš.

Þàŕàḿéţéŕ šçĥéḿàš​

Ţööļš đéçļàŕé þàŕàḿéţéŕ šçĥéḿàš ṽîà ţĥé tool.SchemaProvider îñţéŕƒàçé ŵîţĥ ComponentSchema îñ ţĥé core/schema/ þàçķàĝé:

type SchemaProvider interface {
Schema() *schema.ComponentSchema
}

type ComponentSchema struct {
ID string // "$id"
Version string // "$version"
Title string
Description string
Type string // "object"
ToolMeta *ToolMeta // tool identity (see above)
Groups []ParameterGroup // UI groupings ("ui:groups")
StepMeta *StepMeta // bridge step metadata, when applicable
Properties map[string]PropertySchema // parameter definitions
RawJSON json.RawMessage // full schema access
}

schema.FromStruct(cfg, meta) ĝéñéŕàţéš à ComponentSchema ƃý ŕéƒļéçţîñĝ öñ à Ĝö šţŕüçţ. Îţ šüþþöŕţš šţŕüçţ ţàĝš ƒöŕ àđđîţîöñàļ ḿéţàđàţà:

type PseudoConfig struct {
ExpansionPercent int `schema:"description=Text expansion percentage,min=0,max=200"`
Prefix string `schema:"description=Prefix for pseudo text"`
Suffix string `schema:"description=Suffix for pseudo text"`
InternalField string `schema:"-"` // excluded from schema
}

schema.ApplyConfig() ƃŕîđĝéš map[string]any çöñƒîĝüŕàţîöñ (ƒŕöḿ ƒļöŵ ÝÀḾĻ) ţö à ţýþéđ šţŕüçţ ṽîà à ĴŠÖÑ ŕöüñđ-ţŕîþ.

Ţĥé ToolRegistry šţöŕéš šçĥéḿàš àļöñĝšîđé ƒàçţöŕîéš ṽîà RegisterWithSchema(name, factory, schema). Àļļ ƃüîļţ-îñ ţööļš ŕéĝîšţéŕ àüţö-ĝéñéŕàţéđ šçĥéḿàš. Šçĥéḿà-đŕîṽéñ ƒéàţüŕéš:

  • ÇĻÎ ƒļàĝš: cli.RegisterSchemaFlags() àüţö-ĝéñéŕàţéš Çöƃŕà ƒļàĝš ƒŕöḿ ţĥé šçĥéḿà, ḿàþþîñĝ çàḿéļÇàšé þŕöþéŕţîéš ţö ķéƃàƃ-çàšé ƒļàĝš.
  • Ƒļöŵ éđîţöŕ: šçĥéḿà-đŕîṽéñ çöñƒîĝ þàñéļš ƒöŕ ţööļ ñöđéš, ŕéüšîñĝ ţĥé šàḿé éđîţöŕ çöḿþöñéñţ ţĥàţ đŕîṽéš ƒöŕḿàţ çöñƒîĝüŕàţîöñ.
  • Ṽàļîđàţîöñ: ComponentSchema.Validate() çĥéçķš þàŕàḿéţéŕ ṽàļüéš àĝàîñšţ ţĥé šçĥéḿà.
  • ĴŠÖÑ éẋþöŕţ: kapi tools schema <name> þŕîñţš ţĥé šçĥéḿà ƒöŕ àñý ţööļ.
  • ḾÇÞ éẋþöšüŕé: host/mcp_tools.go ŕéĝîšţéŕš éṽéŕý ÇĻÎ-ṽîšîƃļé ţööļ öñ ţĥé kapi mcp šţđîö šéŕṽéŕ, þŕöĵéçţîñĝ ţĥé ţööļ'š šçĥéḿà þļüš à text îñþüţ îñţö ţĥé ḾÇÞ îñþüţ šçĥéḿà àñđ ŕüññîñĝ ţĥé ţööļ öṽéŕ ţĥé šüþþļîéđ ţéẋţ. Ţĥé éẋþöšéđ šéţ îš šçöþéđ ƃý ḿöđé, ḿîŕŕöŕîñĝ ţĥé đéšķţöþ'š þŕöĵéçţ/àđ-ĥöç šþļîţ: îñšîđé à ķàþî þŕöĵéçţ öñļý ţĥé ţööļš ţĥé þŕöĵéçţ đéçļàŕéš àŕé àđṽéŕţîšéđ, ŵîţĥ ţĥé þŕöĵéçţ'š ţàŕĝéţ ļàñĝüàĝé àš ţĥé đéƒàüļţ; àđ-ĥöç, ţĥé ƒüļļ šéţ îš éẋþöšéđ. Ŕéšöüŕçé-ŵŕàþþîñĝ ĥéļþéŕš (ṽöîçé þŕöƒîļé, ţéŕḿš, çöñţéñţ ḿéḿöŕý) šţàý ĥàñđ-àüţĥöŕéđ îñ host/mcp_voice.go.

Ḿöđéļ-ƃàçķéđ ţööļ šçĥéḿàš îñçļüđé þŕöṽîđéŕ ƒîéļđš (þŕöṽîđéŕ, ÀÞÎ ķéý, ḿöđéļ, ŵîţĥ éñüḿ šüþþöŕţ ƒöŕ þŕöṽîđéŕ šéļéçţîöñ), šö ţĥéîŕ ÇĻÎ ƒļàĝš àŕé ĝéñéŕàţéđ ţĥé šàḿé ŵàý àš àñý öţĥéŕ ţööļ'š.

Ŕéĝîšţŕàţîöñ​

Ţööļš ŕéĝîšţéŕ îñţö à registry.ToolRegistry ŵîţĥ à ñàḿé, ƒàçţöŕý ƒüñçţîöñ, àñđ öþţîöñàļ þàŕàḿéţéŕ šçĥéḿà:

reg.RegisterWithSchema("pseudo-translate", func() tool.Tool {
return NewPseudoTranslateTool(&PseudoConfig{Prefix: "▒ ", Suffix: " ▒", TargetLocale: "qps"})
}, toolSchema(&PseudoConfig{Prefix: "▒ ", Suffix: " ▒"},
toolMeta("pseudo-translate", "Pseudo Translate", schema.CategoryTranslation, ...)))

Ţĥé ƒàçţöŕý îš à žéŕö-àŕĝüḿéñţ func() tool.Tool (registry.ToolFactory); îţ ŕéţüŕñš à ţööļ ƃüîļţ ƒŕöḿ à đéƒàüļţ çöñƒîĝ, ŵîţĥ ñö éŕŕöŕ ŕéţüŕñ. À šéþàŕàţé çöñƒîĝ ƒàçţöŕý (SetConfigFactory) ƃüîļđš ţĥé ţööļ ƒŕöḿ à çöñƒîĝ ḿàþ ŵĥéñ ƒļöŵ ÝÀḾĻ öṽéŕŕîđéš ţĥé đéƒàüļţš.

RegisterAll(reg) îñ core/tools/register.go àüţö-ŕéĝîšţéŕš àļļ ƃüîļţ-îñ ţööļš. Ţĥé ḿöđéļ-ƃàçķéđ ţööļš àŕé àüţö-ŕéĝîšţéŕéđ šéþàŕàţéļý ƃý aitools.RegisterAll àñđ mttools.RegisterAll (core/ai/tools, core/mt/tools), çàļļéđ àļöñĝšîđé ţĥé ƃüîļţ-îñš đüŕîñĝ àþþ îñîţ. Éàçĥ ŕéĝîšţéŕš ŵîţĥ à đéƒàüļţ öƒƒļîñé ƒàçţöŕý þļüš à çöñƒîĝ ƒàçţöŕý; ţĥé ŕéàļ þŕöṽîđéŕ îš ŕéšöļṽéđ ƒŕöḿ ţĥé çŕéđéñţîàļ-ƃéàŕîñĝ çöñƒîĝ ḿàþ àţ ţööļ-çŕéàţîöñ ţîḿé, ñöţ àţ ŕéĝîšţŕàţîöñ ţîḿé (É-07).

À þļüĝîñ ḿàñîƒéšţ çàñ đéçļàŕé ƒļöŵ ţööļš (capabilities.tools), àñđ ţĥé ŕéĝîšţŕý çàñ ļîšţ à ţööļ îţ çàññöţ ƃüîļđ (ToolRegistry.RegisterMetadata), ƃüţ ţĥé ĥöšţ ŕéĝîšţéŕš ñö þļüĝîñ ţööļ, šö à ƒļöŵ ŕüñš ţĥé ƃüîļţ-îñ ţööļš. À þļüĝîñ ŕéàçĥéš à ƒļöŵ ţĥŕöüĝĥ îţš ƒöŕḿàţš àñđ îţš šéĝḿéñţàţîöñ éñĝîñéš (É-05).

Ţööļ ĝŕöüþš (þļüĝĝàƃļé ƃàçķéñđš)​

Šöḿé ţööļš àŕé à ƒàḿîļý öƒ îñţéŕçĥàñĝéàƃļé ƃàçķéñđš ŕàţĥéŕ ţĥàñ öñé îḿþļéḿéñţàţîöñ: segmentation ŕüñš öñ ŠŔẊ ŕüļéš, ÜÀẊ-29, ţĥé ƃŕöŵšéŕ Intl.Segmenter, àñ ĻĻḾ, öŕ àñ ḾĻ šéĝḿéñţéŕ; qa ŕüñš đéţéŕḿîñîšţîç ŕüļéš öŕ àñ ĻĻḾ ĵüđĝé; translate ŕüñš àñý ḿöđéļ þŕöṽîđéŕ; entity-extract ŕüñš à ļöçàļ ÑÉŔ ḿöđéļ, àñ ĻĻḾ, öŕ ƃöţĥ. Éàçĥ ƃàçķéñđ çàŕŕîéš îţš öŵñ çöñƒîĝüŕàţîöñ àñđ ţĥé ƒàḿîļý ĥàš à šéñšîƃļé đéƒàüļţ.

À ţööļ ĝŕöüþ ḿöđéļš ţĥîš: à ţööļ ŵĥöšé ƃéĥàṽîöüŕ îš þŕöṽîđéđ ƃý öñé öƒ šéṽéŕàļ šéļƒ-đéšçŕîƃîñĝ ḿéḿƃéŕš, šéļéçţéđ ƃý à đîšçŕîḿîñàţöŕ ƒîéļđ, ŵîţĥ à đéƒàüļţ ḿéḿƃéŕ àñđ çöḿḿöñ çöñƒîĝ. Ţĥé üšéŕ þîçķš à ḿéḿƃéŕ àñđ çöñƒîĝüŕéš öñļý ţĥàţ öñé; ţĥé ĝŕöüþ ñéṽéŕ ḿéŕĝéš ḿéḿƃéŕš' þàŕàḿéţéŕš ţöĝéţĥéŕ.

reg.RegisterGroup(registry.ToolGroupDef{
Name: "segmentation",
Discriminator: "engine", // the config key that selects the member
Default: "srx",
Common: commonSchema, // discriminator + shared options + ToolMeta
Members: members, // each: Name, Label, Description, own Schema
ConfigFactory: NewSegmentationFromConfig, // dispatches on the discriminator
})

Ḿéḿƃéŕš àŕé ñöţ šéþàŕàţéļý-ŕéĝîšţéŕéđ ţööļš; ţĥéý ƃéļöñĝ ţö ţĥé ĝŕöüþ, àñđ ţĥé çàñđîđàţé ḿéḿƃéŕš àļŕéàđý éẋîšţ àš đöḿàîñ šüƃ-ŕéĝîšţŕîéš: šéĝḿéñţàţîöñ éñĝîñéš (Ḿ-02) àñđ ḿöđéļ þŕöṽîđéŕš (É-07).

À ḿéḿƃéŕ ḿàý çàŕŕý îţš öŵñ ƒàçţöŕý (ToolGroupMember.Factory). Ţĥé ĝŕöüþ'š ŕéĝîšţéŕéđ ConfigFactory đîšþàţçĥéš öñ ţĥé đîšçŕîḿîñàţöŕ: à ḿéḿƃéŕ ŵîţĥ à ƒàçţöŕý îš ƃüîļţ đîŕéçţļý, ţĥé ŕéšţ ƒàļļ ţĥŕöüĝĥ ţö ţĥé ĝŕöüþ'š ƒàçţöŕý. Ţĥîš îš ţĥé šéàḿ ƒöŕ ŕüñţîḿé-çöñţŕîƃüţéđ ḿéḿƃéŕš: RegisterGroup đéƒîñéš ţĥé ƃüîļţ-îñ ḿéḿƃéŕš, àñđ AddGroupMember(group, member) àþþéñđš öñé ļàţéŕ (ŕéçöḿþöšîñĝ ţĥé ƒļàţ šçĥéḿà, MemberSchema, ţĥé ToolInfo.Group ḿéţàđàţà, àñđ ţĥé đîšþàţçĥéŕ), šö à šöüŕçé öüţšîđé ţĥé ĝŕöüþ'š öŵñ þàçķàĝé çàñ éẋţéñđ îţ ŵîţĥöüţ ţĥàţ þàçķàĝé ķñöŵîñĝ. Ţĥé đîšçŕîḿîñàţöŕ ṽàļüé šéļéçţš ţĥé ŕîĝĥţ ƃàçķéñđ, ƃüîļţ-îñ öŕ çöñţŕîƃüţéđ.

Ƒöŕ þļüĝîñ-çöñţŕîƃüţéđ ḿéḿƃéŕš, šéĝḿéñţàţîöñ ŵîŕéš îţš éñĝîñéš ƒŕöḿ ţĥé ḿàñîƒéšţ segmenters[] çàþàƃîļîţý îñţö ţĥé šéĝḿéñţàţîöñ éñĝîñé šüƃ-ŕéĝîšţŕý öṽéŕ à đéđîçàţéđ Segment ŔÞÇ (É-05); šéĝḿéñţàţîöñ ḿéḿƃéŕš àŕé ñàŕŕöŵ šüƃ-çöḿþöñéñţš (ţéẋţ → ƃöüñđàŕîéš), ñöţ ƒüļļ ţööļš. Ţĥé öţĥéŕ ĝŕöüþš' ḿéḿƃéŕš àŕé ƒüļļ ƃļöçķ-þŕöçéššîñĝ ţööļš; à ḿàñîƒéšţ àñđ đàéḿöñ ţŕàñšþöŕţ ƒöŕ çöñţŕîƃüţîñĝ ţĥöšé îš ñöţ ýéţ ƃüîļţ.

À ĝŕöüþ îš à šîñĝļé ŕéĝîšţŕý éñţŕý, šö ƒļàţ çöñšüḿéŕš àŕé üñàƒƒéçţéđ; îţ šéŕṽéš ţŵö ŕéñđéŕîñĝš ƒŕöḿ öñé đéƒîñîţîöñ:

  • Ḿàšţéŕ-đéţàîļ (ţĥé çöñƒîĝ ÜÎ, ţĥé đöçš ŕéƒéŕéñçé) ŕéàđš ToolInfo.Group (ḿéḿƃéŕš, đéƒàüļţ, đîšçŕîḿîñàţöŕ) àñđ MemberSchema(group, member), àñđ ŕéñđéŕš ţĥé çöḿḿöñ ƒîéļđš þļüš à ḿéḿƃéŕ šéļéçţöŕ þļüš öñļý ţĥé šéļéçţéđ ḿéḿƃéŕ'š öŵñ šçĥéḿà. Ñöţĥîñĝ îš ḿéŕĝéđ öŕ ĥîđđéñ.
  • Ƒļàţ þŕöĵéçţîöñ (ÇĻÎ ƒļàĝš, ḾÇÞ îñþüţ, àñđ ţĥé ŕéĝîšţŕý'š Schema(id)) îš îñĥéŕéñţļý ƒļàţ (çöƃŕà ƒļàĝš àñđ à šîñĝļé îñþüţ šçĥéḿà çàññöţ ƃé šéļéçţéđ îñţö àţ þàŕšé ţîḿé), šö ţĥé ĝŕöüþ þŕöĵéçţš ţö öñé šçĥéḿà ṽîà schema.ComposeVariants: à đîšçŕîḿîñàţöŕ select þļüš éàçĥ ḿéḿƃéŕ'š ƒîéļđš, ĝŕöüþéđ àñđ ĝàţéđ ţö ţĥéîŕ ḿéḿƃéŕ. ComposeVariants îš ţĥéŕéƒöŕé à þŕöĵéçţîöñ öƒ à ĝŕöüþ, ñöţ ţĥé ḿöđéļ.

Ţĥé đîšçŕîḿîñàţöŕ çàŕŕîéš à đéƒàüļţ, šö ţĥé ƃàŕé ţööļ ŵöŕķš ŵîţĥ ñö çöñƒîĝüŕàţîöñ. À qa çöñƒîĝ šéļéçţš îţš ƃàçķéñđ ŵîţĥ mode àļöñé; à provider šéļéçţš ñöţĥîñĝ.

Àññöţàţîöñ-ƃàšéđ çöḿḿüñîçàţîöñ​

Ţööļš çöḿḿüñîçàţé ţĥŕöüĝĥ öṽéŕļàýš àñđ àññöţàţîöñš öñ Ƃļöçķš. À ţýþîçàļ þîþéļîñé:

sourcechanentity-extractchanrecyclechantranslatechanterm-checkchanqachansink
  • entity-extract àđđš OverlayEntity ŵîţĥ ñàḿéđ éñţîţîéš àñđ ţéŕḿ çàñđîđàţéš.
  • recycle ŕéàđš éñţîţý àññöţàţîöñš ƒöŕ ĝéñéŕàļîžéđ ḿàţçĥîñĝ àñđ àđđš àñ àļţéŕñàţîṽé ţŕàñšļàţîöñ.
  • translate ŕéàđš ţéŕḿ àñđ éñţîţý àññöţàţîöñš ƒöŕ çöñţéẋţ-àŵàŕé ţŕàñšļàţîöñ.
  • term-check ṽéŕîƒîéš ţéŕḿîñöļöĝý çöñšîšţéñçý îñ ţĥé ţàŕĝéţ.
  • qa ṽàļîđàţéš ţŕàñšļàţîöñ ǫüàļîţý.

Éàçĥ ţööļ ŕéàđš ţĥé àññöţàţîöñš îţ çàŕéš àƃöüţ àñđ àđđš îţš öŵñ, ķééþîñĝ ţööļš ļööšéļý çöüþļéđ ţĥŕöüĝĥ à šĥàŕéđ đàţà ḿöđéļ ŕàţĥéŕ ţĥàñ đîŕéçţ đéþéñđéñçîéš.

Ƃüîļţ-îñ ţööļ îñṽéñţöŕý​

Àļļ ƃüîļţ-îñ ţööļš ŕéĝîšţéŕ ṽîà RegisterAll() îñ core/tools/register.go; ţĥé ḿöđéļ-ƃàçķéđ öñéš ŕéĝîšţéŕ ƒŕöḿ core/ai/tools àñđ core/mt/tools. Ţĥé àüţĥöŕîţàţîṽé ļîšţ ŵîţĥ éṽéŕý þàŕàḿéţéŕ îš ţĥé ĝéñéŕàţéđ Ţööļ Ŕéƒéŕéñçé; ţĥé çàţéĝöŕîéš ƃéļöŵ àŕé ţĥé šĥàþé öƒ îţ.

Ţŕàñšļàţîöñ (þŕöđüçé ţàŕĝéţ çöñţéñţ): translate (à ḿöđéļ þŕöṽîđéŕ), recycle (çöñţéñţ ḿéḿöŕý, éẋàçţ àñđ ƒüžžý), diff-leverage (ŕéüšé ƒŕöḿ à þŕéṽîöüš đöçüḿéñţ ṽéŕšîöñ), pseudo-translate (đéţéŕḿîñîšţîç ţŕàñšļàţîöñ-ŕéàđîñéšš ţéšţîñĝ), translate-after.

Ǫüàļîţý (ṽàļîđàţé ŵîţĥöüţ ŕéŵŕîţîñĝ çöñţéñţ): qa (ŕüļé-ƃàšéđ, öŕ àñ ĻĻḾ ĵüđĝé ŵîţĥ mode: ai), review (þéŕ-ţŕàñšļàţîöñ šçöŕé, àššéššḿéñţ àñđ šüĝĝéšţîöñ), term-check, dnt-check (àļîàš dnt), placeholder-check, voice-check, voice-vocab-check, xml-validation.

Ţĥé qa çĥéçķšéţ àļšö çàŕŕîéš ļéñĝţĥ çöñšţŕàîñţš (ŕàţîö àñđ àƃšöļüţé çĥàŕàçţéŕ àñđ ŵöŕđ ļîḿîţš), îñṽàļîđ öŕ ƒöŕƃîđđéñ çĥàŕàçţéŕš àñđ çĥàŕšéţ çöñƒöŕḿàñçé, ŕéĝéẋ þàţţéŕñ ŕüļéš (ŕéǫüîŕéđ àñđ ƒöŕƃîđđéñ), àñđ çŕöšš-ƃļöçķ ţŕàñšļàţîöñ çöñšîšţéñçý, ŕàţĥéŕ ţĥàñ šþļîţţîñĝ éàçĥ ŕüļé ƒàḿîļý îñţö îţš öŵñ ţööļ.

Àñàļýšîš (ŕéàđ-öñļý ḿéţŕîçš àñđ ŕéþöŕţš): entity-extract, term-extract, voice-infer, encoding-detect.

Ţéẋţ þŕöçéššîñĝ (ŕéŵŕîţé, šéĝḿéñţ, öŕ ŕéđàçţ): case-transform, search-replace, whitespace-correct, inline-codes-remove, span-classify, tag-protect, properties-set, create-target, remove-target, segmentation, media-refine, redact, unredact, þļüš ţĥé šţŕéàḿ-šĥàþîñĝ batch, layer-processor, external-command, àñđ script.

Ƃýţé-ļéṽéļ öüţþüţ šţýļé (ƂÖḾ, ñéŵļîñéš, çĥàŕšéţ) îš ŵŕîţéŕ çöñƒîĝüŕàţîöñ, ñöţ à þîþéļîñé šţàĝé: šéţ output.bom / output.newline / output.encoding üñđéŕ àñý ƒöŕḿàţ'š çöñƒîĝ àñđ éṽéŕý ŵŕîţéŕ àþþļîéš ţĥéḿ àš à šĥàŕéđ þöšţ-éñçöđé šţéþ (É-02).

external-command àñđ script àŕé ţĥé éẋéç çļàšš: ţĥéîŕ ĵöƃ îš ţö ŕüñ çöđé ţĥé çöñƒîĝüŕàţîöñ ñàḿéš, ŕàţĥéŕ ţĥàñ ţö ţŕàñšƒöŕḿ çöñţéñţ ŵîţĥ çöđé ķàþî šĥîþš. Ţĥéý àŕé öŕđîñàŕý ţööļš öñ ţĥé çöḿḿàñđ ļîñé (kapi exec ŕüñš ƃöţĥ), ƃüţ à ŕéçîþé çàññöţ àŕḿ öñé šîļéñţļý. Ŵĥîçĥ šüŕƒàçéš ḿàý ñàḿé ţĥéḿ, àñđ ĥöŵ à ŕéçîþé àšķš, îš É-06.

Ḿöđéļ-ƃàçķéđ ţööļš​

Ḿöđéļ-ƃàçķéđ ţööļš àŕé ŕéĝîšţéŕéđ àţ šţàŕţüþ ļîķé ţĥé öţĥéŕ ƃüîļţ-îñš, šö ţĥéý àþþéàŕ îñ kapi tools àñđ ŕéšöļṽé îñ ƒļöŵš. Ţĥéîŕ đîšţîñĝüîšĥîñĝ ţŕàîţ îš þŕöṽîđéŕ îñĵéçţîöñ: ţĥé ŕéĝîšţŕý ĥöļđš à đéƒàüļţ öƒƒļîñé-þŕöṽîđéŕ ƒàçţöŕý, àñđ ţĥé ŕéàļ þŕöṽîđéŕ, ŵîţĥ çŕéđéñţîàļš, îš šüþþļîéđ öñ đéḿàñđ ṽîà ţĥé çöñƒîĝ ƒàçţöŕý ŵĥéñ ţĥé ţööļ îš îñšţàñţîàţéđ. Ţĥéý üšé ţĥé šàḿé Tool îñţéŕƒàçé àñđ ŵöŕķ îđéñţîçàļļý îñ ƒļöŵš. Ţŕàñšļàţîöñ îš öñé translate ţööļ àçŕöšš éṽéŕý ƃàçķéñđ, ŵîţĥ ţĥé ƃàçķéñđ çĥöšéñ ƃý --provider, àñđ ǫüàļîţý öñé qa ţööļ, ŵîţĥ ţĥé ƃàçķéñđ çĥöšéñ ƃý --mode (É-07).

Ƒļöŵ šţéþš ƒöŕḿàţ​

Ƒļöŵš àŕé àüţĥöŕéđ àš à ÝÀḾĻ šţéþ ļîšţ. Ţĥé þàŕšéŕ çöḿþîļéš ţĥé ļîšţ ţö ţĥé đéƒîñîţîöñ ĝŕàþĥ, àñđ ţĥé ĥöšţ ƃüîļđš ţĥé öŕđéŕéđ ţööļ çĥàîñ ţĥàţ ŕüñš (É-01):

À ƒļöŵ'š šöüŕçé àñđ šîñķ àŕé çöñţéẋţ-ŕéšöļṽéđ ƃîñđîñĝš (É-04), ñöţ ƒîéļđš öƒ ţĥé ƒļöŵ đöçüḿéñţ; ţĥé šţéþš çàŕŕý öñļý ţĥé çöḿþöšîţîöñ.

apiVersion: v1
kind: FlowDefinition
metadata:
name: Production Pipeline
spec:
steps:
- tool: recycle
config:
fuzzyThreshold: 75
- tool: translate
config:
provider: anthropic
- tool: qa
- tool: term-check
- tool: xml-validation

Šţéþš ŕüñ îñ ţĥé öŕđéŕ ļîšţéđ. Ţĥé đéƒîñîţîöñ þàŕšéŕ àļšö àççéþţš à parallel: ƃļöçķ, ŵĥîçĥ ñö ĥöšţ þàţĥ ŕüñš àš çöñçüŕŕéñţ ƃŕàñçĥéš. Ţĥé script šţéþ ļéţš àüţĥöŕš đŕöþ îñ çüšţöḿ ĴàṽàŠçŕîþţ ŵĥéñ ñö éẋîšţîñĝ ţööļ ƒîţš.

Ḿüţàƃļé šţŕéàḿîñĝ ḿöđéļ​

Ţööļš ḿöđîƒý Ƃļöçķš îñ þļàçé àš ţĥéý ƒļöŵ ţĥŕöüĝĥ çĥàññéļš. Ţĥîš îš à đéļîƃéŕàţé ţŕàđé-öƒƒ:

  • Þéŕƒöŕḿàñçé: ñö çöþýîñĝ öŕ đéļţà àççüḿüļàţîöñ ƒöŕ ĥîĝĥ-ṽöļüḿé šţŕéàḿîñĝ; žéŕö àļļöçàţîöñ þéŕ ţööļ ƒöŕ þàšš-ţĥŕöüĝĥ Þàŕţ ţýþéš.
  • Šîḿþļîçîţý: ţööļš ŕéàđ àñđ ŵŕîţé ƒîéļđš öñ ţĥé šàḿé Ƃļöçķ. Ñö îḿḿüţàƃļé ƃüîļđéŕš, ļéñšéš, öŕ þàţçĥ àþþļîçàţîöñ.
  • Þŕöṽéñ þàţţéŕñ: ţĥé Öķàþî Ƒŕàḿéŵöŕķ, ţĥé Ĵàṽà çöñţéñţ àñđ ţŕàñšļàţîöñ ƒŕàḿéŵöŕķ ñéöķàþî ŕéîḿàĝîñéš, üšéš ţĥé šàḿé ḿüţàƃļé-éṽéñţ ḿöđéļ àçŕöšš ţĥöüšàñđš öƒ þŕöđüçţîöñ ŵöŕķƒļöŵš.

Đöçüḿéñţ-ļéṽéļ îḿḿüţàƃîļîţý îš àçĥîéṽéđ ƃý éẋţéŕñàļ šţöŕàĝé ļàýéŕš ţĥàţ ṽéŕšîöñ éñţîŕé Ƃļöçķ šţàţéš. Ŵîţĥîñ à šîñĝļé þîþéļîñé éẋéçüţîöñ, ḿüţàƃļé šţŕéàḿîñĝ îš ţĥé ŕîĝĥţ ţŕàđé-öƒƒ.

Šţàĝéš þàšš ţĥé šàḿé Ƃļöçķ ƒŕöḿ öñé ţö ţĥé ñéẋţ, šö šéñđîñĝ à Þàŕţ öñ à çĥàññéļ ĥàñđš ŕéšþöñšîƃîļîţý ƒöŕ îţš Ƃļöçķ ţö ţĥé ŕéçéîṽéŕ: à ĥàñđļéŕ ƒîñîšĥéš îţš ŵŕîţéš ƃéƒöŕé ţĥé Þàŕţ îš éḿîţţéđ àñđ ļéàṽéš ţĥé Ƃļöçķ àļöñé àƒţéŕŵàŕđš. ParallelBlockTool ŕéļîéš öñ ţĥîš, šîñçé éàçĥ öƒ îţš ŵöŕķéŕš ĥöļđš à đîšţîñçţ Ƃļöçķ. À çàļļéŕ ţĥàţ šéñđš öñé Ƃļöçķ ţö šéṽéŕàļ çöñçüŕŕéñţ ŕéçéîṽéŕš, àš tool.Tee đöéš, ĥàš ţö àđđ îţš öŵñ çööŕđîñàţîöñ.

Çöñţéñţ îḿḿüţàƃîļîţý ƃý çàþàƃîļîţý​

À ţööļ'š ŵŕîţé šüŕƒàçé îš à çöḿþîļé-ţîḿé þŕöþéŕţý: îţ đéçļàŕéš ŵĥàţ îţ ḿàý ŵŕîţé ƃý ŵĥîçĥ ƃļöçķ ĥàñđļéŕ îţ šéţš öñ BaseTool, àñđ ţĥé ĥàñđļéŕ'š þàŕàḿéţéŕ ţýþé ḿàķéš ţĥé ŵŕöñĝ ŵŕîţéš üñŕéþŕéšéñţàƃļé.

ĤàñđļéŕṼîéŵḾàý ŵŕîţé
Annotate(BlockView)šöüŕçé + ţàŕĝéţ ŕéàđ-öñļýöṽéŕļàýš, àññöţàţîöñš, þŕöþéŕţîéš
Produce(VariantView)šöüŕçé ŕéàđ-öñļýđéŕîṽéđ éđîţîöñš (ţŕàñšļàţîöñš, àñđ ţöñé öŕ çĥàññéļ éđîţîöñš ƃý ķéý), þļüš ţĥé àƃöṽé
Transform(BlockView)šöüŕçé + ţàŕĝéţ ŕéàđ-öñļýàñ éđîţ þļàñ ţĥé ƒŕàḿéŵöŕķ àþþļîéš ţö šöüŕçé
  • Àñàļýšîš àñđ çĥéçķ ţööļš (qa, term-check, entity-extract, ţĥé šéĝḿéñţéŕ) šéţ Annotate. BlockView éẋþöšéš ñö šöüŕçé öŕ ţàŕĝéţ šéţţéŕ, šö ţĥéý çàññöţ ḿüţàţé çöñţéñţ; ţĥéý éḿîţ öṽéŕļàýš, àññöţàţîöñš, àñđ þŕöþéŕţîéš.
  • Ţàŕĝéţ-þŕöđüçîñĝ ţööļš (translate, recycle, create-target) šéţ Produce àñđ ŵŕîţé ţàŕĝéţš; šöüŕçé šţàýš ŕéàđ-öñļý.
  • Ţŕàñšƒöŕḿéŕš (ŕéđàçţîöñ, ñöŕḿàļîžàţîöñ, çàšé àñđ éñçöđîñĝ çöñṽéŕšîöñ) àŕé ţĥé öñļý ţööļš ţĥàţ ŕéŵŕîţé ţĥé éđîţîöñ à ƃļöçķ ŵàš ŕéàđ îñ, àñđ ţĥéý ñéṽéŕ đö šö đîŕéçţļý. À ţŕàñšƒöŕḿéŕ îš à ŕéàđ-öñļý éđîţ þŕöđüçéŕ: îţ îñšþéçţš ţĥé ƃļöçķ àñđ ŕéţüŕñš àñ éđîţ þļàñ: à šéţ öƒ šţŕüçţüŕéđ model.RunEditš (à šþàñ → ŕéþļàçéḿéñţ ḿàþ), îñ-þļàçé ţéẋţ éđîţš ţĥàţ ķééþ ţĥé îñļîñé çöđéš, šţŕüçţüŕé àñđ ŕüñ ƒļàĝš ţĥéý ļéàṽé àļöñé (à šüƃšţîţüţîöñ, à çàšé çöñṽéŕšîöñ), àñý öŕîĝîñàļš ţö ṽàüļţ (ŕéçöṽéŕàƃļé ţŕàñšƒöŕḿéŕš šüçĥ àš ŕéđàçţîöñ), öŕ àñ öþàǫüé ŵĥöļé-ƃļöçķ ŕéþļàçéḿéñţ ƒöŕ ŕéŵŕîţéš ŵîţĥ ñö đéŕîṽàƃļé ḿàþþîñĝ. À šîñĝļé ƒŕàḿéŵöŕķ-öŵñéđ àþþļîéŕ ṽàüļţš àñý šéçŕéţš ƒîŕšţ, ţĥéñ çöḿþîļéš ţĥé þļàñ îñţö çĥàñĝé öþéŕàţîöñš (EditPlan.Ops) àñđ àþþļîéš ţĥéḿ ţĥŕöüĝĥ change.ApplyBlock, ŵĥîçĥ àþþļîéš ţĥé éđîţš, ŕéƃàšéš ţĥé šüŕṽîṽîñĝ ŕüñ-àñçĥöŕéđ öṽéŕļàýš öƒ ţĥé ŕéŵŕîţţéñ éđîţîöñ öñçé (model.RemapOverlays) šö šéĝḿéñţàţîöñ, ţéŕḿš, àñđ éñţîţîéš ƒöļļöŵ ţĥé ŕéŵŕîţé, àñđ ƃöüñđš-çĥéçķš ţĥé ŕéšüļţ, àļļ àţöḿîçàļļý. Ƃéçàüšé ţööļ çöđé ĥöļđš ñö šöüŕçé šéţţéŕ, à ţŕàñšƒöŕḿéŕ çàññöţ çöŕŕüþţ ŕüñ-àñçĥöŕîñĝ öŕ ļéàķ à šéçŕéţ; àñ öþàǫüé ŵĥöļé-ƃļöçķ ŕéþļàçéḿéñţ đŕöþš ţĥé öṽéŕļàýš îţ çàññöţ ŕéƃàšé. Ŕéçöṽéŕàƃļé ţŕàñšƒöŕḿéŕš ķééþ ţĥé öŕîĝîñàļ îñ à ƃļöçķ àññöţàţîöñ öŕ à šîđéçàŕ ṽàüļţ àñđ ŕéšţöŕé îţ öñ ţĥé ŵàý öüţ. Ţĥé àþþļîéŕ ŕéþļàçéš à šöüŕçé ţĥŕöüĝĥ Block.EditSourceRuns, ŵĥîçĥ ķééþš ţĥé šöüŕçé ţĥé ŕéàđéŕ þŕöđüçéđ, šö à ŵŕîţéŕ çàñ ţéļļ à ŕéŵŕîţţéñ ƃļöçķ ƒŕöḿ àñ üñţöüçĥéđ öñé (Block.SourceAsRead): îţ ŵŕîţéš àñ üñţöüçĥéđ ƃļöçķ àš îţ ŵàš ŕéàđ àñđ éñçöđéš ţĥé ñéŵ ŵöŕđîñĝ öƒ à ŕéŵŕîţţéñ öñé ƒöŕ îţš ƒöŕḿàţ.

Ţĥé ŕéàđ ṽîéŵš ĥàñđ ƃàçķ ţĥé ƃļöçķ'š ļîṽé ŕüñ šļîçéš, ŵĥîçĥ Ĝö çàññöţ ḿàķé đééþļý îḿḿüţàƃļé ŵîţĥöüţ çöþýîñĝ. Šö à ƃàçķšţöþ îñ BaseTool'š ƃļöçķ đîšþàţçĥ çöñţéñţ-ĥàšĥéš šöüŕçé àñđ ţàŕĝéţš àŕöüñđ éàçĥ ĥàñđļéŕ àñđ éŕŕöŕš îƒ à ĥàñđļéŕ éđîţéđ à šüŕƒàçé îţš çàþàƃîļîţý ƒöŕƃîđš, çàţçĥîñĝ îñ-þļàçé éđîţš ḿàđé ţĥŕöüĝĥ ţĥöšé àļîàšéđ šļîçéš. Ĥàšĥîñĝ éṽéŕý ƃļöçķ ţŵîçé þéŕ ĥàñđļéŕ îš đéṽ àñđ ţéšţ ţööļîñĝ, ñöţ þŕöđüçţîöñ ŵöŕķ, šö îţ îš öƒƒ üñļéšš à çàļļéŕ àšķš ƒöŕ îţ: àñ éẋéçüţöŕ öþţš à ŵĥöļé ŕüñ îñ ŵîţĥ flow.WithImmutabilityCheck, àñý đîšþàţçĥ þàţĥ öþţš îñ þéŕ çöñţéẋţ ŵîţĥ tool.WithImmutabilityCheck, àñđ ţĥé ţööļ, ţööļš, àñđ ƒļöŵ ţéšţ šüîţéš ţüŕñ îţ öñ ƒöŕ éṽéŕý ţéšţ. change.ApplyBlock ļîķéŵîšé àššéŕţš ţĥàţ éṽéŕý šüŕṽîṽîñĝ öṽéŕļàý šþàñ öñ àñ éđîţîöñ îţ ŕéŵŕîţéš šţîļļ ŕéšöļṽéš îñ ƃöüñđš àĝàîñšţ ţĥé ñéŵ ŕüñš, öñ ţĥé šöüŕçé àñđ öñ éṽéŕý ţàŕĝéţ, šö à ŕéƃàšé ţĥàţ ļéƒţ àñ öṽéŕļàý đàñĝļîñĝ îš ŕéĵéçţéđ; ţĥàţ çĥéçķ îš üñçöñđîţîöñàļ.

À ĥàñđļéŕ'š ṽîéŵ àþþļîéš îţš ŵŕîţéš ţĥé šàḿé ŵàý. Éàçĥ ţàŕĝéţ ŵŕîţé, þŕöṽéñàñçé šţàḿþ àñđ öṽéŕļàý ŵŕîţé îš àñ öþéŕàţîöñ àþþļîéđ àţ öñçé ţĥŕöüĝĥ change.ApplyBlock, àš ţĥé ţööļ, šö à ĥàñđļéŕ ŕéàđš ŵĥàţ îţ ŵŕöţé: à ñéŵ ţàŕĝéţ îţ šţàḿþš ķééþš ţĥé šţàḿþ. À ţööļ'š ŵŕîţé ţĥàţ çĥàñĝéš à ţàŕĝéţ'š ŵöŕđîñĝ ḿàķéš ţĥé ţàŕĝéţ à đŕàƒţ, šîñçé ñöƃöđý ĥàš ŕéàđ ŵĥàţ ţĥé ţööļ ŵŕöţé, àñđ ķééþš ţĥé öŕîĝîñ ţĥàţ ñàḿéš ŵĥö þŕöđüçéđ îţ; à ţööļ ŕéçöŕđš ŵĥàţ îţ þŕöđüçéđ îţšéļƒ ŵîţĥ îţš šţàḿþ. À ţàŕĝéţ ŵŕîţé îñ ţĥé ƃļöçķ'š šöüŕçé ļàñĝüàĝé ŕéàçĥéš à ţàŕĝéţ ţĥé ƃļöçķ ĥöļđš îñ ţĥàţ ļàñĝüàĝé, àñđ îš ŕéƒüšéđ ŵĥéñ ţĥé ƃļöçķ ĥöļđš ñöñé, šö îţ ñéṽéŕ ŕéþļàçéš ţĥé šöüŕçé. À ŵŕîţé ţĥé àþþļîéŕ ŕéƒüšéš îš ţĥé ĥàñđļéŕ'š éŕŕöŕ. Ţĥé çöñţŕàçţ ţĥé öþéŕàţîöñš ƒöļļöŵ îš îñ ţĥé çĥàñĝé àþþļîéŕ ñöţé.

Ŵĥàţ à ŕüñ'š ţööļš ļéàṽé îñ éàçĥ ƃļöçķ ŕéàçĥéš à ƒîļé ţĥŕöüĝĥ ţĥé ƒöŕḿàţ ŵŕîţéŕ àñđ ţĥé ƒîļé ĥöḿé à çĥàñĝé šéţ çöḿḿîţš ţĥŕöüĝĥ (É-01), àñđ îñšîđé à þŕöĵéçţ ţĥé ķàþî ĥöšţ ŕéçöŕđš éàçĥ đöçüḿéñţ ţĥé ŕüñ ŵŕöţé àš ţĥé ƒļöŵ'š content.edit (É-09): ţĥé ŕéṽîšîöñš öƒ ţĥé éđîţîöñš ţĥé ŕüñ ḿöṽéđ, éàçĥ ţŕàñšļàţîöñ'š ƃàšîš, àñđ ţĥé šţàḿþ ţĥé þŕöđüçîñĝ ţööļ ļéƒţ, ŵĥîçĥ à ƒîļé öƒ šţŕîñĝš ĥàš ñöŵĥéŕé ţö ķééþ.

À ţööļ ţĥàţ ĝéñüîñéļý ñééđš ţĥé ḿàẋîḿàļ šüŕƒàçé (script, ŵĥîçĥ ŕüñš àŕƃîţŕàŕý ĴàṽàŠçŕîþţ) öṽéŕŕîđéš Process îñšţéàđ àñđ šéļƒ-ĝàţéš šöüŕçé ḿüţàţîöñ ƃéĥîñđ îţš öŵñ ƒļàĝ (allowSourceMutation). Ţĥé šçŕîþţ ĥàñđš ƃàçķ à ŵĥöļé ƃļöçķ, àñđ change.Diff(before, after) ţüŕñš ţĥé þàîŕ îñţö öþéŕàţîöñš, éàçĥ ĝüàŕđéđ ƃý ţĥé ŕéṽîšîöñ öƒ ţĥé éđîţîöñ îţ çĥàñĝéš: set_content ƒöŕ àñ éđîţîöñ àđđéđ öŕ ŕéŵŕîţţéñ, replace_text ŵĥéŕé öñé ţéẋţ éđîţ ŵîţĥ éṽéŕý îñļîñé çöđé ķéþţ đéšçŕîƃéš ţĥé çĥàñĝé, àñđ remove_edition. Ţĥéý àþþļý ţĥŕöüĝĥ change.ApplyBlock àš ţĥé script ţööļ, šö à ŵĥöļé-ƃļöçķ ŵŕîţé ḿééţš ţĥé šàḿé ŕüļéš àš à ţýþéđ öñé.

Ţĥé šàḿé ƒüñçţîöñ ļéţš à ŕüñ šĥöŵ ŵĥàţ îţ ŵöüļđ đö. Üñđéŕ --print-ops (kapi exec <tool>, kapi run, kapi up, àñđ ţĥé ƒļöŵ þöŕçéļàîñš šüçĥ àš kapi translate àñđ kapi pseudo-translate), ţĥé ŕüñ çöḿḿîţš ţĥŕöüĝĥ à ĥöḿé ţĥàţ ŵŕîţéš ñöţĥîñĝ, àñđ ţĥé đéŕéñçé ƃéţŵééñ éàçĥ ƃļöçķ àš ţĥé ŕéàđéŕ ĝàṽé îţ àñđ àš ţĥé ŵŕîţéŕ ŕéçéîṽéđ îţ ƃéçöḿéš ţĥé çĥàñĝé šéţ ţĥé ŕüñ þŕîñţš, ŵĥîçĥ kapi apply àþþļîéš (É-09). ksed --print-ops þŕîñţš ţĥé öþéŕàţîöñš îţš šüƃšţîţüţîöñš çöḿþîļé ţö ţĥé šàḿé ŵàý.

Ţŕàñšƒöŕḿéŕ þļàçéḿéñţ​

Ţŕàñšƒöŕḿéŕš àñđ àñàļýžéŕš àŕé öŕđîñàŕý šţéþš îñ öñé öŕđéŕéđ ţööļ ļîšţ; ţĥéŕé îš ñö šéþàŕàţé šţŕüçţüŕàļ šţàĝé. Ƃéçàüšé ţĥé àþþļîéŕ ḿüţàţéš îñļîñé àñđ îñ öŕđéŕ, éàçĥ ţŕàñšƒöŕḿéŕ šéţţļéš ţĥé šöüŕçé ƃéƒöŕé ļàţéŕ šţéþš öƃšéŕṽé îţ, šö àñàļýšîš ţĥàţ đéþéñđš öñ à ţŕàñšƒöŕḿ (šéĝḿéñţàţîöñ öṽéŕ ñöŕḿàļîžéđ ţéẋţ, öŕ àñ àññöţàţöŕ ƒééđîñĝ à ŕéđàçţöŕ šüçĥ àš entity-extract → redact) šééš ţĥé àþþļîéđ ŕéšüļţ.

Öŕđéŕîñĝ šàƒéţý îš à þļàçéḿéñţ þàšš ţĥàţ ŕüñš ƃéšîđé ţĥé đàţà-ƒļöŵ çöñţŕàçţ, üšîñĝ ţĥé çàþàƃîļîţý àñđ SideEffects à ţööļ àļŕéàđý đéçļàŕéš:

ŠéṽéŕîţýŔüļéŔàţîöñàļé
Éŕŕöŕà ţŕàñšƒöŕḿéŕ ḿüšţ ñöţ ƒöļļöŵ à šţéþ ţĥàţ þŕöđüçéš à çöḿḿîţţéđ ţàŕĝéţ, üñļéšš îţ þŕöđüçéš ţĥé ţàŕĝéţ þöŕţ îţšéļƒ (unredact ŕéŵŕîţéš ƃöţĥ šîđéš çöĥéŕéñţļý)ŕéŵŕîţîñĝ šöüŕçé öŕþĥàñš ţĥé ţàŕĝéţš, ŵĥîçĥ àñçĥöŕ ţö îţ
Éŕŕöŕà ŕéçöṽéŕàƃļé (ŕéđàçţîñĝ) ţŕàñšƒöŕḿéŕ ḿüšţ ŕüñ ƃéƒöŕé àñý šţéþ ţĥàţ éĝŕéššéš šöüŕçé ţö à ŕéḿöţé šîñķ, éẋçéþţ ţĥé šţéþ öŕ šţéþš þŕöđüçîñĝ àñ îñþüţ îţš çöñƒîĝ-ŕéšöļṽéđ çöñţŕàçţ ŕéǫüîŕéšöţĥéŕŵîšé üñþŕöţéçţéđ šöüŕçé ļéàķš ƃéƒöŕé ŕéđàçţîöñ àþþļîéš; à çļöüđ ÑÉŔ ƒééđîñĝ éñţîţý-đŕîṽéñ ŕéđàçţîöñ îš ţĥé đöçüḿéñţéđ đéţéçţîöñ ţŕàđé-öƒƒ (Ç-10)
Ŵàŕñîñĝà ţŕàñšƒöŕḿéŕ þļàçéđ ļàţéŕ ţĥàñ îţš éàŕļîéšţ ṽàļîđ šļöţ (àƒţéŕ îţš ļàšţ ŕéǫüîŕéđ îñþüţ)éṽéŕý öṽéŕļàý þŕéšéñţ àţ àþþļý ţîḿé ḿüšţ ƃé ŕéƃàšéđ; àñ éàŕļîéŕ šļöţ àṽöîđš ţĥé ŵöŕķ

Ţĥé ŕéḿöţé-éĝŕéšš ŕüļé ķéýš öƒƒ à ŕéḿöţé šöüŕçé éĝŕéšš šîđé 郃éçţ, đîšţîñçţ ƒŕöḿ à þļàîñ ÀÞÎ çàļļ, šö à ļöçàļ đéţéçţöŕ öŕ ţéŕḿ ļööķüþ đöéš ñöţ ţŕîþ îţ ŵĥîļé à çļöüđ-þŕöṽîđéŕ çàļļ đöéš. Ţĥé 郃éçţ îţšéļƒ îš çöñƒîĝ-ŕéƒîñéđ: à ḿöđéļ ţööļ þöîñţéđ àţ à ļöçàļ þŕöṽîđéŕ çàŕŕîéš ñö ŕéḿöţé éĝŕéšš. Ţööļš, îñçļüđîñĝ þļüĝîñš, çöñţŕîƃüţé ţĥéîŕ öŵñ þļàçéḿéñţ đîàĝñöšţîçš ţĥŕöüĝĥ ţĥé šàḿé çöñƒîĝ-đéŕîṽéđ çöñţŕàçţ ĥööķ ţĥàţ ŕéšöļṽéš à ţööļ'š ŕéǫüîŕéđ îñþüţš ƒŕöḿ îţš çöñƒîĝüŕàţîöñ. Ƒöŕ éẋàḿþļé ŕéđàçţîöñ ŕéǫüîŕéš àñ üþšţŕéàḿ entity öṽéŕļàý öñļý ŵĥéñ éñţîţý đéţéçţîöñ îš éñàƃļéđ, àñđ öñļý à ŕéǫüîŕéđ îñþüţ éẋéḿþţš îţš þŕöđüçéŕ ƒŕöḿ ţĥé éĝŕéšš ŕüļé, šö à ŕüļéš-öñļý redact þļàçéđ àƒţéŕ à çļöüđ ÑÉŔ šţéþ îš šţîļļ ŕéĵéçţéđ.

Çöñšéǫüéñçéš​

  • Îḿþļéḿéñţîñĝ à ñéŵ ţööļ ŕéǫüîŕéš öñļý éḿƃéđđîñĝ BaseTool àñđ šéţţîñĝ öñé ĥàñđļéŕ ƒüñçţîöñ ƒîéļđ.
  • Üñĥàñđļéđ Þàŕţ ţýþéš þàšš ţĥŕöüĝĥ àüţöḿàţîçàļļý; ţĥéŕé îš ñö ŕîšķ öƒ àççîđéñţàļļý đŕöþþîñĝ Þàŕţš.
  • Éṽéŕý çöñţéñţ ŵŕîţé à ţööļ ḿàķéš, ţĥŕöüĝĥ à ṽîéŵ, àñ éđîţ þļàñ öŕ change.Diff, îš àñ öþéŕàţîöñ change.ApplyBlock àþþļîéš, šö öñé šéţ öƒ ŕüļéš ĝüàŕđš éṽéŕý ŵŕîţé (É-09).
  • Šçĥéḿà-đŕîṽéñ ÇĻÎ ƒļàĝš, ƒļöŵ-éđîţöŕ çöñƒîĝ þàñéļš, àñđ ṽàļîđàţîöñ àļļ šĥàŕé öñé šçĥéḿà ŕéþŕéšéñţàţîöñ, šö à çĥàñĝé ţö à ţööļ'š çöñƒîĝ þŕöþàĝàţéš àüţöḿàţîçàļļý.
  • ÎÖ çöñţŕàçţš éñàƃļé ƒļöŵ-ļéṽéļ ļöçàļé îñƒéŕéñçé: ţĥé ŕüññéŕ ŵöŕķš öüţ ŵĥéţĥéŕ ţö îţéŕàţé þŕöĵéçţ ţàŕĝéţš, ŕüñ öñçé öñ šöüŕçé, öŕ ŕüñ ƒöŕ à šþéçîƒîç ļöçàļé šéţ ƒŕöḿ ţĥé đéçļàŕéđ çàŕđîñàļîţý.
  • Àññöţàţîöñ-ƃàšéđ îñţéŕ-ţööļ çöḿḿüñîçàţîöñ ķééþš ţööļš ļööšéļý çöüþļéđ ţĥŕöüĝĥ šĥàŕéđ đàţà ŕàţĥéŕ ţĥàñ đîŕéçţ đéþéñđéñçîéš.
  • Ţýþéđ çöñšţàñţš ƒöŕ öṽéŕļàý ţýþéš, šîđé 郃éçţš, àñđ ļöçàļé çàŕđîñàļîţý çàţçĥ ţýþöš àţ çöḿþîļé ţîḿé àñđ éñàƃļé ÎĐÉ àüţöçöḿþļéţé.
  • Ḿîẋéđ-çàŕđîñàļîţý ƒļöŵš ŕéšöļṽé çļéàñļý ţĥŕöüĝĥ þàšš üñîöñ; ţööļ àüţĥöŕš đö ñöţ çööŕđîñàţé ļöçàļé îţéŕàţîöñ.
  • Ţĥé çàþàƃîļîţý-ţýþéđ ĥàñđļéŕ ḿàķéš ţĥé ŵŕöñĝ ŵŕîţé üñŕéþŕéšéñţàƃļé ŕàţĥéŕ ţĥàñ ḿéŕéļý đîšçöüŕàĝéđ, àñđ ţĥé šîñĝļé àþþļîéŕ ḿéàñš öṽéŕļàý ŕéƃàšîñĝ àñđ šéçŕéţ ṽàüļţîñĝ àŕé ŵŕîţţéñ öñçé ŕàţĥéŕ ţĥàñ þéŕ ţŕàñšƒöŕḿéŕ.
  • Ţööļ ĝŕöüþš ļéţ à ƒàḿîļý öƒ îñţéŕçĥàñĝéàƃļé ƃàçķéñđš šĥàŕé öñé ţööļ ŵĥîļé éàçĥ ƃàçķéñđ ķééþš îţš öŵñ çöñƒîĝ; ḿéḿƃéŕš çöḿé ƒŕöḿ đöḿàîñ ŕéĝîšţŕîéš öŕ þļüĝîñš, àñđ ţĥé šàḿé đéƒîñîţîöñ đŕîṽéš ţĥé ḿàšţéŕ-đéţàîļ çöñƒîĝ ÜÎ àñđ ţĥé ƒļàţ ÇĻÎ/đöçš/ḾÇÞ þŕöĵéçţîöñ.

Ŕéļàţéđ​