CVL Quarry Selection Compendium

Written 2026-05-05 after the "variant system" clarification. This is a handoff note for future Careervector work on CVL selection, variants, hybrid sections, section inclusion, AI tailoring, and document fit.

Product Meta

Careervector is not a Word-like document editor. It is a workspace quarry that can produce many physically precise CV/CL variants.

The workspace owns the source quarry: more content than any final document can contain. Five pages of raw material in the base workspace can be healthy because a job-specific output will select only the best fitting subset.

The user story is:

  • I know the target document shape: usually a CV with at most 2 pages, maybe plus a project page, maybe plus a skills page, and a cover letter with its own page budget.
  • I put all relevant reusable content into one workspace quarry.
  • I add alternatives and variants where the content may differ while the structural slot stays the same.
  • For each job, human and AI select, rewrite where allowed, and render until the document fits the target shape.
  • I do not maintain hundreds of separate CV files. I maintain one quarry that can create hundreds of precise outputs.

The value is the constrained composition loop. Word can edit one document. Careervector edits a quarry and solves the selection/fit problem repeatedly.

The intended layout is known beforehand. The content differs each time because the system mixes a fresh cocktail for every job from the same metadocument. Format rules are the shepherd: they keep humans and agents from straying while working inside a complicated quarry.

The metadocument must be understandable without a manual. A future profile tab may become a chatbot/AI entity that helps a user construct this quarry, but the near-term architecture should already make the model legible to humans and to naive connected chatbots. If a fresh Claude/ChatGPT-style MCP/API client enters the workspace, the exposed model, tool descriptions, and UI labels should teach enough of the quarry/selection/fit contract for it to be useful.

There are two different chatbot stories:

  1. Near term: an external chatbot connects to an existing workspace through MCP/API and operates the quarry. The quarry may already be valid, invalid, or under construction. The chatbot must be able to inspect it, understand the current constraints, and make explicit edits.
  2. Far future: an embedded profile/quarry assistant interviews or guides a user to construct a metadocument from scratch. This is product onboarding and stewardship, not the immediate API operating surface.

Near-term API operation must support concrete instructions such as:

  • add a new summary section on the second page
  • make that summary an OPEN section with a five-line prompt/target
  • write or improve the section prompt
  • make two sections variants of each other
  • untangle sections that should no longer be variants
  • adjust i|b|s|L constraints
  • add shape-equivalent variants to a bullet/item/section
  • inspect why a quarry or tailored output is not fitting

The first story is tool operation. The second story is human shepherding. Do not block the first on the second.

Lego Model

The most useful mental model is lego.

The brick shape is the structural role:

  • a section slot
  • an item slot inside a list section
  • a heading line
  • a subheading line
  • a bullet line
  • a sub-bullet line
  • an explicit spacer or page break
  • an appendix/project/skills page slot

The brick color is the content:

  • wording variant
  • emphasis variant
  • project-specific example
  • domain-specific skill phrasing
  • language/cultural version
  • job-tailored generated text

Variants are powerful because they keep the same brick shape while changing the color. Ideally, a one-line bullet variant replaces another one-line bullet variant. A summary variant should target the same line budget as the other summary variants. A section-level variant should fit the same page/slot budget as the section it replaces.

This "same shape, different color" rule is what lets the system compose a CV mechanically. If alternatives have wildly different structure or rendered height, they are still selectable, but they are no longer cheap variants; they become layout decisions and must show fit pressure explicitly.

The way to make a quarry composable is to make every brick structurally predictable:

  • OPEN text is predictable when generation is constrained to an exact line target. The words may be new for every job, but the generated brick still has a known rendered size.
  • HYBRID sections are predictable when selection from their microquarry is bounded. The section owns limits such as max/exact items, bullets, subs, and eventually section-kind/page budgets.
  • Variants are predictable when every member of the variant group is the same size/shape. The content differs; the slot cost does not.

This is how new content and job-specific selection can coexist with a stable document shape. The quarry is allowed to be rich, but every allowed choice must respect the brick contract for its slot.

Core Primitive

For the system, there should be one primitive:

A parent owns a pool of candidate children and a selected ordered subset.

This applies at every level:

  • document root selects sections
  • a page/appendix slot selects sections
  • a section selects items
  • an item selects subheadings and bullets
  • a bullet selects sub-bullets
  • a variant group selects exactly one alternative child

The UI can use different user-facing words, but the storage, ops, tailoring, and rendering should not be separate systems.

