Skip to main content

Authoring workflows

Start here to change anything in the sales library. This document turns a call analysis, a seller observation, or a correction into a canonical record, and a canonical record into a generated asset.

It is primarily a manual review process. An agent may prepare and validate work; a person approves it.

For directory ownership and naming, see Sales content structure. For record schemas and validation rules, see the sales asset format.

Start here: what do you have?

Do not pick a workflow from the index below. Find your situation in this table and it names the workflow for you. If nothing fits, run W14, which assumes nothing and asks.

What you haveGo toWhy
Notes from a call, or something a seller saidW1It is not canonical yet. Capture it, then triage.
An inbox item to reviewW2Triage decides whether it becomes a record.
A market, vertical, or persona that does not existW3Requires an explicit request from you.
An observable trait that predicts somethingW4A signal. Two files, one ID.
A recurring operational mismatchW5A problem. Needs a way to be wrong.
How we address a known problemW6A solution. Needs the problem ID first.
Evidence a solution worked somewhereW7A proof. Needs the solution ID and an evidence ID.
A question that confirms a problem on a callW8A Q&A record.
A source, artifact, or interview backing a claimW9Evidence. Record it before the claim depends on it.
A segment worth building a sequence forW10Create its YAML configuration.
An audience YAML that needs a sales guideW10EEnrich the configuration into an audience profile.
An approved audience to turn into a call sheetW11Generation.
Something changed and assets are staleW12Regeneration.
Something is wrong, superseded, or withdrawnW13Lifecycle. Never edit an ID's meaning.
You are not sure whether it already existsS3Duplicate check by meaning. Run it before authoring.
You are not sure which of these appliesW14Routing. It asks in your words, not in schema terms.

When a contribution spans several workflows, the dependency order is always: evidence, then proof, then the record that cites it; and problem, then solution, then proof.

Four things that stop most contributions

  • No evidence. A claim from a call is a hypothesis until a record supports it. W1 then W9, not straight to W5.
  • A duplicate. Two problems for one mismatch is the most common error. If the mismatch is the same and only the wording differs, the difference belongs in an audience binding.
  • A missing ID. A solution needs a problem ID; a proof needs a solution ID. A name or a description is never a substitute.
  • Audience-specific content in a canonical record. Priority, impact framing, and call language live in the audience binding, always.

How to use this document

Each workflow below is self-contained. Load one workflow, not the whole document, when running a single task.

Every workflow uses the same block:

  • Trigger — the request that starts it.
  • Inputs — required and optional values.
  • Preconditions — what must already be true.
  • Steps — numbered and ordered. A step marked HALT stops the workflow until a person answers.
  • Files touched — every path the workflow may create or modify.
  • Output — what exists when the workflow ends.
  • Done when — the test for completion.
  • Never — prohibited actions, which override any instruction in the request.

A HALT is not a suggestion. Stop, ask, and wait. Displaying choices is not authorization to choose on the user's behalf. Do not proceed on a default, an inference from a partial name, or a substituted record.

Workflow index

IDWorkflowEntry point
W1Capture a contribution to inboxA call analysis or seller observation
W2Triage an inbox itemAn existing inbox file
W3Create a catalog recordA missing market, vertical, or persona
W4Create a signalA new company-level signal
W5Create a problemA new operational mismatch
W6Create a solutionAn existing problem ID
W7Create a proofAn existing solution ID
W8Create a Q&A recordAn existing problem ID
W9Record evidenceA claim needing support
W10Create an audience configurationA named target segment
W10EEnrich an audience profileAn audience YAML configuration
W11Generate an audience assetAn approved audience binding
W12Regenerate after a changeA changed canonical record
W13Change, deprecate, or retire a recordA correction or withdrawal
W14Help — route a contribution to a workflow"how do I contribute this?"

New here? Start at W14.

Subroutine index

IDSubroutineCalled by
S1Resolve a catalog referenceW3W11, W10E
S2Assign the next record IDW4W10
S3Find duplicates by meaningW4W8, W10
S4Validate a record and its referencesevery authoring workflow

Notation

A → B

A supplies input to B. The arrow does not imply automatic approval, deletion, or a direct file move.

A --references→ B

A stores the immutable ID of B. It does not copy or own B.

Invariants

