Display Name
Analytical Piece Generator
Display Description
Produce one publication-voice analytical piece per qualifying event cluster as a distinct genre parallel to News. The framework dispatches Ora’s canonical analytical modes against MSI cluster substrate plus the finalized news article, applies a news-floor discipline filter to the mode outputs (treatise §5.5 line), composes a single Analysis under that discipline, writes it to /analyses/[slug], and appends an idempotent locked-format “Going deeper” cross-reference block to the source news article between the body and the algorithmic-disclosure footer. The Analysis tier does not invent analytical primitives; those live in Ora’s mode registry and are loaded by mode_id at dispatch time.
Version 0.3.0 (2026-06-03 — Reader Clarity Discipline; see the v0.3.0 section immediately below) layers the MSI Analysis Style Guide onto the §5.5 filter across Layers 3–5. Version 0.2.0 (2026-05-31 — Variety Expansion; see the v0.2.0 section below, which supersedes the closed-mode-set + cluster-required design in the v0.1.0 body). Originally drafted 2026-05-27 (v0.1.0) from Handoff — MSI News-Side Analytical Layer Planning 2026-05-27.md. Version 0.4.0 (2026-06-09 — Honest reconciliation with the live pipeline; see the section immediately below) supersedes any conflicting build-state claim in the v0.1.0–v0.3.0 body.
v0.4.0 — Honest reconciliation with the live pipeline (2026-06-09)
This section reconciles the spec with what actually runs in production. The v0.1.0–v0.3.0 body below describes a six-layer design (L1 enrich → L2 select → L3 dispatch → L4 compose → L5 screen → L6 emit) plus an editorial-supervisor floor screen, a human-review gate, and JSON-LD wrapping that were never wired into the live pipeline. Where anything below conflicts with this section, this section governs. Per publisher direction 2026-06-09 the unbuilt enforcement apparatus is not being built — the items marked “not built” below are retired, not deferred.
The live path. Production runs scripts/analyses_pass_daily.py → tools/analyses_engine_pass.py::produce_analyses_for_article → msi_engine.produce_analysis(gear=4, post_process_fn=post_process_analysis) → Step-B tools/analyses_post_process.py::post_process_analysis, invoked by tools/continuous_cycle.py::produce_analyses. The legacy scripts/analysis_generator.py::run_analysis_pipeline (and publish_cycle.py::step_run_analysis) is dormant — gated by MSI_RUN_ANALYSIS=1, off by default. The detailed L3/L4/L5/L6 “Processing Layers” below describe that dormant path; in production the analytical work is one consolidated gear-4 compose pass, not separate dispatch/compose/screen passes.
Built and live (confirmed in code):
- Worthiness pre-selection —
analyses_pass_daily.py::_select_worthysends only the top ~25% most-affording articles per day (SELECT_PCT,--select-pct), with hero-source priority + a daily hero floor (MSI_ANALYSIS_HERO_PRIORITY/_MAX,MSI_ANALYSIS_HERO_FLOOR). - The rotation scheduler (v0.2.0 #5) is built and wired.
tools/analysis_scheduler.pyis imported and called inanalyses_engine_pass.py(schedule/read_demonstration_history/ScheduleConfig.from_env). It applies a per-DAY emission budget (MSI_ANALYSES_DAILY_BUDGET, default 20), rolling-window reuse caps (window_n30,per_mode_cap/per_lens_cap4), novelty weighting (long-tail-first), a lens-forward spotlight, and per-day no-repeat. It falls back toselect_modes’ interim per-article cap only if the scheduler/router imports raise. - Data-driven mode + lens selection —
mode_routing.eligible_modes+lens_routing.eligible_lenses(the hardcoded Tier-A/B/C trigger block inselect_modesis unreachable dead code). Cluster-less routing (G2 relaxed). Gates that actually fire: G1 length floor 600 words; G3 floor-value intensity ≥0.5. - Prompt-side discipline (the only floor enforcement). The §5.5 news-floor discipline + the Analysis Style Guide travel inside the author model’s system prompt (
L4_COMPOSITION_SYSTEM_PROMPT+MSI_ANALYSIS_STYLE_GUIDE, assembled bytools/analyses_mode_text.py::build_analysis_mode_text, which also injects the modes’## ANALYTICAL PERSPECTIVES). There is no separate screen. - Step-B scaffolding (
post_process_analysis) — headline parse → de-shout → fit (regenerate if over the 120-char cap) → clamp; frontmatter build; leading-separator strip; meta-commentary (“notes-to-self”) strip;## Summaryguarantee; empty-body/stub refusal (assert_article_not_stub, escapeMSI_ALLOW_STUB). - Image inheritance — inherit the source PNG only, gated ~0.25 (
MSI_IMAGE_INHERIT_RATE) with a daily hero floor; no Analysis-specific render; dangling image refs ignored. - Idempotent linking — “Going deeper” tail-edit (
<!-- analysis-link:slug -->) + inverseanalyses:/article_slugs:cross-references; one-analysis-per-story claim (MSI_ANALYSES_ONE_PER_ARTICLE); per-(cluster_id, sorted(mode_ids))idempotency. - Provenance actually emitted by
build_analysis_frontmatter:headline,tail_edit_topic,publish_date,primary_entities,primary_themes,floor_values_engaged,article_slugs,ora_modes,analytical_lenses,lens_forward,source_cluster_id,framework_version,license(CC0),ai_generated,draft, and (conditionally)image.
NOT built — retracts the body’s claims (this supersedes Milestones 5–6, Governing Principle 10, Execution Tier’s Layer-5 line, the Layer 5–6 detail, Setup Questions’ regenerate mode, and Persona descriptor #5):
- No editorial-supervisor MindSpec / floor screen.
msi-editorial-supervisoris not built (seeanalysis_generator.pyheader comments). No floor-crossing screen, norequires_rewrite/requires_pen_name_routing/requires_human_reviewdispositions, no reroute-to-Pipeline-3 runs on the live path. Governing Principle 10 describes an unbuilt component. - No post-authoring quote / hedge / style / banned-term audit.
screen_analysis()(quote-verification, hedge-preservation,_style_guide_lint) exists but is called only from the dormantrun_analysis_pipeline; it never runs on the live path, and even there it is warning-only. Thebanned-vocabulary.json/contested-terms.json/dead-metaphors.json/attribution-verbs.jsonscans are inert — those config files do not exist on disk. The verbatim-quote and hedge-preservation rules are enforced only by the author model’s prompt, not re-checked afterward. - No human-review queue and no
regenerate-after-review mode. Not built; there is no review queue, hold state, or reviewer flag path. - No JSON-LD
Articlewrapper (Milestone 6 §6). Analyses carry YAML frontmatter validated by the Astro/Zodanalysescontent-collection schema; no JSON-LD / schema.org wrapper is emitted. - Several declared provenance fields are not emitted.
geographic_location,gdelt_event_ids,consensus_floor_version,publication_mindspec_version,generation_timestamp,topic_tags,figures, and the structured aggregates the/analysesschema declares (claims,sources,figures_aggregate) are NOT produced bybuild_analysis_frontmatter(they are.optional(), so the build does not break). The “What the pipeline injects” table below overstates the emitted set; the real emitted set is the bullet under “Built and live” above. - This framework markdown is not loaded at runtime. Unlike the News Article Generator (which reads
Framework — MSI News Article Generator.mdby filename via_FRAMEWORK_SPEC_REL), the analyses generator loads no framework doc; the live instruction set is the Python constantsL4_COMPOSITION_SYSTEM_PROMPT+MSI_ANALYSIS_STYLE_GUIDEplus the loaded Ora mode files. This document is descriptive only.
v0.3.0 — Reader Clarity Discipline (2026-06-03)
This section adds a reader-clarity layer on top of v0.2.0; it changes no routing, selection, or schema. It governs the VOICE of the emitted prose. Canonical guide: MSI Analysis Style Guide. Worked before/after on a live piece: ~/Desktop/Kuwait-airport-analysis-REWRITE.md.
Problem. v0.2.0 made Analyses various and careful (§5.5) but not clear. Live pieces read as dry, technical, and self-referential: they open with machine labels (“Subtype: causal_claim”) and method headings (“Epistemic Architecture and Institutional Incentives”), assume the reader already knows what an analysis is for, and never answer “so what / why do I care.” The §5.5 filter restrains; nothing in v0.2.0 motivates or translates.
Fix — the MSI Analysis Style Guide, incorporated at every prose-bearing step. The guide is a single canonical insert (MSI_ANALYSIS_STYLE_GUIDE in ora-project/scripts/analysis_generator.py) wired in at:
- Layer 3 (per-mode dispatch). Every mode dispatch’s user prompt carries the short form (
MSI_ANALYSIS_STYLE_GUIDE_L3): plain language, no-motive (function not intent), preserve hedges — so the raw analytical material composes clean. - Layer 4 (composition). The full guide is appended to
L4_COMPOSITION_SYSTEM_PROMPT, so §5.5 (careful) and the clarity layer (clear) travel together in the one composition pass. This is the primary gate: the lede opens on why this framing matters (not the mission); the standing “what an analysis is / facts not in dispute / no claim about intent” note moves to a single foot-line; techniques are named once in plain reader-words; jargon is translated; headings name the payoff; the body closes with the reader’s own checklist of questions. - Layer 5 (screen).
_style_guide_lintadds non-blocking warnings for house jargon (§4), sentences that ascribe intent to the outlet (§2), and mission-boilerplate ledes (§1). Informational in v0.3.0 (consistent with the v0.2 screen scope); a future v0.4 may gate on it.
The motive line (load-bearing). §5.5 already bars motive theories about named people in the news. v0.3.0 extends the identical discipline to the news outlet itself: describe what the text DOES and its EFFECT, never what the reporter or publication INTENDED. The propaganda dimension is a function claim (whose account a telling advances), never a motive claim. This keeps the Analysis factual per the analysis-techniques rather than an op-ed — even though a reader may infer motive on their own.
Unchanged from v0.2.0. All routing, mode/lens selection, scheduling, schema, idempotency, image inheritance, §5.5, CC0. Layers 1–2 (ingestion/enrichment + selection) emit no reader prose and are exempt by design.
Open item. The mandated ## Summary block still prints a reader-facing **Subtype:** <subtype> machine label; flagged for removal from the body (keep it in frontmatter). Tracked in MSI Tracker.
v0.2.0 — Variety Expansion (2026-05-31)
This section supersedes the closed-mode-set and cluster-required design recorded in the v0.1.0 body below. The v0.1.0 text is retained as the design-history record; where it conflicts with this section, this section governs. Full design narrative + validation: Paper — MSI Analyses Variety Expansion 2026-05-31.md.
v0.1.0 deliberately dispatched a closed, curated set of ~17 modes and required a cluster JSON on disk (skip-silently otherwise). In practice that produced zero Analyses across a ~12,800-article corpus: most articles never matched the ~10 modes the selector actually triggered, and most carried no cluster JSON. v0.2.0 reframes the Analysis tier around the publisher’s directive — use real news to demonstrate the widest possible variety of analytical techniques, rotating esoteric techniques in periodically — and makes the pipeline produce continuously and variously, while staying honest (a technique is applied only where the article genuinely affords it — Governing Principle 4 preserved).
What changed
-
Open, data-driven mode selection (supersedes Governing Principle 1’s closed set).
select_modesno longer hardcodes per-mode triggers; it routes throughora-project/tools/mode_routing.py::eligible_modes, acolumn_routing-style matcher that scores an article’s frontmatter signals (headline + primary_themes + topic_tags + primary_entities + geographic_location, plus clusterap_keywordswhen present) and the Layer-1 enrichment against a per-mode trigger table covering 48 text-operable analytical modes (every analytical mode in the registry except the 6 meta/bypass modes and the 4 vision modes). Generous but evidence-based. -
The lens axis is now first-class. Each Ora mode declares an
## ANALYTICAL PERSPECTIVESblock of de Bono thinking-tools + mental-model lenses (game theory, behavioral economics, systems thinking, …) — the “tools” the modes carry. v0.2.0 records the lenses a piece demonstrates in two new frontmatter fields,analytical_lenses(techniques the article affords) andlens_forward(a single foregrounded lens); can produce lens-forward Analyses where a named technique is the explicit subject (“the prisoner’s dilemma in the tariff war”); and reaches the ~30 high-value lenses no mode loads by injecting a spotlight lens on demand. Lens matcher:ora-project/tools/lens_routing.py. -
The tools actually reach the model (load-bearing fix). Ora’s
build_system_prompt_for_gearresolves a mode’s## ANALYTICAL PERSPECTIVESand injects the lens definitions into the gear-4 breadth analyst — but only fromcontext_pkg["mode_text"], and only when that mode_text is a real Ora-mode-shaped document. v0.1.0 passed the L4 composer prompt as mode_text and demoted the real modes to truncated user-prompt text, so the lenses never resolved. v0.2.0 builds a canonical Ora-mode-shaped system prompt (ora-project/tools/analyses_mode_text.py) carrying the union of the group’s modes’ perspectives (so they inject), with the §5.5 discipline + the=== HEADLINE ===output contract folded into the canonical sections; inlined chunks are heading-demoted so an embedded##cannot truncate a section. Prerequisite: the mental-model registry (~/ora/lenses/, 240 content Lenses) is assembled on the server from the vaultLenses/source. -
Cluster-less routing (supersedes Governing Principle 4 + Open Implementation Note #6’s cluster requirement). Gate G2 is relaxed: cluster-less articles are evaluated on frontmatter alone; the gate fails only when an article has neither a cluster nor any routable frontmatter signal. The full ~12,800-article back-catalog is now reachable. (G1 length floor and honest-skip still apply.)
-
Rotation scheduler — variety over time + cost governance.
ora-project/tools/analysis_scheduler.pyselects, from the eligible modes/lenses, a bounded dispatch group per article: novelty-weighted (least-recently-demonstrated rises), reuse-capped (no mode/lens dominates a rolling window), with a lens-forward spotlight and a per-DAY emission budget; it reads the recent/analysesdemonstration history to rotate the long tail. It is also the cost governor — the continuous cycle’s--limitcaps articles-walked, not analyses-emitted, so per-article fan-out is bounded here. -
Whole-corpus backfill.
analyses_pass_daily.pygained a bounded backfill (--since/--until/--dry-run, recent-first), sharing one production loop with the daily pass. -
Vision modes — gated off. information-density, spatial-reasoning, compositional-dynamics, ma-reading are present but hard-gated: never eligible unless both gear-4 analyst endpoints are vision-capable AND the article carries a usable image. Off by default (the corpus is image-poor).
Schema additions
/analyses (src/content/config.ts) gains analytical_lenses: z.array(z.string()).default([]) and lens_forward: z.string().optional().
Unchanged from v0.1.0
The Analysis genre + §5.5 news-floor discipline; the model-authors-prose / pipeline-injects-metadata split; institutional byline; idempotent tail-edit + inverse-reference; production on Ora’s gear-4 run_gear4 cascade with consolidation="corpus"; CC0.
Architectural Note
This framework is Pipeline 2b in MSI’s three-pipeline publication architecture:
- Pipeline 1 —
news-article-generator(existing) produces and finalizes the news article from a cluster. Layer 2 of MSI’s overall publication pipeline. Its body is not modified by Pipeline 2b; only a minimal idempotent tail block is appended. - Pipeline 2b —
analytical-piece-generator(this framework) consumes the cluster JSON plus the finalized news article markdown and produces one or more Analysis pieces (per the split-when-in-doubt rule below). - Pipeline 3 —
advocacy-column-generators(existing voice frameworks, updated in parallel column-side work) run last, consuming the Analysis as upstream input when one exists.
The three pipelines run sequentially over the same cluster. Pipeline 2b’s failure does not block Pipeline 1’s publication (graceful degradation). Pipeline 3’s column generators reference the Analysis rather than re-deriving analytical work.
Mode dispatch surface. Pipeline 2b calls Ora’s project-facing public API:
orchestrator.boot.load_mode(mode_id)— loads the canonical mode markdown from~/ora/modes/<mode_id>.md. The mode file’s content IS the analytical primitive’s specification; this framework does not duplicate it.orchestrator.model_dispatch.invoke_chat(system_prompt, user_prompt, *, slot="breadth", ...)— invokes a model through Ora’s routing config; raisesModelDispatchErrorwith stable error codes on failure.
The operative analytical prompts live in ~/ora/modes/*.md. Reference — Analytical Territories.md is the architecture catalog and dispatch-policy documentation; the per-mode prompts that drive the analytical work are the mode files.
No new MSI analytical-primitives framework. Earlier handoff versions proposed extracting cui-bono / wicked-problems / root-cause / steel-man / frame-audit / propaganda-audit / stakeholder-mapping into a new MSI Framework — Analytical Techniques.md. That proposal is retired. Those primitives have canonical specifications in Ora’s mode registry; this framework dispatches against them. The mapping is recorded in §Layer 2 below and verified against Reference — Analytical Territories.md as of 2026-05-27.
Image inheritance — no Analysis-specific image generation. When the source news article has a cover image in its frontmatter, the Analysis inherits the same image: reference. No new render is invoked. No Analysis-specific cadence rule exists. Rationale: News and Analysis on the same cluster are the same story at different depths; visual coherence between the surfaces signals that explicitly, and a parallel cadence would burn render cost on near-duplicate prompts. When the source news article has no cover image, the Analysis publishes without one. The browse page (/analyses, identical template to /news) handles the missing-image case the same way the news browse page does.
The framework runs under CC0. Its prompts, configuration files, and outputs are public-domain. Reused rules from the News framework (style/voice scans, banned-vocab, contested-terms, hedge preservation, “said” as default, fair-use distance) are loaded from the same configuration files; nothing is forked.
Model Contract vs Pipeline Contract
The model authors prose. The pipeline injects authoritative metadata, the source list, the image (inherited from the source news article), provenance, and licensing. This split mirrors the News Article Generator’s v1.3.0 architecture and exists for the same reason: every field the model is asked to re-emit is a hallucination surface.
What the model emits
A single markdown file with YAML frontmatter, restricted to:
headline— Analysis headline. Distinct from the source news article’s headline. SVO present-tense, ≤80 characters (editorial target), sentence-case, no clickbait. Hard limit: theanalysesAstro schema (src/content/config.ts) capsheadlineat 120 characters andtail_edit_topicat 100. A model headline that exceeds the cap fails the content-collection build (InvalidContentEntryDataError) and takes the entiresrc/site build down — so the pipeline clamps both at the metadata chokepoint (build_analysis_frontmatter) and never trusts the model to honor the length. See Open Implementation Note #12.tail_edit_topic(frontmatter, ≤6 words) — short topic descriptor used in the tail-edit text on the source news article. Example: “the building-code enforcement collapse” or “the SCOTUS dissent’s media reception.” Not the full headline; a phrasal noun-clause that completes “Read MSI’s analysis of ___.”primary_entities(frontmatter, list of strings) — editorial interpretation of the Analysis’s main actors.primary_themes(frontmatter, list of strings) — editorial interpretation of the Analysis’s thematic frame.floor_values_engaged(frontmatter, list of{value, intensity}objects) — which treatise §3 floor values the Analysis engages and at what intensity (0–1). The Analysis must engage at least one floor value at meaningful intensity.## Summarybody section — same load-bearing surface as in News: subtype line + 3–6 bullets honoring the Three Grammar Rules (named actors, resolved pronouns, concrete verbs) and the one-claim-per-bullet rule. The first bullet is a complete thesis statement of the Analysis. Subtype defaults tocausal_claimfor most analytical pieces;factfor primer/orientation pieces;evaluativeis forbidden (that’s Advocacy register).- Body prose — flat analytical narrative beneath the Summary, length follows material, no target. Opens with a prose lede paragraph that elaborates the bullets. Stays inside the news floor per the discipline filter in §Layer 4 below.
The model does NOT emit the ## Sources body section, the source list, the image, the cross-reference fields, or any provenance / licensing / classification metadata.
What the pipeline injects after the model returns
| Field | Source |
|---|---|
publish_date | wall-clock UTC at write time |
geographic_location | cluster.geographic_resolution.primary_location |
cluster_id | cluster.cluster_id |
gdelt_event_ids | cluster.gdelt_event_ids |
article_slugs | [source_news_article_slug] (the news article this Analysis ties to) |
ora_modes | the list of Ora mode_ids this Analysis dispatched (filled by Layer 3) |
framework_version | constant MSI_ANALYSIS_FRAMEWORK_VERSION |
consensus_floor_version | constant MSI_CONSENSUS_FLOOR_VERSION |
publication_mindspec_version | constant MSI_PUBLICATION_MINDSPEC_VERSION |
license | constant (CC0 URL) |
ai_generated | constant true |
generation_timestamp | wall-clock UTC at write time |
topic_tags | classifier pass against IPTC Media Topics closed vocabulary (same classifier as News) |
image | inherited from the source news article’s image: frontmatter field if present; absent otherwise. No Analysis-specific render is invoked. |
figures | rare for Analysis pieces; inherited from source article when the figure is load-bearing for the analytical claim being made |
## Sources body section | built from cluster.cluster_members[] exactly as News does it; identical machine-generation path |
byline | constant string “Main Street Independent” (same as news) |
| The idempotent tail-edit block on the source news article | constructed by Layer 6 from tail_edit_topic + Analysis slug + the locked format |
If the model emits any of these fields, the pipeline discards the model’s value and overwrites with authoritative data. Telemetry logs the discrepancy as a non-fatal warning.
Consequence for the model’s reading discipline
The cluster JSON and the finalized news article markdown are both authoritative provenance records for the analytical substrate. The model never invents specifics; the news-floor discipline filter (Layer 4) catches and rewrites any output that would assert an unattributed analytical claim, name a pattern in publication voice, theorize motive, or pass character judgment.
Setup Questions
Cluster
Required. The validated event-cluster object that produced the source news article. Same object the News Article Generator consumed at Layer 1. Conforms to the cluster schema in Framework — MSI News Article Generator.md.
News article markdown
Required. The finalized news article as written by the News Article Generator (post-Layer 7 output). Used as the primary analytical substrate alongside the cluster.
News article path
Required. Absolute path to the source news article .md file. Used by Layer 6 to apply the idempotent tail-edit.
Task
Required. Same task dict the News Article Generator consumes; carries the run-level metadata (mode = generate/regenerate, configuration version pin, human-review sample bypass).
Mode
Optional. One of:
generate(default) — produce one or more Analyses from the cluster + source news article.regenerate— re-produce an Analysis after a Layer 5 human reviewer returns it with revision instructions. Carries the reviewer’s flag set into Layer 4 and Layer 5 as constraints.
The framework has no correction mode for Analyses in v1; if a source cited by an Analysis issues a correction that affects analytical claims, the source-correction-monitor framework’s response is to regenerate the affected Analysis from scratch rather than patch it inline. Whether that becomes a dedicated mode is deferred to v2.
Purpose
To produce, from one qualifying event cluster and the finalized news article that cluster generated, one or more publication-voice analytical pieces that:
- Dispatch the Ora analytical modes whose trigger signals the cluster and article satisfy.
- Compose the mode outputs into a single substantive analytical piece per coherent perspective, splitting into multiple Analyses when the dispatched modes concern distinct dimensions (default: split when in doubt).
- Stay inside the consensus values floor — the Analysis’s voice does not assert what the floor does not authorize. Pattern names appear in cited authority voice only; motive theories are cut or rewritten as documented-conduct; character judgments are cut or replaced with sourced contradictions; hedges in source material are preserved.
- Append an idempotent locked-format tail-edit to the source news article so readers of News can navigate to the Analysis.
- Inherit the source news article’s cover image when present; publish without an image otherwise.
- Carry frontmatter cross-references on both surfaces (News’s
analyses: [slug]; Analysis’sarticle_slugs: [news_slug]). - Disclose AI-generation origin and CC0 license in both human-readable and machine-readable form.
- Skip silently — without authoring around the gap — when a mode’s trigger fires but its source material is unavailable.
- Skip silently — without publication-blocking — when no mode’s trigger fires for a cluster.
The framework’s success criterion is not “the Analysis reads well.” It is: the dispatched mode set matches what the cluster substrate warrants; every analytical claim in publication voice stays inside the floor; every specific traces to source material; the tail-edit on News is idempotent and locked-format; the cross-references on both surfaces are consistent; and the Analysis publishes without blocking the News article when anything fails.
Input Contract
Primary input — cluster JSON
The framework receives the same cluster object that the News Article Generator consumed. Schema fully specified in Framework — MSI News Article Generator.md §“Input Contract”. No new cluster-level fields are required for the Analysis tier — additional analytical signals are derived at Layer 1 via the cluster-enrichment pass.
Primary input — finalized news article markdown
The post-Layer-7 output of the News Article Generator, including:
- Frontmatter (headline, lede, nut_graf, publish_date, image, primary_entities, primary_themes, floor_values_engaged, sources, metadata, related_stories, draft)
## Summarybody section (thesis-grade bullets with named actors, resolved pronouns, concrete verbs)- Body prose
## Sourcesbody section
The finalized article is the higher-quality analytical substrate versus the raw cluster bodies, because it has already passed Layer 5 style/voice/verification and Layer 6 floor screening. The Analysis pipeline reads both — cluster + article — and the enrichment pass at Layer 1 derives analytical signals from both.
Primary input — news article path
Absolute path to the news article’s .md file in ~/sites/mainstreetindependent/src/content/articles/. Used by Layer 6 to apply the tail-edit in place.
Secondary input — framework configuration
The framework consults at runtime:
Reference — Analytical Territories.md— Ora’s canonical mode registry; the dispatch policy in Layer 2 maps cluster signals tomode_ids defined here. Read as documentation; not loaded as prompt material.Reference — MSI Treatise.md— editorial foundation; §4.2 (attribution as discipline) and §5 (the line between reporting and analysis) govern the news-floor discipline filter at Layer 4.Reference — MSI Consensus Values Floor.md— the five floor values.Reference — MSI Editorial Router.md— the publication-level MindSpec (msi-editorial-supervisor) consulted at Layer 5 for residual floor-crossing detection.Reference — MSI Bad-Faith Techniques Catalog.md— used in the same way News uses it; the bad-faith catalog informsframe-audit/propaganda-auditdispatch and the style/voice pass.banned-vocabulary.json,contested-terms.json,dead-metaphors.json,attribution-verbs.json— reused from News; loaded for the Layer 5 style/voice pass.~/ora/modes/<mode_id>.md— loaded per-dispatched-mode viaorchestrator.boot.load_mode(mode_id)at Layer 3.
The framework records the version of each configuration file applied, in metadata, so any Analysis can be replayed against the configuration that produced it.
Output Contract
Primary output — one or more structured Analysis objects
A list of Analysis objects (1 or 2 per qualifying cluster, per the integrate-or-split rule at §Layer 2). Each object is both the Analysis and the publication payload for the static-site builder. Schema:
| Field | Type | Description |
|---|---|---|
headline | string (≤80 chars) | Analysis headline, distinct from the source news article’s headline. |
tail_edit_topic | string (≤6 words) | Short phrasal noun-clause used in the tail-edit on the source news article. Completes “Read MSI’s analysis of ___.” |
publish_date | ISO-8601 date | The Analysis’s publication date (typically same as source news article’s). |
image | object, optional | Inherited from source news article’s image: frontmatter when present. Same imageSchema as the news article schema. |
sources | array | Per-source structured entries; built by the pipeline from cluster.cluster_members[] exactly as the News framework builds them. |
metadata | object | Provenance, licensing, generation parameters, primary entities, themes, geographic location, floor-engagement, ora_modes dispatched, article_slugs cross-reference, human-review status and triggers. |
article_slugs | array of strings | The news article slug(s) this Analysis ties to. Typically exactly one. |
ora_modes | array of strings | The Ora mode_ids this Analysis dispatched. ≥1 per Analysis. |
draft | boolean, default false | Frontmatter draft flag for content-collection builds. |
body content | Markdown | The post-frontmatter body: ## Summary section (3–6 bullets honoring Three Grammar Rules) followed by flat analytical prose. ## Sources section appended by the pipeline. |
Secondary output — idempotent tail-edit on the source news article
Per handoff §6.2 (publisher-locked): the Analysis pipeline appends a marked section to the source news article between the article body and the algorithmic-disclosure footer, with a horizontal rule above. Format:
[Article body content]
---
<!-- analysis-link:slug-of-analysis -->
**Going deeper:** [Read MSI's analysis of [tail_edit_topic] →](/analyses/[slug])
[Algorithmic-disclosure footer]
When two Analyses split off the same cluster (per the split-when-in-doubt rule at §Layer 2), both **Going deeper:** lines appear under one horizontal rule, each with its own marker:
---
<!-- analysis-link:slug-1 -->
**Going deeper:** [Read MSI's analysis of [topic-1] →](/analyses/slug-1)
<!-- analysis-link:slug-2 -->
**Going deeper:** [Read MSI's analysis of [topic-2] →](/analyses/slug-2)
[Algorithmic-disclosure footer]
The article body is otherwise unmodified.
Secondary output — cross-reference frontmatter updates
- On the source news article:
analyses: [slug-1, slug-2, ...]is added to frontmatter (existing field if News schema is updated; new field otherwise). - On the Analysis:
article_slugs: [source_news_slug]records the upstream link.
Non-publication outputs
When the framework declines to publish (cluster fails the cluster-level gates at Layer 2; no Ora mode’s trigger fires; every dispatched mode skips silently for missing source material; Layer 5 human-review block), the framework returns a diagnostic object with decision: "not_published", reason, failed_layer, and any partial structured material produced. The diagnostic is not published; it is logged for audit and surfaced to the publisher. Importantly, non-publication of an Analysis never blocks the source news article from publishing. Graceful degradation per Governing Principle 9.
Execution Tier
Standard tier (6 layers), Agent-mode with stage boundaries.
Six sequential processing layers. Each layer has a declared input contract from the prior layer and a declared output contract to the next. Layer 5 includes the editorial-supervisor MindSpec query (the publication-level floor check) and the human-review gate, fired by exception. Layer 6 writes the Analysis, inherits the image, applies the tail-edit, and updates cross-references.
Stage boundaries are logical. In agent rendering each layer is its own stage with a context reset; in single-pass rendering they are sequential prompt sections inside one window. The intellectual content does not change across renderings.
Milestones Delivered
The framework’s project-level milestones, declared inline per the canonical milestones-delivered schema.
Milestone 1: Cluster + Article Ingested and Enriched
- Endpoint produced: A normalized substrate object containing the cluster JSON, the parsed news article (frontmatter + body), and the derived analytical signals: named beneficiary, frame-source-in-body presence and type, named-actor classification (expert / official / partisan / witness / other), anniversary-or-retrospective flag, framing-divergence-across-sources flag, wicked-problem flag, named-experts-on-record set, official-messaging-dominance score.
- Verification criterion: The cluster JSON validates against the News framework’s Input Contract; the news article frontmatter parses; every derived signal carries a provenance note (which cluster member or article passage supports the classification); signals with insufficient evidence are emitted as
null, not guessed. - Layers covered: Layer 1 (Cluster + Article Ingestion and Enrichment).
- Required prior milestones: None.
- Gear: 4.
- Output format: Normalized substrate object + enrichment report (per-signal provenance).
- Drift check question: Does every enrichment signal trace to a specific cluster member or article passage, and have any signals been inferred without evidentiary support?
Milestone 2: Modes Selected and Integration Decided
- Endpoint produced: A list of one or two mode dispatch groups, each group containing one or more Ora
mode_ids to be dispatched together as a single Analysis. The cluster-level gates have been evaluated; if any failed, the milestone produces a non-publication disposition with reason. The integrate-or-split decision has been made per the operative rule (integrate when perspectives coherently overlap; split when perspectives concern distinct dimensions; default split when in doubt). - Verification criterion: Cluster-level gates evaluated (length floor ≥600 words on source article; cluster significance score above threshold; ≥1 identifiable beneficiary/interested actor/downstream stake; ≥1 floor value engaged at meaningful intensity); the mode selection table has been consulted against the enriched signals; the integrate-or-split decision is recorded with rationale; no mode is selected whose trigger signals are absent in the enriched substrate.
- Layers covered: Layer 2 (Mode Selection and Integration Decision).
- Required prior milestones: M1.
- Gear: 4.
- Output format: List of mode dispatch groups (each a list of
mode_ids) + selection rationale per mode + integration rationale per group. - Drift check question: Was the integrate-or-split decision biased toward integration when the perspectives actually concern distinct dimensions (the default is split when in doubt — overriding it requires a positive coherence finding, not the absence of a divergence finding)?
Milestone 3: Ora Modes Dispatched
- Endpoint produced: For each mode dispatch group, a set of Ora mode outputs (one per
mode_idin the group). Modes whose per-mode source-material requirements are unmet are skipped silently; the skip is recorded in the dispatch log but does not produce a non-publication disposition for the group (the group continues with whatever modes did dispatch). A group whose modes all skipped is dropped from the active dispatch set. - Verification criterion: For each dispatched mode,
orchestrator.boot.load_mode(mode_id)returned non-empty content;orchestrator.model_dispatch.invoke_chat(...)returned a non-error string; mode-specific source-material requirements (named experts available forroot-cause-analysis; framing divergence present forsynthesis/dialectical-analysis; etc.) were checked before dispatch; skipped modes are logged with the unmet requirement. - Layers covered: Layer 3 (Per-Mode Dispatch).
- Required prior milestones: M2.
- Gear: 4.
- Output format: Per-group mode-outputs map:
{group_index: {mode_id: mode_output_text}}+ skip log. - Drift check question: Did any mode dispatch proceed despite its source-material requirements being unmet (skip-silently is the operative discipline, not author-around-the-gap)?
Milestone 4: Analysis Composed Under News-Floor Discipline
- Endpoint produced: For each active dispatch group, an Analysis markdown body (headline candidate,
## Summarysection per the bullet rules, lede paragraph, body prose) composed from the group’s mode outputs and rewritten through the news-floor discipline filter. The filter applies the treatise §5.5 line as a constrained rewrite: pattern names migrate from publication voice to cited authority voice; motive theories about named individuals are cut or rewritten as documented-conduct; character judgments are cut or replaced with sourced contradictions; hedging language from input is preserved; length follows material with no padding. - Verification criterion: Every analytical claim in publication voice is either (a) a factual recap traceable to cluster sources, (b) an attributed analytical claim with named authority, or (c) an explicitly hedged inference; no pattern name (“regulatory capture,” “kleptocracy,” “manufactured controversy”) appears in publication voice unless attributed; no motive theory about a named individual appears at all; no character judgment about a named individual appears at all; every hedge in input source material is present in output; the bullet rules (Three Grammar Rules, one-claim-per-bullet, count 3–6) hold for the
## Summarysection. - Layers covered: Layer 4 (Composition + News-Floor Discipline Filter).
- Required prior milestones: M3.
- Gear: 4.
- Output format: Per-Analysis markdown body (Summary + lede + body prose).
- Drift check question: Has any Ora mode output’s analytical voice been laundered into publication voice without the discipline filter rewriting it through cited authority?
Milestone 5: Style, Voice, Verification, and Floor Screen Complete
- Endpoint produced: Either (a) a clean disposition with no flags fired for each Analysis, or (b) a flagged disposition where the Analysis is queued for human review with the trigger set and the editorial-supervisor MindSpec rationale. The style/voice scans from the News framework’s Layer 5 are applied (banned-vocabulary, contested-terms in narrator voice, dead-metaphors, attribution-verb normalization to “said,” active-voice ≥80%, hedge-preservation). The quote-verification pass from the News framework’s Layer 4 is applied (every quotation verbatim from cluster sources). The editorial-supervisor MindSpec query is invoked to detect floor-crossing residue the Layer 4 discipline filter may have missed.
- Verification criterion: Every named scan run and passed; any failure triggered a regeneration with the failed scan’s constraint added; every quotation verbatim-matched to cluster sources (mismatches forced removal and regeneration without the quote); the editorial-supervisor MindSpec query was invoked on each Analysis and the disposition recorded; flag triggers (if any) are recorded with rationale.
- Layers covered: Layer 5 (Style/Voice/Verification + Editorial-Supervisor Floor Screen).
- Required prior milestones: M4.
- Gear: 4.
- Output format: Per-Analysis disposition record (
clean | flagged_pending | flagged_approved | flagged_revised | flagged_blocked) plus trigger set plus supervisor rationale. - Drift check question: Has any contested term migrated into Analysis narrator voice, has any input hedge been dropped, has any quotation been paraphrased into quotation marks, or has the editorial-supervisor MindSpec been bypassed for any Analysis?
Milestone 6: Analyses Emitted; Tail-Edit Applied; Cross-References Updated
- Endpoint produced: Per Analysis: schema-validated structured Analysis object written to
~/sites/mainstreetindependent/src/content/analyses/<slug>.md; JSON-LD Article wrapping applied; AI-disclosure and CC0 declaration embedded; image inherited from source news article when present;article_slugs: [source_news_slug]on the Analysis. Per source news article: idempotent tail-edit block applied between body and footer (per the locked format in the Output Contract);analyses: [...]updated in source article frontmatter. Idempotency markers (<!-- analysis-link:<slug> -->) detected and skipped if already present. - Verification criterion: Each Analysis’s output validates against the Astro
analysescontent-collection schema and JSON-LD; AI-disclosure language present; CC0 declared in human-readable footer and JSON-LDlicense; stable URL/analyses/<slug>assigned; source news article’s body is unchanged outside the marked tail-edit section; tail-edit block conforms exactly to the locked format; idempotency check passed (re-running the pipeline against the same cluster does not duplicate the tail-edit block or the Analysis file). - Layers covered: Layer 6 (Output Emission, Image Inheritance, Tail-Edit, Cross-References).
- Required prior milestones: M5.
- Gear: 4.
- Output format: Per-Analysis: final structured Analysis object + write path. On source news article: updated
.mdwith tail-edit block + updatedanalyses:frontmatter field. - Drift check question: Does the emitted Analysis validate against schema, carry AI-disclosure and CC0, point at the source news article via
article_slugs, and inherit the source article’s image when present; AND is the source news article’s body unchanged outside the marked tail-edit section?
Governing Principles
These principles govern decisions inside the framework. When a layer-level rule is silent, resolve by the principle in priority order.
1. Dispatch, do not author
The framework selects which Ora analytical modes to dispatch and composes their outputs. It does not implement analytical primitives. The mode’s specification — what cui-bono analysis IS, what frame-audit IS — lives in ~/ora/modes/<mode_id>.md. When tempted to encode an analytical operation inline (“cui-bono works like X”), the right move is to look harder at the Ora registry; the apparent gap is almost always a mapping problem, not a missing mode. This framework does not propose additions to the Ora registry.
2. The news-floor discipline filter is the operative test
Ora mode outputs arrive in analytical voice — they will often exceed news-floor discipline as a matter of course. The Layer 4 discipline filter applies treatise §5.5 line as a constrained rewrite: pattern names get attributed to cited authority; motive theories get cut or rewritten as documented-conduct; character judgments get cut or replaced with sourced contradictions; hedging is preserved. The Analysis is publication voice — it explains, it does not argue. Anything the publication’s voice would have to adopt a perspective the floor does not authorize to claim, the filter rewrites or removes.
3. Split when in doubt
When multiple modes’ triggers fire for the same cluster:
- Coherent overlap (e.g.,
cui-bono+consequences-and-sequelon a policy story) → integrate into a single Analysis with coherent sections. - Distinct dimensions (e.g.,
consequences-and-sequelon a court ruling +propaganda-auditon the dissent’s media reception) → split into two Analyses. - Default behavior: split when in doubt. The burden of proof is on integration, not split. An apparent overlap that turns out to be two distinct stories produces a worse Analysis than two clean separate ones.
4. Skip silently when source material is unmet
Each Ora mode has source-material requirements (named experts on record, framing divergence present, etc.). When a mode’s cluster-level trigger fires but its source material is unavailable, the mode does not dispatch and the framework does not author the analytical move to fill the gap. The skip is logged; the publication does not pretend.
5. Length follows material
No word-count targets. Analyses typically run 1,200–4,500 words but the operative constraint is the analytical material the dispatched modes produce. Padding to hit a length is a quality failure; truncating substantive analysis to hit a length is a worse one.
6. The Analysis tier is publication voice, not heteronymic
The Analysis is published under “Main Street Independent” byline (same as News). It carries the publication’s institutional voice constrained by the consensus values floor. It is not an op-ed. It is not a column. Pen-name voices live in Advocacy (Pipeline 3) and consume the Analysis as upstream input rather than re-deriving the analytical work.
7. Idempotency at both (cluster_id, mode_ids) and tail-edit level
- An Analysis for
(cluster_id, sorted(mode_ids))is generated at most once. Re-running the pipeline against the same cluster with the same dispatch group is a no-op. - The tail-edit marker
<!-- analysis-link:<slug> -->in the source news article body is checked before insertion; re-running does not duplicate the block. - A mode added to the dispatch in a later run produces a new Analysis (different mode_ids set ⇒ different identity) with its own tail-edit; the existing tail-edit and Analysis are preserved.
8. Image inheritance, not Analysis-specific render
The Analysis inherits the source news article’s image: field when present. No Analysis-specific render is invoked. No counter-based or per-Nth cadence rule exists. When the source news article has no cover image, the Analysis publishes without one. Visual coherence between News and Analysis on the same cluster is editorially correct and the operative discipline; a parallel cadence would produce near-duplicate prompts at duplicated cost. If the publisher later decides specific Analysis dispatches warrant distinct visual treatment (e.g., distributional-cui-bono pieces), that becomes a separate v2 decision; v1 inherits.
9. Graceful degradation — never block News
If any Layer 1–6 step fails, the source news article publishes normally. The Analysis pipeline can re-run later, succeed, and add itself via the idempotent tail-edit and frontmatter update. No publication blocking from the Analysis tier.
10. The editorial-supervisor MindSpec is the floor’s runtime locus
Layer 5’s residual floor-crossing check is a query to msi-editorial-supervisor (same MindSpec the News framework’s Layer 6 consults). The supervisor returns floor-internal / requires-rewrite / requires-pen-name-routing / requires-human-review / non-publishable, with rationale. The framework treats the supervisor’s decision as authoritative within its scope. Analytical content that the supervisor routes to requires-pen-name-routing is dropped from the Analysis (not laundered into publication voice) and may be picked up by Pipeline 3 columns; analytical content the supervisor flags requires-human-review blocks publication of the affected Analysis until reviewer signs off.
11. Symmetric standards across speakers
Same Layer 4 discipline filter, Layer 5 verification, defamation thresholds, protected-category rules, and bad-faith-handling thresholds apply to every speaker. Asymmetric output produced by symmetric application is FAIRNESS working correctly. The bad-faith catalog’s consistency_standard principle is the operational form of this rule for Analyses.
12. CC0 throughout
Framework, prompts, configuration files, and emitted Analyses are CC0. The Analysis’s body, the tail-edit text, and the structured frontmatter are all CC0-published. No restricted material is reproduced.
13. Reader-clarity discipline (v0.3.0)
Every prose-bearing step incorporates the MSI Analysis Style Guide (the MSI_ANALYSIS_STYLE_GUIDE insert). §5.5 keeps the Analysis careful; the style guide keeps it clear — an Analysis that is accurate but reads like an encyclopedia entry has failed. The lede opens on why this story’s framing matters, never on the mission or the method; the standing explainer lives in one foot-line; techniques are named once in plain reader-words; house jargon is translated; and the §5.5 no-motive rule extends from named individuals to the news outlet itself (describe effect, never intent; propaganda is a function claim, not a motive claim). Priority: when clarity and §5.5 appear to conflict, §5.5 wins on substance (what may be claimed) and the style guide wins on delivery (how it is said).
Persona
The framework’s prompt-level persona for the Layer 4 composition + discipline-filter step is a composite of named exemplars, limited to five capability descriptors per the Araujo et al. (2025) finding on persona drift.
You compose substantive analytical prose with the wire discipline of a Reuters investigations editor (attribution-saturated, named-authority-driven, structurally explanatory), the standards-desk caution of a New York Times national-news editor (every analytical claim either factual recap or attributed inference; hedges preserved; reputational care for named individuals), and the explanatory craft of an Atlantic long-form features writer working within attribution discipline (long form, named experts, explicit chains of reasoning, no rhetorical bluster). You apply the discipline of verification described by Bill Kovach and Tom Rosenstiel — never assert what the source material does not authorize, never invent specifics, be transparent about the analytical operation being performed. You operate from the consensus values floor articulated in the Main Street Independent treatise §3 and stay inside it: pattern names migrate to cited authority voice; motive theories about named individuals are not made; character judgments are not made; hedging is preserved. The Ora analytical mode whose specification is in your system prompt has done the analytical work; your job is to render its output as a publication-voice Analysis that meets the floor’s discipline without losing the analytical substance.
The five capability descriptors:
- Reuters investigations editor — attribution-saturated analytical voice; named-authority-driven; structurally explanatory.
- NYT standards-desk editor — every analytical claim sourced or hedged; reputational care; no editorial pattern-naming in narrator voice.
- Atlantic long-form features craft — explanatory at length, named experts, explicit reasoning chains, no bluster.
- Kovach/Rosenstiel discipline of verification — never assert what source material does not authorize; never invent specifics; transparent about method.
- Floor-disciplined analytical composer — applies treatise §5.5 line as a constrained rewrite on Ora mode outputs; routes floor-crossing residue to the editorial-supervisor query and (where applicable) to Pipeline 3 columns rather than into Analysis voice.
Excluded persona attributes: years of experience, personal biographical detail, op-ed / columnist voice, investigative-reporter swagger, identification with a specific named outlet. Same exclusions as News framework, same Araujo-et-al. rationale.
Processing Layers
Layer 1 — Cluster + Article Ingestion and Enrichment
Entry condition: A cluster object received from the orchestration script + the finalized news article markdown + the news article path + the task dict.
Operations:
-
Cluster schema validation. The cluster validates against the News framework’s Input Contract. Missing or malformed → non-publication response with diagnostic.
-
News article parse. Frontmatter and body parsed;
## Summarybullets and## Sourcessection extracted; word count computed. -
Cluster-shape detection. Sniff
cluster_idprefix:cluster_2026_*→ GDELT-cascade shape (fullselection_rationaledict, populatedaggregated_themes, multi-sourcecluster_members);cluster_ap_*→ AP-backfill shape (free-textselection_rationale, emptyaggregated_themes, single-wire-sourcecluster_members[0],_msi_meta.ap_keywordscarries the topic signal). Layer 1’s downstream signal-extraction routes accordingly. Per-shape adapters live inanalysis_generator.py; this framework documents the contract, not the per-shape implementation detail. -
Cluster-enrichment pass — derive analytical signals. Read both cluster bodies (from
cluster_members[].full_text_or_abstract) and the news article body. Compute:- Named beneficiary — the entity that benefits from the cluster’s central status-quo change (distinct from
primary_entity, which is the anchor entity). Derived via a small LLM pass against cluster bodies + the news article’s## Summary; null if no named beneficiary is identifiable from source material. - Frame-source-in-body presence and type — whether the cluster substrate contains a press release, official statement, campaign messaging, or corporate communication, classified by
{type: press_release | official_statement | campaign_messaging | corporate_communication | none, source_id: src_NNN}. Cluster-memberoutlet_classprovides a partial signal; the enrichment LLM pass refines it from body content. - Named-actor classification — for each entity in
pre_extracted_entities, classify as{expert, official, partisan, witness, other}based on how the cluster substrate refers to them. Used by mode-source-material checks at Layer 3. - Anniversary-or-retrospective flag — true if cluster substrate or news article contains anniversary framing (“X years ago today,” “the third such incident this year,” “looking back on”) or retrospective framing.
- Framing-divergence-across-sources flag — true if cluster members substantively differ in how they frame the central event (computed from differences in
## Summary-equivalent thesis claims across cluster member bodies + outlet ideological tier where available). - Wicked-problem flag — true if cluster substrate contains named expert assessments characterizing the problem as wicked / intractable / multi-causal-with-no-clean-solution.
- Major-ideological-conflict flag — true if cluster substrate documents a conflict whose participants frame their positions in worldview-incompatible terms (named scholars on record).
- Official-messaging-dominance score — fraction of cluster substrate that originates from a single named official source (informs
propaganda-auditdispatch). - Named-experts-on-record set — entities classified as
expertwho appear in the cluster substrate as direct sources. Informsroot-cause-analysis,red-team-assessment,scenario-planning,probabilistic-forecasting,pre-mortem-fragility,wicked-problems. - Named-critics-on-record set — entities on record critiquing a proposed plan/policy. Informs
red-team-assessment.
- Named beneficiary — the entity that benefits from the cluster’s central status-quo change (distinct from
-
Provenance per signal. Every derived signal carries a note pointing at the cluster member id (or
news_article) and the passage that supports the classification. Signals with insufficient evidence are emitted asnull, not guessed. -
Cluster-level gate pre-check. Compute and record:
- News article word count (must be ≥600 to proceed; else non-publication).
- Cluster significance score (from cluster
_msi_metaand the article’sfloor_values_engagedintensities). - At least one named beneficiary, interested actor, or downstream stake identifiable.
- At least one floor value engaged at meaningful intensity (≥0.5 on the 0–1 scale).
Gate-failures at this layer produce a clean non-publication response with reason; News article publication is unaffected.
Invariant check at Layer 1 → 2 boundary: the normalized substrate contains the cluster JSON, the parsed article, and the enrichment signals (or explicit nulls); every signal carries provenance; cluster-level gate pre-checks have been recorded.
Carry-forward to Layer 2: the normalized substrate + the gate-check report.
Layer 2 — Mode Selection and Integration Decision
Entry condition: Normalized substrate from Layer 1.
Operations:
- Cluster-level gate evaluation. If any gate failed at Layer 1, emit non-publication with reason. Otherwise proceed.
- Per-mode trigger evaluation. Walk the mode-selection table below; for each row, check whether the cluster substrate satisfies the trigger signal. Mark the mode as a dispatch candidate when it does.
Tier A — frequent dispatch (workhorses). Default-fire when their trigger signals are present.
Ora mode_id | Territory | Trigger signal in the enrichment substrate |
|---|---|---|
cui-bono | T2 | Named beneficiary present + cluster documents a status-quo change |
consequences-and-sequel | T6 | Cluster documents a policy change, court ruling, regulatory action, or corporate move with named downstream actors |
frame-audit | T1 | Frame-source-in-body present (press release / official statement / campaign messaging / corporate communication) |
stakeholder-mapping | T8 | ≥6 named entities in article frontmatter primary_entities (deterministic floor) AND LLM-verified distinct-interest. Do NOT use cluster.pre_extracted_entities — AP-backfill caps that field at 3, making it constant and useless as a variable signal. Calibrated 2026-05-27 at 77% fire rate among gate-passing AP-backfill articles. |
quick-orientation | T14 | News article’s topic is technical / foreign / specialized AND no prior MSI coverage exists in related_stories |
Tier B — selective dispatch. Fire when their specific trigger signal is present.
Ora mode_id | Territory | Trigger signal |
|---|---|---|
root-cause-analysis | T4 | Cluster documents a failure / incident / crisis AND named-experts-on-record set is non-empty with at least one offering causal attribution |
strategic-interaction | T18 | Cluster substrate shows multiple actors visibly responding to each other (named, on record) |
process-tracing | T4 | Anniversary-or-retrospective flag is true AND named-experts-on-record set non-empty |
pre-mortem-fragility | T7 | Cluster engages systems-stability concerns AND named-experts-on-record offer fragility assessments |
scenario-planning | T6 | Cluster is high-uncertainty future-anchored AND named experts offer scenarios on record |
probabilistic-forecasting | T6 | Cluster contains a specific resolvable question AND named forecasters on record |
synthesis | T12 | Framing-divergence-across-sources flag true AND the divergences are about interpretation (call this when integrative composition is the dominant need) |
dialectical-analysis | T12 | Framing-divergence-across-sources flag true AND the divergences are about underlying values (call this when thesis-antithesis composition is the dominant need) |
propaganda-audit | T1 | Official-messaging-dominance score >0.6 AND scholarly criteria for propaganda technique apply |
red-team-assessment | T15 | Cluster’s central artifact is a proposed plan / policy AND named-critics-on-record set non-empty |
Tier C — rare dispatch.
Ora mode_id | Territory | Trigger signal |
|---|---|---|
wicked-problems | T2 | Wicked-problem flag true AND named experts characterize the area as such on record |
worldview-cartography | T9 | Major-ideological-conflict flag true AND named scholars on record |
causal-dag | T4 | Cluster substrate documents a recurring pattern AND named experts offer systems-level causal modeling on record |
bayesian-hypothesis-network | T5 | Cluster contains ≥2 competing explanations AND named experts adjudicate between them on record |
The mapping was verified against Reference — Analytical Territories.md (as of 2026-05-27). All mode_ids above resolve to existing modes in ~/ora/modes/. No Ora-registry additions are proposed.
-
Source-material pre-check (advisory). For each candidate mode, the per-mode source-material requirements (more detailed than the trigger signal — e.g., for
red-team-assessmentthe named critics’ on-record critique passages must be in the substrate, not just their names) are checked. Modes whose requirements are advisory-unmet are flagged for Layer 3 (which makes the final skip-silently decision). -
Integrate-or-split decision (the operative rule). Given the candidate-mode set:
- Same-perspective overlap — modes whose outputs operate on the same fact pattern with mutually supporting analytical moves (e.g.,
cui-bono+consequences-and-sequelon the same policy change;frame-audit+propaganda-auditon the same official-messaging dominance). → Integrate into one dispatch group. - Distinct-perspective dimensions — modes whose outputs operate on materially different aspects of the cluster (e.g.,
consequences-and-sequelon a court ruling +propaganda-auditon the dissenting party’s media reception of it). → Split into separate dispatch groups (each becomes its own Analysis). - Default behavior: split. The integration decision requires a positive coherence finding (“these modes’ outputs share the same fact pattern and the same named actors”). Absent that, split. A wrongly-integrated Analysis bundles two stories under one piece; a wrongly-split pair produces two clean Analyses with their own tail-edit lines — the cost of wrong-split is lower than wrong-integration.
- Same-perspective overlap — modes whose outputs operate on the same fact pattern with mutually supporting analytical moves (e.g.,
-
Dispatch-group emission. Emit one or two mode dispatch groups, each a list of
mode_ids. If a group has zero members after source-material pre-check, drop it; if all groups drop, emit non-publication.
Invariant check at Layer 2 → 3 boundary: every dispatch group has ≥1 mode_id; every mode_id traces to a satisfied trigger signal in the substrate; the integration decision is recorded with rationale.
Carry-forward to Layer 3: dispatch groups + per-mode trigger-satisfaction notes + per-mode source-material status (ready | skip_pending).
Layer 3 — Per-Mode Dispatch
Entry condition: Dispatch groups from Layer 2.
Operations:
For each dispatch group, for each mode_id in the group:
- Source-material final check. Re-verify the mode’s source-material requirements against the substrate. If unmet, skip silently — log the skip with the unmet requirement; do not author around the gap.
- Load mode prompt.
mode_prompt = orchestrator.boot.load_mode(mode_id). Ifmode_promptis empty (mode file not found), log a hard error and skip the mode; do not proceed with an empty system prompt. - Compose mode input package. Build the user prompt:
- The cluster’s enriched substrate digest (cluster-level facts; named entities with classification; floor values engaged with intensity; named-beneficiary, frame-source, etc.).
- The finalized news article markdown (frontmatter +
## Summary+ body +## Sources). - Mode-specific framing (a short header telling the mode it is being dispatched as part of an Analysis pipeline, and that its output will be composed into a publication-voice Analysis under news-floor discipline — so it should produce substantive analytical content with attributable specifics, not vague “could be argued” formulations).
- Invoke.
result = orchestrator.model_dispatch.invoke_chat(system_prompt=mode_prompt, user_prompt=composed_input, slot="breadth", context="autonomous"). OnModelDispatchError, log the error and skip the mode (graceful per-mode degradation); the dispatch group continues with whatever modes did succeed. - Collect. Record the mode output under the group’s mode-outputs map.
After all modes in all groups have dispatched:
- Group survival check. A dispatch group with zero successful mode outputs is dropped. If all groups drop, emit non-publication with reason “all modes skipped or errored.” News article publication is unaffected.
Invariant check at Layer 3 → 4 boundary: every surviving dispatch group has ≥1 mode output; every mode output is non-empty; the dispatch log records every skip and every error with reason.
Carry-forward to Layer 4: surviving dispatch groups with their mode-outputs maps + the full dispatch log (skipped modes, errored modes, succeeded modes).
Layer 4 — Composition Under News-Floor Discipline
Entry condition: Surviving dispatch groups + mode-outputs maps from Layer 3.
For each surviving dispatch group, produce one Analysis markdown body.
Operations (per group):
-
Multi-mode integration (within-group). When the group has >1 mode_id, integrate their outputs into a single coherent analytical narrative. The composition arranges the modes’ contributions into coherent sections without forcing them into a rigid template —
cui-bonomaterial becomes the “who benefits” section,consequences-and-sequelbecomes the “what happens next” section,frame-auditbecomes the “how this is being framed” section, and so on. Section ordering follows news-pyramid priority on the dispatched substance: which mode’s substance most directly answers the news article’s “why does this matter” gets the lede. -
Headline candidate. Generate the Analysis headline: SVO present-tense, ≤80 chars, sentence-case, distinct from the source news article’s headline. Should signal the analytical move (“How [X] benefits when [Y]” / “What [Z] means for [stakes]” / “Why [pattern] keeps recurring”). No clickbait, no superlatives.
-
tail_edit_topic. Generate the short topic phrase (≤6 words) that completes “Read MSI’s analysis of ___.” in the tail-edit. Examples: “the building-code enforcement collapse,” “the SCOTUS dissent’s media reception,” “who benefits from the new tariff.” -
## Summarysection. 3–6 bullets per the News framework’s Summary rules. First bullet is a complete thesis statement of the Analysis (named actor + concrete verb + specific analytical claim). Remaining bullets are supporting analytical points. Honor the Three Grammar Rules (named actors, resolved pronouns, concrete verbs) and the one-claim-per-bullet rule. Subtype:causal_claimfor most analytical pieces;factfor primer/orientation pieces fromquick-orientation;evaluativeis forbidden — that’s Advocacy register. -
Lede paragraph. A single prose paragraph after the Summary, elaborating the bullets. Hard-news inverted-pyramid form: highest-news-value Five-W answers + the analytical claim that the rest of the body develops.
-
Body prose. Flat narrative under the lede; length follows material; no targets. Sections are rendered as Markdown headings within the body, ordered by declining significance per inverted pyramid.
-
News-floor discipline filter (the operative pass). Walk the composed prose and rewrite for treatise §5.5 compliance:
- Pattern names in publication voice → cited authority voice. “This is regulatory capture” (publication voice asserting a pattern) → “[Named scholar / institution] has characterized the regulatory environment as regulatory capture, citing [specific evidence].” The pattern name stays; what changes is who is voicing the claim.
- Motive theories about named individuals → cut or rewritten as documented-conduct. “Senator X reversed her position because she was pressured by [interest]” (motive theory) → “Senator X reversed her position. Lobbying records show [interest] reported contacts with her office during the period in question.” Document the conduct; do not author the psychological explanation.
- Character judgments about named individuals → cut or replaced with sourced contradictions. “[Figure] is dishonest” → either cut (the analytical move was inappropriate for publication voice) or replaced with sourced specifics: “[Figure]‘s [date] statement contradicts [Figure]‘s [other date] statement on the same matter.”
- Hedging language preserved. Every hedge (“according to,” “alleged,” “reportedly,” “appears to”) in the cluster substrate or news article is preserved in the Analysis prose. Hedge-loss is a Tier-1 error and forces regeneration.
- Plain-language naming vocabulary (“theft,” “graft,” “scam” — per
Reference — MSI Publication-Level Editorial Disciplines.md§3) is forbidden in publication voice for the Analysis. Those vocabulary moves belong in Advocacy (Pipeline 3 columns); the Analysis describes the conduct in sourced terms. - No “Maximal-Accusation Lead at SUBSTANTIVE FRAME.” That’s an Advocacy-register publication-level discipline (
Reference — MSI Publication-Level Editorial Disciplines.md§2); the Analysis opens with the analytical claim under attribution discipline, not the maximal accusation. - No Anti-Politeness / Over-Shoot Mandates (
Reference — MSI Publication-Level Editorial Disciplines.md§5–§6). Those mandates operationalize Advocacy voices’ register-fidelity; they do not apply to publication-voice Analysis. Analysis prose may read as measured/restrained where the analytical substance is measured/restrained — that is news-floor discipline, not editorial cowardice. - Symmetric-Application preserved (
Reference — MSI Publication-Level Editorial Disciplines.md§4 — treatise §3.5). Every analytical claim that surfaces conduct from one coalition is subject to the same analytical standard applied to comparable conduct from the opposing coalition, when the substrate supports the comparison. Asymmetric output produced by symmetric application is FAIRNESS working correctly. - Meta-Discipline (claims made and let stand) applies (
Reference — MSI Publication-Level Editorial Disciplines.md§7). The Analysis does not narrate its own analytical thread (“This analysis will demonstrate…” / “Reading this through the cui-bono lens…”), does not pre-rebut imagined responses, does not reference its own register, does not scope-clip from what the substrate supports, does not defer moral assessment to outside authorities to soften. The dispatched-mode lens does its work; the Analysis carries the result. - Quotes verbatim. Any text in quotation marks in the Analysis must verbatim-match (allowing only whitespace/punctuation variation) text in the cluster substrate, the news article, or the dispatched mode outputs. Mismatched quotes are removed and the prose regenerates without them.
-
Length discipline. No padding. If a dispatched mode’s output is thin (the mode dispatched but produced limited analytical substance), the Analysis is shorter; do not invent material to extend it. If the dispatched modes produced rich substance, the Analysis is longer; do not truncate to hit a length.
-
Cross-section coherence pass. Verify the lede’s analytical claim is supported by the body’s sections; verify the
## Summarybullets match what the body actually claims; verify the headline matches the body. Mismatches force regeneration of the inconsistent element.
Invariant check at Layer 4 → 5 boundary: every analytical claim in publication voice traces to either a factual recap from cluster sources, an attributed analytical claim with named authority, or an explicitly hedged inference; no pattern name in publication voice unless attributed; no motive theory about a named individual; no character judgment; every input hedge preserved; bullet rules pass; cross-section coherence holds.
Carry-forward to Layer 5: per-group composed Analysis markdown (headline + tail_edit_topic + Summary + lede + body).
Layer 5 — Style/Voice/Verification + Editorial-Supervisor Floor Screen
Entry condition: Composed Analyses from Layer 4 (one per surviving dispatch group).
Operations (per Analysis):
-
Style/voice scans (reuse News framework Layer 5 implementations):
- Banned-vocabulary scan against
banned-vocabulary.json(editorializing-drift adjectives). - Contested-terms scan against
contested-terms.json— flagged terms allowed only inside attributed quotes, never in narrator voice. - Dead-metaphor scan against
dead-metaphors.json. - Attribution-verb scan: ≥80% of attribution verbs must be “said” / “told”; other verbs require explicit signal in input justifying their connotation.
- Active-voice scan: ≥80% of declarative sentences active; passive acceptable only where agent is genuinely unknown or patient is the news.
- Hedge-preservation re-scan: re-verify every input hedge appears in output. Layer 4 was already supposed to preserve them; this is the belt-and-suspenders check.
Any scan failure triggers a focused regeneration of the failing section with the violated constraint added as a discipline note in the regeneration prompt.
- Banned-vocabulary scan against
-
Quote verification. Every text-in-quotation-marks string in the Analysis must verbatim-match (allowing only whitespace/punctuation variation) to text in the cluster substrate, the news article, or the dispatched mode outputs. Mismatches force the quote’s removal and prose regeneration without it. Attribution chain (speaker, role, source URL) must be complete for every quote.
-
Bad-faith-handling pass. Walk the bad-faith catalog (
Reference — MSI Bad-Faith Techniques Catalog.md); if any technique’s detection criteria are met by content present in the Analysis substrate, the catalog’sjournalistic_templatelanguage is the operative way to name the pattern under attribution discipline. The Analysis can name the pattern when criteria are met; the catalog supplies the language. -
Editorial-supervisor MindSpec floor screen. Invoke
msi-editorial-supervisor(the publication-level MindSpec consulted by News Layer 6) with the Analysis as input. Supervisor disposition possibilities:floor_internal— Analysis stays inside the floor; proceed.requires_rewrite— supervisor identifies specific claims that cross the floor; pipeline re-runs Layer 4 discipline filter with the supervisor’s rationale as additional constraint, then re-invokes the supervisor (single retry; second failure escalates torequires_human_review).requires_pen_name_routing— supervisor identifies analytical content that requires Advocacy register; that content is dropped from the Analysis (not laundered) and logged for Pipeline 3 column consumption. The Analysis publishes with the remaining content; if nothing remains, the Analysis is dropped entirely and non-publication is emitted.requires_human_review— block publication until reviewer signs off. Same Layer-6 disposition record format as News.non_publishable— drop the Analysis entirely; emit non-publication with reason; News publication is unaffected.
-
Defamation, premature-identification, PII, vulnerable-population checks. Same checks the News framework Layer 6 runs. Any flag fires → human-review gate. The Analysis tier’s defamation surface is potentially elevated because Analyses make analytical claims about named figures’ positions and conduct; the discipline filter from Layer 4 mostly handles this, but Layer 5 is the belt-and-suspenders pass.
Invariant check at Layer 5 → 6 boundary: every Analysis is either clean or flagged_* with a reviewer disposition; no Analysis with an unresolved flag is forwarded to Layer 6 for emission.
Carry-forward to Layer 6: per-Analysis disposition (clean or flagged_approved) + the final Analysis markdown.
Layer 6 — Output Emission, Image Inheritance, Tail-Edit, Cross-References
Entry condition: Cleared Analyses from Layer 5.
Operations (per Analysis):
-
Frontmatter build. Construct the Analysis frontmatter by combining model-emitted fields (
headline,tail_edit_topic,primary_entities,primary_themes,floor_values_engaged) with pipeline-injected fields (publish_date,geographic_location,cluster_id,gdelt_event_ids,article_slugs,ora_modes,framework_version,consensus_floor_version,publication_mindspec_version,license,ai_generated,generation_timestamp,topic_tags,byline). -
Image inheritance. If the source news article’s frontmatter has an
image:field, copy it verbatim to the Analysis frontmatter. If absent, noimage:field is emitted; the Analysis publishes without a cover image. No render is invoked. -
## Sourcesbody section. Built by the pipeline fromcluster.cluster_members[]exactly as the News framework builds it. Same source IDs (cluster member order). The model did not emit this; the pipeline overwrites if it did. -
Slug assignment.
slug = f"{publish_date}-{slugify(headline)[:max_len]}", with collision suffix-1,-2, etc. when needed. -
Write the Analysis file.
~/sites/mainstreetindependent/src/content/analyses/<slug>.md. Pre-write idempotency check: if a file already exists with the samecluster_idAND same sortedora_modeslist in its frontmatter, skip the write and treat the existing file as the canonical output for this dispatch group. -
JSON-LD wrapping. Wrap as
@type: Article(notNewsArticle; the Analysis is analytical content, not breaking news). Declarelicense(CC0),isBasedOn(cluster source URLs + source news article URL),author(publication-as-organization),publisher,datePublished,dateModified,_provenance(framework version + AI-disclosure language +ora_modesdispatched). -
Source news article tail-edit. Read the source news article file. Check for the marker
<!-- analysis-link:<this-analysis-slug> -->; if present, skip the tail-edit (idempotent). Otherwise, locate the algorithmic-disclosure footer; insert the marked tail-edit block immediately before it with a horizontal rule above. Format (locked per handoff §6.2):--- <!-- analysis-link:<slug> --> **Going deeper:** [Read MSI's analysis of <tail_edit_topic> →](/analyses/<slug>)When a second Analysis from the same cluster is being added, its tail-edit line is inserted within the same marked section (one
---above, the new**Going deeper:**line appended after the existing one), preserving order by Analysis publish time. -
Source news article frontmatter update. Add this Analysis’s slug to the source article’s
analyses:frontmatter array (append; deduplicate). The article schema’sanalyses: string[]field is added by the Astro content collection update (see Files-Touched below). -
Build-trigger. Send the build-on-server trigger for both the new Analysis file and the modified news article.
-
Column-orchestrator handshake. After each Analysis is successfully written and the source news article’s
analyses:field is updated, the orchestration script that authors Advocacy columns for the same cluster must receive the Analysis’s slug. The handshake mechanism is column-side:column_post_process.post_process_columnacceptstask["news_article_slug"]andtask["analysis_article_slug"](perWorking — MSI Voice-Analysis Integration Spec 2026-05-27.md§4 and MSI commit 4d208b147); the column orchestrator (backfill_orchestrator._author_one_columnand equivalents) must pass these through the task dict so the “Going deeper:” cross-link block renders above the column’s heteronymic footer. This framework’s responsibility: ensure each emitted Analysis’s slug is surfaced to the orchestration layer in a form the column orchestrator can consume (e.g., the same cluster-keyed cache the orchestrator already reads, or an explicit return value fromrun_analysis_pipeline). The implementation detail lives in the orchestration glue, not inanalysis_generator.pyitself, but the framework requires the slug be made available — orphaned Analyses (no column link-back) are a discipline failure.
Invariant check at Layer 6 completion: the Analysis validates against the Astro analyses schema; AI-disclosure language is present in frontmatter and JSON-LD; CC0 is declared; the source news article’s body is unchanged outside the marked tail-edit section; the tail-edit conforms exactly to the locked format; idempotency markers are present and detected on re-runs.
Failure-mode triggers: Schema validation failure → log and emit non-publication for this Analysis; the source news article tail-edit is NOT applied (we don’t link to an Analysis that didn’t publish). Tail-edit application failure (e.g., source article missing the disclosure footer anchor) → log a warning, write the Analysis, and surface the orphan-Analysis condition to the publisher for manual reconciliation.
Files-Touched and Coordinated Changes
Vault — new
Framework — Analytical Piece Generator.md(this file).
Vault — modified
Registry — Ora Overview and Document Registry.md— register the new framework file under Part 2 (Frameworks).
Vault — NOT touched (architectural lock)
Framework — MSI News Article Generator.md— unchanged.Reference — Analytical Territories.md— unchanged. Canonical source for analytical primitives. No additions proposed.Reference — MSI Treatise.md— unchanged.Reference — MSI Journalistic Standards for Algorithmic News Article Generation.md— unchanged.- No new MSI
Framework — Analytical Techniques.md— that proposal is retired per handoff §1.3.
MSI repo — new (post-framework-review)
~/sites/mainstreetindependent/ora-project/scripts/analysis_generator.py— pipeline implementation per the layer operations above.~/sites/mainstreetindependent/src/content/analyses/— new content directory.- New Astro pages:
/analyses(browse index using news page template, sorted most recent first) +/analyses/[slug](detail using individual news template family).
MSI repo — modified (post-framework-review)
- Orchestration script — wire-up to call
run_analysis_pipelineafter News finalization. Same orchestration script that today runs News. ~/sites/mainstreetindependent/src/content/config.ts— addanalysescontent collection schema; addanalyses: string[]field to thearticlescollection schema.- Site navigation/menu component — rename Opinion → Advocacy; add Analysis between News and Advocacy.
MSI repo — NOT touched (architectural lock)
~/sites/mainstreetindependent/ora-project/scripts/cluster_selector.py— unchanged. Analytical signals derived in the analysis_generator’s Layer 1 enrichment pass, not by the selector. (Q1 decision recorded 2026-05-27.)~/sites/mainstreetindependent/ora-project/scripts/article_generator.py— unchanged. The news article body is not modified by the Analysis pipeline.- News-image-render scripts (
news_image_render.py,render_article_figures.py,render_figure.py,render_missing_article_images.py,article_image_sweeper.py) — unchanged. The Analysis pipeline inherits images from source articles and does not invoke its own renders. - The column path in any script — column-side work (parallel session per handoff §12).
- The algorithmic-disclosure footer architecture — 2026-05-10 decision of record stands.
- The Editorial Router’s routing decisions.
Coordinated parallel work (tracked in handoff §12; not part of this framework’s implementation)
- Update each voice framework’s
## CROSS-REFERENCESto cite canonical Oramode_ids rather than inline-describing techniques. - Update each column framework’s input contract to accept the optional Analysis article — adding an “Analysis Article Integration” section per voice. Source-of-truth for the per-voice mapping:
Working — MSI Voice-Analysis Integration Spec 2026-05-27.md(vault). The spec defines four integration patterns (1 Direct inheritance / 2 Substrate consumption / 3 Extension/augmentation / 4 Detail mining) and supplies per voice: the Oramode_ids the voice consumes; the voice’s value-add layer; the re-derivation failure mode to audit against. The actual 14-framework edit pass lands on the column-side thread after the Analysis tier reaches production-validation. - Update
column_post_process.pyto render the cross-link block in the column tail (source News + source Analysis URLs when available). Landed in MSI commit 4d208b147 —post_process_columnacceptstask["news_article_slug"]andtask["analysis_article_slug"]; when either is set, a “Going deeper:” line renders above the per-voice heteronymic footer. When neither is set, the block renders empty (backward-compatible). - Update the signature-audit prompt with a “no re-derivation” rule. Landed in MSI commit 4d208b147 —
column_signature_audit.pydetects an## ANALYSIS ARTICLEheader in the AUTHOR USER PROMPT and grades whether the column re-derives analytical work the Analysis already published. The column orchestrator must splice the Analysis into the user prompt using exactly that header so the audit’s detection clause fires.
Open Implementation Notes
Carried forward for the implementation session (post-framework-review) to address inside analysis_generator.py:
- Per-mode source-material requirements registry. Layer 3’s source-material final check needs a concrete per-
mode_idrequirements list (e.g.,red-team-assessmentrequires named critics’ on-record critique passages, not just their names). This is a small implementation registry insideanalysis_generator.py; not specified in the Ora mode files (the Ora modes are general-analytical specifications; MSI’s analytical-substrate requirements for dispatching them are MSI’s concern). - Composition prompt for Layer 4. The composition step uses an LLM call to weave mode outputs into Analysis prose under news-floor discipline. The prompt itself is implementation detail; the framework’s Persona, Governing Principles §1–§3, and Layer 4 discipline rules are the operative specification for what that prompt must enforce.
- Worked-example cluster. Implementation thread picks a recent qualifying cluster, runs Layer 1–6 end-to-end, and reviews the Analysis output against this framework. Stage by Ora-mode tier: Tier A modes first, validate; then Tier B; then Tier C.
- Astro schema. The
analysescontent-collection schema mirrors thearticlesschema in most fields; differences are documented insrc/content/config.tsand not duplicated here. - Browse-page treatment when image inheritance leaves the Analysis without a cover. The browse page (
/analyses) reuses the news page template per the locked decision. The news page already handles articles without cover images (text-only card); the analyses browse page inherits that behavior — no special-case styling for Analyses-without-images. - Cluster-JSON availability for AP-backfill pipeline (RESOLVED 2026-05-27). Earlier finding: only ~38% of recent AP-clustered articles have a matching cluster JSON on disk, and dates beyond 2026-05-17 have no cluster JSONs at all. Investigation: the AP-backfill code path (
ap_cluster_backfill.py,ap_stage1.py) DOES write cluster JSONs viacluster_path.write_text(json.dumps(cluster, ...)). The gap is operational — AP-backfill scheduling stopped after 2026-05-17. Code path is intact; runtime invocation has gone quiet. Resolution: option (a) — publisher restores AP-backfill scheduling on a separate thread; Analysis tier keeps skip-silently as its policy when cluster JSON is missing (v0.2 default). Implication: Analyses won’t generate for articles published during the cluster-JSON gap until AP-backfill is rerun for those dates and cluster JSONs are backfilled. Skip-silently per Governing Principle 4. - Cluster-shape awareness. The framework’s Layer 1 enrichment must handle both GDELT-cascade clusters (
cluster_2026_*prefix; fullselection_rationaledict; multi-sourcecluster_members; populated_msi_meta.aggregated_themes) and AP-backfill clusters (cluster_ap_*prefix; free-textselection_rationale; single-wire-source; emptyaggregated_themes;_msi_meta.ap_keywordscarries the topic signal). The shape-detection step at Layer 1 op 3 routes to per-shape signal extractors. AP-backfill is the dominant shape in current production volume (100% of recent published articles); the framework is calibrated against it. The GDELT shape is the future-state shape (the cluster_selector.py path exists but isn’t producing live volume). - Production-rate sizing. Deterministic-signal smoke test (2026-05-27) estimated ~25–30 Analyses per day at current AP-backfill volume. Full-fidelity smoke test (Option B, n=30 articles, 2026-05-27) refined to ~37 Analyses/day at current AP-backfill state (38% cluster-JSON-availability bottleneck) and ~98/day if cluster-JSON persistence is fixed (open item #6 above). Mode-fire rates: stakeholder-mapping 80%, consequences-and-sequel 64%, frame-audit 56%, red-team-assessment 28%, cui-bono 12%, quick-orientation 8%. Split-when-in-doubt rule fires on 48% of qualifying articles. Sizing the production environment for compute/Buzz remains pending decision after worked-example cluster end-to-end (next session).
## ANALYSIS ARTICLEheader convention. When Layer 3 actual dispatch (v0.2) is wired, the orchestration glue that hands an Analysis to a column generator must splice the Analysis into the column’s user prompt under an exact## ANALYSIS ARTICLEheader socolumn_signature_audit.py’s no-re-derivation detection clause fires (MSI commit 4d208b147). PerWorking — MSI Voice-Analysis Integration Spec 2026-05-27.md§2. This is an orchestration-layer concern, not aanalysis_generator.pyconcern, but the framework requires the convention be honored by callers.- Halt-code regex pattern. When Layer 3 actual dispatch (v0.2) is wired, the dispatch wrapper should adopt the halt-code recognition pattern from
gear3_orchestrator.py::_classify_author_output(MSI commit f8217375f):^HALT-[A-Z]+and^halt_[a-z]+regex match at output start. Ora modes may emit halt markers (the column-side classifier already recognizes them with an expanded canonical list); the Analysis-tier orchestrator should recognize them parallel-fashion so a mode’s HALT is propagated as a per-mode skip rather than treated as analytical content. - Two architectural decisions recorded (2026-05-27):
- Phukher Propaganda Analyzer remains a Phukher-specific operator’s-eye enrichment. The Analysis tier’s
propaganda-auditdispatch produces the publication-voice structural finding (“this artifact deploys techniques X, Y, Z per scholarly criteria”); Phukher’s Propaganda Analyzer is the voice-specific operator’s-eye annotation layer that becomes the column body. The relationship is Pattern 3 (Extension/augmentation) per the integration spec; Phukher’s Analyzer effectively becomes a “dispatch enrichment” stage when an Analysis exists, taking the Analysis’s findings as substrate and producing the operator’s-eye annotation. Confirmed with publisher 2026-05-27. - Editorial Board WSJ/NR Catalogues remain EB-private. The Analysis tier’s
frame-audit/propaganda-auditdispatch on WSJ or NR source artifacts uses the canonical Ora mode prompts WITHOUT loading the EB-curated Catalogues. The Catalogues are EB’s signature analytical tool that distinguishes EB’s voice work; loading them into the Analysis tier would dilute both layers (Analysis becomes EB-flavored when applied to WSJ/NR; EB loses its distinctive Catalogue-aware register). EB’s column extends the Analysis’s general-purpose frame-audit foundation with the Catalogue-aware operator’s-eye layer per Pattern 3. Confirmed with publisher 2026-05-27.
- Phukher Propaganda Analyzer remains a Phukher-specific operator’s-eye enrichment. The Analysis tier’s
- Headline / tail length caps are pipeline-enforced — and are a hard build dependency (LIMITATION, 2026-05-31). The model is instructed to keep the headline ≤80 chars, but
headlineis a generation surface and the model does not reliably honor the bound. A live backfill emitted a 135-character headline that violated theanalysesschema’s hard 120-charheadlinecap and broke the Astro content-collection build (InvalidContentEntryDataError: String must contain at most 120 character(s)) — which freezes everysrc/deploy, not just/analyses, until the offending file is repaired. The schema caps are hard:headline≤120,tail_edit_topic≤100 (src/content/config.ts). Because every model-emitted field is a hallucination surface (per §Model Contract vs Pipeline Contract), the pipeline now clamps both atbuild_analysis_frontmatter— the single point the legacy L6 path and the live W9analyses_post_processpath converge on — cutting at a word boundary so a clamped headline still reads as a clean phrase. ConstantsHEADLINE_MAX_CHARS=120/TAIL_EDIT_MAX_CHARS=100inanalysis_generator.py. Caveat: the clamp protects forward production only; a file already written to disk before the clamp keeps its over-cap frontmatter and must be repaired in place (a single over-cap file is enough to fail the whole build). The ≤80 target remains the editorial goal for headline quality; 120 is the non-negotiable build-safety floor.
References Cited
Reference — MSI Treatise.md— particularly §2.6 (continuum), §3 (five floor values), §4.2 (attribution as discipline), §4.4 (publication structure), §5 (the line between reporting and analysis), §5.5 (worked examples — the operative discipline filter).Reference — Analytical Territories.md— Ora’s canonical analytical mode registry. The 17mode_ids dispatched by this framework all exist in this registry. No additions proposed.Reference — MSI Journalistic Standards for Algorithmic News Article Generation.md— sourcing, attribution, hedging, voice, bad-faith-handling disciplines; reused for Layer 5.Framework — MSI News Article Generator.md— Pipeline 1; this framework runs after News finalization; shares cluster contract, source-list construction, style/voice configs, and the editorial-supervisor MindSpec query.Reference — MSI Report.md— project genesis and architecture.Reference — MSI Editorial Router.md— the publication-level MindSpec consulted at Layer 5.Reference — MSI Bad-Faith Techniques Catalog.md— bad-faith catalog reused at Layer 5.Reference — MSI Publication-Level Editorial Disciplines.md— canonical specification of publication-level disciplines (Fictional-Heteronym Foundation, Maximal-Accusation Lead, Plain-Language Naming, Symmetric-Application, Anti-Politeness, Over-Shoot, Meta-Discipline, Confession-of-Complicity, Citation Convention). Layer 4 discipline filter applies §4 (Symmetric-Application — news-floor) and §7 (Meta-Discipline — applies to Analysis voice); §2 / §3 / §5 / §6 / §8 are Advocacy-register disciplines the Analysis tier does NOT adopt.Working — MSI Voice-Analysis Integration Spec 2026-05-27.md— per-voice integration patterns (1/2/3/4) and Oramode_ids each voice consumes from the Analysis. Source-of-truth for the column-side INPUT CONTRACT additions tracked in §Coordinated parallel work.Handoff — MSI News-Side Analytical Layer Planning 2026-05-27.md— the canonical handoff this framework operationalizes.
End of Framework — Analytical Piece Generator.