Useful user-facing names:

  • "variant" for exactly-one alternatives
  • "checkmarks" for multi-selection
  • "optional sections" for root/section-level selection
  • "target lines" and "fit" for rendered-space pressure

Internal name:

  • selection group

Why The Earlier Generalization Was Incomplete

Adding minCount / maxCount style cardinality is useful, but it is not the architecture by itself.

The real unification is not "range of possibilities." It is:

  • variants, hybrid checkmarks, section inclusion, and AI selection are the same selection game over different parents and different child types
  • the selection game is coupled to rendered-space budgets
  • the chosen subset is the document
  • the quarry remains larger than the document

Cardinality is only one property of a selection group. It says how many children may be selected. It does not itself say that variants, checkboxes, sections, prompts, and render-fit should share one lifecycle.

Selection Rules

A selection group needs enough policy to model all current CVL choosing mechanisms without special subsystems.

Common rules:

  • always include all children
  • choose exactly 1
  • choose exactly n
  • choose up to n
  • choose at least n
  • choose any subset

Important: this rule is a constraint on the selected set, not the whole product goal. The bigger goal is still "select content that fits the target document shape."

The selection state must preserve order because render order matters.

At minimum:

type Selection = {
  active: string[];      // ordered selected child ids
  minCount?: number;
  maxCount?: number;
};

But the product may eventually need richer metadata around the same primitive:

type SelectionPolicy = {
  rule: 'all' | 'exactly' | 'upTo' | 'atLeast' | 'range' | 'any';
  count?: number;
  minCount?: number;
  maxCount?: number;
  budget?: SelectionBudget;
  presentation?: 'variant-border' | 'checklist' | 'section-card' | 'locked';
  selectedBy?: 'human' | 'agent' | 'pipeline' | 'system';
};

Do not confuse presentation with storage. "Variant border" and "checkbox" are UI affordances for the same underlying operation.

Budget And Fit

Selection is valuable only because the output has a physical shape.

The document shape is a steward-defined format concern. The system must be general: the format editor should eventually let a steward define rules such as "2-1-1" rather than baking CV-specific page assumptions into CVL logic.

Example shape rules:

  • CV main body, often 2 pages max
  • optional project page
  • optional skills page
  • CL page budget
  • locale/page-size constraints such as A4 vs Letter

Sections can belong to a shape kind. A "project" kind may have to fit on one project page; a "skills" kind may have its own page; cover letters are almost always one page, so CL overflow usually means the quarry/content/format rule is wrong or still under construction.

The steward defines what "valid" means for a workspace/document shape. CVL and the pipeline should consume that rule; they should not hard-code one universal validity policy.

The local selection group can have count-like budgets:

  • max items (i)
  • max bullets per item (b)
  • max subs per bullet (s)
  • target lines (L)

The renderer supplies actual budgets:

  • rendered line count
  • rendered height
  • page count
  • page overflow
  • remaining space

The Typst render is the truth. The i|b|s numbers are helpful authoring and prompt constraints, but they are proxies. They shape the search space before rendering; they do not prove fit.

The final loop should be:

  1. Select candidate subset from quarry.
  2. Generate OPEN content within explicit line budgets.
  3. Render with Typst.
  4. Measure actual page/line/height fit.
  5. If overflow or bad whitespace appears, select/swap/trim/regenerate.
  6. Preserve the quarry and record the job-specific selected output.

Advanced future layer: global line balancing. For a one-page cover letter, it may be acceptable for one section to take one extra line if another section takes one fewer line. The recently added min/max selection cardinality can help with this, and a future executor could be given a total document budget plus local ranges rather than only fixed per-section limits. Do not make this part of the first unification step. It gives more judgment back to routine executors and makes the architecture harder; it can be bolted on after the steward-defined shape system and basic selection unification are stable.

UI Direction

Use one model with multiple affordances.

Exactly-one groups:

  • show bordered variant alternatives
  • selected member has strong border/background
  • unselected members stay visible because the quarry is valuable
  • this can apply to sections, items, bullets, subheadings, and subs

Multi-select groups:

  • show checkmarks
  • selected rows still need a clear selected border or background
  • count rule should be visible: "2 of 5", "up to 4", or "4 selected"

Section-level selection:

  • sections can use the same border/checkmark language
  • required/fixed sections can look locked or always-on
  • optional sections can show an inclusion control
  • exactly-one section alternatives can use the same variant border treatment as lower-level variants