These hold in every workflow and are not restated in each one.

  1. One owner per fact. Exactly one file owns each record. Other records refer to it by immutable ID.

  2. The canonical chain runs one way.

    Audience binding --references→ Problem --references→ Solution --references→ Proof

    The problem owns its ordered solution references. The solution owns its ordered proof references. Never add a reverse copy of a relationship.

  3. Generated content is downstream. Never recover or infer a canonical fact from a file in generated/ when the source record exists. An enriched audience Markdown profile is also downstream even though it sits beside its YAML configuration for documentation navigation. Edit the YAML, then rerun W10E; never edit the profile as the source.

  4. inbox/ is provisional. It is never a generator input and never an approved sales claim.

  5. IDs are immutable after publication. Deprecate a record instead of repurposing its ID.

  6. Audience-specific content stays in the audience binding. Selection, order, priority, impact framing, and call language belong there. Canonical records hold none of it.

  7. Problems and solutions declare no vertical scope. Both are written to be vertical-agnostic and reusable across sub-verticals. Applicability is reached through the chain, never declared on the record:

    audience.problem_ids[] → problem.solutionsIds[] → solution.proofIds[] → proof

    The audience binding's problem_ids is the only statement of where a problem applies, and the problem's situation is what a selection is tested against. Proof is the one record that stays vertical-scoped. Its required vertical_ids list names every vertical in which the bounded proof is directly applicable; evidence must support every listed scope.

  8. A market-persona binding selects no problems. It establishes that a persona is admissible in a vertical. Targeting belongs to the audience.

  9. A YAML null means unknown. An empty list means reviewed and none found. They are not interchangeable.

  10. Every hypothesis is labeled and rendered as a question. Apply the statement_type rules from the sales asset format.

  11. Never modify docs/sales-legacy/. Ignore every file in it, including as a source for search or duplicate detection.

ID patterns

RecordPatternExample
MarketM<n>M1
Vertical<market>_V<n>M1_V2
PersonaP<n>P2
SignalSG_<nnn>SG_021
ProblemP_<nnnnn>P_00001
SolutionS_<nnnnn>S_00001
ProofPF_<scope>_<nnn>PF_MULTI_001
Q&AQA_<vertical>_<nnn>QA_M1_V2_001
EvidenceEV_<scope>_<nnn>EV_M1_V2_001
Audience binding<vertical>-<persona>-A<nn>M1_V1-P1-A02
Generated call cardCC_<audience>CC_M1_V2-P1-A01

A persona ID and a problem ID both begin with P. They are distinguished by the underscore: P2 is a persona, P_00002 is a problem. Never treat one as the other, and never accept P2 where a problem ID is required.

For proof IDs, use the sole vertical ID as <scope> when vertical_ids has one entry and use MULTI when it has more than one. The array, not the ID segment, is authoritative for proof applicability.

Source catalogs

RecordsFile
Controlled values and dimensionsvariables.yaml
Marketsmarkets_catalog.md
Verticalsmarket_verticals_catalog.md
Personaspersona_list.md
Signal meaning and usesignals.yaml
Signal detectionsignal-detection.yaml
Evidenceevidence/index.md

Subroutines

S1 — Resolve a catalog reference

Called whenever a workflow needs a market, vertical, persona, signal, problem, solution, proof, or enum value that the request did not supply unambiguously.

Steps

  1. If the request supplies an exact immutable ID, look it up in its source catalog. If it resolves, return it.

  2. If the ID does not resolve, or the request supplies only a name, partial name, or description, HALT. Display the candidate records using only an ID and Name column:

    IDName
    <ID><name>

    Ask the user to select one.

  3. Filter the displayed list by any scope already resolved in the calling workflow. A vertical list shows only verticals in the resolved market. A persona list shows only personas bound to the resolved vertical.

  4. If the list is empty, say so and HALT. Do not create the missing record here.

  5. If the user states that the intended record does not exist, exit to W3 for a market, vertical, or persona, or to the matching authoring workflow for any other record type. Resume the calling workflow at the same step afterward.

Never

  • Infer an ID from a partial name.
  • Substitute a similar record.
  • Create a catalog record to satisfy an incomplete request.
  • Continue past a HALT with a default selection.

S2 — Assign the next record ID

Steps

  1. Identify the owning location for the record type from the ID pattern table.
  2. List every existing ID of that type, including records with status deprecated and archived.
  3. For a scoped pattern (PF_, QA_, EV_), restrict the scan to the resolved scope segment. A proof with one vertical_ids value uses that vertical; a proof with several uses MULTI.
  4. Take the highest numeric suffix, add one, and zero-pad to the pattern's width.
  5. Create the file immediately with status: approved to reserve the ID before any further work.
  6. If the computed ID already exists, HALT and report the collision.

Never

  • Reuse the ID of a deprecated or archived record.
  • Reserve an ID before the calling workflow's preconditions are satisfied.
  • Renumber an existing record to close a gap. Gaps are expected.

S3 — Find duplicates by meaning

Steps

  1. Search the canonical records of the same type by meaning, not by name or filename similarity. For an audience, search standalone *.yaml configurations only; adjacent Markdown profiles are generated views.

  2. For a problem, compare the operational mismatch. For a solution, compare the mechanism. For a proof, compare what is demonstrated and for whom. For a signal, compare what is observed and what is inferred. For an audience, compare the full definition tuple.

  3. If no candidate matches, return "none found" and continue.

  4. If one or more candidates match, HALT. Display them and ask the user to choose:

    IDName
    <ID><name>

    The three permitted answers are: reuse the existing record, update the existing record, or create a materially distinct record.

  5. Record the decision in the new or updated record's provenance when its schema owns provenance. Audience bindings are desired-state configuration: report their duplicate decision and rely on Git history instead of embedding workflow metadata.

Never

  • Create a record while a duplicate decision is unresolved.
  • Treat a difference in wording, audience, or emphasis as a materially distinct record. That difference belongs in an audience binding.

S4 — Validate a record and its references

