From 59e52a029730b95db03b666df25f767d6d166afa Mon Sep 17 00:00:00 2001 From: Perseus Computing <51974392+tcconnally@users.noreply.github.com> Date: Mon, 17 Aug 2026 23:45:30 +0000 Subject: [PATCH 1/3] fix(government): clarify audience fit labels --- government/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/government/index.html b/government/index.html index ebf9852b..3871d8be 100644 --- a/government/index.html +++ b/government/index.html @@ -68,7 +68,7 @@
Government · primes · technical partners

Capability statement.

Infrastructure for AI agents that need their context, memory, and evidence to stay inside the mission boundary.

Perseus Computing builds local-first infrastructure for controlled, disconnected, private-VPC, and regulated environments. Start with the document; choose a tailored version only when the conversation calls for it.

-
Three send-ready versions

Choose the version for the conversation.

Each version keeps the same evidence and procurement facts while changing the front door and fit language.

Primary fit

Cyber & Networks

For AI/ML, DevSecOps, cyber, and enterprise IT workflows where context, memory, and evidence must stay inside the controlled network.Cyber / IT

Download PDF
Enabling fit

C3BM

For software factories and distributed decision workflows where Perseus can sit beside—not replace—the mission platform.Software factory / decisions

Download PDF
Partner-led

Electronic Systems

For a prime, integrator, or technical partner exploring local, reviewable AI around sensing, EW, PNT, or mission-system workflows.Partner / integration

Download PDF
+
Three send-ready versions

Choose the version for the conversation.

Cyber & Networks is the clearest direct route. C3BM is enabling; Electronic Systems is partner-led.

Strongest direct fit

Cyber & Networks

For AI/ML, DevSecOps, cyber, and enterprise IT workflows where context, memory, and evidence must stay inside the controlled network.Cyber / IT

Download PDF
Enabling / adjacent fit

C3BM

For software factories and distributed decision workflows where Perseus can sit beside—not replace—the mission platform.Software factory / decisions

Download PDF
Partner-led / conditional fit

Electronic Systems

For a prime, integrator, or technical partner exploring local, reviewable AI around sensing, EW, PNT, or mission-system workflows.Partner / integration

Download PDF
What is inside

A reader can scan it in two minutes.

Page 01 / fit

What Perseus builds

The problem with lost state, the local context–memory–evidence system, the audience fit, and the smallest useful first conversation.

Page 02 / proof

Why the boundary matters

Measured evidence, procurement identifiers, licensing and SBOM posture, deployment options, and a direct contact path.

At a glance

The facts a buyer needs first.

Deployment
Local-first

Air-gapped, on-premises, private VPC, or controlled network.

Assessment
110 / 110

SPRS score; CMMC Level 2 self-assessment posture is scoped explicitly.

Identity
CAGE 22JC5

Perseus Computing LLC · UEI PJS2LW7HAK35.

License
MIT

SBOM materials published; no mandatory proprietary runtime.

Need the right front door?

Bring the workflow. We will bring the smallest credible path.

Send the mission workflow, its data boundary, and the integration surface. Thomas can point you to the right version or technical conversation.

From 5ae9797d49306bee4259c41ac690573e1ee8fd46 Mon Sep 17 00:00:00 2001 From: Perseus Computing <51974392+tcconnally@users.noreply.github.com> Date: Mon, 17 Aug 2026 23:57:04 +0000 Subject: [PATCH 2/3] fix(government): remove founder-specific contact language --- government/index.html | 18 +++++++++--------- scripts/build_capability_statement.py | 4 ++-- tests/test_capability_download.py | 4 +++- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/government/index.html b/government/index.html index 3871d8be..ce258f28 100644 --- a/government/index.html +++ b/government/index.html @@ -3,8 +3,8 @@ -Capability statement | Perseus Computing - +Mission fit | Perseus Computing + @@ -60,20 +60,20 @@ - +
-
Government · primes · technical partners

Capability statement.

Infrastructure for AI agents that need their context, memory, and evidence to stay inside the mission boundary.

Perseus Computing builds local-first infrastructure for controlled, disconnected, private-VPC, and regulated environments. Start with the document; choose a tailored version only when the conversation calls for it.

-
Three send-ready versions

Choose the version for the conversation.

Cyber & Networks is the clearest direct route. C3BM is enabling; Electronic Systems is partner-led.

Strongest direct fit

Cyber & Networks

For AI/ML, DevSecOps, cyber, and enterprise IT workflows where context, memory, and evidence must stay inside the controlled network.Cyber / IT

Download PDF
Enabling / adjacent fit

C3BM

For software factories and distributed decision workflows where Perseus can sit beside—not replace—the mission platform.Software factory / decisions

Download PDF
Partner-led / conditional fit

Electronic Systems

For a prime, integrator, or technical partner exploring local, reviewable AI around sensing, EW, PNT, or mission-system workflows.Partner / integration

Download PDF
+
Government · primes · technical partners

Mission fit for controlled AI.

Infrastructure for AI agents that need their context, memory, and evidence to stay inside the mission boundary.

Perseus Computing builds local-first infrastructure for controlled, disconnected, private-VPC, and regulated environments. Start with the document; choose a tailored version only when the conversation calls for it.

+
Three audience routes

Choose the version for the conversation.

Cyber & Networks is the clearest direct route. C3BM is enabling; Electronic Systems is partner-led.

Strongest direct fit

Cyber & Networks

For AI/ML, DevSecOps, cyber, and enterprise IT workflows where context, memory, and evidence must stay inside the controlled network.Cyber / IT

Download PDF
Enabling / adjacent fit

C3BM

For software factories and distributed decision workflows where Perseus can sit beside—not replace—the mission platform.Software factory / decisions

Download PDF
Partner-led / conditional fit

Electronic Systems

For a prime, integrator, or technical partner exploring local, reviewable AI around sensing, EW, PNT, or mission-system workflows.Partner / integration

Download PDF
What is inside

A reader can scan it in two minutes.

Page 01 / fit

What Perseus builds

The problem with lost state, the local context–memory–evidence system, the audience fit, and the smallest useful first conversation.

Page 02 / proof

Why the boundary matters

Measured evidence, procurement identifiers, licensing and SBOM posture, deployment options, and a direct contact path.

At a glance

The facts a buyer needs first.

Deployment
Local-first

Air-gapped, on-premises, private VPC, or controlled network.

Assessment
110 / 110

SPRS score; CMMC Level 2 self-assessment posture is scoped explicitly.

Identity
CAGE 22JC5

Perseus Computing LLC · UEI PJS2LW7HAK35.

License
MIT

SBOM materials published; no mandatory proprietary runtime.

-
Need the right front door?

Bring the workflow. We will bring the smallest credible path.

Send the mission workflow, its data boundary, and the integration surface. Thomas can point you to the right version or technical conversation.

+
Need the right front door?

