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.