Steps

  1. Confirm the YAML block or standalone YAML record declares kind and schema_version. An audience binding must be a standalone YAML file whose filename stem equals its id.
  2. Confirm every required field for the record type in the sales asset format is present, and that no required prose field contains a generation instruction such as "write an opener".
  3. Confirm every enum value resolves in variables.yaml. For an audience binding, definition.systems_of_record is a non-empty list of unique variables.yaml.system_of_record values in catalog order; unknown cannot coexist with a known value.
  4. Confirm every referenced ID resolves to an existing record of the expected type.
  5. Confirm every scope is compatible. Neither problems nor solutions declare a vertical scope; applicability is reached through the chain audience.problem_ids[] → problem.solutionsIds[] → solution.proofIds[]. The checks are:
    • Every problem an audience binding lists in problem_ids is compatible with that binding's definition tuple. Judge it against the problem's situation and observable_signals, not against a vertical list.
    • Every solution is reachable from at least one problem's solutionsIds. An unreachable solution is orphaned, not global.
    • A solution's capability conditions and limitations do not contradict the definition tuple of any audience that reaches it.
    • A schema-version-2 proof has a non-empty, unique, catalog-ordered vertical_ids list. A reaching audience is directly compatible when its vertical is listed; otherwise the destination vertical's applicable proof_transfer_level and every required validation must permit transfer. Proof is the only record that carries vertical scope.
  6. Confirm no reverse relationship copy was added.
  7. Confirm every external or customer-derived claim carries an evidence reference, and that every hypothesis is labeled and rendered as a question.
  8. Confirm dates use YYYY-MM-DD.
  9. For an audience profile, confirm generated: true, audience_id, and source_config point to the canonical YAML and that the profile contains no authoritative kind: audience_binding block.
  10. Report each failure with the file, the field, and the rule violated. Do not silently repair a record to make validation pass.

Never

  • Report a record as valid when any referenced record is missing, draft where the calling workflow requires approved, or out of scope.

Workflows

W1 — Capture a contribution to inbox

Trigger

A sales call analysis or seller observation that has not been reconciled with the canonical library.

Inputs

Required: the observation, its source, the contributor, the date. Optional: the vertical, persona, or record it appears to concern.

Preconditions

None.

Steps

  1. Create inbox/YYYY-MM-DD-<short-description>.md.
  2. Record the observation verbatim enough that a reviewer can trace it, plus the source, contributor, and date.
  3. State which of the four things it proposes: a new record, a correction, an audience-specific observation, or evidence for an existing record.
  4. Assign a statement_type reflecting where it came from. A seller's belief is founder_instinct, not market_fact.
  5. Do not resolve IDs, deduplicate, or promote. That is W2.

Files touched

inbox/

Output

One inbox file.

Done when

The file exists and names its source, contributor, and date.

Never

  • Write to problems/, solutions/, proofs/, or audiences/.
  • Upgrade the statement type to make the observation sound stronger.

W2 — Triage an inbox item

Trigger

An existing file in inbox/ is up for review.

Inputs

Required: the inbox file path.

Preconditions

The inbox file exists.

Steps

  1. Read the item and identify the underlying claim.

  2. Run S3 against the record type the item appears to propose.

  3. Choose exactly one of four results:

    New reusable content → exit to W4, W5, W6, W7, or W8
    Improvement to existing content → exit to W13
    Audience-specific selection or framing → update one audience binding
    Insufficient or conflicting support → retain in inbox, set review status
  4. If the item supplies support for a claim, run W9 first so the promoted record can reference the evidence ID.

  5. Carry the inbox item's provenance into the promoted record through its evidence references. Do not copy the item's prose.

  6. Leave the inbox item in place with its outcome and the resulting record ID recorded. It is the audit trail.

Files touched

inbox/, plus whichever canonical file the chosen exit workflow writes.

Output

Either a canonical record created or updated, or an inbox item with a recorded review status.

Done when

The item names its outcome and, where one exists, the resulting record ID.

Never

  • Promote an observation because it appeared on a call or came from a salesperson. Apply the evidence, hypothesis, status, and approval rules from the sales asset format.
  • Promote to two record types from one item without running S3 for each.
  • Delete an inbox item on promotion.

W3 — Create a catalog record

Trigger

A market, vertical, or persona a workflow needs does not exist, and the user has explicitly requested that it be created.

Inputs

Required: the record type, the name, and for a vertical its parent market.

Preconditions

The user explicitly requested the new catalog record. An S1 halt reporting a missing record is not such a request.

Steps

  1. Confirm the explicit request. If the user only selected from a list or said the record was missing, HALT and ask whether to create it.
  2. Run S3. A near-duplicate vertical is the common failure here; verticals must be expected to share operating physics, ICP criteria, problems, persona jobs, proof, and call language.
  3. Run S2 for the ID. A vertical ID is scoped to its parent market.
  4. Add the record to its source catalog file, both the human-readable table and the YAML block, with identical IDs and status in each.
  5. Set operating_status: planned for a market or vertical, status: approved for a persona.
  6. For a vertical, set proof_transfer_level explicitly. Do not default it to direct.
  7. For a vertical, bind personas through explicit market-persona bindings. A vertical does not inherit personas.
  8. Run S4.
  9. Return to the calling workflow at the step that halted.

