{"slug":"cortex-broadcast","title":"cortex-broadcast","summary":"llm-wiki style broadcast ingest — conversational update of related existing pages when a Raw has been distilled. Use when the user says \"broadcast\", \"跑 broadcast\", \"compound this into the vault\", \"merge pending-merge\", \"process broadcast queue\", or when cortex-distill invokes bro","platform":"Claude","tags":[],"authorName":"LLM Mart","authorSlug":"llm-mart","score":0,"source":"github","price":null,"verified":false,"createdAt":"2026-09-07T18:44:04.395361Z","repo":{"url":"https://github.com/XBlueSky/cortexes","stars":21,"forks":4,"license":"Apache-2.0","updatedAt":"2026-09-22T03:59:52Z"},"bodyHtml":"<hr>\n<h2>name: cortex-broadcast\ndescription: &gt;\nllm-wiki style broadcast ingest — conversational update of related existing\npages when a Raw has been distilled. Use when the user says \"broadcast\",\n\"跑 broadcast\", \"compound this into the vault\", \"merge pending-merge\",\n\"process broadcast queue\", or when cortex-distill invokes broadcast inline\nafter Step 8 commit (automatic dispatch for every new / pending-merge Raw).</h2>\n<h1>Cortex Broadcast — Compounding Ingest</h1>\n<p>Propagate insights from a distilled Raw into related existing Notes/Projects\npages through conversational per-page edits.</p>\n<h2>Resolve Vault Path and Config</h2>\n<p>Read <code>~/.cortex/config.json</code>:</p>\n<pre><code>jq -r '.vault_path' ~/.cortex/config.json\njq -r '.broadcast.target_top_n // 5' ~/.cortex/config.json\njq -r '.broadcast.target_min_score // 0.40' ~/.cortex/config.json\n</code></pre>\n<p>If the config file doesn't exist, tell the user to run <code>/cortexes:genesis</code> first.</p>\n<h2>Step 1: Resolve Arguments</h2>\n<p>The command supports three invocations:</p>\n<table>\n<thead>\n<tr>\n<th>Form</th>\n<th>Action</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>/cortexes:broadcast</code> (no args)</td>\n<td>Pop the first (oldest) Raw from the eligible queue</td>\n</tr>\n<tr>\n<td><code>/cortexes:broadcast &lt;raw-path&gt;</code></td>\n<td>Use the specified Raw (relative or absolute path)</td>\n</tr>\n<tr>\n<td><code>/cortexes:broadcast --list</code></td>\n<td>Print the eligible queue and exit</td>\n</tr>\n</tbody>\n</table>\n<h2>Step 2: Build Eligible Queue</h2>\n<p>A Raw is eligible iff its marker meets <strong>all</strong> of:</p>\n<ul>\n<li>Contains <code>&lt;!-- distilled: YYYY-MM-DD → ... --&gt;</code> (Phase 1 processed).</li>\n<li>Outcome is <code>new</code> or <code>pending-merge</code> (the marker content after <code>→</code> is\neither a path like <code>Notes/X.md</code> / <code>Projects/Y/Z.md</code>, <strong>or</strong> starts with\n<code>pending-merge:</code>; anything else — <code>(skip: routine)</code>, <code>(no insight)</code>,\nor the pre-Phase-1 legacy <code>(no extractable content)</code> — is ineligible).</li>\n<li>Does not already contain any of: <code>| broadcast:</code>, <code>| merged:</code>,\n<code>| no-broadcast:</code>.</li>\n</ul>\n<p>Build the list via:</p>\n<pre><code>cortex-vec broadcast-queue --root &lt;vault&gt;/Raw\n</code></pre>\n<p>This applies the three criteria above against each Raw's authoritative marker\n(header marker, or last non-empty line) and returns the result FIFO by path.\nDo <strong>NOT</strong> <code>grep</code> the marker string — a meta-session's body quotes it many\ntimes, which fools a substring scan. To inspect one file, use\n<code>cortex-vec raw-state &lt;file&gt;</code>.</p>\n<h2>Step 3: Handle <code>--list</code></h2>\n<p>If the user invoked <code>--list</code>, print each queued Raw with:</p>\n<ul>\n<li>Relative path from vault</li>\n<li>Outcome (extract from marker: <code>new</code> if target is a path; <code>pending-merge</code>\nif marker contains <code>pending-merge:</code>)</li>\n<li>Original target (for <code>pending-merge</code> Raws; <code>—</code> for <code>new</code>)</li>\n</ul>\n<p>Format:</p>\n<pre><code>Eligible queue (N Raws):\n\n  1. Raw/2026/04/17/141013_session_webapi-Notification.md\n     outcome: pending-merge → Projects/libsynosysnotify/synooauth flow chart.md (0.48)\n\n  2. Raw/2026/04/17/163941_session_libsynosdk.md\n     outcome: new → Projects/libsynosdk/build-flag-semantics.md\n\nRun /cortexes:broadcast to process the first, or /cortexes:broadcast &lt;path&gt; for a specific one.\n</code></pre>\n<p>Exit after listing.</p>\n<h2>Step 4: Select Raw and Read Content</h2>\n<p>If no args: pick the first entry from the queue.\nIf <code>&lt;raw-path&gt;</code> arg: verify it's eligible; abort with a clear error if not.</p>\n<p>Read:</p>\n<ol>\n<li>The Raw's full content (frontmatter + all sections).</li>\n<li>The Raw's distilled marker; parse the outcome and (for pending-merge)\nthe original target path and score.</li>\n</ol>\n<h2>Step 5: Find Candidate Pages</h2>\n<p>Pick the <strong>most content-ful Discovery or Decision bullet</strong> — the longest bullet\nwith concrete referents (symbols, file paths, bug mechanisms). This is the same\nheuristic as cortex-distill Stage 2 uses.</p>\n<p>Run:</p>\n<pre><code>cortex-vec search \"&lt;bullet text&gt;\" --n &lt;target_top_n&gt;\n</code></pre>\n<p>If the Raw's frontmatter has <code>repo:</code>, also pass <code>--repo &lt;name&gt;</code> when the\nquery topic looks repo-specific. Omit otherwise.</p>\n<p>Filter results to those with <code>score &gt;= target_min_score</code>.</p>\n<h3>If no candidates pass the threshold</h3>\n<p>If <code>cortex-vec</code> ran successfully but zero results meet <code>score &gt;= target_min_score</code>:</p>\n<ul>\n<li>For outcome <code>new</code>: skip Steps 6–8 entirely. Jump to Step 9 with <code>pages_touched = []</code> and tag the terminal state as <code>no-candidates</code> (distinct from <code>no-changes</code>). Step 9.1 will produce the marker <code>broadcast: &lt;today&gt; → (no candidates)</code>.</li>\n<li>For outcome <code>pending-merge</code>: the original pending-merge target is still pre-selected in Step 6 regardless of threshold (per Step 6's \"absent\" clause). Proceed to Step 7 as normal with a single-entry menu.</li>\n</ul>\n<p>Announce to the user before jumping:</p>\n<pre><code>No candidate pages scored at or above &lt;threshold&gt; for this Raw.\nFinalizing as broadcast: (no candidates). Marker will reflect this.\n</code></pre>\n<h3>Fallback if <code>cortex-vec</code> is unavailable</h3>\n<p>If the command errors (not found, ECONNREFUSED, etc.):</p>\n<ol>\n<li>Read <code>&lt;vault&gt;/_index.md</code>.</li>\n<li>Use your own semantic judgment to pick up to <code>target_top_n</code> candidate\npages that look related to the Raw.</li>\n<li>Note <code>candidates_source: llm-fallback</code> for the log entry later.</li>\n</ol>\n<h2>Step 6: Pre-select Pending-Merge Target</h2>\n<p>If the Raw's outcome is <code>pending-merge</code>:</p>\n<ul>\n<li>Extract the target path from the marker.</li>\n<li>Find that path in the candidate list.\n<ul>\n<li>If present: mark it as pre-selected <code>[x]</code>.</li>\n<li>If absent (score now below threshold, or file renamed): <strong>still\ninclude it</strong> as a pre-selected entry at the top, with a note\n<code>(below current threshold)</code>. Original distill intent overrides current\nthreshold.</li>\n</ul>\n</li>\n</ul>\n<p>Example of the menu line in this case:</p>\n<pre><code>[x] 1. Projects/libsynosysnotify/synooauth flow chart.md (0.48)  ← pending-merge target (below current threshold)\n</code></pre>\n<p>All other candidates default to unchecked <code>[ ]</code>.</p>\n<h2>Step 7: Present Menu and Confirm</h2>\n<p>Display:</p>\n<pre><code>Broadcast target candidates for &lt;raw-filename&gt;:\n\n  [x] 1. &lt;path&gt; (&lt;score&gt;)      ← pending-merge target   (if applicable)\n  [ ] 2. &lt;path&gt; (&lt;score&gt;)\n  [ ] 3. &lt;path&gt; (&lt;score&gt;)\n  ...\n\nToggle: number (1–N) to flip, 'a' all, 'n' none, then Enter to confirm.\nCancel: type 'quit' to abort the menu without marking the Raw (no commits have been made yet).\n</code></pre>\n<p>Read the user's toggles until they confirm. Build the final selected list.\nIf the list is empty after confirmation, jump directly to Step 9 with\n<code>pages_touched = []</code> — this will write a <code>broadcast: &lt;date&gt; → (no changes)</code>\nmarker.</p>\n<h2>Step 8: Per-Page Conversational Edit Loop</h2>\n<p>For each selected page, in menu order:</p>\n<ol>\n<li>Read the target page's full content.</li>\n<li>Announce the page to the user:\n<pre><code>=== [1/3] Editing Notes/Nginx/Web benchmark.md ===\n</code></pre>\n</li>\n<li>Identify candidate change types from the Raw vs the page:\n<ul>\n<li>Prose rewrite of a section that overlaps topically</li>\n<li>Wikilink insertion (add <code>[[raw-filename]]</code> or <code>[[new-page-from-raw]]</code>)</li>\n<li>Contradiction flag (see Contradiction Handling below)</li>\n<li>Summary / intro revision if the Raw substantially changes the page's\nframing</li>\n</ul>\n</li>\n<li>Propose change #1. Be specific: show the exact before/after for the\naffected section, not a prose description.</li>\n<li>Read the user's response:\n<ul>\n<li><code>yes</code> / <code>y</code> → apply to working copy</li>\n<li><code>no</code> / <code>n</code> → discard this proposal</li>\n<li>Free-form text (e.g. \"shorter\", \"use the Raw's terminology\", \"insert\nunder the Fix section instead\") → revise the proposal, re-show, re-ask</li>\n</ul>\n</li>\n<li>Propose change #2. Iterate.</li>\n<li>Stop condition — whichever comes first:\n<ul>\n<li>You (the LLM) have no further useful changes to propose; announce\n\"No more proposals for this page.\" and await user confirmation.\nValid user responses at this point: <code>y</code> / <code>yes</code> / <code>done</code> / <code>next</code> /\nEnter → proceed to write the page. Any free-form text → interpret\nas a new change request and restart proposals.</li>\n<li>User types <code>done</code> / <code>next</code> / <code>skip</code> to end this page.</li>\n<li>User types <code>abort</code> / <code>cancel</code> to end the entire session (see Abort).</li>\n</ul>\n</li>\n<li>Apply the accumulated approved changes to the page file using the Edit\ntool (never overwrite wholesale; use targeted Edits).</li>\n<li>Refresh embedding:\n<pre><code>cortex-vec upsert &lt;relative-page-path&gt;\n</code></pre>\n</li>\n<li>Commit this page's edit in the vault repo:\n<pre><code>cd &lt;vault&gt;\ngit add &lt;relative-page-path&gt;\ngit commit -m \"broadcast: update &lt;page-title&gt; from &lt;raw-filename&gt;\"\n</code></pre>\n<code>&lt;page-title&gt;</code> = the <code>title:</code> from the page's frontmatter, or the H1\nheading if no frontmatter.</li>\n</ol>\n<h3>Contradiction Handling</h3>\n<p>If the Raw contains a claim that directly contradicts a claim in the page:</p>\n<ol>\n<li>Locate the conflicting claim in the page.</li>\n<li>Propose inline flag at that location:\n<pre><code>⚠️ Contradicts [[&lt;raw-filename&gt;]]: &lt;one-line statement of the conflict&gt;\n</code></pre>\n</li>\n<li>This proposal enters the normal flow (Step 8.5):\n<ul>\n<li><code>yes</code> → accept flag</li>\n<li><code>no</code> → skip</li>\n<li>Free-form (e.g., \"the new info is correct, delete the old claim\")\n→ rewrite the old claim with new info; no <code>⚠️</code> flag</li>\n</ul>\n</li>\n<li>Each accepted flag increments a counter for the log entry.</li>\n</ol>\n<p>(Note: <code>abort</code>/<code>cancel</code> during page conversation is distinct from <code>quit</code> at the menu stage — <code>quit</code> happens before any page commits, <code>abort</code> may leave prior committed pages intact.)</p>\n<h3>Abort Mid-Page</h3>\n<p>If the user types <code>abort</code> / <code>cancel</code> during page conversation:</p>\n<ul>\n<li>Do <strong>not</strong> apply any uncommitted in-memory changes from this page.</li>\n<li>Already-committed prior pages from this session stand.</li>\n<li>Do <strong>not</strong> update the Raw marker or append log entry.</li>\n<li>Exit the skill cleanly with a message:\n<pre><code>Aborted. &lt;N&gt; pages committed, Raw marker unchanged.\nRe-run /cortexes:broadcast &lt;raw-path&gt; to resume.\n</code></pre>\n</li>\n</ul>\n<h2>Step 9: Finalize Raw Marker and Log</h2>\n<p>After all selected pages are committed (or the selected list was empty):</p>\n<h3>9.1 Update Raw marker</h3>\n<p>Read the current marker line — the authoritative <code>&lt;!-- distilled: ... --&gt;</code>\nline, which is either the header marker (before the first <code>### User</code> turn) or\nthe last non-empty line. (<code>cortex-vec raw-state &lt;raw&gt;</code> confirms its outcome.)\nDetermine the terminal segment to append based on outcome and result:</p>\n<table>\n<thead>\n<tr>\n<th>Case</th>\n<th>New segment</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Outcome <code>new</code>, ≥1 page committed</td>\n<td><code>\\| broadcast: &lt;today&gt; → [[page1]], [[page2]]</code></td>\n</tr>\n<tr>\n<td>Outcome <code>new</code>, 0 pages (menu empty or all unchecked)</td>\n<td><code>\\| broadcast: &lt;today&gt; → (no changes)</code></td>\n</tr>\n<tr>\n<td>Outcome <code>new</code>, no candidates returned</td>\n<td><code>\\| broadcast: &lt;today&gt; → (no candidates)</code></td>\n</tr>\n<tr>\n<td>Outcome <code>pending-merge</code>, ≥1 page committed</td>\n<td><strong>Append</strong> <code> \\| merged: &lt;today&gt; → [[page1]], [[page2]]</code> after the existing <code>pending-merge: ... (score)</code> segment. Do NOT remove or modify the <code>pending-merge:</code> text. Final line: <code>&lt;!-- distilled: YYYY-MM-DD → pending-merge: &lt;path&gt; (&lt;score&gt;) \\| merged: &lt;today&gt; → [[page1]], [[page2]]</code> + closing <code>--&gt;</code>.</td>\n</tr>\n<tr>\n<td>Outcome <code>pending-merge</code>, 0 pages committed</td>\n<td>append <code>\\| broadcast: &lt;today&gt; → (no changes)</code> after the existing <code>pending-merge:</code> segment</td>\n</tr>\n</tbody>\n</table>\n<p>Date format: <code>YYYY-MM-DD</code>.</p>\n<p>Use the Edit tool to replace the marker line.</p>\n<h3>9.2 Append log entry</h3>\n<p>Compose the entry with placeholders substituted. Append to <code>&lt;vault&gt;/log.md</code>\nusing the Edit tool (preferred) or:</p>\n<pre><code>printf '\\n%s\\n' \"$ENTRY\" &gt;&gt; \"&lt;vault&gt;/log.md\"\n</code></pre>\n<p>Where <code>$ENTRY</code> is:</p>\n<pre><code>## [YYYY-MM-DD HH:MM] broadcast | &lt;raw-filename&gt;\n- source_outcome: &lt;new|pending-merge&gt;\n- pages_touched: [[page1]], [[page2]]\n- contradictions_flagged: N\n- repo: &lt;repo or (none)&gt;\n</code></pre>\n<p>Field rules:</p>\n<ul>\n<li><p><code>source_outcome</code>: <code>new</code> or <code>pending-merge</code> (derived from pre-broadcast\nmarker).</p>\n</li>\n<li><p><code>pages_touched</code>: wikilink-formatted list of actually committed pages.\nIf empty: write <code>pages_touched: (none)</code>.</p>\n</li>\n<li><p><code>contradictions_flagged</code>: integer count of accepted <code>⚠️</code> flags. Omit\nthe line if zero.</p>\n<p>Example log entry with zero contradictions (<code>contradictions_flagged</code> line absent):</p>\n<pre><code>## [2026-04-20 14:32] broadcast | &lt;raw&gt;.md\n- source_outcome: new\n- pages_touched: [[page1]]\n- repo: (none)\n</code></pre>\n</li>\n<li><p><code>repo</code>: from Raw frontmatter <code>repo:</code> or <code>(none)</code>.</p>\n</li>\n<li><p>If Step 5 fallback ran (cortex-vec unavailable), add\n<code>candidates_source: llm-fallback</code> as a final line.</p>\n</li>\n</ul>\n<h3>9.3 Commit Raw marker + log</h3>\n<p>Single commit in the vault repo:</p>\n<pre><code>cd &lt;vault&gt;\ngit add &lt;raw-relative-path&gt; log.md\ngit commit -m \"broadcast: finalize &lt;raw-filename&gt;\"\n</code></pre>\n<h2>Step 10: Offer Next Raw</h2>\n<p>Detect the invocation mode:</p>\n<ul>\n<li><strong>Inline mode</strong>: dispatched from within an active cortex-distill session\n(Step 9 dispatches broadcast for every new / pending-merge Raw\nautomatically). Return cleanly to the distill flow when finalized —\ndo not prompt for next Raw; distill manages its own iteration.</li>\n<li><strong>Standalone mode</strong>: invoked by <code>/cortexes:broadcast</code> (with or without\nargs) from a fresh shell — i.e., not from within distill.</li>\n</ul>\n<p>In standalone mode, if:</p>\n<ul>\n<li>Skill was invoked by <code>/cortexes:broadcast</code> without args, AND</li>\n<li>The eligible queue still has entries after this run,</li>\n</ul>\n<p>then ask the user:</p>\n<pre><code>Process next eligible Raw (&lt;count&gt; remaining)? (y/n)\n</code></pre>\n<ul>\n<li><code>y</code> → return to Step 4 with next queue entry.</li>\n<li><code>n</code> → exit with summary: \"Broadcast session complete. </li>\n</ul>\n","files":[{"path":"SKILL.md","sizeBytes":13024,"isText":true}],"reviewScore":null,"reviewSummary":null,"trust":{"provenance":"trusted-source-unreviewed","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow.","bodySource":null},"bodyLocked":false,"purchaseUrl":null,"sourceUrl":null,"report":{"provenance":"trusted-source-unreviewed","screen":{"ran":true,"outcome":"clean","suspicious":0,"notes":0,"hiddenCharacters":false},"virusScan":{"engine":"clamav","status":"clean","scannedAt":"2026-09-25T06:49:40.358799Z","sha256":"C6751FADBF63BD5524236B4881A07505B2F6784267F5AE89E53689FE84F18945","sizeBytes":5569},"review":null,"source":{"repositoryUrl":"https://github.com/XBlueSky/cortexes","path":"skills/cortex-broadcast","license":"Apache-2.0","commit":"ff2eaeb522f21bb1022ff25b090aad0072d2aca1","subtreeSha":"96C83689AC63A0655C91549363421444462A6CE25794A06F2361914FBF17D5B3","lastSyncedAt":"2026-09-25T06:49:31.454583Z"},"reviewedAt":"2026-09-25T06:49:58.730176Z","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow."},"install":[{"target":"skills-cli","command":"npx skills add https://github.com/XBlueSky/cortexes/tree/plugin/skills/cortex-broadcast"},{"target":"claude-code","command":"claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install xbluesky-cortexes@llmmart"},{"target":"git","command":"git clone https://github.com/XBlueSky/cortexes.git"}]}