Bring the workflow. We will bring the smallest credible path.

Send the mission workflow, its data boundary, and the integration surface. We can point you to the right version or technical conversation.

- + diff --git a/scripts/build_capability_statement.py b/scripts/build_capability_statement.py index 64952a2f..374e07cc 100644 --- a/scripts/build_capability_statement.py +++ b/scripts/build_capability_statement.py @@ -366,7 +366,7 @@ def build(profile_name: str, profile: dict, claims: dict) -> Path: facts = Table([[ fact_block("Company", [ ("Legal name", "Perseus Computing LLC"), - ("Business", "U.S. small business · founder-led technical access"), + ("Business", "U.S. small business · technical access"), ("UEI / CAGE", "PJS2LW7HAK35 / 22JC5"), ("NAICS", "541715 · 541511 · 541512"), ("SAM.gov", "Active — All Awards"), @@ -400,7 +400,7 @@ def build(profile_name: str, profile: dict, claims: dict) -> Path: story.append(Spacer(1, 12)) boundary = Table([[ rich("DEPLOYMENT BOUNDARY
Run the context, memory, and evidence layers where the program keeps its working data. Air-gapped, on-premises, private VPC, and controlled-network deployment are supported postures.", st["body_tiny"]), - rich("CONTACT
Thomas Connally, Founder
perseus@perseus.observer", st["body_tiny"]), + rich("CONTACT
perseus@perseus.observer", st["body_tiny"]), ]], colWidths=[4.72 * inch, 2.63 * inch]) boundary.setStyle(TableStyle([ ("BACKGROUND", (0, 0), (0, 0), PALE_BLUE), diff --git a/tests/test_capability_download.py b/tests/test_capability_download.py index 492e6e8a..0288ece7 100644 --- a/tests/test_capability_download.py +++ b/tests/test_capability_download.py @@ -47,7 +47,9 @@ def test_tailored_capability_artifacts_exist_and_public_copy_is_not_internal_wor def test_government_landing_is_single_purpose_and_exposes_all_three_custom_routes(): landing = (ROOT / "government" / "index.html").read_text(encoding="utf-8") - assert "Capability" in landing and "statement." in landing + assert "Mission fit for" in landing and "controlled AI" in landing + assert "Email Thomas" not in landing + assert "Thomas Connally" not in landing assert "Choose the version for the conversation." in landing assert "Cyber-Networks.pdf" in landing assert "C3BM.pdf" in landing From 36266069af5a165ea235a720a4e34d87affce268 Mon Sep 17 00:00:00 2001 From: Perseus Computing <51974392+tcconnally@users.noreply.github.com> Date: Tue, 18 Aug 2026 00:27:34 +0000 Subject: [PATCH 3/3] feat(government): publish flat capability brief layout --- ...omputing-LLC-Capability-Statement-C3BM.pdf | Bin 7769 -> 7562 bytes ...LC-Capability-Statement-Cyber-Networks.pdf | Bin 7771 -> 7545 bytes ...apability-Statement-Electronic-Systems.pdf | Bin 7792 -> 7567 bytes ...eus-Computing-LLC-Capability-Statement.pdf | Bin 7914 -> 7704 bytes scripts/build_capability_statement.py | 523 ++++++------------ 5 files changed, 175 insertions(+), 348 deletions(-) diff --git a/government/assets/Perseus-Computing-LLC-Capability-Statement-C3BM.pdf b/government/assets/Perseus-Computing-LLC-Capability-Statement-C3BM.pdf index c53945c9eb6098d0736fcd4be441cd2f4c72bb18..1013ca60773e1beb3d1057a10740b6e80dd6ccaa 100644 GIT binary patch literal 7562 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 LF8~;?g5 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 Z499N;80Yo*ZGc*h2K5UBhjZ!I{|2eHyJr9Z diff --git a/government/assets/Perseus-Computing-LLC-Capability-Statement-Cyber-Networks.pdf b/government/assets/Perseus-Computing-LLC-Capability-Statement-Cyber-Networks.pdf index 04017cd8f14ba1102b52486c22024bfb793d46a2..a10d706a471e908659751233b2aece1a24285a47 100644 GIT binary patch literal 7545 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 BjPU>f literal 7771 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 PfiM`!@~^;hPyPBoL7$+W literal 7792 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 uw-&Dz=C^C_s(q@? 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 diff --git a/scripts/build_capability_statement.py b/scripts/build_capability_statement.py index 374e07cc..66bc1183 100644 --- a/scripts/build_capability_statement.py +++ b/scripts/build_capability_statement.py @@ -1,14 +1,8 @@ #!/usr/bin/env python3 -"""Build a readable master and three audience-specific capability statements. +"""Build the public master and audience-specific defense capability briefs. -The layout intentionally uses two Letter pages instead of compressing every -claim into a single dense sheet: - - page 1: mission problem, Perseus system, fit, first conversation - page 2: measured evidence, procurement facts, deployment boundary, contact - -All public figures are read from the canonical claims.json registry. Profiles -change the audience framing and fit language, not the evidence layer. +The layout uses equal-width evidence rows, horizontal information bands, and +no unequal decorative cards. Public figures come from claims.json. """ from __future__ import annotations @@ -19,419 +13,252 @@ from reportlab.lib import colors from reportlab.lib.colors import HexColor -from reportlab.lib.enums import TA_CENTER, TA_LEFT +from reportlab.lib.enums import TA_LEFT from reportlab.lib.pagesizes import letter from reportlab.lib.styles import ParagraphStyle from reportlab.lib.units import inch -from reportlab.platypus import ( - BaseDocTemplate, - Frame, - HRFlowable, - PageBreak, - PageTemplate, - Paragraph, - Spacer, - Table, - TableStyle, -) +from reportlab.platypus import BaseDocTemplate, Frame, HRFlowable, PageBreak, PageTemplate, Paragraph, Spacer, Table, TableStyle ROOT = Path(__file__).resolve().parents[1] PROFILES = ROOT / "scripts" / "capability_profiles.json" -OUTPUT_DIR = ROOT / "government" / "assets" +OUT = ROOT / "government" / "assets" NAVY = HexColor("#10283D") -NAVY_2 = HexColor("#1A3C57") BLUE = HexColor("#2E789F") GREEN = HexColor("#25704D") -GOLD = HexColor("#B57925") INK = HexColor("#17242D") MUTED = HexColor("#4E626D") FAINT = HexColor("#6D8089") -PALE_BLUE = HexColor("#EDF4F8") -PALE_GREEN = HexColor("#EDF7F1") -PALE_GOLD = HexColor("#FBF4E8") RULE = HexColor("#C8D5DB") +PALE = HexColor("#F4F7F8") +PALE_BLUE = HexColor("#EDF4F8") WHITE = colors.white - PAGE_W, PAGE_H = letter -def make_styles() -> dict[str, ParagraphStyle]: - base = ParagraphStyle( - "base", - fontName="Helvetica", - fontSize=9.1, - leading=12.2, - textColor=INK, - spaceAfter=0, - ) +def styles() -> dict[str, ParagraphStyle]: + base = ParagraphStyle("base", fontName="Helvetica", fontSize=9.2, leading=12.2, textColor=INK) return { - "brand": ParagraphStyle("brand", fontName="Helvetica-Bold", fontSize=15.5, leading=17, textColor=WHITE), - "brand_sub": ParagraphStyle("brand_sub", fontName="Helvetica", fontSize=7.3, leading=9, textColor=HexColor("#D6E7F1")), - "eyebrow": ParagraphStyle("eyebrow", fontName="Helvetica-Bold", fontSize=7.4, leading=9, textColor=GREEN, tracking=0.8), - "eyebrow_white": ParagraphStyle("eyebrow_white", fontName="Helvetica-Bold", fontSize=7.2, leading=9, textColor=HexColor("#D5E8F7"), tracking=0.7), - "hero_title": ParagraphStyle("hero_title", fontName="Helvetica-Bold", fontSize=25.5, leading=28.2, textColor=NAVY, spaceAfter=6), - "hero_title_compact": ParagraphStyle("hero_title_compact", fontName="Helvetica-Bold", fontSize=21.5, leading=24.2, textColor=NAVY, spaceAfter=6), - "lead": ParagraphStyle("lead", parent=base, fontSize=11.1, leading=14.4, textColor=INK), - "body": ParagraphStyle("body", parent=base, fontSize=9.2, leading=12.0), - "body_small": ParagraphStyle("body_small", parent=base, fontSize=8.25, leading=10.6), - "body_tiny": ParagraphStyle("body_tiny", parent=base, fontSize=7.4, leading=9.2, textColor=MUTED), - "section": ParagraphStyle("section", fontName="Helvetica-Bold", fontSize=10.2, leading=12, textColor=NAVY), - "card_title": ParagraphStyle("card_title", fontName="Helvetica-Bold", fontSize=11.3, leading=13.1, textColor=NAVY), - "card_text": ParagraphStyle("card_text", parent=base, fontSize=8.25, leading=10.5, textColor=MUTED), - "label": ParagraphStyle("label", fontName="Helvetica-Bold", fontSize=7.2, leading=8.6, textColor=GREEN), - "label_blue": ParagraphStyle("label_blue", fontName="Helvetica-Bold", fontSize=7.2, leading=8.6, textColor=BLUE), - "label_gold": ParagraphStyle("label_gold", fontName="Helvetica-Bold", fontSize=7.2, leading=8.6, textColor=GOLD), - "metric_value": ParagraphStyle("metric_value", fontName="Helvetica-Bold", fontSize=20, leading=21, textColor=GREEN, alignment=TA_LEFT), - "metric_label": ParagraphStyle("metric_label", fontName="Helvetica-Bold", fontSize=8.2, leading=9.8, textColor=NAVY), - "metric_detail": ParagraphStyle("metric_detail", parent=base, fontSize=7.4, leading=9.2, textColor=MUTED), - "identity": ParagraphStyle("identity", fontName="Helvetica", fontSize=7.5, leading=9.4, textColor=FAINT), - "footer": ParagraphStyle("footer", fontName="Helvetica", fontSize=6.7, leading=8.1, textColor=FAINT, alignment=TA_CENTER), - "callout": ParagraphStyle("callout", parent=base, fontSize=9.1, leading=12.0, textColor=NAVY), - "at_glance_value": ParagraphStyle("at_glance_value", fontName="Helvetica-Bold", fontSize=9.2, leading=11, textColor=NAVY), - "at_glance_label": ParagraphStyle("at_glance_label", fontName="Helvetica-Bold", fontSize=6.8, leading=8.2, textColor=FAINT), + "header_brand": ParagraphStyle("header_brand", fontName="Helvetica-Bold", fontSize=13.6, leading=15, textColor=WHITE), + "header_meta": ParagraphStyle("header_meta", fontName="Helvetica", fontSize=7.2, leading=8.5, textColor=HexColor("#D6E7F1")), + "eyebrow": ParagraphStyle("eyebrow", fontName="Helvetica-Bold", fontSize=7.2, leading=8.5, textColor=GREEN), + "eyebrow_blue": ParagraphStyle("eyebrow_blue", fontName="Helvetica-Bold", fontSize=7.2, leading=8.5, textColor=BLUE), + "title": ParagraphStyle("title", fontName="Helvetica-Bold", fontSize=25.5, leading=27.5, textColor=NAVY, spaceAfter=7), + "title_compact": ParagraphStyle("title_compact", fontName="Helvetica-Bold", fontSize=20.5, leading=22.5, textColor=NAVY, spaceAfter=6), + "lead": ParagraphStyle("lead", parent=base, fontSize=11.0, leading=14.3, textColor=INK), + "body": ParagraphStyle("body", parent=base, fontSize=9.1, leading=12.0), + "body_small": ParagraphStyle("body_small", parent=base, fontSize=8.2, leading=10.4, textColor=MUTED), + "body_tiny": ParagraphStyle("body_tiny", parent=base, fontSize=7.2, leading=9.0, textColor=MUTED), + "section": ParagraphStyle("section", fontName="Helvetica-Bold", fontSize=10.4, leading=12.2, textColor=NAVY), + "label": ParagraphStyle("label", fontName="Helvetica-Bold", fontSize=7.0, leading=8.3, textColor=GREEN), + "label_blue": ParagraphStyle("label_blue", fontName="Helvetica-Bold", fontSize=7.0, leading=8.3, textColor=BLUE), + "label_muted": ParagraphStyle("label_muted", fontName="Helvetica-Bold", fontSize=7.0, leading=8.3, textColor=FAINT), + "band_value": ParagraphStyle("band_value", fontName="Helvetica-Bold", fontSize=9.0, leading=10.5, textColor=NAVY), + "module_title": ParagraphStyle("module_title", fontName="Helvetica-Bold", fontSize=11.2, leading=12.8, textColor=NAVY), + "metric_value": ParagraphStyle("metric_value", fontName="Helvetica-Bold", fontSize=14.5, leading=16, textColor=GREEN), + "metric_label": ParagraphStyle("metric_label", fontName="Helvetica-Bold", fontSize=8.0, leading=9.4, textColor=NAVY), + "metric_detail": ParagraphStyle("metric_detail", parent=base, fontSize=7.2, leading=8.8, textColor=MUTED), + "footer": ParagraphStyle("footer", fontName="Helvetica", fontSize=6.6, leading=8, textColor=FAINT), + "callout": ParagraphStyle("callout", parent=base, fontSize=8.6, leading=11.1, textColor=WHITE), } -def p(text: str, style: ParagraphStyle) -> Paragraph: +def plain(text: str, style: ParagraphStyle) -> Paragraph: return Paragraph(escape(text).replace("\n", "
"), style) -def rich(text: str, style: ParagraphStyle) -> Paragraph: +def markup(text: str, style: ParagraphStyle) -> Paragraph: return Paragraph(text, style) -def section_heading(title: str, st: dict[str, ParagraphStyle], color=BLUE) -> list: - return [ - rich(escape(title.upper()), st["section"]), - HRFlowable(width="100%", thickness=0.7, color=color, spaceBefore=1, spaceAfter=7), - ] - +def rule_section(title: str, st: dict[str, ParagraphStyle]) -> list: + return [markup(escape(title.upper()), st["section"]), HRFlowable(width="100%", thickness=0.65, color=RULE, spaceBefore=3, spaceAfter=8)] -def bullet(label: str, text: str, st: dict[str, ParagraphStyle]) -> Paragraph: - return rich(f"  {escape(label)} {escape(text)}", st["body_small"]) - -def header(st: dict[str, ParagraphStyle], page_label: str) -> Table: - left = [rich("PERSEUS COMPUTING LLC", st["brand"]), rich("CONTEXT · MEMORY · EVIDENCE", st["brand_sub"])] - right = [rich(escape(page_label.upper()), st["eyebrow_white"]), rich("CAPABILITY STATEMENT · 2026", st["brand_sub"])] - table = Table([[left, right]], colWidths=[4.65 * inch, 2.75 * inch]) - table.setStyle(TableStyle([ +def header(page_title: str, st: dict[str, ParagraphStyle]) -> Table: + left = [markup("PERSEUS COMPUTING LLC", st["header_brand"]), markup("CONTEXT · MEMORY · EVIDENCE", st["header_meta"])] + right = [markup(escape(page_title.upper()), st["header_meta"]), markup("DEFENSE CAPABILITY BRIEF · 2026", st["header_meta"])] + t = Table([[left, right]], colWidths=[4.65 * inch, 2.70 * inch]) + t.setStyle(TableStyle([ ("BACKGROUND", (0, 0), (-1, -1), NAVY), ("VALIGN", (0, 0), (-1, -1), "MIDDLE"), ("ALIGN", (1, 0), (1, 0), "RIGHT"), - ("LEFTPADDING", (0, 0), (0, 0), 13), - ("RIGHTPADDING", (0, 0), (0, 0), 5), - ("LEFTPADDING", (1, 0), (1, 0), 5), - ("RIGHTPADDING", (1, 0), (1, 0), 13), - ("TOPPADDING", (0, 0), (-1, -1), 10), - ("BOTTOMPADDING", (0, 0), (-1, -1), 10), + ("LEFTPADDING", (0, 0), (0, 0), 12), ("RIGHTPADDING", (0, 0), (0, 0), 4), + ("LEFTPADDING", (1, 0), (1, 0), 4), ("RIGHTPADDING", (1, 0), (1, 0), 12), + ("TOPPADDING", (0, 0), (-1, -1), 9), ("BOTTOMPADDING", (0, 0), (-1, -1), 9), ])) - return table + return t -def at_a_glance(profile: dict, st: dict[str, ParagraphStyle]) -> Table: +def info_band(profile: dict, st: dict[str, ParagraphStyle]) -> Table: + fit = "Three audience routes" if profile["audience_label"].startswith("MASTER") else str(profile.get("fit_tag") or "") rows = [ - [p("PRIMARY FIT", st["at_glance_label"]), p(profile["fit_tag"], st["at_glance_value"])], - [p("DEPLOYMENT", st["at_glance_label"]), p("Local / air-gapped / private VPC", st["at_glance_value"])], - [p("PROCUREMENT", st["at_glance_label"]), p("SAM active · CAGE 22JC5", st["at_glance_value"])], - [p("CONTACT", st["at_glance_label"]), p("perseus@perseus.observer", st["at_glance_value"])], + [markup("FOCUS
" + escape(fit), st["body_small"]), markup("DEPLOYMENT
Local · air-gapped · private VPC", st["body_small"]), markup("IDENTITY
UEI PJS2LW7HAK35 · CAGE 22JC5", st["body_small"]), markup("LICENSE
MIT · SBOM published", st["body_small"])], ] - table = Table(rows, colWidths=[0.88 * inch, 2.13 * inch]) - table.setStyle(TableStyle([ - ("BACKGROUND", (0, 0), (-1, -1), PALE_BLUE), - ("BOX", (0, 0), (-1, -1), 0.6, RULE), - ("INNERGRID", (0, 0), (-1, -1), 0.35, RULE), + t = Table(rows, colWidths=[1.84 * inch] * 4) + t.setStyle(TableStyle([ + ("BACKGROUND", (0, 0), (-1, -1), PALE), + ("LINEABOVE", (0, 0), (-1, 0), 0.55, RULE), + ("LINEBELOW", (0, 0), (-1, 0), 0.55, RULE), + ("LINEBEFORE", (1, 0), (-1, 0), 0.35, RULE), ("VALIGN", (0, 0), (-1, -1), "TOP"), - ("LEFTPADDING", (0, 0), (-1, -1), 7), - ("RIGHTPADDING", (0, 0), (-1, -1), 7), - ("TOPPADDING", (0, 0), (-1, -1), 7), - ("BOTTOMPADDING", (0, 0), (-1, -1), 7), + ("LEFTPADDING", (0, 0), (-1, -1), 9), ("RIGHTPADDING", (0, 0), (-1, -1), 9), + ("TOPPADDING", (0, 0), (-1, -1), 8), ("BOTTOMPADDING", (0, 0), (-1, -1), 8), ])) - return table + return t -def module_card(number: str, title: str, text: str, background, st: dict[str, ParagraphStyle]) -> Table: - cell = [ - rich(escape(number), st["label"]), - Spacer(1, 9), - rich(escape(title), st["card_title"]), - Spacer(1, 5), - p(text, st["card_text"]), - ] - table = Table([[cell]], colWidths=[2.36 * inch]) - table.setStyle(TableStyle([ - ("BACKGROUND", (0, 0), (-1, -1), background), - ("BOX", (0, 0), (-1, -1), 0.45, RULE), +def two_column_copy(left_label: str, left_text: str, right_label: str, right_text: str, st: dict[str, ParagraphStyle]) -> Table: + left = [markup(escape(left_label.upper()), st["label_blue"]), Spacer(1, 6), plain(left_text, st["body"])] + right = [markup(escape(right_label.upper()), st["label"]), Spacer(1, 6), plain(right_text, st["body"])] + t = Table([[left, right]], colWidths=[3.65 * inch, 3.70 * inch]) + t.setStyle(TableStyle([ + ("LINEBEFORE", (1, 0), (1, 0), 0.7, RULE), ("VALIGN", (0, 0), (-1, -1), "TOP"), - ("LEFTPADDING", (0, 0), (-1, -1), 10), - ("RIGHTPADDING", (0, 0), (-1, -1), 10), - ("TOPPADDING", (0, 0), (-1, -1), 10), - ("BOTTOMPADDING", (0, 0), (-1, -1), 11), + ("LEFTPADDING", (0, 0), (0, 0), 0), ("RIGHTPADDING", (0, 0), (0, 0), 14), + ("LEFTPADDING", (1, 0), (1, 0), 14), ("RIGHTPADDING", (1, 0), (1, 0), 0), + ("TOPPADDING", (0, 0), (-1, -1), 0), ("BOTTOMPADDING", (0, 0), (-1, -1), 0), ])) - return table + return t -def fit_table(profile: dict, st: dict[str, ParagraphStyle]) -> Table: - data = [] - for label, text, tag in profile["fit_rows"]: - tag_style = st["label_gold"] if tag == "PRIMARY FIT" else st["label_blue"] if tag == "ENABLING FIT" else st["label"] - data.append([rich(f"{escape(label)}
{escape(tag)}", tag_style), p(text, st["body_small"])]) - table = Table(data, colWidths=[1.62 * inch, 5.58 * inch]) - table.setStyle(TableStyle([ - ("BACKGROUND", (0, 0), (0, -1), PALE_GREEN), - ("GRID", (0, 0), (-1, -1), 0.4, RULE), +def system_table(st: dict[str, ParagraphStyle]) -> Table: + rows = [ + [markup("CONTEXT
Before action", st["module_title"]), plain("Resolves repository, ticket, deployment, and decision state into bounded context before an agent uses it.", st["body_small"])], + [markup("MEMORY
Across sessions", st["module_title"]), plain("Retains governed, bitemporal memory with durable journaling and explicit authority boundaries.", st["body_small"])], + [markup("EVIDENCE
After action", st["module_title"]), plain("Links actions and decisions to evidence, authority, and time so a reviewer can reconstruct what happened.", st["body_small"])], + ] + t = Table(rows, colWidths=[1.85 * inch, 5.50 * inch]) + t.setStyle(TableStyle([ + ("BACKGROUND", (0, 0), (-1, -1), PALE), + ("LINEABOVE", (0, 0), (-1, 0), 0.55, RULE), + ("LINEBELOW", (0, -1), (-1, -1), 0.55, RULE), + ("LINEBELOW", (0, 0), (-1, -2), 0.35, RULE), ("VALIGN", (0, 0), (-1, -1), "TOP"), - ("LEFTPADDING", (0, 0), (-1, -1), 8), - ("RIGHTPADDING", (0, 0), (-1, -1), 8), - ("TOPPADDING", (0, 0), (-1, -1), 7), - ("BOTTOMPADDING", (0, 0), (-1, -1), 7), + ("LEFTPADDING", (0, 0), (-1, -1), 9), ("RIGHTPADDING", (0, 0), (-1, -1), 9), + ("TOPPADDING", (0, 0), (-1, -1), 8), ("BOTTOMPADDING", (0, 0), (-1, -1), 8), ])) - return table + return t -def metric_card(value: str, label: str, detail: str, st: dict[str, ParagraphStyle]) -> Table: - cell = [rich(escape(value), st["metric_value"]), Spacer(1, 5), rich(escape(label), st["metric_label"]), Spacer(1, 4), p(detail, st["metric_detail"])] - table = Table([[cell]], colWidths=[3.54 * inch]) - table.setStyle(TableStyle([ - ("BACKGROUND", (0, 0), (-1, -1), PALE_GREEN), - ("BOX", (0, 0), (-1, -1), 0.5, RULE), +def fit_table(profile: dict, st: dict[str, ParagraphStyle]) -> Table: + data = [[markup("ROUTE", st["label_muted"]), markup("USE", st["label_muted"]), markup("ROLE", st["label_muted"])]] + for label, text, tag in profile["fit_rows"]: + role = {"PRIMARY FIT": "Direct fit", "ENABLING FIT": "Enabling fit", "PARTNER-LED": "Partner-led"}.get(tag, tag.title()) + data.append([markup(f"{escape(label)}", st["body_small"]), plain(text, st["body_small"]), markup(escape(role), st["label"])]) + t = Table(data, colWidths=[1.62 * inch, 4.53 * inch, 1.20 * inch]) + t.setStyle(TableStyle([ + ("BACKGROUND", (0, 0), (-1, 0), PALE_BLUE), + ("LINEABOVE", (0, 0), (-1, 0), 0.55, RULE), + ("LINEBELOW", (0, -1), (-1, -1), 0.55, RULE), + ("LINEBELOW", (0, 1), (-1, -2), 0.35, RULE), ("VALIGN", (0, 0), (-1, -1), "TOP"), - ("LEFTPADDING", (0, 0), (-1, -1), 11), - ("RIGHTPADDING", (0, 0), (-1, -1), 11), - ("TOPPADDING", (0, 0), (-1, -1), 11), - ("BOTTOMPADDING", (0, 0), (-1, -1), 11), + ("LEFTPADDING", (0, 0), (-1, -1), 8), ("RIGHTPADDING", (0, 0), (-1, -1), 8), + ("TOPPADDING", (0, 0), (-1, -1), 7), ("BOTTOMPADDING", (0, 0), (-1, -1), 7), ])) - return table + return t -def fact_block(title: str, rows: list[tuple[str, str]], background, st: dict[str, ParagraphStyle]) -> Table: - body = [rich(escape(title.upper()), st["eyebrow"])] - for label, value in rows: - body.extend([rich(f"{escape(label)}
{escape(value)}", st["body_small"]), Spacer(1, 5)]) - table = Table([[body]], colWidths=[3.54 * inch]) - table.setStyle(TableStyle([ - ("BACKGROUND", (0, 0), (-1, -1), background), - ("BOX", (0, 0), (-1, -1), 0.5, RULE), +def evidence_table(claims: dict, st: dict[str, ParagraphStyle]) -> Table: + rows = [[markup("MEASURE", st["label_muted"]), markup("RESULT", st["label_muted"]), markup("WHAT IT SHOWS", st["label_muted"]), markup("SCOPE", st["label_muted"])]] + values = [ + ("LongMemEval QA", claims["longmemeval_cot"]["value"], "Answer quality when the agent receives the official context-of-thought protocol.", "Official-CoT mean · 3 signed runs"), + ("Session retrieval", claims["longmemeval_retrieval_recall10"]["value"], "Relevant session memories remain available to the later task.", "Retrieval-only · recall@10"), + ("BEAM correctness", claims["beam_correctness"]["value"], "The deterministic gauntlet stays correct across token tiers.", "128K–10M token tiers"), + ("Durable write", claims["vault_durable_write_100k"]["value"], "Sustained write behavior at a 100K-entity scale.", "Signed report · not bulk insert"), + ] + for name, value, meaning, scope in values: + rows.append([markup(f"{escape(name)}", st["metric_label"]), markup(escape(value), st["metric_value"]), plain(meaning, st["body_small"]), plain(scope, st["metric_detail"])]) + t = Table(rows, colWidths=[1.45 * inch, .82 * inch, 3.12 * inch, 1.96 * inch]) + t.setStyle(TableStyle([ + ("BACKGROUND", (0, 0), (-1, 0), PALE_BLUE), + ("LINEABOVE", (0, 0), (-1, 0), 0.55, RULE), + ("LINEBELOW", (0, -1), (-1, -1), 0.55, RULE), + ("LINEBELOW", (0, 1), (-1, -2), 0.35, RULE), + ("VALIGN", (0, 0), (-1, -1), "MIDDLE"), + ("LEFTPADDING", (0, 0), (-1, -1), 7), ("RIGHTPADDING", (0, 0), (-1, -1), 7), + ("TOPPADDING", (0, 0), (-1, -1), 8), ("BOTTOMPADDING", (0, 0), (-1, -1), 8), + ])) + return t + + +def flat_fact_table(title: str, rows: list[tuple[str, str]], st: dict[str, ParagraphStyle]) -> Table: + data = [[markup(escape(title.upper()), st["eyebrow_blue"]), ""]] + data.extend([[markup(f"{escape(k)}", st["body_small"]), plain(v, st["body_small"])] for k, v in rows]) + t = Table(data, colWidths=[1.18 * inch, 2.50 * inch]) + t.setStyle(TableStyle([ + ("SPAN", (0, 0), (1, 0)), + ("LINEABOVE", (0, 0), (-1, 0), 0.55, RULE), + ("LINEBELOW", (0, -1), (-1, -1), 0.55, RULE), + ("LINEBELOW", (0, 1), (-1, -2), 0.35, RULE), ("VALIGN", (0, 0), (-1, -1), "TOP"), - ("LEFTPADDING", (0, 0), (-1, -1), 11), - ("RIGHTPADDING", (0, 0), (-1, -1), 11), - ("TOPPADDING", (0, 0), (-1, -1), 11), - ("BOTTOMPADDING", (0, 0), (-1, -1), 7), + ("LEFTPADDING", (0, 0), (-1, -1), 0), ("RIGHTPADDING", (0, 0), (-1, -1), 8), + ("TOPPADDING", (0, 0), (-1, -1), 6), ("BOTTOMPADDING", (0, 0), (-1, -1), 6), ])) - return table + return t -def page_chrome(canvas, doc) -> None: +def footer(canvas, doc) -> None: canvas.saveState() canvas.setStrokeColor(RULE) - canvas.setLineWidth(0.45) - canvas.line(doc.leftMargin, 0.34 * inch, PAGE_W - doc.rightMargin, 0.34 * inch) + canvas.setLineWidth(.45) + canvas.line(doc.leftMargin, .32 * inch, PAGE_W - doc.rightMargin, .32 * inch) canvas.setFillColor(FAINT) - canvas.setFont("Helvetica", 6.7) - canvas.drawString(doc.leftMargin, 0.20 * inch, "Perseus Computing LLC · perseus.observer · perseus@perseus.observer") - canvas.drawRightString(PAGE_W - doc.rightMargin, 0.20 * inch, f"{doc.page} / 2") + canvas.setFont("Helvetica", 6.6) + canvas.drawString(doc.leftMargin, .18 * inch, "Perseus Computing LLC · perseus.observer · perseus@perseus.observer") + canvas.drawRightString(PAGE_W - doc.rightMargin, .18 * inch, f"{doc.page} / 2") canvas.restoreState() -def build(profile_name: str, profile: dict, claims: dict) -> Path: - st = make_styles() - output = OUTPUT_DIR / profile["filename"] - output.parent.mkdir(parents=True, exist_ok=True) - doc = BaseDocTemplate( - str(output), - pagesize=letter, - leftMargin=0.56 * inch, - rightMargin=0.56 * inch, - topMargin=0.42 * inch, - bottomMargin=0.52 * inch, - title=f"Perseus Computing LLC — {profile['audience_label']}", - author="Perseus Computing LLC", - subject="Capability statement", - ) - frame = Frame(doc.leftMargin, doc.bottomMargin, doc.width, doc.height, id="capability") - doc.addPageTemplates([PageTemplate(id="capability", frames=[frame], onPage=page_chrome)]) - - c = claims +def build(name: str, profile: dict, claims: dict) -> Path: + st = styles() + OUT.mkdir(parents=True, exist_ok=True) + path = OUT / profile["filename"] + doc = BaseDocTemplate(str(path), pagesize=letter, leftMargin=.60*inch, rightMargin=.60*inch, topMargin=.42*inch, bottomMargin=.50*inch, title="Perseus Computing Defense Capability Brief", author="Perseus Computing LLC") + frame = Frame(doc.leftMargin, doc.bottomMargin, doc.width, doc.height, id="brief") + doc.addPageTemplates([PageTemplate(id="brief", frames=[frame], onPage=footer)]) story: list = [] - # PAGE 1: orient the reader before listing proof. - story.append(header(st, profile["audience_label"])) - story.append(Spacer(1, 13)) - story.append(rich("CAPABILITY STATEMENT", st["eyebrow"])) - hero_title_style = st["hero_title_compact"] if len(profile["headline"]) > 62 else st["hero_title"] - hero = [ - rich(escape(profile["headline"]), hero_title_style), - p(profile["lead"], st["lead"]), - Spacer(1, 8), - rich("UEI PJS2LW7HAK35    CAGE 22JC5    SAM Active    HQ Austin, Texas", st["identity"]), - ] - hero_table = Table([[hero, at_a_glance(profile, st)]], colWidths=[4.25 * inch, 3.10 * inch]) - hero_table.setStyle(TableStyle([ - ("VALIGN", (0, 0), (-1, -1), "TOP"), - ("LEFTPADDING", (0, 0), (-1, -1), 0), - ("RIGHTPADDING", (0, 0), (0, 0), 13), - ("RIGHTPADDING", (1, 0), (1, 0), 0), - ("TOPPADDING", (0, 0), (-1, -1), 0), - ("BOTTOMPADDING", (0, 0), (-1, -1), 0), - ])) - story.append(hero_table) - story.append(Spacer(1, 16)) - - story.extend(section_heading("The problem we solve", st)) - problem = Table([[ - p(profile["problem"], st["body"]), - rich(f"WHAT CHANGES

{escape(profile['change'])}", st["callout"]), - ]], colWidths=[4.25 * inch, 3.10 * inch]) - problem.setStyle(TableStyle([ - ("BACKGROUND", (1, 0), (1, 0), PALE_GOLD), - ("BOX", (1, 0), (1, 0), 0.5, HexColor("#E5C58C")), - ("VALIGN", (0, 0), (-1, -1), "TOP"), - ("LEFTPADDING", (0, 0), (0, 0), 0), - ("RIGHTPADDING", (0, 0), (0, 0), 13), - ("LEFTPADDING", (1, 0), (1, 0), 11), - ("RIGHTPADDING", (1, 0), (1, 0), 11), - ("TOPPADDING", (0, 0), (-1, -1), 10), - ("BOTTOMPADDING", (0, 0), (-1, -1), 10), - ])) - story.append(problem) - story.append(Spacer(1, 16)) - - story.extend(section_heading("The Perseus system", st)) - modules = Table([[ - module_card("01 / CONTEXT", "Before the agent acts", "Resolves repository, ticket, deployment, and decision state into bounded context before a model uses it.", PALE_BLUE, st), - module_card("02 / MEMORY", "After the session ends", "Vault retains encrypted, bitemporal memory with durable journaling and explicit authority boundaries.", PALE_GREEN, st), - module_card("03 / EVIDENCE", "When the work is reviewed", "Ledger links actions and decisions to evidence, authority, and time instead of leaving the record in an opaque dashboard.", PALE_GOLD, st), - ]], colWidths=[2.36 * inch, 2.36 * inch, 2.36 * inch]) - modules.setStyle(TableStyle([ - ("VALIGN", (0, 0), (-1, -1), "TOP"), - ("LEFTPADDING", (0, 0), (-1, -1), 0), - ("RIGHTPADDING", (0, 0), (0, 0), 7), - ("RIGHTPADDING", (1, 0), (1, 0), 7), - ("RIGHTPADDING", (2, 0), (2, 0), 0), - ("TOPPADDING", (0, 0), (-1, -1), 0), - ("BOTTOMPADDING", (0, 0), (-1, -1), 0), - ])) - story.append(modules) - story.append(Spacer(1, 16)) - - story.extend(section_heading("Where this fits", st)) - story.append(fit_table(profile, st)) - story.append(Spacer(1, 15)) - first = Table([[rich(f"FIRST CONVERSATION   {escape(profile['discussion'])}", st["callout"])]], colWidths=[7.35 * inch]) - first.setStyle(TableStyle([ - ("BACKGROUND", (0, 0), (-1, -1), NAVY), - ("TEXTCOLOR", (0, 0), (-1, -1), WHITE), - ("BOX", (0, 0), (-1, -1), 0.5, NAVY), - ("LEFTPADDING", (0, 0), (-1, -1), 11), - ("RIGHTPADDING", (0, 0), (-1, -1), 11), - ("TOPPADDING", (0, 0), (-1, -1), 9), - ("BOTTOMPADDING", (0, 0), (-1, -1), 9), - ])) - story.append(first) - - # PAGE 2: evidence and procurement details with more room to breathe. - story.append(PageBreak()) - story.append(header(st, "Evidence and procurement")) - story.append(Spacer(1, 14)) - story.append(rich("EVIDENCE AND PROCUREMENT", st["eyebrow"])) - story.append(rich("Proof first. Claims stay attached to their method.", st["hero_title_compact"])) - story.append(p("The figures below are drawn from the public claims registry. They are presented with the measurement family and condition that give each number meaning.", st["lead"])) - story.append(Spacer(1, 16)) - - story.extend(section_heading("Measured evidence", st)) - metrics = [ - metric_card(c["longmemeval_cot"]["value"], "LongMemEval QA", "Official-CoT mean of three signed runs.", st), - metric_card(c["longmemeval_retrieval_recall10"]["value"], "Session retrieval recall@10", "Retrieval-only session-level result.", st), - metric_card(c["beam_correctness"]["value"], "BEAM correctness", "Every 128K–10M token tier; deterministic gauntlet.", st), - metric_card(c["vault_durable_write_100k"]["value"], "Durable sustained write", "Signed scale report at 100K entities; not an in-memory insert rate.", st), - ] - metric_grid = Table([[metrics[0], metrics[1]], [metrics[2], metrics[3]]], colWidths=[3.68 * inch, 3.68 * inch]) - metric_grid.setStyle(TableStyle([ - ("VALIGN", (0, 0), (-1, -1), "TOP"), - ("LEFTPADDING", (0, 0), (0, -1), 0), - ("RIGHTPADDING", (0, 0), (0, -1), 7), - ("LEFTPADDING", (1, 0), (1, -1), 0), - ("RIGHTPADDING", (1, 0), (1, -1), 0), - ("TOPPADDING", (0, 0), (-1, -1), 0), - ("BOTTOMPADDING", (0, 0), (-1, 0), 10), - ("BOTTOMPADDING", (0, 1), (-1, 1), 0), - ])) - story.append(metric_grid) - story.append(Spacer(1, 7)) - story.append(p("Measured on named hardware with signed or committed reports and rerunnable methods. Methodology variants remain separately labeled. No customer ROI, customer cost savings, or compliance certification is implied by these figures.", st["body_tiny"])) - story.append(Spacer(1, 17)) - - story.extend(section_heading("Procurement facts", st)) - facts = Table([[ - fact_block("Company", [ - ("Legal name", "Perseus Computing LLC"), - ("Business", "U.S. small business · technical access"), - ("UEI / CAGE", "PJS2LW7HAK35 / 22JC5"), - ("NAICS", "541715 · 541511 · 541512"), - ("SAM.gov", "Active — All Awards"), - ], PALE_BLUE, st), - fact_block("Security and deployment", [ - ("Boundary", "On-premises, air-gapped, private VPC, or controlled network"), - ("Readiness", "SPRS 110/110 · CMMC Level 2 final self-assessment, enclave scope"), - ("Software", "MIT license · published SBOM · NIST AI RMF-aligned architecture"), - ("Data posture", "No required cloud service, API key, or vendor runtime"), - ("Integration", "Partner-led where mission hardware or sensors are involved"), - ], PALE_GREEN, st), - ]], colWidths=[3.68 * inch, 3.68 * inch]) - facts.setStyle(TableStyle([ - ("VALIGN", (0, 0), (-1, -1), "TOP"), - ("LEFTPADDING", (0, 0), (0, 0), 0), - ("RIGHTPADDING", (0, 0), (0, 0), 7), - ("LEFTPADDING", (1, 0), (1, 0), 0), - ("RIGHTPADDING", (1, 0), (1, 0), 0), - ("TOPPADDING", (0, 0), (-1, -1), 0), - ("BOTTOMPADDING", (0, 0), (-1, -1), 0), - ])) - story.append(facts) - story.append(Spacer(1, 17)) - - display_label = { - "MASTER CAPABILITY STATEMENT": "Master", - "CYBER & NETWORKS": "Cyber & Networks", - "C3BM": "C3BM", - "ELECTRONIC SYSTEMS": "Electronic Systems", - }[profile["audience_label"]] - story.append(Spacer(1, 12)) - boundary = Table([[ - rich("DEPLOYMENT BOUNDARY
Run the context, memory, and evidence layers where the program keeps its working data. Air-gapped, on-premises, private VPC, and controlled-network deployment are supported postures.", st["body_tiny"]), - rich("CONTACT
perseus@perseus.observer", st["body_tiny"]), - ]], colWidths=[4.72 * inch, 2.63 * inch]) - boundary.setStyle(TableStyle([ - ("BACKGROUND", (0, 0), (0, 0), PALE_BLUE), - ("BACKGROUND", (1, 0), (1, 0), PALE_GREEN), - ("BOX", (0, 0), (-1, -1), 0.5, RULE), - ("INNERGRID", (0, 0), (-1, -1), 0.35, RULE), - ("VALIGN", (0, 0), (-1, -1), "TOP"), - ("LEFTPADDING", (0, 0), (-1, -1), 8), - ("RIGHTPADDING", (0, 0), (-1, -1), 8), - ("TOPPADDING", (0, 0), (-1, -1), 7), - ("BOTTOMPADDING", (0, 0), (-1, -1), 7), - ])) - story.append(boundary) - story.append(Spacer(1, 5)) - story.append(rich(f"Updated {escape(str(c['_meta']['updated']))} · {escape(display_label)} version · Source-linked public claims", st["footer"])) - + # Page 1: orientation and fit. + story += [header("Mission fit", st), Spacer(1, 14), markup("PERSEUS COMPUTING LLC", st["eyebrow"])] + headline = "Infrastructure for AI agents in controlled environments." if name == "master" else profile["headline"] + story += [markup(escape(headline), st["title"] if len(headline) < 60 else st["title_compact"]), plain(profile["lead"], st["lead"]), Spacer(1, 12), info_band(profile, st), Spacer(1, 13)] + story += rule_section("The useful difference", st) + story += [two_column_copy("The problem", profile["problem"], "The layer", profile["change"], st), Spacer(1, 12)] + story += rule_section("What Perseus provides", st) + [system_table(st), Spacer(1, 12)] + story += rule_section("Where it fits", st) + [fit_table(profile, st), Spacer(1, 8)] + call = Table([[markup(f"FIRST CONVERSATION   {escape(profile['discussion'])}", st["callout"])]], colWidths=[7.35*inch]) + call.setStyle(TableStyle([("BACKGROUND", (0, 0), (-1, -1), NAVY), ("LEFTPADDING", (0, 0), (-1, -1), 10), ("RIGHTPADDING", (0, 0), (-1, -1), 10), ("TOPPADDING", (0, 0), (-1, -1), 9), ("BOTTOMPADDING", (0, 0), (-1, -1), 9)])) + story.append(call) + + # Page 2: evidence and procurement without unequal boxes. + story += [PageBreak(), header("Evidence and procurement", st), Spacer(1, 14), markup("EVIDENCE AND PROCUREMENT", st["eyebrow"]), markup("Proof with the condition attached.", st["title_compact"]), plain("The figures below are kept separate by measurement family so a reviewer can see what each result does—and does not—establish.", st["lead"]), Spacer(1, 16)] + story += rule_section("Measured evidence", st) + [evidence_table(claims, st), Spacer(1, 7), plain("Measured on named hardware with signed or committed reports and rerunnable methods. No customer ROI, customer cost savings, or compliance certification is implied by these figures.", st["body_tiny"]), Spacer(1, 18)] + story += rule_section("Procurement and deployment", st) + left = flat_fact_table("Company", [("Legal name", "Perseus Computing LLC"), ("Business", "U.S. small business · technical access"), ("UEI / CAGE", "PJS2LW7HAK35 / 22JC5"), ("NAICS", "541715 · 541511 · 541512"), ("SAM.gov", "Active — All Awards")], st) + right = flat_fact_table("Security and boundary", [("Deployment", "On-premises, air-gapped, private VPC, or controlled network"), ("Readiness", "SPRS 110/110 · CMMC Level 2 self-assessment, enclave scope"), ("Software", "MIT license · published SBOM"), ("Data posture", "No required cloud service, API key, or vendor runtime"), ("Integration", "Partner-led where mission hardware or sensors are involved")], st) + facts = Table([[left, right]], colWidths=[3.68*inch, 3.67*inch]) + facts.setStyle(TableStyle([("VALIGN", (0, 0), (-1, -1), "TOP"), ("LINEBEFORE", (1, 0), (1, 0), .7, RULE), ("LEFTPADDING", (0, 0), (0, 0), 0), ("RIGHTPADDING", (0, 0), (0, 0), 14), ("LEFTPADDING", (1, 0), (1, 0), 14), ("RIGHTPADDING", (1, 0), (1, 0), 0), ("TOPPADDING", (0, 0), (-1, -1), 0), ("BOTTOMPADDING", (0, 0), (-1, -1), 0)])) + story += [facts, Spacer(1, 17)] + story += rule_section("Scope in one sentence", st) + story += [plain("Perseus is the infrastructure around the model: context before action, governed memory across sessions, and evidence after action. It is not a claim to replace a mission platform, prime integrator, or sensor system.", st["body"]), Spacer(1, 14)] + contact = Table([[markup("CONTACT   perseus@perseus.observer · perseus.observer", st["body_small"]), markup("UPDATED   " + escape(str(claims["_meta"]["updated"])), st["body_small"])]], colWidths=[5.75*inch, 1.60*inch]) + contact.setStyle(TableStyle([("BACKGROUND", (0, 0), (-1, -1), PALE_BLUE), ("LINEABOVE", (0, 0), (-1, 0), .55, RULE), ("LINEBELOW", (0, 0), (-1, 0), .55, RULE), ("VALIGN", (0, 0), (-1, -1), "MIDDLE"), ("LEFTPADDING", (0, 0), (-1, -1), 9), ("RIGHTPADDING", (0, 0), (-1, -1), 9), ("TOPPADDING", (0, 0), (-1, -1), 8), ("BOTTOMPADDING", (0, 0), (-1, -1), 8)])) + story.append(contact) doc.build(story) - print(f"wrote {output}") - return output + return path def main() -> None: parser = argparse.ArgumentParser() - parser.add_argument("--profile", choices=["master", "cyber-networks", "c3bm", "electronic-systems"], default="master") - parser.add_argument("--all", action="store_true", help="build the master and all tailored variants") + parser.add_argument("--all", action="store_true") + parser.add_argument("--profile", default="master") args = parser.parse_args() registry = json.loads((ROOT / "claims.json").read_text(encoding="utf-8")) profiles = json.loads(PROFILES.read_text(encoding="utf-8")) - selected = list(profiles) if args.all else [args.profile] - for name in selected: - build(name, profiles[name], registry["claims"] | {"_meta": registry["_meta"]}) + names = list(profiles) if args.all else [args.profile] + for name in names: + print(build(name, profiles[name], registry["claims"] | {"_meta": registry["_meta"]})) if __name__ == "__main__":