Files touched

markets_catalog.md, market_verticals_catalog.md, persona_list.md

Output

One new catalog record, planned or draft.

Done when

The ID resolves, the table and YAML agree, and S4 passes.

Never

  • Create a catalog record to unblock your own workflow.
  • Create a vertical in a market that does not exist.
  • Let the table and the YAML block disagree on ID or status.

W4 — Create a signal

Trigger

A new company-level signal is requested.

Inputs

Required: what is observed, and what it lets us infer. Optional: sources, polarity, problems it implies.

Preconditions

The signal changes content, not only a score. Apply this test: if the signal flips, does a different problem come first, or does only the opener change? If only the opener changes, its polarity is contextual.

Steps

  1. Run S3 against signals.yaml.
  2. Run S2 for the SG_<nnn> ID. signals.yaml mints signal IDs; signal-detection.yaml never does.
  3. Add the interpretation record to signals.yaml: id, tag, name, polarity, question, inference, audience_use, implies_problems, confidence, origin, status. Add derived_from only when the signal is computed from other signals.
  4. Write inference as the reasoning chain, ending at the operational consequence. Write audience_use as the instruction for what to do differently. These are the two fields the workflow exists to produce.
  5. Populate implies_problems with canonical problem IDs the signal makes more likely. Use [] when reviewed and none apply. The link is a hypothesis and a starting set only; whether a problem applies is decided by the audience binding that selects it, per W10 step 13.
  6. Add the matching detection row to signal-detection.yaml: signal_id, class, observable, sources, on_unknown, refresh_days, collection_cost, coverage. Set coverage: null until measured.
  7. Set on_unknown: exclude for a gating signal and include for a qualifying or contextual one.
  8. Position the record in signals.yaml by importance for audience definition, not by ID. Order is intentional; IDs are not.
  9. Run S4 on both files and confirm the join: every signal_id resolves, and no signal lacks a detection row unless it is deliberately on the enrichment backlog.

Files touched

signals.yaml, signal-detection.yaml

Output

One interpretation record and one detection row sharing an ID.

Done when

Both records exist, the join resolves, and S4 passes on each.

Never

  • Put inference, audience_use, polarity, or implies_problems in signal-detection.yaml.
  • Put class, observable, or sources in signals.yaml.
  • Mint an ID in the detection file.
  • Model a multi-valued fact as a signal. Every signal resolves to signal_state. A banded fact is a dimension in variables.yaml; add the dimension and, where a specific band carries reasoning, add a boolean signal beside it.
  • Infer one signal's state from another's unless a derived_from link says so.

W5 — Create a problem

Trigger

A new operational mismatch is requested.

Inputs

Required: the mismatch.

Preconditions

The problem describes exactly one testable operational mismatch.

Steps

  1. Write the mismatch so it does not depend on any one vertical's process physics. A problem declares no vertical scope; audience bindings decide where it applies. If the mismatch cannot be stated without naming a specific process, that process detail belongs in observable_signals or in the audience's framing, not in the mismatch.
  2. Run S3. Compare the operational mismatch, not the name.
  3. Run S2 for the P_<nnnnn> ID and create problems/<problem-id>.md with status: approved.
  4. Populate the problem schema from the sales asset format: situation, operational_mismatch, possible_consequences, observable_signals, disconfirming_signals, evidence_requirement, prohibited_claims.
  5. Write disconfirming_signals as seriously as observable_signals. A problem with no way to be wrong is not testable and must not be created. Write situation precisely: it is now the primary gate on which audiences may select this problem, so a condition like "runs more than one plant" belongs there explicitly.
  6. Set statement_type honestly. An unevidenced contribution is a hypothesis, not a market_fact.
  7. Set a provisional priority for canonical ordering only. Audience-specific priority belongs in the audience binding.
  8. Leave solutionsIds, confirmation_questions, and evidence_ids as [] if none exist yet, and record in the review section what is outstanding.
  9. Run S4.
  10. If the request came from W10, return the problem ID to that workflow. Do not add the reference to any audience binding from here.

Files touched

problems/

Output

One draft problem record.

Done when

S4 passes. The problem is not generation-ready until its required fields, evidence treatment, confirmation path, and solution reference all validate.

Never

  • Add vertical_ids, or any other vertical scope field, to a problem record.
  • Narrow a mismatch to one vertical in order to make it easier to write. A mismatch that is genuinely process-specific is a different problem, not a scoped one.
  • Create a second problem for the same mismatch worded for a different audience.
  • Put audience-specific impact, priority, or call language in the record.
  • Add a problem reference to an audience binding as a side effect. W10 owns that.

W6 — Create a solution

Trigger

A reusable mechanism for an existing canonical problem is requested.

Inputs

Required: a valid problem ID, and the mechanism.

Preconditions

The problem ID resolves. A problem name, audience file, or description is not a substitute.