Fit feedback:

  • show local counters where they influence the AI: i, b, s, L
  • show rendered measurements where possible: lines, overflow, page count, spare space
  • preserve the whitespace markers because vertical space is part of the game
  • if a variant has a different rendered cost than its siblings, surface that difference instead of hiding it

The UI must let the user feel the target shape first: "I am filling a 2-page CV from a quarry," not "I am editing a linear document."

AI Contract

Agents must understand the quarry/selection model explicitly.

There are two actor classes, and they must not be conflated.

Quarry stewards:

  • humans
  • strong chatbots
  • MCP/API agents
  • any high-capability actor explicitly tasked with improving the workspace

Stewards may change the quarry. They can add variants, tune budgets, rewrite bricks, restructure sections, promote useful tailored edits, and accept responsibility that the resulting quarry produces fitting documents.

Tailoring executors:

  • the routine tailoring pipeline
  • cheap/high-volume section selectors
  • bounded OPEN generators
  • automated rerun/repair stages that operate inside existing rules

Executors do not own quarry validity. They make routine selections inside the current quarry, generate bounded content where allowed, render/check, and report the result. If the quarry cannot produce a valid document under its own rules, the executor should fail clearly or delegate back to a steward. It should not silently redesign the quarry.

The durable contract is:

Stewards maintain quarry validity. Executors operate inside a valid quarry.

This is why MCP/API guidance matters: a strong agent can be asked to create or repair a quarry that produces fitting CVs. The mechanistic tailoring bots cannot and should not be expected to solve that architectural problem on their own.

For HYBRID content:

  • the AI selects from the quarry
  • it should return selected ids or indices, not rewritten content
  • the caller reconstructs from quarry content verbatim
  • variant constraints are selection constraints
  • i|b|s are selection/shape constraints

For OPEN content:

  • the AI generates text
  • target line count is binding product intent
  • generated text must be measured after render
  • if it does not fit, regeneration/repair should happen

For variants:

  • the AI chooses the member whose content is most appropriate for the job and whose rendered shape fits the slot
  • if all variants are intended to be shape-equivalent, the AI should not choose one that breaks the target shape unless told to prefer content over fit

For sections:

  • section inclusion is not special; it is root/page-slot selection
  • an AI may choose 2 sections out of 3 because the target document cannot fit all 3
  • the selection reason should include both relevance and fit pressure

For MCP/API:

  • tools should expose exact tree paths and selection state
  • agents must see inactive candidates, not only currently active output
  • agents must see constraints and rendered measurements where available
  • "delete" is not how tailoring drops content; selection is
  • a naive connected chatbot should receive enough terminology, constraints, and candidate/selection context to understand the metadocument without a separate manual

Executor failure should be diagnostic, not creative. Example:

No valid CV could be produced under the current quarry constraints. The selected Experience and Skills sections fit, but Projects exceeds the target document by 9 lines. Delegate to a quarry steward.

Current Code Map

There are already multiple partial implementations of the same idea.

