docs: OpenBroadcast and OpenGuest, the broadcaster-and-guest framework as OpenProfile.md sections (#168)

* docs: OpenBroadcast and OpenGuest, the broadcaster-and-guest framework as OpenProfile.md sections

Anthony: "broadcasters and guests is the usual framework for live audio
shows, radio, podcasts" and OpenProfile.md should carry it so a platform
(anyfans) can match hosts with guests from two files rather than two
forms. OpenExpert folds into OpenGuest: an expert is a guest with
Expertise and Credentials.

OpenBroadcast is the `## Broadcast` section: Show, Kind, Format, Live,
Cadence, Length, Language, Audience (host's own unit), Feed, Topics,
Seeking, Not, Slots, Remote, Book, and Pays / Charges (unstated by
default, because pay-to-play is the thing a guest is most often not
told). OpenGuest is the `## Guest` section: Available, Expertise,
Credentials, Pitch, Formats, Live, Languages, Availability, Lead time,
Remote, Rate, Pays, Appeared on, Press, Book, Not. Matching scores
Topics/Seeking against Expertise/Topics, Slots against Availability,
Pays/Charges against Rate/Pays; both Not keys are absolute; a platform
never fills a key the person did not write. Both landing pages share
profile-section-page.tsx. OpenProfile.md names the two sections in rule
4 and in Related standards. Registered in the four places.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014cmNRtR2vL1p89dbVQ7FZJ

* ci: trigger workflows

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Anthony Ettinger 2026-09-12 20:30:42 -07:00 • committed by GitHub
parent 0fe1d423df
commit a005d7c716
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 464 additions and 1 deletions

View file

@ -34,6 +34,8 @@ export function GET(): Response {
- [OpenRecipe.md](${SITE_URL}/openrecipe): One Markdown file that is a recipe: summary block (Serves, Prep, Cook, Cuisine, Diet, Author, Source), ingredients and steps as written, notes, nutrition; served next to the page or linked with rel="openrecipe"; schema.org/Recipe JSON-LD is derived from it, never the reverse. - [OpenRecipe.md](${SITE_URL}/openrecipe): One Markdown file that is a recipe: summary block (Serves, Prep, Cook, Cuisine, Diet, Author, Source), ingredients and steps as written, notes, nutrition; served next to the page or linked with rel="openrecipe"; schema.org/Recipe JSON-LD is derived from it, never the reverse.
- [OpenAffiliate](${SITE_URL}/openaffiliate): One file a merchant serves about the commission it pays, at /.well-known/openaffiliate.json: programs with what pays (sale, subscription, signup, lead, install), percent or amount, attribution window, hold days and payout methods; four calls let a person or an agent join with an OpenProfile.md, link with ?oa=code, read its own ledger and get paid to its own address. No network in the money; reference implementation crawlproof.com/affiliate. - [OpenAffiliate](${SITE_URL}/openaffiliate): One file a merchant serves about the commission it pays, at /.well-known/openaffiliate.json: programs with what pays (sale, subscription, signup, lead, install), percent or amount, attribution window, hold days and payout methods; four calls let a person or an agent join with an OpenProfile.md, link with ?oa=code, read its own ledger and get paid to its own address. No network in the money; reference implementation crawlproof.com/affiliate.
- [OpenThreat](${SITE_URL}/openthreat): One file a security tool serves about what it found in the open, at /.well-known/openthreat.json: findings in public repositories, attacks on the reporter's own infrastructure, indicators and advisories, with severity, rule, subject and status. Private subjects are never in it, secrets are never located while open, announcing is on by default with a one-switch opt-out. First reporter threatcrush.com/discovery, first directory nichedb.dev/c/threats. - [OpenThreat](${SITE_URL}/openthreat): One file a security tool serves about what it found in the open, at /.well-known/openthreat.json: findings in public repositories, attacks on the reporter's own infrastructure, indicators and advisories, with severity, rule, subject and status. Private subjects are never in it, secrets are never located while open, announcing is on by default with a one-switch opt-out. First reporter threatcrush.com/discovery, first directory nichedb.dev/c/threats.
- [OpenBroadcast](${SITE_URL}/openbroadcast): The Broadcast section of an OpenProfile.md: the show a person hosts (podcast, radio, live audio, stream) with kind, format, cadence, audience, topics, slots, whether it pays or charges guests, and who the host is seeking, so a host and a guest are matched from two files rather than two forms.
- [OpenGuest](${SITE_URL}/openguest): The Guest section of an OpenProfile.md: that a person will appear on shows, with expertise, credentials, pitch, formats, availability, rate, past appearances and dealbreakers. An expert is a guest with Expertise and Credentials. Matched against OpenBroadcast.
- [AgentSwarm](${SITE_URL}/agent-swarm): Provider-neutral agent orchestration, model routing, and cost controls. - [AgentSwarm](${SITE_URL}/agent-swarm): Provider-neutral agent orchestration, model routing, and cost controls.
- [AgentByte](${SITE_URL}/agentbyte): Agent screening sessions, policy events, and APIs. - [AgentByte](${SITE_URL}/agentbyte): Agent screening sessions, policy events, and APIs.
- [Credential Sharing](${SITE_URL}/credential-sharing): End-to-end-encrypted team vaults, plus source/target credential diffs, approval, sync, rollback, and audit. - [Credential Sharing](${SITE_URL}/credential-sharing): End-to-end-encrypted team vaults, plus source/target credential diffs, approval, sync, rollback, and audit.

View file

@ -0,0 +1,61 @@
import type { ReactNode } from "react";
import type { Metadata } from "next";
import { ProfileSectionPage, type ProfileSection } from "@/components/profile-section-page";
export const metadata: Metadata = {
title: "OpenBroadcast · LogicSRC",
description:
"OpenBroadcast is the Broadcast section of an OpenProfile.md: the show a person hosts (podcast, radio, live audio, stream), its format, cadence, audience, topics and slots, and who the host is seeking, so a host and a guest are matched from two files rather than two forms.",
alternates: { canonical: "/openbroadcast" }
};
const SPEC: ProfileSection = {
name: "OpenBroadcast",
slug: "openbroadcast",
section: "Broadcast",
tagline:
"What a person hosts, live or recorded, on air or online, and who they are looking for on it.",
problem:
"Every show has a booking page and every booking page is a form. A host who wants guests fills in four of them, and each holds half of what a guest needs to know: what the show is about, who listens, how long a segment runs, whether it is live, what the host wants this month. A guest's agent asked which shows on climate finance record in the evening in Europe reads twelve pages twelve ways. The host wrote the answers once and typed them into forms that will not hand them back.",
sample: `## Broadcast
- **Show**: The Analytical Engine
- **Kind**: podcast
- **Format**: interview
- **Live**: no
- **Cadence**: weekly
- **Length**: 45 min
- **Language**: en
- **Audience**: 12k downloads/episode
- **Feed**: https://ada.example/podcast/feed.xml
- **Topics**: computing history, mathematics, women in science
- **Seeking**: historians, engineers with a story, first-time guests welcome
- **Not**: crypto, product pitches
- **Slots**: Tue and Thu 18:00-20:00 Europe/London
- **Remote**: yes
- **Book**: https://ada.example/podcast/book
- **Pays**: no
- **Charges**: no`,
keys: [
["Show, Kind, Format", "name; podcast, radio, live-audio, stream, video, newsletter, series; interview, panel, solo, call-in, roundtable, narrative", "What the show is. Two shows are two sections, or ### groups in one."],
["Live, Cadence, Length, Language, Since", "yes / no / both; weekly, monthly, seasonal; a duration; language tags; a year or month", "As the host writes them."],
["Audience", "the host's figure in the host's unit", "12k downloads/episode, 3,000 live listeners. A reader shows the unit and never compares across units."],
["Feed, Listen, Watch, Network", "URLs; a name or OpenProfile.md URL", "Feed is the episode list; RSS already is the spec for it."],
["Topics, Seeking, Not", "loosely matched words", "What the show covers, who the host wants, what the host will not book. Not wins over everything."],
["Slots, Remote, Book", "as written with a timezone; yes / no / preferred / in-person only; URL", "When and how a guest appears, and where to ask."],
["Pays, Charges", "no, yes, or an amount", "Whether the show pays guests and whether it charges them. Unstated by default, because pay-to-play is the thing a guest is most often not told."]
],
matching:
"A booking platform reads a host's Broadcast and a guest's Guest section and scores the pair from what both wrote: Topics and Seeking against Expertise and Topics, Slots against Availability, Language against Languages, Remote against Remote, Pays and Charges against Rate and Pays. Both Not keys are absolute. Everything else is a score, and the platform says how it scored. The platform never fills a key the person did not write.",
absent: [
["No episode list", "Feed is the episode list, and RSS already is the spec."],
["No audience verification", "Audience is the host's figure. A platform that verifies it labels the verification as its own."],
["No booking protocol", "Book is a link. What happens there is the platform's business."],
["No JSON", "The Markdown is the canonical copy; a structured view is derived on every read."]
],
counterpart: ["OpenGuest", "openguest"]
};
export default function OpenBroadcastPage(): ReactNode {
return <ProfileSectionPage spec={SPEC} />;
}

View file

@ -0,0 +1,60 @@
import type { ReactNode } from "react";
import type { Metadata } from "next";
import { ProfileSectionPage, type ProfileSection } from "@/components/profile-section-page";
export const metadata: Metadata = {
title: "OpenGuest · LogicSRC",
description:
"OpenGuest is the Guest section of an OpenProfile.md: that a person is available to appear on shows, their expertise and credentials, formats, availability, rate, past appearances and dealbreakers, so a guest and a host are matched from two files rather than two forms. An expert is a guest with Expertise and Credentials.",
alternates: { canonical: "/openguest" }
};
const SPEC: ProfileSection = {
name: "OpenGuest",
slug: "openguest",
section: "Guest",
tagline:
"That a person will appear on other people's shows, what they can speak to, when, on what terms, and where they have been heard before.",
problem:
"An expert who is happy to be interviewed has no way to say so that a host's search will find. They fill in a guest-matching site, a speaker bureau, a press page and a line in a bio, and each holds a fragment: topics on one, availability on another, the fee nowhere. A host's agent asked who can talk about analytical engines, records in the evening in Europe and does not charge reads a hundred profiles a hundred ways.",
sample: `## Guest
- **Available**: yes
- **Expertise**: analytical engines, early computing, mathematics education
- **Pitch**: Wrote the first program for a machine that was never built, and can explain why that matters now.
- **Formats**: interview, panel
- **Live**: both
- **Languages**: en, fr
- **Timezone**: Europe/London
- **Availability**: weekday evenings, some weekends
- **Remote**: preferred
- **Lead time**: 2 weeks
- **Rate**: free
- **Pays**: no
- **Appeared on**: [The Analytical Engine](https://ada.example/podcast/ep12), [BBC Radio 4](https://bbc.example/babbage)
- **Credentials**: Countess of Lovelace; first published algorithm, 1843
- **Not**: crypto, pay-to-play, politics
- **Book**: https://ada.example/book`,
keys: [
["Available", "yes, no, selectively, or a date range", "Absent is unstated, never available."],
["Expertise, Credentials, Pitch", "loosely matched words; as written; one or two lines", "The expert half of the framework: an expert is a guest with Expertise and Credentials. Detail lives in the Resume link."],
["Formats, Live, Languages", "interview, panel, solo, call-in, debate, live-audio; yes / no / both; language tags", "What the guest will do."],
["Location, Timezone, Availability, Lead time, Remote", "as written", "When and how the guest can appear."],
["Rate, Pays", "free, an amount, negotiable; no, yes, an amount", "What the guest charges, and whether they will pay to appear. A guest who writes Pays: no is not shown pay-to-play shows."],
["Appeared on, Press, Book", "links", "Past appearances a host can listen to; a press page; where to ask."],
["Not", "loosely matched words", "What the guest will not do or discuss. Wins over everything else."]
],
matching:
"A booking platform reads a guest's Guest and a host's Broadcast section and scores the pair from what both wrote: Expertise and Topics against Topics and Seeking, Availability against Slots, Languages against Language, Remote against Remote, Rate and Pays against Pays and Charges. Both Not keys are absolute. The platform never fills a key the person did not write; Appeared on is the one key it may add to, only with the appearances it booked itself, marked as its own.",
absent: [
["No ratings", "A host who wants to know how a guest was listens to Appeared on."],
["No exclusivity", "Every platform may read the file. A platform that wants a guest to itself has a contract, not a profile."],
["No taxonomy of expertise", "Expertise is the words the person wrote."],
["No JSON", "The Markdown is the canonical copy."]
],
counterpart: ["OpenBroadcast", "openbroadcast"]
};
export default function OpenGuestPage(): ReactNode {
return <ProfileSectionPage spec={SPEC} />;
}

View file

@ -23,6 +23,8 @@ const STATIC_ROUTES: Array<{
{ path: "/openprd", changeFrequency: "weekly", priority: 0.9 }, { path: "/openprd", changeFrequency: "weekly", priority: 0.9 },
{ path: "/asdlc", changeFrequency: "weekly", priority: 0.9 }, { path: "/asdlc", changeFrequency: "weekly", priority: 0.9 },
{ path: "/openprofile", changeFrequency: "weekly", priority: 0.9 }, { path: "/openprofile", changeFrequency: "weekly", priority: 0.9 },
{ path: "/openbroadcast", changeFrequency: "weekly", priority: 0.9 },
{ path: "/openguest", changeFrequency: "weekly", priority: 0.9 },
{ path: "/openmcp", changeFrequency: "weekly", priority: 0.9 }, { path: "/openmcp", changeFrequency: "weekly", priority: 0.9 },
{ path: "/openaccess", changeFrequency: "weekly", priority: 0.9 }, { path: "/openaccess", changeFrequency: "weekly", priority: 0.9 },
{ path: "/openserver", changeFrequency: "weekly", priority: 0.9 }, { path: "/openserver", changeFrequency: "weekly", priority: 0.9 },

View file

@ -0,0 +1,130 @@
import Link from "next/link";
import type { ReactNode } from "react";
import { SiteShell } from "@/components/site-shell";
import { mono, pre, table, td, th } from "../app/openontology/ui";
/**
* One landing page shape for the specifications that are a section of
* OpenProfile.md (OpenBroadcast, OpenGuest). The section lives in the
* person's profile file; the page says what the section's keys mean and
* what the other half is.
*/
export type ProfileSection = {
name: string;
slug: string;
/** The `## Heading` in the profile. */
section: string;
tagline: string;
problem: ReactNode;
/** The example section, Markdown. */
sample: string;
/** Key, values, meaning. */
keys: Array<[string, string, string]>;
/** How a platform matches this section against its counterpart. */
matching: string;
absent: Array<[string, string]>;
/** The other half: name and slug. */
counterpart: [string, string];
};
export function ProfileSectionPage({ spec }: { spec: ProfileSection }): ReactNode {
const [otherName, otherSlug] = spec.counterpart;
return (
<SiteShell active={spec.name}>
<div className="band">
<div className="section-head">
<p className="eyebrow">LogicSRC standards surface · OpenProfile.md section</p>
<h2>{spec.name}</h2>
<p>{spec.tagline}</p>
</div>
<p style={{ color: "#41505d" }}>{spec.problem}</p>
<p style={{ color: "#5b6b7a" }}>
Status: 0.1. A <code style={mono}>## {spec.section}</code> section in a person&apos;s or
a show&apos;s <Link href="/openprofile">OpenProfile.md</Link>, matched against{" "}
<Link href={`/${otherSlug}`}>{otherName}</Link>. Every key is optional and kept as
written; what is not written is unstated, and a platform never fills it in.
</p>
</div>
<div className="band">
<div className="section-head">
<h2>The section</h2>
</div>
<pre style={pre}>{spec.sample}</pre>
</div>
<div className="band">
<div className="section-head">
<h2>The keys</h2>
</div>
<table style={table}>
<thead>
<tr>
<th style={th}>Key</th>
<th style={th}>Values</th>
<th style={th}>Meaning</th>
</tr>
</thead>
<tbody>
{spec.keys.map(([key, values, meaning]) => (
<tr key={key}>
<td style={td}>
<code style={mono}>{key}</code>
</td>
<td style={td}>{values}</td>
<td style={td}>{meaning}</td>
</tr>
))}
</tbody>
</table>
</div>
<div className="band">
<div className="section-head">
<h2>Matching</h2>
</div>
<p style={{ color: "#41505d" }}>{spec.matching}</p>
</div>
<div className="band">
<div className="section-head">
<h2>What is deliberately absent</h2>
</div>
<table style={table}>
<tbody>
{spec.absent.map(([what, why]) => (
<tr key={what}>
<td style={td}>
<strong>{what}</strong>
</td>
<td style={td}>{why}</td>
</tr>
))}
</tbody>
</table>
</div>
<div className="band">
<div className="section-head">
<h2>Where everything lives</h2>
</div>
<ul style={{ color: "#41505d", lineHeight: 1.9, paddingLeft: "1.1rem" }}>
<li>
<Link href={`/docs/${spec.slug}`}>Specification</Link>: the section, every key,
matching, discovery
</li>
<li>
<Link href={`/${otherSlug}`}>{otherName}</Link>: the other half of the
broadcaster-and-guest framework
</li>
<li>
<Link href="/openprofile">OpenProfile.md</Link>: the file the section lives in, found
at <code style={mono}>/.well-known/openprofile.md</code> or through{" "}
<code style={mono}>rel=&quot;openprofile&quot;</code>
</li>
</ul>
</div>
</SiteShell>
);
}

View file

@ -15,6 +15,8 @@ const NAV: Array<{ href: string; label: string; external?: boolean }> = [
{ href: "/openprd", label: "OpenPRD" }, { href: "/openprd", label: "OpenPRD" },
{ href: "/asdlc", label: "ASDLC" }, { href: "/asdlc", label: "ASDLC" },
{ href: "/openprofile", label: "OpenProfile" }, { href: "/openprofile", label: "OpenProfile" },
{ href: "/openbroadcast", label: "OpenBroadcast" },
{ href: "/openguest", label: "OpenGuest" },
{ href: "/openmcp", label: "OpenMCP" }, { href: "/openmcp", label: "OpenMCP" },
{ href: "/openaccess", label: "OpenAccess" }, { href: "/openaccess", label: "OpenAccess" },
{ href: "/openserver", label: "OpenServer" }, { href: "/openserver", label: "OpenServer" },

View file

@ -18,6 +18,8 @@ export const DOC_SLUGS = [
"openjob", "openjob",
"openresume", "openresume",
"openprofile", "openprofile",
"openbroadcast",
"openguest",
"openmcp", "openmcp",
"openaccess", "openaccess",
"openserver", "openserver",

107
docs/openbroadcast.md Normal file
View file

@ -0,0 +1,107 @@
# OpenBroadcast
OpenBroadcast is the `Broadcast` section of an [OpenProfile.md](/openprofile): what a person or organisation hosts, live or recorded, on air or online, and what they are looking for on it. A podcast, a radio show, a live audio room, a stream, a newsletter interview series. It is written down on its own so a booking platform, a guest, a directory and a host's own agent all mean the same thing by the same key, and so a host can be matched with a guest from two files rather than two forms. It is maintained by Profullstack, Inc. as part of the LogicSRC open-standards surface.
Status: **0.1**. One of the two halves of the broadcaster-and-guest framework; the other is [OpenGuest](/docs/openguest). Both are sections of OpenProfile.md, which is where the person's name, accounts and topics already live.
Slug: `openbroadcast`
## The problem
Every show has a booking page and every booking page is a form. A host who wants guests fills in Podmatch, MatchMaker, a Calendly and a Google Form, and each holds half of what a guest needs to know: what the show is about, who listens, how long a segment runs, whether it is live, what the host is looking for this month. A guest's agent asked "which shows on climate finance are looking for guests and record in the evening, Europe" reads twelve pages twelve ways. The host wrote the answers once, in their head, and typed them into forms that will not hand them back.
The host already has a profile file. The section is what the show needs to say, in it.
## The shape
```markdown
## Broadcast
- **Show**: The Analytical Engine
- **Kind**: podcast
- **Format**: interview
- **Live**: no
- **Cadence**: weekly
- **Length**: 45 min
- **Language**: en
- **Audience**: 12k downloads/episode
- **Since**: 2024-03
- **Feed**: https://ada.example/podcast/feed.xml
- **Listen**: https://ada.example/podcast
- **Topics**: computing history, mathematics, women in science
- **Seeking**: historians, engineers with a story, first-time guests welcome
- **Not**: crypto, product pitches
- **Slots**: Tue and Thu 18:00-20:00 Europe/London
- **Remote**: yes
- **Book**: https://ada.example/podcast/book
- **Pays**: no
- **Charges**: no
```
A person with two shows writes two `## Broadcast` sections, or one section with `### <show name>` groups under it.
## The keys
Every key is optional and every one is kept as written. A reader that understands one uses it, and shows the rest.
About the show:
- `Show`: the name. Absent, the section is the person's unnamed broadcast and the profile's name stands in.
- `Kind`: `podcast`, `radio`, `live-audio`, `stream`, `video`, `newsletter`, `series`, or the host's own word.
- `Format`: `interview`, `panel`, `solo`, `call-in`, `roundtable`, `narrative`, or a list.
- `Live`: `yes`, `no`, or `both`. A live show has `Slots`; a recorded one may too.
- `Cadence`: `daily`, `weekly`, `fortnightly`, `monthly`, `seasonal`, or as written.
- `Length`: a duration as a person writes it, `45 min`, `2 h`.
- `Language`: one or more language tags.
- `Audience`: the host's own figure in the host's own unit: `12k downloads/episode`, `3,000 live listeners`, `40k subscribers`. A reader shows the unit and never compares across units.
- `Since`: when the show started, a year or a month.
- `Feed`: the RSS feed. `Listen`: where a person listens. `Watch`: where a person watches.
- `Network`: the network or station, if any, as a name or an OpenProfile.md URL.
- `Topics`: what the show covers, matched loosely the way OpenProfile.md Topics are. Absent means the profile's Topics.
About who the host is looking for:
- `Seeking`: the guests the host wants, in the host's words: roles, backgrounds, kinds of story. Matched loosely against a guest's `Expertise`, `Topics` and `Pitch`.
- `Not`: what the host will not book. A hit here wins over everything else.
- `Slots`: when recording or airing happens, as written, with a timezone.
- `Remote`: `yes`, `no`, `preferred`, `in-person only`.
- `Book`: the booking URL. Absent, `Email` in the identity block is the way in.
- `Pays`: whether the show pays guests: `no`, `yes`, or an amount. `Charges`: whether the show charges guests to appear: `no`, `yes`, or an amount. Both default to unstated, and a reader shows unstated, because pay-to-play is the thing a guest most wants to know and most often is not told.
Unknown keys are kept, so `Producer`, `Sponsor` and `Rating` all work.
## Matching
A booking platform reads a host's `Broadcast` and a guest's `Guest` section and scores the pair from what both wrote: the host's `Topics` and `Seeking` against the guest's `Expertise` and `Topics`, the host's `Not` against everything the guest said, the guest's `Not` against everything the host said, `Slots` against `Availability`, `Language` against `Languages`, `Remote` against `Remote`, `Pays` and `Charges` against `Rate` and `Pays`. Both `Not` keys are absolute. Everything else is a score, and the platform says how it scored.
The platform never fills a key the person did not write, from the show's feed, the person's photo, or another platform. What is not written is unstated.
## Discovery
The section lives in the person's or the show's OpenProfile.md, found the three ways that document names: `/.well-known/openprofile.md`, `<link rel="openprofile">`, or a platform path. A show with its own domain serves its own profile with `Kind: organization` in the identity block and this section under it; a person who hosts serves the section in their own file and names the show. A directory that meets both keeps both, because the show's file and the host's file are two claims, and a `Host` key in the show's file pointing at the host's profile, with the host's `Accounts` pointing back, is the verification.
## What is deliberately absent
**No episode list.** `Feed` is the episode list, and RSS already is the spec for it.
**No audience verification.** `Audience` is the host's figure. A platform that verifies it labels the verification as its own.
**No booking protocol.** `Book` is a link. What happens there is the platform's business.
**No JSON.** As OpenProfile.md: the Markdown is the canonical copy and any structured view is derived on every read.
## Related standards
- [OpenProfile.md](/openprofile): the file this section lives in; the identity block, Accounts and Topics it relies on.
- [OpenGuest](/docs/openguest): the other half; a guest's `Expertise`, `Availability`, `Rate` and `Pitch` are what this section is matched against.
- [OpenAccess](/openaccess): how a booking platform's agent carries the grant it needs to book on a person's behalf.
## Version history
| Version | Date | Change |
|---|---|---|
| 0.1 | 2026-09-13 | First publication: the Broadcast section, the show keys, the seeking keys, matching, discovery through a show's or a host's OpenProfile.md. |
## License
The specification text is CC BY 4.0. Serve it, copy it, extend it.

96
docs/openguest.md Normal file
View file

@ -0,0 +1,96 @@
# OpenGuest
OpenGuest is the `Guest` section of an [OpenProfile.md](/openprofile): that a person is available to appear on other people's shows, what they can speak to, when, on what terms, and what they have appeared on before. An expert, an author, a founder, a researcher, a comedian, a caller. It is written down on its own so a booking platform, a host, a directory and the guest's own agent all mean the same thing by the same key, and so a guest can be matched with a show from two files rather than two forms. It is maintained by Profullstack, Inc. as part of the LogicSRC open-standards surface.
Status: **0.1**. One of the two halves of the broadcaster-and-guest framework; the other is [OpenBroadcast](/docs/openbroadcast). Both are sections of OpenProfile.md, which is where the person's name, accounts, topics and resume already live.
Slug: `openguest`
## The problem
An expert who is happy to be interviewed has no way to say so that a host's search will find. They fill in a guest-matching site, a speaker bureau, a press page on their own domain and a line in a bio, and each holds a different fragment: the topics on one, the availability on another, the fee nowhere. A host's agent asked "who can talk about analytical engines, records in the evening in Europe, and does not charge" reads a hundred profiles a hundred ways. The person wrote the answers once and gave them away.
The person already has a profile file, and a resume behind it. The section is what a host needs to know, in it.
## The shape
```markdown
## Guest
- **Available**: yes
- **Expertise**: analytical engines, early computing, mathematics education
- **Pitch**: Wrote the first program for a machine that was never built, and can explain why that matters now.
- **Formats**: interview, panel
- **Live**: both
- **Languages**: en, fr
- **Location**: London
- **Timezone**: Europe/London
- **Availability**: weekday evenings, some weekends
- **Remote**: preferred
- **Lead time**: 2 weeks
- **Rate**: free
- **Pays**: no
- **Appeared on**: [The Analytical Engine](https://ada.example/podcast/ep12), [BBC Radio 4](https://bbc.example/in-our-time/babbage)
- **Press**: https://ada.example/press
- **Credentials**: Countess of Lovelace; first published algorithm, 1843
- **Not**: crypto, pay-to-play, politics
- **Book**: https://ada.example/book
```
## The keys
Every key is optional and every one is kept as written.
About the guest:
- `Available`: `yes`, `no`, `selectively`, or a date range. Absent means unstated, and a platform that lists guests shows unstated, not available.
- `Expertise`: the subjects the person can speak to with authority, matched loosely the way OpenProfile.md Topics are. This is the expert half of the framework: an expert is a guest with `Expertise` and `Credentials`, and needs no other section.
- `Pitch`: one or two lines a host can read aloud to decide. It is the guest's own words.
- `Credentials`: why the person is worth hearing on `Expertise`, as written: a title, a book, a paper, a job. The detail lives in the `Resume` link in the identity block.
- `Formats`: `interview`, `panel`, `solo`, `call-in`, `debate`, `live-audio`, or a list. `Live`: `yes`, `no`, `both`.
- `Languages`: one or more language tags, if not already in the identity block.
- `Location`, `Timezone`: where the person is and what clock they keep; both may sit in the identity block instead.
- `Availability`: when, as written: `weekday evenings`, `Tue-Thu`, `not before 2027`. `Lead time`: how much notice is needed.
- `Remote`: `yes`, `no`, `preferred`, `in-person only`.
- `Rate`: what the guest charges to appear: `free`, an amount, or `negotiable`. `Pays`: whether the guest will pay to appear: `no`, `yes`, or an amount. Both default to unstated. A guest who writes `Pays: no` is not shown pay-to-play shows.
- `Appeared on`: past appearances, one per bullet or comma-separated, each a link when there is one. A host reads them to hear the guest before asking.
- `Press`: a press or speaker page. `Book`: where to ask. Absent, `Email` in the identity block is the way in.
- `Not`: what the guest will not do or discuss. A hit here wins over everything else.
Unknown keys are kept, so `Agent`, `Headshot` and `Bio` all work.
## Matching
A booking platform reads a guest's `Guest` and a host's `Broadcast` section and scores the pair from what both wrote: the guest's `Expertise` and `Topics` against the host's `Topics` and `Seeking`, both `Not` keys against everything the other side said, `Availability` against `Slots`, `Languages` against `Language`, `Remote` against `Remote`, `Rate` and `Pays` against `Pays` and `Charges`. Both `Not` keys are absolute. Everything else is a score, and the platform says how it scored.
The platform never fills a key the person did not write, from a resume, a photo, a past episode or another platform. What is not written is unstated. `Appeared on` is the one key a platform may add to, and only with the appearances it booked itself, marked as its own.
## Discovery
The section lives in the person's OpenProfile.md, found the three ways that document names. A platform that lists guests serves each guest's file at a platform path and links it from the guest's page, so a host that only knows the page still finds the file.
## What is deliberately absent
**No ratings.** A host who wants to know how a guest was listens to `Appeared on`.
**No exclusivity.** A guest's file may be read by every platform. A platform that wants a guest to itself has a contract, not a profile.
**No structured taxonomy of expertise.** `Expertise` is the words the person wrote.
**No JSON.** As OpenProfile.md: the Markdown is the canonical copy.
## Related standards
- [OpenProfile.md](/openprofile): the file this section lives in; `Resume` in its identity block is where the credentials are detailed.
- [OpenBroadcast](/docs/openbroadcast): the other half; a host's `Topics`, `Seeking`, `Slots`, `Pays` and `Charges` are what this section is matched against.
- [OpenResume.md](/docs/openresume): what the person has done, at length.
## Version history
| Version | Date | Change |
|---|---|---|
| 0.1 | 2026-09-13 | First publication: the Guest section, the guest keys, the expert half as Expertise and Credentials, matching, discovery. |
## License
The specification text is CC BY 4.0. Serve it, copy it, extend it.

View file

@ -115,7 +115,7 @@ Values that look like an email address or a URL become links; anything else stay
**3. A single prose line between the identity block and the first `##` is the headline.** One line. It is the bio a directory shows next to your name. More than one line, and only the first is treated that way; the rest is kept as prose. **3. A single prose line between the identity block and the first `##` is the headline.** One line. It is the bio a directory shows next to your name. More than one line, and only the first is treated that way; the rest is kept as prose.
**4. `##` opens a section.** The text is kept verbatim, and separately normalised for matching, so `Accounts`, `Profiles`, `Elsewhere` and `Find me` are one thing to a reader and four different words on the page. The normalised names in common use are `accounts`, `topics`, `reshare`, `operator`, `match`, `photos`, `links`, `about`, `projects`, `services` and `contact`. `Dating`, `Matching`, `Partner` and `Looking for` normalise to `match`. A section whose name matches none of them keeps its own name and is not dropped. **4. `##` opens a section.** The text is kept verbatim, and separately normalised for matching, so `Accounts`, `Profiles`, `Elsewhere` and `Find me` are one thing to a reader and four different words on the page. The normalised names in common use are `accounts`, `topics`, `reshare`, `operator`, `match`, `photos`, `broadcast`, `guest`, `links`, `about`, `projects`, `services` and `contact`. `Broadcast` and `Guest` are specified on their own as [OpenBroadcast](/docs/openbroadcast) and [OpenGuest](/docs/openguest): the show a person hosts and the appearances a person offers, matched against each other. `Dating`, `Matching`, `Partner` and `Looking for` normalise to `match`. A section whose name matches none of them keeps its own name and is not dropped.
**5. Every bullet under Accounts is one account, and the URL is the identity.** `[Bluesky](https://bsky.app/profile/ada.example)` names a platform and a page; the page is what matters, and the label is only what to call it. `bluesky: ada.example` and `https://bsky.app/profile/ada.example` on a line of their own are accepted too. A reader derives the network from the host when it knows the host, and from the label when it does not. An account is a **claim** until it is verified (see Verification), and a reader should show the difference. **5. Every bullet under Accounts is one account, and the URL is the identity.** `[Bluesky](https://bsky.app/profile/ada.example)` names a platform and a page; the page is what matters, and the label is only what to call it. `bluesky: ada.example` and `https://bsky.app/profile/ada.example` on a line of their own are accepted too. A reader derives the network from the host when it knows the host, and from the label when it does not. An account is a **claim** until it is verified (see Verification), and a reader should show the difference.
@ -226,6 +226,7 @@ By hand, in any editor, in five minutes. Or:
## Related standards ## Related standards
- [OpenResume.md](/docs/openresume): what you have done, in the same spirit. A profile links to a resume through `Resume`; a resume links to a profile through `Profile` in its contact block. - [OpenResume.md](/docs/openresume): what you have done, in the same spirit. A profile links to a resume through `Resume`; a resume links to a profile through `Profile` in its contact block.
- [OpenBroadcast](/docs/openbroadcast) and [OpenGuest](/docs/openguest): the `Broadcast` and `Guest` sections, for matching hosts with guests.
- [OpenJob](/docs/openjob): what the work is. - [OpenJob](/docs/openjob): what the work is.
- [OpenCreds](/opencreds): where the tokens behind the accounts are kept. A profile never contains a credential. - [OpenCreds](/opencreds): where the tokens behind the accounts are kept. A profile never contains a credential.
- [ASDLC](/asdlc): how the tools that serve and read these files get built. - [ASDLC](/asdlc): how the tools that serve and read these files get built.