Skip to main content
Restricted Access: This documentation is only accessible to @tenzo.ai and @salv.ai email addresses.
Handoff and hops follow the module and stage-orchestrator contract: outputs do not name the next module; composition links do. This page is how a job gets its snapshot. It does not change Admin → Modules chrome.

What composition is

A job’s module composition is the ordered list of module kinds that job runs, plus the terminal-out connections between them. Resume Review and AI Interview are the V1 kinds. Ingest is not a module: it is the admit-and-park pipe that always sits in front of the first authored module. Author named journey templates on Admin → Templates Bank → Modules. The landing view is the template list. Opening one is a graph canvas: a bank of modules on the left and a pannable, zoomable map in the rest of the page. Full screen expands the same editor to the viewport. Cards show the module name, a one-line purpose, and each exit already labeled with its next step (Pass → AI Interview, Resume Rejected → Stop). Change that destination from the dropdown on the exit. You can still drag a handle. Drag a card corner to widen it so the labels stay on one line. Click the card body to open a right panel in the same workspace. Double-click or Open inner graph replaces the map with that module’s Tenzo-stage flow. Click a stage card to open its drawer. Every stage can take extra actions that fire outside the regular graph — send email, send SMS, write an ATS note, update a custom field, or update the ATS application stage. Those are not extra stages. Outreach cannot take email or SMS because that stage already reaches out; ATS updates still work there. Extra actions stay on the click-in for now; they are not saved on the template and do not run. Resume Review has Awaiting Review on the left (start), Pass and Resume Rejected on the right (end stages), and Re-review on the card (hold — it does not leave the module). AI Interview has Outreach in and Call Completed out. Those handles come from the compiled inner graph, not from hardcoded card copy. Parks, accommodations, and Opted Out stay inside the click-in, not extra journey cards. Each kind can appear once. Save persists the template. Bank edits do not change in-flight jobs until you reassign. The system Default journey is read-only (Resume Review continue → AI Interview → Stop, Resume Review end → Stop). Duplicate it to make a copy. A fixed Ingest card sits left of the first module. It is not in the bank and has no remove control. The solid edge is Ingest → first module start. Dotted Ingest edges to other starts are a preview of saved start maps, not live routing. Mapped ATS stages show on the Ingest card. Hover a module start label to see that module’s map; edit either map from the drawer. On Ingest and each module start, the drawer can map ATS stages. Those maps are saved on the template. They are not live: candidates still enter at the first module after Ingest. Empty is not “all ATS stages”. A stage can map to only one start on that template, including Ingest. Do not say “Campaign” in that UI. The Templates Bank item is Modules.

Job assignment

A job gets exactly one journey. Assignment order is job override → parent job template → integration rule (Assign Journey Template) → system Default. On AI Interview Behavior → Candidate journey, pick inherit or override, then Open to preview the snapshot on that job. The first snapshot for a new job compiles today’s AI Resume Review Only toggle when the job inherits Default. After that, the snapshot is the runtime list.

What this is not

This slice does not ship:
  • backend start-stage jumping (resolve_post_ingest_module_start)
  • persisted or executed extra actions (the click-in picker is authoring-only)
  • recruiter stage renames (Resume Rejected / Failed Knockout stay as they are)
  • a separate Journey Templates page
  • a persisted INGEST module row
  • TenzoStageOrchestrator executing the compile (later slice)
Those belong to later TEN-925 work. See Module-owned stage orchestration.

Compiler

compile_v1_composition(interviews_enabled=...) is a pure function used only when no campaign journey snapshot exists. Resume Review is always first. AI Interview is included only when interviews are enabled (ai_resume_review_only_settings.enabled is false). Identity and display names come from the pipeline ModuleDefinition registry. Allowed inner hops still come from the pipeline compile, not this sequence helper. A snapshot, when present, compiles through composition_from_graph with source journey_snapshot. The coordinator reads that list. The frontend compile helper uses the same keys and display names (resume_review, ai_interview / Resume Review, AI Interview) so the map and the backend type stay aligned. The job preview map is a visual overlay only; it uses the same inner-graph compile for card ports and click-in, and does not author inner edges.

Handoff reads composition

When the flag is on and a snapshot omits Interview, Resume Review continue_handoff does not call Interview activate. In-flight runs do not re-fire on save. When there is no snapshot, resume-only jobs still get a bypassed Interview run so they project to SKIP_OUTREACH. See AI Interview module.

Recruiter list

Composition does not change TenzoStage. Parks stay overlays. The list, filters, and ATS automation keep reading the compatibility projection.