Canonical tree-of-choices layer:

  • packages/schemas/src/node.schema.ts
    • Node has children and selection.active
    • Invariant: selection.active[] is a subset of child ids
  • packages/ops/src/*
    • selection.update, node.create, node.update, node.delete, etc.
  • apps/mcp/src/tools/set_selection.ts
    • MCP-facing selection mutation tool
  • apps/mcp/src/tools/get_cvl_tree.ts
    • MCP-facing tree read surface

Legacy/current DocumentStack layer:

  • packages/schemas/src/document.schema.ts
    • DocumentStack.sections
    • Section.maxItems, maxBullets, maxSubs
    • variantGroup on sections/items/bullets/subheadings/subs
    • groupState with { included, active }
  • packages/domain/src/variants.ts
    • normalizes variantGroup
    • implements exactly-one variant behavior and inclusion
  • apps/web/src/lib/components/cvl/CVLEditor.svelte
    • section list, expand/collapse, add sections
    • toggleWithVariants, isSelectedV2, onBreakOut
    • right controls for Auto, L, i, b, s
    • TODOs around dedicated groupState ops
  • apps/web/src/lib/components/cvl/editors/ListEditor.svelte
    • visual variant borders for item/bullet/subheading/sub groups
    • selection IDs like {section}.{item}.bullet.{bullet}
    • check/variant affordances inside list content

Tailoring and AI selection:

  • packages/domain/src/tailor/prompts/hybrid.ts
    • HYBRID prompt asks the AI to pick up to maxItems
    • variant groups are described as mutually exclusive
    • AI returns indices, not rewritten content
  • packages/domain/src/tailor/generate.ts
    • selectHybridItems validates max items and variant violations
    • selected quarry items are copied verbatim into tailored output
    • groupState is reconstructed after generation
  • packages/domain/src/tailor/variant-sync.ts
    • maps kept tailored content back to quarry variant groups

Rendering and fit:

  • packages/domain/src/tailor/prompts/system.ts
    • includes page budget and one-line bullet rule
  • packages/domain/src/ruler-items.ts
    • extracts measure IDs matching editor overflow dots
  • packages/domain/src/checks.ts
    • checks target lines for text sections
  • apps/web/src/lib/components/cvl/CvGenerator.svelte
    • preview render, page geometry, overflow measurement, Typst compile path
  • apps/web/src/lib/components/cvl/editors/OverflowDot.svelte
    • row-level fit signal
  • apps/web/src/lib/components/cvl/GapBar.svelte
    • whitespace visualization

Adjacent process execution system:

  • docs/ARCHITECTURE-BROWSER-WORKERS-2026-05-05.md
    • browser tabs are first-class workspace workers for expensive process requests
    • MCP/UI/scheduled agents queue durable work; browser/local/server/agent workers claim it
    • this aligns with the steward/executor distinction and should be reused for routine process work rather than inventing a CVL-specific queue
  • apps/web/src/lib/server/process-requests.ts
    • defines request statuses and worker classes (browser, local, server, agent)
    • defines requester classes (human, agent, pipeline, system)

Bridges between Node tree and legacy stack:

  • apps/web/src/lib/profile-stack.ts
  • apps/mcp/src/tools/get_cv_typst.ts
  • apps/web/src/lib/server/workspace-subdoc.ts

These bridge paths are especially important because they reveal the current split: tree selection exists, but rendering and much of the editor still pass through DocumentStack/groupState semantics.

Architectural Tension

The repo already contains the intended abstraction in docs and schema: tree-of-choices. The UI and rendering pipeline still carry the practical v1/v2 DocumentStack system:

  • root sections are mostly a flat list
  • variants are modeled with variantGroup + groupState
  • hybrid selection is item-index selection inside a section
  • section inclusion and page slots are not yet the same primitive everywhere
  • selection constraints and rendered-fit constraints are related but separate

This is not a reason to rip everything out. It is a migration map.

The correct direction is to converge these systems without losing the production knowledge in the current editor.

Branch Starting Assumptions

Answered 2026-05-05 before starting an implementation branch.

First milestone:

  • Work UI-first because the human editor makes the system easier to understand and verify.
  • The first milestone still has to align all stacks on the same basis: UI, data/model layer, MCP/API, tailoring prompts, rendering/fit diagnostics.
  • Do not ship a UI-only concept that agents cannot operate through API.
  • The agent must be able to do the same CVL actions a human can do and must understand the consequences of those actions.

Data/model direction:

  • Think long term. Optimize for readability, correctness, and efficiency because the concept is complicated and easy to break.
  • The current variantGroup concept may remain as an implementation detail or subgroup if it cleanly maps to a more general selectionGroup.
  • It is acceptable for code to still say variantGroup where that improves readability, provided everyone understands it as the exactly-one flavor of selection.
  • Do not force a premature storage migration if a projection/view-model layer makes the transition safer.

Relationships:

  • Section relationships should participate in the same selection game as item and bullet relationships.
  • Section-level variants can use the same visual language as existing variants when the relationship is exactly-one.
  • Multi-section selection can use checkmarks plus clear selected borders.
  • If a relationship is represented with selection rather than direct variantGroup, it must still remain understandable to both UI and agents.

Shape rules:

  • Hardcode a starting 2+1+1 style rule rather than blocking on a full format editor shape-system UI.
  • The format editor does not need to be part of the first milestone.
  • The long-term shape system belongs in format settings, but the first branch may use a fixed rule to prove the concept.

Failure/guardrails:

  • Humans should be allowed to create temporarily "wrong" or under-construction states because exploration is part of quarry building.
  • AI agents need stronger guardrails because silent failure is dangerous.
  • Exact executor failure semantics can be designed later, but the direction is clear: do not let routine AIs silently produce invalid outputs or redesign the quarry without steward responsibility.

Migration Direction

Target state:

  • every selectable relationship is parent children plus selection.active
  • variants are exactly-one selection groups, not a separate variantGroup subsystem
  • hybrid checkmarks are multi-selection groups, not a separate section behavior
  • section inclusion is root/page-slot selection, not a separate visibility flag
  • i|b|s|L limits become selection/shape budgets attached to the relevant parent or slot
  • renderer consumes selected nodes and reports actual fit
  • AI returns selection deltas plus OPEN generated content

Likely phases:

  1. Document current invariants with tests around variant/groupState behavior.
  2. Introduce a canonical SelectionGroup view model that can be projected from existing variantGroup/groupState without changing storage.
  3. Rework UI components to render from the view model, keeping the visual border/checkmark behavior users already understand.
  4. Expose section-level selection using the same view model.
  5. Teach MCP and tailoring prompts to describe all choice surfaces with the same selection language.
  6. Move rendering bridges from groupState toward recursive selected-node traversal.
  7. Migrate storage when the projection layer is proven by browser tests.

Do not make storage migration the first step. The UI/AI semantics need to be right first, and existing behavior must stay browser-verified.

Non-Negotiable Invariants

  • The quarry preserves inactive candidates.
  • Tailoring drops content by selection, not deletion.
  • Hybrid selection copies facts from the quarry unless the tier explicitly permits generation.
  • OPEN generation must stay inside line/page budgets and be measured.
  • A selected set has order.
  • Variants are same-slot alternatives; they should not silently alter document structure unless the UI exposes the layout consequence.
  • The renderer is the source of truth for physical fit.
  • User terminology may vary; system operations should not.
  • All human GUI selection operations need MCP/API equivalents.
  • User-visible editor work must be verified in a browser.

Anti-Patterns

  • Adding a new "section visibility" system beside selection.
  • Treating variants as a UI-only border feature.
  • Letting the AI rewrite HYBRID content when it should select.
  • Hiding inactive quarry material from agents.
  • Using line count as proof of page fit without a Typst render.
  • Letting variants with different rendered heights look equivalent.
  • Inferring identity or selection target from position when stable ids exist.
  • Fixing overflow by deleting quarry content.
  • Migrating storage before the current user affordances are mapped and tested.

Open Design Questions

  • What is the cleanest storage shape for section/page slots? Root-level selection may be enough, but appendix/page slots may need explicit parent nodes.
  • How should rendered height be attached to candidates so both UI and agents can reason about space without compiling after every tiny change?
  • How strict should "same brick shape" be? Exactly one rendered line, same archetype, same child-count budget, same measured height, or merely "close enough with warning"?
  • How should the UI represent a section-level exactly-one group without making the editor feel cluttered?
  • Should i|b|s remain section fields or become selection budgets on child groups?
  • How should a human override fit constraints while keeping the AI honest?
  • How should project/skills appendix pages be modeled: fixed page slots, optional page groups, or document-shape presets?

Design Heuristic

When changing CVL, ask:

  1. What is the parent?
  2. What is the candidate pool?
  3. What selected subset renders?
  4. What rule constrains the subset?
  5. What physical slot or page budget must it fit?
  6. What affordance makes this intuitive to a user?
  7. What exact operation would an MCP agent call?
  8. What Typst/browser evidence proves the selected output still fits?

If a feature cannot answer those questions, it probably belongs to the old split system and needs to be reframed before implementation.

2026-05-05 First Implementation Slice

  • Added a shared @cv/domain/selection-groups projection layer.
  • The bridge from Node tree to DocumentStack now treats root selection.active as canonical for rendered top-level sections and root data.groupState as the compatibility carrier for nested legacy item/bullet/sub variant state.
  • Section variants remain node.data.variantGroup, but the UI now exposes them as section-level selection groups with radio/check behavior, borders, inactive styling, group position chips, and one compact variant-action selector.
  • CVL add-section supports inactive same-group variants and insertion after a source section.
  • GUI group-state edits persist by updating root data.groupState and root selection.active, using the same node/selection ops exposed to agents.
  • MCP gained set_cvl_section_group as an ergonomic section-level parity tool; get_cvl_tree now returns selectionGroups, shape diagnostics, and guidance about variantGroup, root selection, and stored group state.
  • Hardcoded first shape rule is visible in UI and MCP diagnostics: CV main <= 2 pages, projects <= 1 page, skills <= 1 page; CL <= 1 page.

Known limitation: arbitrary subgroup cardinalities inside a flat section array are still represented through either root selection or exact-one variantGroup relationships. Richer subgroup/page-slot modeling probably needs explicit parent nodes or page-slot nodes once the UI language is proven.

Source: wiki/content/archive/2026-05/agent-runs/cvl-quarry-selection-compendium-2026-05-05.md