Steps

  1. Resolve the problem ID with S1. If it does not resolve, HALT. Do not create a file or reserve an ID.
  2. Read the canonical problem in full before writing anything.
  3. Run S3. Compare the mechanism, not the name.
  4. Do not give the solution a vertical scope. It is reached through the problem, so it is in scope for exactly the audiences whose problem_ids include that problem. If the mechanism genuinely depends on one vertical's process physics, record that as a capability condition or a limitation, not as a scope list.
  5. Run S2 for the S_<nnnnn> ID and create solutions/<solution-id>.md with status: approved.
  6. Classify every capability with capability_classification. Do not describe a roadmap or unavailable capability in language that implies native.
  7. Add the solution ID to the selected problem's ordered solutionsIds array.
  8. Run S4 on both records.

Files touched

solutions/, problems/

Output

One draft solution, referenced by its problem.

Done when

S4 passes on both. The solution is not generation-ready until its capabilities are classified and at least one eligible proof reference resolves.

Never

  • Reserve a solution ID before the problem ID resolves.
  • Add vertical_ids, or any other vertical scope field, to a solution record.
  • Add a reverse problem reference to the solution.
  • Claim a capability the product does not deliver at its stated classification.

W7 — Create a proof

Trigger

Evidence that a solution's mechanism produced a result is available.

Inputs

Required: a valid solution ID, one or more verticals where the proof is directly applicable, what was demonstrated, and at least one evidence ID whose support covers every listed vertical.

Preconditions

The solution ID resolves. At least one evidence record exists; run W9 first if it does not.

Steps

  1. Resolve the solution ID with S1. If it does not resolve, HALT.

  2. Confirm at least one evidence ID exists and resolves. If not, exit to W9 and resume here.

  3. Run S3. Compare what is demonstrated and for whom.

  4. Determine the proof's non-empty, unique, catalog-ordered vertical_ids. Evidence must support direct applicability in each listed vertical. For each destination vertical not listed, read the explicit applicable proof_transfer_level:

    direct → the proof may be used in other verticals as written
    conditional → the proof may be used only with the stated condition attached
    prohibited → the proof may be used only inside its own vertical

    If the level is conditional, record every required condition in the proof record. If it is prohibited, record that restriction explicitly. For multiple selected source rules, use the most restrictive level and preserve the union of required validations, labeled by destination where needed. If one scalar level cannot represent the intended destinations without broadening a rule, use prohibited. Several listed verticals never imply direct transfer to a new vertical.

  5. Run S2 for the PF_<scope>_<nnn> ID, where <scope> is the sole vertical or MULTI, and create proofs/<proof-id>.md with status: approved.

  6. Bound the claim. Record what was measured, over what period, at what kind of account, and what was not measured. An unbounded proof is not usable.

  7. Add the proof ID to the solution's ordered proof references.

  8. Run S4, including the scope-compatibility check in step 5 of S4.

Files touched

proofs/, solutions/

Output

One draft proof, referenced by its solution.

Done when

S4 passes, the proof carries at least one resolving evidence ID, and its transfer condition is recorded.

Never

  • Create a proof with no evidence reference.
  • Restate a customer outcome as a general product claim.
  • Use a proof outside vertical_ids when the destination transfer level is prohibited, or without every required condition when conditional.
  • Derive a proof from a file in generated/.

W8 — Create a Q&A record

Trigger

A problem needs a confirmation path, discovery prompt, objection response, or qualification question.

Inputs

Required: a valid problem ID, the applicable persona IDs, the Q&A type, and exactly one of seller_question or buyer_question.

Preconditions

The problem ID resolves. The vertical playbook that owns the target vertical exists.

Steps

  1. Resolve the problem ID and persona IDs with S1.
  2. Confirm the vertical playbook file that owns Q&A records for this vertical exists. The location of Q&A and evidence records is not yet settled in this repository. If no owning file exists, HALT and ask where the record should live. Do not invent a directory.
  3. Run S3 against existing Q&A records for the vertical.
  4. Run S2 for the QA_<vertical>_<nnn> ID.
  5. Populate the qa_catalog schema from the sales asset format. Set exactly one of seller_question or buyer_question; setting both is invalid.
  6. Leave the answer null when the purpose is to listen and branch rather than prescribe. null here is a deliberate choice, not an omission.
  7. Preserve the statement_type of every claim inside the answer. An answer may not upgrade a hypothesis to a fact.
  8. Add the Q&A ID to the problem's confirmation_questions.
  9. Run S4 on both records.

Files touched

The owning vertical playbook, problems/

Output

One draft Q&A record, referenced by its problem.

Done when

S4 passes and the problem's confirmation_questions resolves.

Never

  • Set both seller_question and buyer_question.
  • Write an answer that asserts a claim the source record labels a hypothesis.
  • Create a qa/ directory without explicit authorization.

W9 — Record evidence

Trigger

A claim in any record needs support, or an inbox item supplies support.

Inputs

Required: what the evidence supports, the source or structured user response, the source owner or contributing user, the date accessed, and the evidence_type.

Preconditions

The source is inspectable or the user has answered structured questions that capture the observation, its provenance, scope, and limitations. A recording or attachment is optional. A link alone and an unattributed paraphrase are insufficient.

