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 have | Go to | Why |
|---|---|---|
| Notes from a call, or something a seller said | W1 | It is not canonical yet. Capture it, then triage. |
| An inbox item to review | W2 | Triage decides whether it becomes a record. |
| A market, vertical, or persona that does not exist | W3 | Requires an explicit request from you. |
| An observable trait that predicts something | W4 | A signal. Two files, one ID. |
| A recurring operational mismatch | W5 | A problem. Needs a way to be wrong. |
| How we address a known problem | W6 | A solution. Needs the problem ID first. |
| Evidence a solution worked somewhere | W7 | A proof. Needs the solution ID and an evidence ID. |
| A question that confirms a problem on a call | W8 | A Q&A record. |
| A source, artifact, or interview backing a claim | W9 | Evidence. Record it before the claim depends on it. |
| A segment worth building a sequence for | W10 | Create its YAML configuration. |
| An audience YAML that needs a sales guide | W10E | Enrich the configuration into an audience profile. |
| An approved audience to turn into a call sheet | W11 | Generation. |
| Something changed and assets are stale | W12 | Regeneration. |
| Something is wrong, superseded, or withdrawn | W13 | Lifecycle. Never edit an ID's meaning. |
| You are not sure whether it already exists | S3 | Duplicate check by meaning. Run it before authoring. |
| You are not sure which of these applies | W14 | Routing. 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.
W1thenW9, not straight toW5. - 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
| ID | Workflow | Entry point |
|---|---|---|
W1 | Capture a contribution to inbox | A call analysis or seller observation |
W2 | Triage an inbox item | An existing inbox file |
W3 | Create a catalog record | A missing market, vertical, or persona |
W4 | Create a signal | A new company-level signal |
W5 | Create a problem | A new operational mismatch |
W6 | Create a solution | An existing problem ID |
W7 | Create a proof | An existing solution ID |
W8 | Create a Q&A record | An existing problem ID |
W9 | Record evidence | A claim needing support |
W10 | Create an audience configuration | A named target segment |
W10E | Enrich an audience profile | An audience YAML configuration |
W11 | Generate an audience asset | An approved audience binding |
W12 | Regenerate after a change | A changed canonical record |
W13 | Change, deprecate, or retire a record | A correction or withdrawal |
W14 | Help — route a contribution to a workflow | "how do I contribute this?" |
New here? Start at W14.
Subroutine index
| ID | Subroutine | Called by |
|---|---|---|
S1 | Resolve a catalog reference | W3–W11, W10E |
S2 | Assign the next record ID | W4–W10 |
S3 | Find duplicates by meaning | W4–W8, W10 |
S4 | Validate a record and its references | every 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.
-
One owner per fact. Exactly one file owns each record. Other records refer to it by immutable ID.
-
The canonical chain runs one way.
Audience binding --references→ Problem --references→ Solution --references→ ProofThe problem owns its ordered solution references. The solution owns its ordered proof references. Never add a reverse copy of a relationship.
-
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 rerunW10E; never edit the profile as the source. -
inbox/is provisional. It is never a generator input and never an approved sales claim. -
IDs are immutable after publication. Deprecate a record instead of repurposing its ID.
-
Audience-specific content stays in the audience binding. Selection, order, priority, impact framing, and call language belong there. Canonical records hold none of it.
-
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[] → proofThe audience binding's
problem_idsis the only statement of where a problem applies, and the problem'ssituationis what a selection is tested against. Proof is the one record that stays vertical-scoped. Its requiredvertical_idslist names every vertical in which the bounded proof is directly applicable; evidence must support every listed scope. -
A market-persona binding selects no problems. It establishes that a persona is admissible in a vertical. Targeting belongs to the audience.
-
A YAML
nullmeans unknown. An empty list means reviewed and none found. They are not interchangeable. -
Every hypothesis is labeled and rendered as a question. Apply the
statement_typerules from the sales asset format. -
Never modify
docs/sales-legacy/. Ignore every file in it, including as a source for search or duplicate detection.
ID patterns
| Record | Pattern | Example |
|---|---|---|
| Market | M<n> | M1 |
| Vertical | <market>_V<n> | M1_V2 |
| Persona | P<n> | P2 |
| Signal | SG_<nnn> | SG_021 |
| Problem | P_<nnnnn> | P_00001 |
| Solution | S_<nnnnn> | S_00001 |
| Proof | PF_<scope>_<nnn> | PF_MULTI_001 |
| Q&A | QA_<vertical>_<nnn> | QA_M1_V2_001 |
| Evidence | EV_<scope>_<nnn> | EV_M1_V2_001 |
| Audience binding | <vertical>-<persona>-A<nn> | M1_V1-P1-A02 |
| Generated call card | CC_<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
| Records | File |
|---|---|
| Controlled values and dimensions | variables.yaml |
| Markets | markets_catalog.md |
| Verticals | market_verticals_catalog.md |
| Personas | persona_list.md |
| Signal meaning and use | signals.yaml |
| Signal detection | signal-detection.yaml |
| Evidence | evidence/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
-
If the request supplies an exact immutable ID, look it up in its source catalog. If it resolves, return it.
-
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
IDandNamecolumn:ID Name <ID><name>Ask the user to select one.
-
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.
-
If the list is empty, say so and HALT. Do not create the missing record here.
-
If the user states that the intended record does not exist, exit to
W3for 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
- Identify the owning location for the record type from the ID pattern table.
- List every existing ID of that type, including records with status
deprecatedandarchived. - For a scoped pattern (
PF_,QA_,EV_), restrict the scan to the resolved scope segment. A proof with onevertical_idsvalue uses that vertical; a proof with several usesMULTI. - Take the highest numeric suffix, add one, and zero-pad to the pattern's width.
- Create the file immediately with
status: approvedto reserve the ID before any further work. - 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
-
Search the canonical records of the same type by meaning, not by name or filename similarity. For an audience, search standalone
*.yamlconfigurations only; adjacent Markdown profiles are generated views. -
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.
-
If no candidate matches, return "none found" and continue.
-
If one or more candidates match, HALT. Display them and ask the user to choose:
ID Name <ID><name>The three permitted answers are: reuse the existing record, update the existing record, or create a materially distinct record.
-
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
- Confirm the YAML block or standalone YAML record declares
kindandschema_version. An audience binding must be a standalone YAML file whose filename stem equals itsid. - 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".
- Confirm every enum value resolves in variables.yaml.
For an audience binding,
definition.systems_of_recordis a non-empty list of uniquevariables.yaml.system_of_recordvalues in catalog order;unknowncannot coexist with a known value. - Confirm every referenced ID resolves to an existing record of the expected type.
- 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_idsis compatible with that binding's definition tuple. Judge it against the problem'ssituationandobservable_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
conditionsandlimitationsdo not contradict the definition tuple of any audience that reaches it. - A schema-version-2 proof has a non-empty, unique, catalog-ordered
vertical_idslist. A reaching audience is directly compatible when its vertical is listed; otherwise the destination vertical's applicableproof_transfer_leveland every required validation must permit transfer. Proof is the only record that carries vertical scope.
- Every problem an audience binding lists in
- Confirm no reverse relationship copy was added.
- Confirm every external or customer-derived claim carries an evidence reference, and that every hypothesis is labeled and rendered as a question.
- Confirm dates use
YYYY-MM-DD. - For an audience profile, confirm
generated: true,audience_id, andsource_configpoint to the canonical YAML and that the profile contains no authoritativekind: audience_bindingblock. - 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,
draftwhere the calling workflow requiresapproved, 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
- Create
inbox/YYYY-MM-DD-<short-description>.md. - Record the observation verbatim enough that a reviewer can trace it, plus the source, contributor, and date.
- State which of the four things it proposes: a new record, a correction, an audience-specific observation, or evidence for an existing record.
- Assign a
statement_typereflecting where it came from. A seller's belief isfounder_instinct, notmarket_fact. - 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/, oraudiences/. - 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
-
Read the item and identify the underlying claim.
-
Run
S3against the record type the item appears to propose. -
Choose exactly one of four results:
New reusable content → exit to W4, W5, W6, W7, or W8Improvement to existing content → exit to W13Audience-specific selection or framing → update one audience bindingInsufficient or conflicting support → retain in inbox, set review status -
If the item supplies support for a claim, run
W9first so the promoted record can reference the evidence ID. -
Carry the inbox item's provenance into the promoted record through its evidence references. Do not copy the item's prose.
-
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
S3for 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
- 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.
- 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. - Run
S2for the ID. A vertical ID is scoped to its parent market. - Add the record to its source catalog file, both the human-readable table and the YAML block, with identical IDs and status in each.
- Set
operating_status: plannedfor a market or vertical,status: approvedfor a persona. - For a vertical, set
proof_transfer_levelexplicitly. Do not default it todirect. - For a vertical, bind personas through explicit market-persona bindings. A vertical does not inherit personas.
- Run
S4. - 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
- Run
S3against signals.yaml. - Run
S2for theSG_<nnn>ID. signals.yaml mints signal IDs; signal-detection.yaml never does. - Add the interpretation record to signals.yaml:
id,tag,name,polarity,question,inference,audience_use,implies_problems,confidence,origin,status. Addderived_fromonly when the signal is computed from other signals. - Write
inferenceas the reasoning chain, ending at the operational consequence. Writeaudience_useas the instruction for what to do differently. These are the two fields the workflow exists to produce. - Populate
implies_problemswith 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, perW10step 13. - Add the matching detection row to
signal-detection.yaml:
signal_id,class,observable,sources,on_unknown,refresh_days,collection_cost,coverage. Setcoverage: nulluntil measured. - Set
on_unknown: excludefor agatingsignal andincludefor aqualifyingorcontextualone. - Position the record in signals.yaml by importance for audience definition, not by ID. Order is intentional; IDs are not.
- Run
S4on both files and confirm the join: everysignal_idresolves, 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, orimplies_problemsin signal-detection.yaml. - Put
class,observable, orsourcesin 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_fromlink 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
- 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_signalsor in the audience's framing, not in the mismatch. - Run
S3. Compare the operational mismatch, not the name. - Run
S2for theP_<nnnnn>ID and createproblems/<problem-id>.mdwithstatus: approved. - Populate the problem schema from the sales asset format:
situation,operational_mismatch,possible_consequences,observable_signals,disconfirming_signals,evidence_requirement,prohibited_claims. - Write
disconfirming_signalsas seriously asobservable_signals. A problem with no way to be wrong is not testable and must not be created. Writesituationprecisely: 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. - Set
statement_typehonestly. An unevidenced contribution is a hypothesis, not amarket_fact. - Set a provisional
priorityfor canonical ordering only. Audience-specific priority belongs in the audience binding. - Leave
solutionsIds,confirmation_questions, andevidence_idsas[]if none exist yet, and record in the review section what is outstanding. - Run
S4. - 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.
W10owns 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
- Resolve the problem ID with
S1. If it does not resolve, HALT. Do not create a file or reserve an ID. - Read the canonical problem in full before writing anything.
- Run
S3. Compare the mechanism, not the name. - 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_idsinclude that problem. If the mechanism genuinely depends on one vertical's process physics, record that as a capabilityconditionor alimitation, not as a scope list. - Run
S2for theS_<nnnnn>ID and createsolutions/<solution-id>.mdwithstatus: approved. - Classify every capability with
capability_classification. Do not describe aroadmaporunavailablecapability in language that impliesnative. - Add the solution ID to the selected problem's ordered
solutionsIdsarray. - Run
S4on 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
-
Resolve the solution ID with
S1. If it does not resolve, HALT. -
Confirm at least one evidence ID exists and resolves. If not, exit to
W9and resume here. -
Run
S3. Compare what is demonstrated and for whom. -
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 applicableproof_transfer_level:direct → the proof may be used in other verticals as writtenconditional → the proof may be used only with the stated condition attachedprohibited → the proof may be used only inside its own verticalIf the level is
conditional, record every required condition in the proof record. If it isprohibited, 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, useprohibited. Several listed verticals never imply direct transfer to a new vertical. -
Run
S2for thePF_<scope>_<nnn>ID, where<scope>is the sole vertical orMULTI, and createproofs/<proof-id>.mdwithstatus: approved. -
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.
-
Add the proof ID to the solution's ordered proof references.
-
Run
S4, including the scope-compatibility check in step 5 ofS4.
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_idswhen the destination transfer level isprohibited, or without every required condition whenconditional. - 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
- Resolve the problem ID and persona IDs with
S1. - 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.
- Run
S3against existing Q&A records for the vertical. - Run
S2for theQA_<vertical>_<nnn>ID. - Populate the
qa_catalogschema from the sales asset format. Set exactly one ofseller_questionorbuyer_question; setting both is invalid. - Leave the answer
nullwhen the purpose is to listen and branch rather than prescribe.nullhere is a deliberate choice, not an omission. - Preserve the
statement_typeof every claim inside the answer. An answer may not upgrade a hypothesis to a fact. - Add the Q&A ID to the problem's
confirmation_questions. - Run
S4on 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_questionandbuyer_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
- Determine the scope segment for the ID: a vertical ID for one vertical,
MULTIfor several explicitly supported verticals, orPRODUCTfor a product fact. - Use
docs/sales/content/evidence/<evidence-id>.mdas the owning file, with one canonical evidence record per file. - Run
S3against existing evidence records in scope. - Run
S2for theEV_<scope>_<nnn>ID. - Populate the
evidence_catalogschema:type,title,source,publisher_or_owner,published_at,accessed_at, andsupports. For interactive evidence, describe the authoring session insource, name the contributing user or role inpublisher_or_owner, and preserve the user's observation faithfully insupportsornotes. Use a stable task, thread, transcript, or session reference when available. When none exists, preserve the relevant answer innotesso the evidence record itself is inspectable. - Record
supportsas what the evidence establishes, not as the conclusion you want from it. - Set
published_at: nullwhen the source carries no publication date. Do not substitute the access date. - Add the evidence ID to the
evidence_idsof every record it supports. - 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_atin place ofpublished_at. - Cite one evidence record as support for a claim broader than its
supportsfield.
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
- Resolve the market, its vertical, the reusable persona, and every controlled
definition value with
S1. - Normalize
systems_of_recordtovariables.yaml.system_of_recordorder. Reject an empty list and rejectunknownwhen any known system is present. - Separate optional pre-call selection signals from conditions learned during a conversation. A discovered condition starts as a question, not a filter.
- Run
S3againstaudiences/*.yaml, comparing the full definition tuple. Treat systems of record as a normalized set, so input order cannot create a duplicate audience. - Run
S2within the vertical-persona pair and reserve the next immutable audience ID. - Write
audiences/<vertical-id>-<persona-id>-A<nn>.yamlwithkind: audience_binding,schema_version: 2, andstatus: approved. - 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.
- Run
S4on the standalone YAML and report every approval or generation blocker. - Offer
W10Eas 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.
S4reports no configuration error. Approval-readiness blockers may remain on a draft.
Never
- Put the canonical
audience_bindingblock 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
W11yourself.
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
- Run
S4on the audience YAML. - Resolve its market, vertical, persona, signal, problem, solution, proof, and other referenced records from canonical sources.
- 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.
- 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.
- Preserve sourced wording. Label every unsourced expansion as a hypothesis and phrase it as a question where the statement-type rules require.
- Write
audiences/<audience-id>.mdwithkind: audience_profile,generated: true,audience_id,source_config, andsource_status. Any documentationstatusfield mirrorssource_status. - Confirm the profile contains no
kind: audience_bindingblock and no canonical fact absent from the YAML or its resolved references. - 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
W11merely 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
- Confirm the binding's status is
approved. If it isdraftorreview, HALT. A draft binding is never a generator input. - Run
S4on the YAML binding and on every record in every referenced chain. Confirm each referenced solution and proof isapproved, notdraft. - Confirm every proof's transfer condition permits use in this audience's vertical. Drop a proof that does not qualify and record the drop.
- Resolve
contextualsignals now, per account. These shape the opener and nothing else: they must not add, remove, or reorder a problem. - Render the call sheet using the generated call-sheet shape from the sales
asset format, into
generated/CC_<audience-id>.md. - Stamp provenance: every source record ID, its status at generation time, and the generation date.
- Render every hypothesis as a question. Render no
prohibited_claimscontent in any form. - Where a claim's
statement_typeis 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
draftorreviewbinding, or from a chain containing adraftsolution or proof. - Introduce a claim, number, or outcome absent from the source records.
- Let a
contextualsignal 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
-
Classify the change:
Referenced canonical record changed→ identify every referencing audience YAML→ rerun W10E→ rerun W11 when its approved generation inputs changedAudience YAML changed→ rerun W10E→ rerun W11 when the binding remains generation-readyAudience profile changed directly→ discard the edit and rerun W10EGenerated call sheet changed directly→ discard the edit and rerun W11 -
For a canonical change, search every
audiences/*.yamlbinding for the changed ID. Search by ID, not by name or profile wording. -
Run
W10Efor every affected audience, including drafts. -
Run
W11only for affected bindings that still satisfy its preconditions. -
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
-
Resolve the record with
S1. -
Choose the action:
Content is wrong or incomplete → update the one owning fileRecord is superseded → set status deprecated, name the successor IDRecord is withdrawn from use → set status archivedMeaning would change → do not edit; create a new record -
If the change would alter what the ID means, HALT. Never repurpose a published ID. Deprecate it and mint a new one.
-
Update the single owning file. Never edit a copy or a referencing record's restatement of the content.
-
Find every record referencing this ID and check each still validates. A deprecated solution leaves its problem without an approved chain.
-
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.
-
Where the source catalog has both a table and a YAML block, update both so IDs and status agree.
-
Run
S4on the changed record and on every referencing record. -
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
- 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.
- 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.
- 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.
- If the user is unsure whether their contribution is new, run
S3for them before recommending an authoring workflow. Finding an existing record is a success, not a dead end. - Explain only the workflow they need. Do not narrate the other thirteen.
- 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.
- 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/viaW1; triage inW2decides 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.
- Search canonical files by immutable ID and by meaning before proposing a new record.
- Put unresolved or unreviewed observations in
inbox/. - Update the one owning canonical file rather than copying content.
- Put audience selection, priority, impact framing, and call language in the standalone audience YAML. Enriched audience Markdown is a generated view.
- Preserve published IDs. Deprecate a record instead of repurposing its ID.
- Treat
inbox/,generated/, and enriched audience Markdown profiles as non-authoritative. - Validate every reference before generating an asset.
- Never modify or read from
docs/sales-legacy/. Ignore every file in it. - Stop at every HALT. Presenting options is not permission to choose.
- Report what you could not complete. A partial result reported honestly is correct; a gap filled by inference is not.
Open questions
- Q&A record location is unsettled. The sales asset format defines
QA_records inside the vertical playbook section, but no vertical playbook file orqa/directory exists.W8therefore halts rather than guessing. - Generated card filenames are unsettled. The pattern is
CC_<audience>, but one audience produced two openers, so both cards ingenerated/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>.yamland enriched<vertical-id>-<persona-id>-A<nn>.md.
Change log
- 2026-08-01 — Migrated
proof_catalogto schema version 2 with required multi-selectvertical_ids; addedPF_MULTI_<nnn>scope IDs; establishedcontent/evidence/as the canonical evidence location; and allowedW9to 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;
unknowncannot coexist with a known system. - 2026-07-26 — Split audience configuration from presentation.
W10now creates standalone audience YAML,W10Eenriches it into Markdown,W11remains approved call-sheet generation, andW12refreshes both downstream layers as applicable. - 2026-07-24 —
size_bandnow holds one or morecompany_sizebands 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
W3catalog records,W4signals,W7proofs,W8Q&A,W9evidence,W11asset generation, andW13record lifecycle, all previously referenced but undefined. AddedW14as the routing entry point for contributors. ExtendedW10to 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.