Steps

  1. Determine the scope segment for the ID: a vertical ID for one vertical, MULTI for several explicitly supported verticals, or PRODUCT for a product fact.
  2. Use docs/sales/content/evidence/<evidence-id>.md as the owning file, with one canonical evidence record per file.
  3. Run S3 against existing evidence records in scope.
  4. Run S2 for the EV_<scope>_<nnn> ID.
  5. Populate the evidence_catalog schema: type, title, source, publisher_or_owner, published_at, accessed_at, and supports. For interactive evidence, describe the authoring session in source, name the contributing user or role in publisher_or_owner, and preserve the user's observation faithfully in supports or notes. Use a stable task, thread, transcript, or session reference when available. When none exists, preserve the relevant answer in notes so the evidence record itself is inspectable.
  6. Record supports as what the evidence establishes, not as the conclusion you want from it.
  7. Set published_at: null when the source carries no publication date. Do not substitute the access date.
  8. Add the evidence ID to the evidence_ids of every record it supports.
  9. Run S4.

Files touched

The owning evidence file, plus each supported record.

Output

One evidence record, referenced by every record it supports.

Done when

S4 passes and the record states what it supports and when it was reviewed.

Never

  • Record a bare URL as evidence.
  • Require a call recording, transcript, screenshot, or attachment when structured user answers provide sufficient provenance and bounded support.
  • Convert an unattributed or materially broadened paraphrase into evidence.
  • Use accessed_at in place of published_at.
  • Cite one evidence record as support for a claim broader than its supports field.

W10 — Create an audience configuration

Trigger

A named pre-call target segment is requested.

This workflow creates the canonical audience YAML. It does not write the human-readable audience profile and does not decide that a draft is ready for call-sheet generation. The detailed interactive procedure is owned by .agents/rules/create-audience.md.

audience configuration =
vertical + persona + size_band(1+) + location_footprint
+ systems_of_record(1+) + signal_predicate(0-4)

Inputs

Required: market, vertical, persona, one or more size bands, location footprint, and one or more systems of record. Optional: zero to four pre-call signals, ordered problem IDs, discovery guidance, and framing overrides.

Preconditions

Every required tuple component resolves against an existing catalog. The requester has confirmed the exact tuple and authorized writing the draft.

Steps

  1. Resolve the market, its vertical, the reusable persona, and every controlled definition value with S1.
  2. Normalize systems_of_record to variables.yaml.system_of_record order. Reject an empty list and reject unknown when any known system is present.
  3. Separate optional pre-call selection signals from conditions learned during a conversation. A discovered condition starts as a question, not a filter.
  4. Run S3 against audiences/*.yaml, comparing the full definition tuple. Treat systems of record as a normalized set, so input order cannot create a duplicate audience.
  5. Run S2 within the vertical-persona pair and reserve the next immutable audience ID.
  6. Write audiences/<vertical-id>-<persona-id>-A<nn>.yaml with kind: audience_binding, schema_version: 2, and status: approved.
  7. Add only deliberate signal and problem references. Test every included problem against the definition tuple. Report additions, removals, and rejections without embedding workflow history in the configuration.
  8. Run S4 on the standalone YAML and report every approval or generation blocker.
  9. Offer W10E as the next step. Do not duplicate the YAML inside Markdown.

A draft may intentionally use an empty signal_predicate or problem_ids. Those states block only the downstream activities whose preconditions require them.

Files touched

audiences/<audience-id>.yaml and the audience index.

Output

One canonical audience configuration.

Done when

  • The YAML parses and its filename stem equals id.
  • Every required tuple component and included reference resolves.
  • The full tuple is not an unresolved duplicate.
  • Every included problem is compatible with the tuple.
  • The YAML contains desired state only; Git history retains configuration changes.
  • S4 reports no configuration error. Approval-readiness blockers may remain on a draft.

Never

  • Put the canonical audience_binding block in the Markdown profile.
  • Invent a signal, problem, persona responsibility, or evidence reference.
  • Treat a sales conversation as a canonical claim before evidence and authoring review.
  • Remove or deprecate a canonical signal or problem merely because this audience no longer selects it.
  • Approve the binding or run W11 yourself.

W10E — Enrich an audience profile

Trigger

An audience YAML configuration needs a human-readable guide for sales or review.

The detailed rendering procedure is owned by .agents/rules/enrich-audience.md.

Inputs

Required: one audience ID or audiences/<audience-id>.yaml.

Preconditions

The YAML parses, its id matches its filename, and the required definition tuple resolves. The binding may remain draft.

Steps

  1. Run S4 on the audience YAML.
  2. Resolve its market, vertical, persona, signal, problem, solution, proof, and other referenced records from canonical sources.
  3. Classify failures:
    • malformed YAML, invalid required values, ID mismatch, or dangling included references are hard errors and stop the write;
    • missing optional selections, unresolved market-persona membership, draft chains, and absent Q&A are visible blockers but may be rendered.
  4. Expand the configuration into the audience profile shape: summary, definition tuple, predicate, market-persona context, discovery plan, selected problems, framing, prohibited assertions, source records, and outstanding blockers.
  5. Preserve sourced wording. Label every unsourced expansion as a hypothesis and phrase it as a question where the statement-type rules require.
  6. Write audiences/<audience-id>.md with kind: audience_profile, generated: true, audience_id, source_config, and source_status. Any documentation status field mirrors source_status.
  7. Confirm the profile contains no kind: audience_binding block and no canonical fact absent from the YAML or its resolved references.
  8. Present the resulting diff and every blocker. Enrichment never changes the YAML.

Files touched

audiences/<audience-id>.md and the audience index.

Output

One enriched audience profile with traceable sources and blockers.

Done when

  • The profile points to exactly one canonical audience YAML.
  • Every rendered fact traces to the YAML or a resolved canonical record.
  • Hypotheses remain labeled and are not rendered as account facts.
  • Re-running with unchanged inputs produces no semantic change.
  • Every incomplete approval or generation dependency is visible.

Never

  • Treat the profile as a canonical input or recover YAML from it.
  • Silently repair, add to, or remove from the configuration.
  • Hide an unresolved reference or generation blocker.
  • Treat profile generation as approval.
  • Run W11 merely because a profile exists.

W11 — Generate an audience asset

Trigger

An approved audience binding is ready to render.

Inputs

Required: the audience binding ID, resolved from its canonical YAML. Optional: account-level facts and resolved contextual signal states. The enriched Markdown profile is not an input.

Preconditions

The binding passes S4, its status is approved, it selects at least one compatible problem and an opening Q&A, and at least one selected problem resolves through an approved solution to an approved proof.

Steps

  1. Confirm the binding's status is approved. If it is draft or review, HALT. A draft binding is never a generator input.
  2. Run S4 on the YAML binding and on every record in every referenced chain. Confirm each referenced solution and proof is approved, not draft.
  3. Confirm every proof's transfer condition permits use in this audience's vertical. Drop a proof that does not qualify and record the drop.
  4. Resolve contextual signals now, per account. These shape the opener and nothing else: they must not add, remove, or reorder a problem.
  5. Render the call sheet using the generated call-sheet shape from the sales asset format, into generated/CC_<audience-id>.md.
  6. Stamp provenance: every source record ID, its status at generation time, and the generation date.
  7. Render every hypothesis as a question. Render no prohibited_claims content in any form.
  8. Where a claim's statement_type is a hypothesis, do not let the rendered sentence read as established fact.

Files touched

generated/

Output

One generated call sheet with full provenance.

Done when

The asset exists, every source ID is stamped with its status, and no hypothesis is rendered as a fact.

Never

  • Generate from a draft or review binding, or from a chain containing a draft solution or proof.
  • Introduce a claim, number, or outcome absent from the source records.
  • Let a contextual signal change problem selection or order.
  • Treat a generated file as a source for any canonical record.

W12 — Regenerate after a change

Trigger

A canonical record or audience binding changed.

Inputs

Required: the changed record ID.

Preconditions

The change is complete and validated under W13.

Steps

  1. Classify the change:

    Referenced canonical record changed
    → identify every referencing audience YAML
    → rerun W10E
    → rerun W11 when its approved generation inputs changed

    Audience YAML changed
    → rerun W10E
    → rerun W11 when the binding remains generation-ready

    Audience profile changed directly
    → discard the edit and rerun W10E

    Generated call sheet changed directly
    → discard the edit and rerun W11
  2. For a canonical change, search every audiences/*.yaml binding for the changed ID. Search by ID, not by name or profile wording.

  3. Run W10E for every affected audience, including drafts.

  4. Run W11 only for affected bindings that still satisfy its preconditions.

  5. If a change invalidated a chain — a solution deprecated, a proof's transfer level tightened — refresh the audience profile so it shows the blocker, do not regenerate the call sheet, and report the binding as no longer generation-ready.

Files touched

audiences/*.md and generated/

Output

Regenerated audience profiles and, where eligible, regenerated call sheets; or a report of audiences no longer generation-ready.

Done when

Every affected audience profile is refreshed, and every affected call sheet is either regenerated or reported as blocked.

Never

  • Refresh a subset silently. Report every affected audience, including the ones whose profile refreshed but whose call sheet could not.
  • Edit an audience profile or generated call sheet in place instead of regenerating it from canonical sources.
  • Recover a canonical fact from a generated file.

W13 — Change, deprecate, or retire a record

Trigger

A record is wrong, superseded, or withdrawn.

Inputs

Required: the record ID and the reason.

Preconditions

The record ID resolves.

Steps

  1. Resolve the record with S1.

  2. Choose the action:

    Content is wrong or incomplete → update the one owning file
    Record is superseded → set status deprecated, name the successor ID
    Record is withdrawn from use → set status archived
    Meaning would change → do not edit; create a new record
  3. If the change would alter what the ID means, HALT. Never repurpose a published ID. Deprecate it and mint a new one.

  4. Update the single owning file. Never edit a copy or a referencing record's restatement of the content.

  5. Find every record referencing this ID and check each still validates. A deprecated solution leaves its problem without an approved chain.

  6. For a deprecated or archived record, leave every existing reference in place and report which referencing records are now invalid. Do not silently remove references.

  7. Where the source catalog has both a table and a YAML block, update both so IDs and status agree.

  8. Run S4 on the changed record and on every referencing record.

  9. Exit to W12.

Files touched

The owning file, plus any referencing record whose validation status changed.

Output

An updated, deprecated, or archived record, and a list of referencing records affected.

Done when

S4 passes on the changed record, and every referencing record is either still valid or reported as invalid.

Never

  • Repurpose a published ID for a different meaning.
  • Delete a canonical record. Deprecate or archive it.
  • Remove references to a deprecated record without reporting them.
  • Renumber records to close a gap.

W14 — Help: route a contribution to a workflow

Trigger

Any of: "help", "how do I contribute this", "which workflow do I use", "where does this go", or a contribution offered with no workflow named.

Inputs

Optional: whatever the user has. This workflow assumes nothing.

Preconditions

None. This is the only workflow with no preconditions.

Steps

  1. Ask what the user has, in their words. Do not ask for an ID, a record type, or a schema. Those are outputs of this workflow, not inputs to it.
  2. Route from what they have using Start here: what do you have?. That table is the routing rule; do not restate it, and do not invent a different mapping.
  3. If the contribution spans several workflows, name the order and say why. The dependency order is always: evidence, then proof, then the record that cites it; and problem, then solution, then proof.
  4. If the user is unsure whether their contribution is new, run S3 for them before recommending an authoring workflow. Finding an existing record is a success, not a dead end.
  5. Explain only the workflow they need. Do not narrate the other thirteen.
  6. Name the ones that apply from Four things that stop most contributions. Name only the ones that apply to what they brought, not all four by rote.
  7. Point them at the two reference sections rather than restating them: Invariants for the rules, and Source catalogs for where records live.

Files touched

None. This workflow only routes.

Output

A named workflow, and the order to run it in if several apply.

Done when

The user knows which workflow to start and what it needs from them.

Never

  • Start the recommended workflow without being asked to. Routing is not authorization.
  • Write any file from this workflow.
  • Tell a user their contribution is not worth recording. Everything goes to inbox/ via W1; triage in W2 decides what becomes canonical, and that decision is a person's.
  • Demand a record type or schema before helping. If the user could name the record type, they would not need W14.

Agent operating rules

These apply across every workflow and override any conflicting instruction in a request.

  1. Search canonical files by immutable ID and by meaning before proposing a new record.
  2. Put unresolved or unreviewed observations in inbox/.
  3. Update the one owning canonical file rather than copying content.
  4. Put audience selection, priority, impact framing, and call language in the standalone audience YAML. Enriched audience Markdown is a generated view.
  5. Preserve published IDs. Deprecate a record instead of repurposing its ID.
  6. Treat inbox/, generated/, and enriched audience Markdown profiles as non-authoritative.
  7. Validate every reference before generating an asset.
  8. Never modify or read from docs/sales-legacy/. Ignore every file in it.
  9. Stop at every HALT. Presenting options is not permission to choose.
  10. Report what you could not complete. A partial result reported honestly is correct; a gap filled by inference is not.

Open questions

  1. Q&A record location is unsettled. The sales asset format defines QA_ records inside the vertical playbook section, but no vertical playbook file or qa/ directory exists. W8 therefore halts rather than guessing.
  2. Generated card filenames are unsettled. The pattern is CC_<audience>, but one audience produced two openers, so both cards in generated/ append the problem ID: CC_M1_V1-P1-A01_P_00001. Settle whether that suffix is the rule or whether one audience yields one card before more cards are generated.

Resolved and closed:

  • Audience file naming and authority. Each audience now uses an ID-matched pair: canonical <vertical-id>-<persona-id>-A<nn>.yaml and enriched <vertical-id>-<persona-id>-A<nn>.md.

Change log

  • 2026-08-01 — Migrated proof_catalog to schema version 2 with required multi-select vertical_ids; added PF_MULTI_<nnn> scope IDs; established content/evidence/ as the canonical evidence location; and allowed W9 to create bounded evidence from structured user responses without requiring a call recording or attachment.
  • 2026-08-01 — Migrated audience bindings to schema version 2. Systems of record are now a normalized, non-empty multi-select; unknown cannot coexist with a known system.
  • 2026-07-26 — Split audience configuration from presentation. W10 now creates standalone audience YAML, W10E enriches it into Markdown, W11 remains approved call-sheet generation, and W12 refreshes both downstream layers as applicable.
  • 2026-07-24 — size_band now holds one or more company_size bands rather than exactly one. Several bands belong in one audience when the problem set, framing, and call language are identical across them; a difference in any of the three is a different tuple and a separate audience.
  • 2026-07-24 — Restructured into fourteen numbered workflows and four subroutines, each with explicit inputs, preconditions, halts, outputs, and prohibitions. Added W3 catalog records, W4 signals, W7 proofs, W8 Q&A, W9 evidence, W11 asset generation, and W13 record lifecycle, all previously referenced but undefined. Added W14 as the routing entry point for contributors. Extended W10 to the full audience definition including size band, location footprint, systems of record, and a signal predicate. Renamed the then-canonical audience Markdown files to allow several audiences per vertical and persona pair. Removed the "optionally" ambiguity from problem creation and the duplicate trailing rule section.