\--- title: "Core Agent AI Pattern — Question‑Free Edition" description: "Refined, shareable Markdown optimized for collaborative editing and Mermaid diagrams." date: 2025-09-23 mermaid: true toc: true --- # \*\*Core Agent Patterns for the Enterprise\*\* ## Table of Contents - \[\*\*Core Agent Patterns for the Enterprise\*\*\](#core-agent-patterns-for-the-enterprise) - \[\*\*Pattern 1 — Read Once, Domain Everywhere (RODE)\*\*\](#pattern-1-read-once-domain-everywhere-rode) - \[\*\*Context\*\*\](#context) - \[\*\*Pattern Principle\*\*\](#pattern-principle) - \[\*\*Lifecycle Example (Real Estate Investor)\*\*\](#lifecycle-example-real-estate-investor) - \[\*\*Sequence Diagram (Real Estate Example)\*\*\](#sequence-diagram-real-estate-example) - \[\*\*Example Domain Documents\*\*\](#example-domain-documents) - \[\*\*Pseudocode (Conceptual)\*\*\](#pseudocode-conceptual) - \[emit DomainAssociated(property, tax\\\_doc)\](#emit-domainassociatedproperty-tax\_doc) - \[\*\*Why It Works for the Investor\*\*\](#why-it-works-for-the-investor) - \[\*\*You said:\*\*\](#you-said) - \[\*\*ChatGPT said:\*\*\](#chatgpt-said) - \[\*\*Core Agent Patterns for the Enterprise (CAPE)\*\*\](#core-agent-patterns-for-the-enterprise-cape) - \[\*\*Pattern: Domain Projection Activator (DPA)\*\*\](#pattern-domain-projection-activator-dpa) - \[\*(formerly “Read Once, Domain Everywhere”)\*\](#formerly-read-once-domain-everywhere) - \[\*\*Also Known As\*\*\](#also-known-as) - \[\*\*Intent\*\*\](#intent) - \[Transform a newly uploaded document into multiple domain documents (finance, legal, property ops, compliance, etc.) without re-reading it across pipelines. Do this by activating domain agents via events, so each agent projects the same source document into its own domain structure and relationships.\](#transform-a-newly-uploaded-document-into-multiple-domain-documents-finance-legal-property-ops-compliance-etc-without-re-reading-it-across-pipelines-do-this-by-activating-domain-agents-via-events-so-each-agent-projects-the-same-source-document-into-its-own-domain-structure-and-relationships) - \[\*\*Motivation (Real Estate Investor)\*\*\](#motivation-real-estate-investor) - \[With DPA, each document is read once, classified once, and then multiple domain agents generate domain documents and associations—traceable back to the single source.\](#with-dpa-each-document-is-read-once-classified-once-and-then-multiple-domain-agents-generate-domain-documents-and-associationstraceable-back-to-the-single-source) - \[\*\*Applicability\*\*\](#applicability) - \[\*\*Structure\*\*\](#structure) - \[\*\*Participants\*\*\](#participants) - \[\*\*Structure Diagram (text)\*\*\](#structure-diagram-text) - \[\*\*Collaboration (Real Estate Example)\*\*\](#collaboration-real-estate-example) - \[\*\*Consequences\*\*\](#consequences) - \[\*\*Known Uses (by analogy)\*\*\](#known-uses-by-analogy) - \[\*\*Sample Pseudocode (Conceptual, no libraries)\*\*\](#sample-pseudocode-conceptual-no-libraries) - \[// Core events (verbs about documents and domain docs) Event DocumentUploaded { doc\\\_id, name, kind\\\_hint } Event DocumentClassified { doc\\\_id, doc\\\_type, attributes } // e.g., property, year, amounts Event DomainStructured { domain\\\_doc\\\_id, domain\\\_type, source\\\_doc\\\_id, fields } Event DomainAssociated { subject\\\_id, relation, object\\\_id } // Ingest & Classify on DocumentUploaded(doc): classification \\= classify\\\_document(doc) // e.g., "tax\\\_bill", "lease" emit DocumentClassified(doc\\\_id=doc.id, doc\\\_type=classification.type, attributes=classification.attributes) // Tax Agent on DocumentClassified e when e.doc\\\_type \\== "tax\\\_bill": fields \\= extract\\\_tax\\\_obligation(e.doc\\\_id, e.attributes) tax\\\_doc \\= create\\\_domain\\\_document("TaxObligation", fields, source=e.doc\\\_id) emit DomainStructured(domain\\\_doc\\\_id=tax\\\_doc.id, domain\\\_type="TaxObligation", source\\\_doc\\\_id=e.doc\\\_id, fields=fields) // Property Agent on DomainStructured s when s.domain\\\_type in \\\["TaxObligation","UtilityExpense","LoanStatement"\\\]: property\\\_id \\= s.fields.property\\\_id update\\\_property\\\_profile(property\\\_id, s.domain\\\_type, s.fields) emit DomainAssociated(subject\\\_id=property\\\_id, relation="has\\\_domain\\\_doc", object\\\_id=s.domain\\\_doc\\\_id) // Cashflow Agent on DomainStructured s when s.domain\\\_type in \\\["TaxObligation","RentSchedule","LoanStatement","UtilityExpense"\\\]: window \\= planning\\\_horizon() forecast \\= recompute\\\_cashflow(window) cash\\\_doc \\= create\\\_domain\\\_document("CashflowForecast", forecast, source\\\_ids=collect\\\_recent\\\_domain\\\_docs(window)) emit DomainStructured(domain\\\_doc\\\_id=cash\\\_doc.id, domain\\\_type="CashflowForecast", source\\\_doc\\\_id="composite", fields=forecast)\](#core-events-verbs-about-documents-and-domain-docs-event-documentuploaded-doc\_id-name-kind\_hint-event-documentclassified-doc\_id-doc\_type-attributes-eg-property-year-amounts-event-domainstructured-domain\_doc\_id-domain\_type-source\_doc\_id-fields-event-domainassociated-subject\_id-relation-object\_id-ingest-classify-on-documentuploadeddoc-classification-classify\_documentdoc-eg-tax\_bill-lease-emit-documentclassifieddoc\_iddocid-doc\_typeclassificationtype-attributesclassificationattributes-tax-agent-on-documentclassified-e-when-edoc\_type-tax\_bill-fields-extract\_tax\_obligationedoc\_id-eattributes-tax\_doc-create\_domain\_documenttaxobligation-fields-sourceedoc\_id-emit-domainstructureddomain\_doc\_idtax\_docid-domain\_typetaxobligation-source\_doc\_idedoc\_id-fieldsfields-property-agent-on-domainstructured-s-when-sdomain\_type-in-taxobligationutilityexpenseloanstatement-property\_id-sfieldsproperty\_id-update\_property\_profileproperty\_id-sdomain\_type-sfields-emit-domainassociatedsubject\_idproperty\_id-relationhas\_domain\_doc-object\_idsdomain\_doc\_id-cashflow-agent-on-domainstructured-s-when-sdomain\_type-in-taxobligationrentscheduleloanstatementutilityexpense-window-planning\_horizon-forecast-recompute\_cashflowwindow-cash\_doc-create\_domain\_documentcashflowforecast-forecast-source\_idscollect\_recent\_domain\_docswindow-emit-domainstructureddomain\_doc\_idcash\_docid-domain\_typecashflowforecast-source\_doc\_idcomposite-fieldsforecast) - \[\*\*Example Domain Documents (Schemas by Words)\*\*\](#example-domain-documents-schemas-by-words) - \[Each domain document references the source document (and optionally exact pages/sections) for accountability.\](#each-domain-document-references-the-source-document-and-optionally-exact-pagessections-for-accountability) - \[\*\*Dynamics (Sequence Diagram)\*\*\](#dynamics-sequence-diagram) - \[\*\*Implementation Notes (Non-technical, business-first)\*\*\](#implementation-notes-non-technical-business-first) - \[\*\*Sample Variations\*\*\](#sample-variations) - \[\*\*Related Patterns\*\*\](#related-patterns) - \[\*\*Forces (Trade-offs)\*\*\](#forces-trade-offs) - \[\*\*Resulting Context (What you get)\*\*\](#resulting-context-what-you-get) - \[\*\*You said:\*\*\](#you-said) - \[\*\*ChatGPT said:\*\*\](#chatgpt-said) - \[We’ll give it a business-friendly name that implies a living, narrative file rather than just a data dump.\](#well-give-it-a-business-friendly-name-that-implies-a-living-narrative-file-rather-than-just-a-data-dump) - \[\*\*Extension to Domain Projection Activator (DPA)\*\*\](#extension-to-domain-projection-activator-dpa) - \[\*\*Artifact: Domain Narrative\*\*\](#artifact-domain-narrative) - \[\*\*Also Known As\*\*\](#also-known-as) - \[(“Domain Narrative” is the preferred name—it conveys structured facts plus descriptive story-like context.)\](#domain-narrative-is-the-preferred-nameit-conveys-structured-facts-plus-descriptive-story-like-context) - \[\*\*Intent\*\*\](#intent) - \[\*\*Motivation (Real Estate Example)\*\*\](#motivation-real-estate-example) - \[This becomes the “front page” for the property, where both humans and AI start.\](#this-becomes-the-front-page-for-the-property-where-both-humans-and-ai-start) - \[\*\*Structure\*\*\](#structure) - \[\*\*Participants\*\*\](#participants) - \[\*\*Diagram\*\*\](#diagram) - \[\*\*Collaboration\*\*\](#collaboration) - \[\*\*Consequences\*\*\](#consequences) - \[\*\*Example Domain Narrative (Markdown for 123 Main St)\*\*\](#example-domain-narrative-markdown-for-123-main-st) - \[\\# Property Narrative: 123 Main Street \*\*\\\*\\\*Last Updated\\\*\\\*\*\*: Sept 22, 2025 \*\*\\\*\\\*Source Docs\\\*\\\*\*\*: 14 (Leases: 2, Tax Bills: 3, Utilities: 6, Loan Statements: 3\\) \\--- \\#\\# Financial Summary \\- \*\*\\\*\\\*Next Tax Payment\\\*\\\*\*\*: $2,500 due Apr 15, 2026 \\- \*\*\\\*\\\*Outstanding Loan\\\*\\\*\*\*: $450,000 @ 5.2%, next installment $2,300 due Oct 1, 2025 \\- \*\*\\\*\\\*Monthly Rent Income\\\*\\\*\*\*: $3,000 (2 tenants) \\- \*\*\\\*\\\*Net Cashflow (last 3 months)\\\*\\\*\*\*: \\+$4,500 \\--- \\#\\# Compliance & Permits \\- Occupancy Permit valid until Dec 2027 \\- Electrical Inspection required by Nov 2025 \\--- \\#\\# Analysis The property is currently \*\*\\\*\\\*cashflow positive\\\*\\\*\*\* with sufficient rent to cover taxes and loan obligations. Risks: \\- One tenant lease expires June 2026 (renewal required). \\- Tax escrow covers only 80% of upcoming liability. \\--- \\#\\# Linked Domain Documents \\- \\\[Tax Obligation 2025-123Main\\\](link) \\- \\\[Tenant Contract – Apt A, Jane Doe\\\](link) \\- \\\[Loan Statement – Acme Bank\\\](link)\](#property-narrative-123-main-street-last-updated-sept-22-2025-source-docs-14-leases-2-tax-bills-3-utilities-6-loan-statements-3-----financial-summary---next-tax-payment-2500-due-apr-15-2026---outstanding-loan-450000-52-next-installment-2300-due-oct-1-2025---monthly-rent-income-3000-2-tenants---net-cashflow-last-3-months-4500-----compliance-permits---occupancy-permit-valid-until-dec-2027---electrical-inspection-required-by-nov-2025-----analysis-the-property-is-currently-cashflow-positive-with-sufficient-rent-to-cover-taxes-and-loan-obligations-risks---one-tenant-lease-expires-june-2026-renewal-required---tax-escrow-covers-only-80-of-upcoming-liability-----linked-domain-documents---tax-obligation-2025-123mainlink---tenant-contract-apt-a-jane-doelink---loan-statement-acme-banklink) - \[\*\*Pseudocode (Conceptual)\*\*\](#pseudocode-conceptual) - \[on DomainDocsUpdated(property\\\_id): docs \\= collect\\\_all\\\_domain\\\_docs(property\\\_id) metadata \\= summarize\\\_metadata(docs) tables \\= render\\\_structured\\\_sections(docs) analysis \\= generate\\\_analysis\\\_text(docs) narrative \\= assemble\\\_markdown(metadata, tables, analysis) attach\\\_to\\\_property(property\\\_id, "DomainNarrative", narrative) emit DomainStructured(domain\\\_doc="DomainNarrative", source\\\_docs=docs)\](#on-domaindocsupdatedproperty\_id-docs-collect\_all\_domain\_docsproperty\_id-metadata-summarize\_metadatadocs-tables-render\_structured\_sectionsdocs-analysis-generate\_analysis\_textdocs-narrative-assemble\_markdownmetadata-tables-analysis-attach\_to\_propertyproperty\_id-domainnarrative-narrative-emit-domainstructureddomain\_docdomainnarrative-source\_docsdocs) - \[\*\*Resulting Context\*\*\](#resulting-context) - \[Every Property in the portfolio now has a Domain Narrative—a living, structured, AI-ready summary file that describes its current state, supported by traceable domain documents derived from uploaded source documents.\](#every-property-in-the-portfolio-now-has-a-domain-narrativea-living-structured-ai-ready-summary-file-that-describes-its-current-state-supported-by-traceable-domain-documents-derived-from-uploaded-source-documents) - \[👉 This makes the Domain Narrative the \*capstone artifact\* of the pattern. It’s analogous to a “Dossier”, but reframed as a Narrative—living, structured, analytical, and AI-first.\](#this-makes-the-domain-narrative-the-capstone-artifact-of-the-pattern-its-analogous-to-a-dossier-but-reframed-as-a-narrativeliving-structured-analytical-and-ai-first) - \[\*\*You said:\*\*\](#you-said) - \[\*\*ChatGPT said:\*\*\](#chatgpt-said) - \[If you want other names with the same weight but different nuance, here are some directions:\](#if-you-want-other-names-with-the-same-weight-but-different-nuance-here-are-some-directions) - \[\*\*Alternatives to Narrative\*\*\](#alternatives-to-narrative) - \[\*\*My short-list (domain-oriented, enterprise-friendly)\*\*\](#my-short-list-domain-oriented-enterprise-friendly) - \[\*\*You said:\*\*\](#you-said) - \[\*\*ChatGPT said:\*\*\](#chatgpt-said) - \[Perfect — let’s lock in “Narrative” as the capstone artifact. That gives you a clean, extensible concept: every top-level domain object can have its own Domain Narrative.\](#perfect-lets-lock-in-narrative-as-the-capstone-artifact-that-gives-you-a-clean-extensible-concept-every-top-level-domain-object-can-have-its-own-domain-narrative) - \[\*\*Core Agent Patterns for the Enterprise (CAPE)\*\*\](#core-agent-patterns-for-the-enterprise-cape) - \[\*\*Extension to Domain Projection Activator\*\*\](#extension-to-domain-projection-activator) - \[\*\*Artifact: Domain Narrative\*\*\](#artifact-domain-narrative) - \[\*\*Intent\*\*\](#intent) - \[\*\*Motivation (Real Estate Example)\*\*\](#motivation-real-estate-example) - \[\*\*Structure\*\*\](#structure) - \[\*\*Participants\*\*\](#participants) - \[\*\*Diagram\*\*\](#diagram) - \[\*\*Example Narrative (Markdown)\*\*\](#example-narrative-markdown) - \[\\# Property Narrative: 123 Main Street \*\*\\\*\\\*Last Updated\\\*\\\*\*\*: Sept 22, 2025 \*\*\\\*\\\*Source Documents\\\*\\\*\*\*: 14 (Leases: 2, Tax Bills: 3, Utilities: 6, Loan Statements: 3\\) \\--- \\#\\# Financial Overview \\- Next Tax Payment: \*\*\\\*\\\*$2,500 due Apr 15, 2026\\\*\\\*\*\* \\- Loan Balance: \*\*\\\*\\\*$450,000 @ 5.2%\\\*\\\*\*\*, next installment \*\*\\\*\\\*$2,300 due Oct 1, 2025\\\*\\\*\*\* \\- Monthly Rent Income: \*\*\\\*\\\*$3,000\\\*\\\*\*\* (2 tenants) \\- Net Cashflow (last 3 months): \*\*\\\*\\\*+$4,500\\\*\\\*\*\* \\--- \\#\\# Compliance & Permits \\- Occupancy Permit valid until Dec 2027 \\- Electrical Inspection required by Nov 2025 \\--- \\#\\# Narrative Analysis The property is currently \*\*\\\*\\\*cashflow positive\\\*\\\*\*\* with sufficient rent to cover taxes and loans. \\- Risk: Lease renewal required June 2026\\. \\- Risk: Tax escrow covers only 80% of upcoming liability. \\- Opportunity: Refinancing could reduce monthly outflows by \\~10%. \\--- \\#\\# Linked Documents \\- \\\[Tax Obligation: 2025 Tax Bill\\\](link) \\- \\\[Tenant Contract: Apt A – Jane Doe\\\](link) \\- \\\[Loan Statement: Acme Bank – Sept 2025\\\](link)\](#property-narrative-123-main-street-last-updated-sept-22-2025-source-documents-14-leases-2-tax-bills-3-utilities-6-loan-statements-3-----financial-overview---next-tax-payment-2500-due-apr-15-2026---loan-balance-450000-52-next-installment-2300-due-oct-1-2025---monthly-rent-income-3000-2-tenants---net-cashflow-last-3-months-4500-----compliance-permits---occupancy-permit-valid-until-dec-2027---electrical-inspection-required-by-nov-2025-----narrative-analysis-the-property-is-currently-cashflow-positive-with-sufficient-rent-to-cover-taxes-and-loans---risk-lease-renewal-required-june-2026---risk-tax-escrow-covers-only-80-of-upcoming-liability---opportunity-refinancing-could-reduce-monthly-outflows-by-10-----linked-documents---tax-obligation-2025-tax-billlink---tenant-contract-apt-a-jane-doelink---loan-statement-acme-bank-sept-2025link) - \[\*\*Collaboration Flow\*\*\](#collaboration-flow) - \[\*\*Consequences\*\*\](#consequences) - \[\*\*You said:\*\*\](#you-said) - \[\*\*ChatGPT said:\*\*\](#chatgpt-said) - \[Below is the full, J2EE-style pattern addendum you can drop into your CAPE book.\](#below-is-the-full-j2ee-style-pattern-addendum-you-can-drop-into-your-cape-book) - \[\*\*Core Agent Patterns for the Enterprise (CAPE)\*\*\](#core-agent-patterns-for-the-enterprise-cape) - \[\*\*Pattern: Domain Projection Activator (DPA) — Narrative Extensions\*\*\](#pattern-domain-projection-activator-dpa-narrative-extensions) - \[\*\*New Artifacts\*\*\](#new-artifacts) - \[\*\*Intent\*\*\](#intent) - \[Provide multi-view storytelling for each domain object and portfolio-level storytelling across many objects—both as structured markdown artifacts that are human-readable and AI-ready, with explicit criteria \\+ lineage baked in.\](#provide-multi-view-storytelling-for-each-domain-object-and-portfolio-level-storytelling-across-many-objectsboth-as-structured-markdown-artifacts-that-are-human-readable-and-ai-ready-with-explicit-criteria-lineage-baked-in) - \[\*\*Motivation (Real Estate)\*\*\](#motivation-real-estate) - \[\*\*Structure\*\*\](#structure) - \[\*\*Participants\*\*\](#participants) - \[\*\*Text Diagram — One Object, Many Perspectives\*\*\](#text-diagram-one-object-many-perspectives) - \[\*\*Text Diagram — Many Objects into a Collection\*\*\](#text-diagram-many-objects-into-a-collection) - \[\*\*Canonical Metadata (words)\*\*\](#canonical-metadata-words) - \[\*\*Criteria Examples (words)\*\*\](#criteria-examples-words) - \[\*\*Event Vocabulary (conceptual)\*\*\](#event-vocabulary-conceptual) - \[\*\*Pseudocode (conceptual only)\*\*\](#pseudocode-conceptual-only) - \[\*\*Build/Refresh a Perspective Narrative\*\*\](#buildrefresh-a-perspective-narrative) - \[\*\*Compose a Collection Narrative\*\*\](#compose-a-collection-narrative) - \[\*\*Fast Recompute (incremental)\*\*\](#fast-recompute-incremental) - \[on PerspectiveNarrativeUpdated(object\\\_id, perspective, n\\\_id): affected\\\_collections \\= find\\\_collections\\\_referencing(object\\\_id, perspective) for col in affected\\\_collections: if col.recompute\\\_policy \\== "on\\\_event": refresh\\\_collection(col.id)\](#on-perspectivenarrativeupdatedobject\_id-perspective-n\_id-affected\_collections-find\_collections\_referencingobject\_id-perspective-for-col-in-affected\_collections-if-colrecompute\_policy-on\_event-refresh\_collectioncolid) - \[\*\*Example: Perspective Narrative (Cashflow) — Markdown Skeleton\*\*\](#example-perspective-narrative-cashflow-markdown-skeleton) - \[\\# Property Narrative — Cashflow Perspective \*\*\\\*\\\*Property\\\*\\\*\*\*: 123 Main Street \*\*\\\*\\\*Perspective\\\*\\\*\*\*: cashflow \*\*\\\*\\\*As Of\\\*\\\*\*\*: 2025-09-22 \*\*\\\*\\\*Source Domain Docs\\\*\\\*\*\*: RentSchedule\\#RS-889, TaxObligation\\#TX-2025-123M, LoanSchedule\\#LN-ACME-77, Utilities\\#UT-SEP-2025 \\#\\# Summary \\- Monthly Rent: \*\*\\\*\\\*$3,000\\\*\\\*\*\* \\- Recurring Outflows: \*\*\\\*\\\*$2,550\\\*\\\*\*\* (Loan $2,300 \\+ Utilities $150 \\+ Misc $100) \\- Next Tax Due: \*\*\\\*\\\*$2,500\\\*\\\*\*\* on \*\*\\\*\\\*2026-04-15\\\*\\\*\*\* \\- Last 90d Net: \*\*\\\*\\\*+$4,500\\\*\\\*\*\* \\#\\# Upcoming 60 Days (Table) | Date | Item | Amount | Status | |------------|------------------|--------|----------| | 2025-10-01 | Loan Installment | 2,300 | due | | 2025-10-05 | Utilities | 150 | forecast | | 2025-10-10 | Rent Inflow | 3,000 | expected | \\#\\# Analysis Cashflow remains positive; buffer sufficient for the next tax cycle. Consider refinancing options to reduce interest burden. \\#\\# Links \\- RentSchedule\\#RS-889 \\- LoanSchedule\\#LN-ACME-77 \\- TaxObligation\\#TX-2025-123M\](#property-narrative-cashflow-perspective-property-123-main-street-perspective-cashflow-as-of-2025-09-22-source-domain-docs-rentschedulers-889-taxobligationtx-2025-123m-loanscheduleln-acme-77-utilitiesut-sep-2025-summary---monthly-rent-3000---recurring-outflows-2550-loan-2300-utilities-150-misc-100---next-tax-due-2500-on-2026-04-15---last-90d-net-4500-upcoming-60-days-table-date-item-amount-status--------------------------------------------------2025-10-01-loan-installment-2300-due-2025-10-05-utilities-150-forecast-2025-10-10-rent-inflow-3000-expected-analysis-cashflow-remains-positive-buffer-sufficient-for-the-next-tax-cycle-consider-refinancing-options-to-reduce-interest-burden-links---rentschedulers-889---loanscheduleln-acme-77---taxobligationtx-2025-123m) - \[\*\*Example: Collection Narrative — “CA Property Narrative 2025”\*\*\](#example-collection-narrative-ca-property-narrative-2025) - \[You can analogously save “East Coast Narrative 2025” with a different criteria and member list.\](#you-can-analogously-save-east-coast-narrative-2025-with-a-different-criteria-and-member-list) - \[\*\*Identity & Traceability (recommended)\*\*\](#identity-traceability-recommended) - \[\*\*Consequences\*\*\](#consequences) - \[\*\*Operational Notes\*\*\](#operational-notes) - \[\*\*Quick Start Checklist\*\*\](#quick-start-checklist) - \[\*\*You said:\*\*\](#you-said) - \[\*\*ChatGPT said:\*\*\](#chatgpt-said) - \[awesome—here are 10 domain examples with high-level domain models you can plug straight into the CAPE patterns (Domain Projection Activator \\+ Narratives). Each one names a clear top-level domain object, key relationships, core documents, and example Perspective/Collection Narratives.\](#awesomehere-are-10-domain-examples-with-high-level-domain-models-you-can-plug-straight-into-the-cape-patterns-domain-projection-activator-narratives-each-one-names-a-clear-top-level-domain-object-key-relationships-core-documents-and-example-perspectivecollection-narratives) - \[\*\*1\\) AI / IT Law & Policy\*\*\](#1-ai-it-law-policy) - \[Collection examples: “EU AI Act Readiness 2025”, “Vendor DPAs—Q4 Review”\](#collection-examples-eu-ai-act-readiness-2025-vendor-dpasq4-review) - \[\*\*2\\) Cooking / Recipe Operations\*\*\](#2-cooking-recipe-operations) - \[Collections: “Weeknight Dinners—October,” “Holiday Menu 2025”\](#collections-weeknight-dinnersoctober-holiday-menu-2025) - \[\*\*3\\) Wine Cellar & Tasting\*\*\](#3-wine-cellar-tasting) - \[Collections: “California Pinot 2020–2022,” “Ready-to-Drink Q1 2026”\](#collections-california-pinot-20202022-ready-to-drink-q1-2026) - \[\*\*4\\) Clinical Trials\*\*\](#4-clinical-trials) - \[Collections: “Phase II Oncology—US Sites,” “Enrollment Health—Q3 2025”\](#collections-phase-ii-oncologyus-sites-enrollment-healthq3-2025) - \[\*\*5\\) Shipping (Parcel / Order Fulfillment)\*\*\](#5-shipping-parcel-order-fulfillment) - \[Collections: “Holiday Peak 2025—OTD,” “International Shipments—Duties”\](#collections-holiday-peak-2025otd-international-shipmentsduties) - \[\*\*6\\) Logistics (Supply Chain Flow)\*\*\](#6-logistics-supply-chain-flow) - \[Collections: “Asia→West Coast—Lead Times,” “Reefer Loads—Loss Analysis”\](#collections-asiawest-coastlead-times-reefer-loadsloss-analysis) - \[\*\*7\\) Home Renovations\*\*\](#7-home-renovations) - \[Collections: “Kitchen Projects 2025,” “Open Permits—City of SF”\](#collections-kitchen-projects-2025-open-permitscity-of-sf) - \[\*\*8\\) Fantasy Football\*\*\](#8-fantasy-football) - \[Collections: “Week 6 League Outlook,” “Playoff Odds—Weeks 10–14”\](#collections-week-6-league-outlook-playoff-oddsweeks-1014) - \[\*\*9\\) Education / Coursework\*\*\](#9-education-coursework) - \[Collections: “STEM Courses—Fall 2025,” “At-Risk Students Dashboard”\](#collections-stem-coursesfall-2025-at-risk-students-dashboard) - \[\*\*10\\) Personal Finance\*\*\](#10-personal-finance) - \[Collections: “Household Budget 2025,” “Debt Reduction Plan—H1 2026”\](#collections-household-budget-2025-debt-reduction-planh1-2026) - \[\*\*How these plug into CAPE\*\*\](#how-these-plug-into-cape) - \[\*\*You said:\*\*\](#you-said) - \[\*\*ChatGPT said:\*\*\](#chatgpt-said) - \[Each one: Domain Model (top object \\+ relationships), Core Documents, Perspective Narratives, Collection Narratives.\](#each-one-domain-model-top-object-relationships-core-documents-perspective-narratives-collection-narratives) - \[\*\*1\\. Domain: Individual Real Estate Residential Investor\*\*\](#1-domain-individual-real-estate-residential-investor) - \[\*\*Top Object: Property\*\*\](#top-object-property) - \[\*\*Core Documents\*\*\](#core-documents) - \[\*\*Perspective Narratives\*\*\](#perspective-narratives) - \[\*\*Collection Narratives\*\*\](#collection-narratives) - \[\*\*2\\. Domain: Software Product Management\*\*\](#2-domain-software-product-management) - \[\*\*Top Object: Product\*\*\](#top-object-product) - \[\*\*Core Documents\*\*\](#core-documents) - \[\*\*Perspective Narratives\*\*\](#perspective-narratives) - \[\*\*Collection Narratives\*\*\](#collection-narratives) - \[\*\*3\\. Domain: Enterprise Software Tech Due Diligence\*\*\](#3-domain-enterprise-software-tech-due-diligence) - \[\*\*Top Object: Target Company\*\*\](#top-object-target-company) - \[\*\*Core Documents\*\*\](#core-documents) - \[\*\*Perspective Narratives\*\*\](#perspective-narratives) - \[\*\*Collection Narratives\*\*\](#collection-narratives) - \[\*\*You said:\*\*\](#you-said) - \[\*\*ChatGPT said:\*\*\](#chatgpt-said) - \[absolutely—here are five pattern cards (J2EE-style) with user story flows added. No code; just crisp domain models, artifacts, narratives, and step-by-step flows you can hand to teams.\](#absolutelyhere-are-five-pattern-cards-j2ee-style-with-user-story-flows-added-no-code-just-crisp-domain-models-artifacts-narratives-and-step-by-step-flows-you-can-hand-to-teams) - \[\*\*1\\) Individual Real Estate Residential Investor\*\*\](#1-individual-real-estate-residential-investor) - \[\*\*Top Object: Property\*\*\](#top-object-property) - \[\*\*User Story Flows\*\*\](#user-story-flows) - \[\*\*2\\) Software Product Management\*\*\](#2-software-product-management) - \[\*\*Top Object: Product\*\*\](#top-object-product) - \[\*\*User Story Flows\*\*\](#user-story-flows) - \[\*\*3\\) Enterprise Software Tech Due Diligence\*\*\](#3-enterprise-software-tech-due-diligence) - \[\*\*Top Object: Target Company\*\*\](#top-object-target-company) - \[\*\*User Story Flows\*\*\](#user-story-flows) - \[\*\*4\\) Medical Preauthorization (Preauth)\*\*\](#4-medical-preauthorization-preauth) - \[\*\*Top Object: Case\*\*\](#top-object-case) - \[\*\*User Story Flows\*\*\](#user-story-flows) - \[\*\*5\\) Insurance Denial Appeal\*\*\](#5-insurance-denial-appeal) - \[\*\*Top Object: Appeal\*\*\](#top-object-appeal) - \[\*\*User Story Flows\*\*\](#user-story-flows) - \[\*\*Notes on Narratives & Collections (applies to all five)\*\*\](#notes-on-narratives-collections-applies-to-all-five) - \[\*\*You said:\*\*\](#you-said) - \[\*\*ChatGPT said:\*\*\](#chatgpt-said) - \[awesome—here’s a clean, plug-and-play Agents & Events addendum for all five domains. I’m using a consistent vocabulary so your platform wiring stays uniform.\](#awesomeheres-a-clean-plug-and-play-agents-events-addendum-for-all-five-domains-im-using-a-consistent-vocabulary-so-your-platform-wiring-stays-uniform) - \[\*\*Event Vocabulary (shared across domains)\*\*\](#event-vocabulary-shared-across-domains) - \[Living Docs Note (applies to all): \*Every\* Perspective Narrative and Collection Narrative is a living markdown artifact. It auto-updates (emits …Updated) whenever any listened-to DomainStructured or DomainAssociated event relevant to its scope occurs.\](#living-docs-note-applies-to-all-every-perspective-narrative-and-collection-narrative-is-a-living-markdown-artifact-it-auto-updates-emits-updated-whenever-any-listened-to-domainstructured-or-domainassociated-event-relevant-to-its-scope-occurs) - \[\*\*1\\) Individual Real Estate Residential Investor\*\*\](#1-individual-real-estate-residential-investor) - \[\*\*Agents (listen → emit)\*\*\](#agents-listen-emit) - \[\*\*2\\) Software Product Management\*\*\](#2-software-product-management) - \[\*\*Agents (listen → emit)\*\*\](#agents-listen-emit) - \[\*\*3\\) Enterprise Software Tech Due Diligence\*\*\](#3-enterprise-software-tech-due-diligence) - \[\*\*Agents (listen → emit)\*\*\](#agents-listen-emit) - \[\*\*4\\) Medical Preauthorization (Preauth)\*\*\](#4-medical-preauthorization-preauth) - \[\*\*Agents (listen → emit)\*\*\](#agents-listen-emit) - \[\*\*5\\) Insurance Denial Appeal\*\*\](#5-insurance-denial-appeal) - \[\*\*Agents (listen → emit)\*\*\](#agents-listen-emit) - \[\*\*Triggering & Refresh Rules (applies to all five)\*\*\](#triggering-refresh-rules-applies-to-all-five) - \[\*\*Quick wiring template (use anywhere)\*\*\](#quick-wiring-template-use-anywhere) - \[\*\*You said:\*\*\](#you-said) - \[\*\*ChatGPT said:\*\*\](#chatgpt-said) - \[Absolutely—let’s make the Classifier Agent explicit and first-class across the catalog. I’ll add a reusable spec \\+ drop-in wiring you can apply to every domain we defined.\](#absolutelylets-make-the-classifier-agent-explicit-and-first-class-across-the-catalog-ill-add-a-reusable-spec-drop-in-wiring-you-can-apply-to-every-domain-we-defined) - \[\*\*Core Agent Patterns for the Enterprise (CAPE)\*\*\](#core-agent-patterns-for-the-enterprise-cape) - \[\*\*Foundational Agent: Classifier (Domain-Aware Metadata Extractor)\*\*\](#foundational-agent-classifier-domain-aware-metadata-extractor) - \[\*\*Purpose\*\*\](#purpose) - \[\*\*Listens → Emits\*\*\](#listens-emits) - \[\*\*What it does (at a glance)\*\*\](#what-it-does-at-a-glance) - \[\*\*Minimal event contract (conceptual)\*\*\](#minimal-event-contract-conceptual) - \[\*\*Reusable sequence (all domains)\*\*\](#reusable-sequence-all-domains) - \[\*\*Domain-Specific Metadata Hints (what the Classifier should emit)\*\*\](#domain-specific-metadata-hints-what-the-classifier-should-emit) - \[\*\*1\\) Individual Real Estate Residential Investor\*\*\](#1-individual-real-estate-residential-investor) - \[\*\*2\\) Software Product Management\*\*\](#2-software-product-management) - \[\*\*3\\) Enterprise Software Tech Due Diligence\*\*\](#3-enterprise-software-tech-due-diligence) - \[\*\*4\\) Medical Preauthorization (Preauth)\*\*\](#4-medical-preauthorization-preauth) - \[\*\*5\\) Insurance Denial Appeal\*\*\](#5-insurance-denial-appeal) - \[\*\*Classifier Agent — Behavioral Pseudocode (drop-in)\*\*\](#classifier-agent-behavioral-pseudocode-drop-in) - \[\*\*Wiring this into each domain’s agent list (concise recap)\*\*\](#wiring-this-into-each-domains-agent-list-concise-recap) - \[\*\*Real Estate Investor (Property)\*\*\](#real-estate-investor-property) - \[\*\*Software Product Management (Product)\*\*\](#software-product-management-product) - \[\*\*Tech Due Diligence (Target Company)\*\*\](#tech-due-diligence-target-company) - \[\*\*Medical Preauth (Case)\*\*\](#medical-preauth-case) - \[\*\*Insurance Denial Appeal (Appeal)\*\*\](#insurance-denial-appeal-appeal) - \[\*\*“Living” Narrative Refresh Matrix (quick reference)\*\*\](#living-narrative-refresh-matrix-quick-reference) - \[In both cases, the Narrative Agent re-renders structured markdown and re-emits …Updated. No manual refresh needed.\](#in-both-cases-the-narrative-agent-re-renders-structured-markdown-and-re-emits-updated-no-manual-refresh-needed) - \[\*\*Acceptance Checklist (Classifier)\*\*\](#acceptance-checklist-classifier) - \[\*\*You said:\*\*\](#you-said) - \[\*\*ChatGPT said:\*\*\](#chatgpt-said) - \[Inside each agent’s handle() I’ve only put descriptive comments (per your request).\](#inside-each-agents-handle-ive-only-put-descriptive-comments-per-your-request) - \[\*/\\\* \\============================================================ CAPE Event Skeleton (TypeScript) — Generic \\+ 3 Domain Samples \\============================================================ \\\*/\* \*/\\\*\\\* \\---------- Core Event Types (generic, reusable) \\---------- \\\*/\* type UUID \\= string; type ISODateTime \\= string; \*/\\\*\\\* A normalized envelope all events travel in. \\\*/\* interface EventEnvelope\\<TPayload \\= unknown\\> { eid: UUID; etype: string; \*// e.g., "DocumentUploaded", "DomainStructured:TaxObligation"\* ts: ISODateTime; tenantId?: string; actor?: { name: string; version?: string }; parents?: UUID\\\[\\\]; opKey?: string; \*// idempotency key\* payload: TPayload; } \*/\\\*\\\* Shared “document seen” primitives across domains \\\*/\* interface DocumentUploaded { docId: UUID; filename: string; sourceUri?: string; hints?: Record\\<string, string\\>; } interface DocumentClassified { docId: UUID; domainHint: string; \*// e.g., "real\\\_estate", "product", "preauth"\* docType: string; \*// e.g., "tax\\\_bill", "prd"\* keyFields: Record\\<string, unknown\\>; routingKeys?: string\\\[\\\]; confidence: number; provenance?: Array\\<{ field: string; page?: number; section?: string }\\>; } \*/\\\*\\\* Generic “a domain document was created/updated” \\\*/\* interface DomainStructured\\<TDoc extends string \\= string, TBody \\= unknown\\> { docType: TDoc; \*// e.g., "TaxObligation"\* subjectId: UUID; \*// top-level domain object (Property, Product, Case)\* docId: UUID; \*// id of this domain doc\* body: TBody; \*// typed per docType in domain modules\* } \*/\\\*\\\* Domain relationships were created/updated \\\*/\* interface DomainAssociated { subjectId: UUID; \*// e.g., Property ID\* links: Array\\<{ rel: string; \*// e.g., "has\\\_domain\\\_doc", "derived\\\_from"\* toId: UUID; evidence?: unknown; }\\>; } \*/\\\*\\\* Narratives (perspective & collection) \\\*/\* interface PerspectiveNarrativeUpsert { narrativeId: UUID; objectId: UUID; \*// a Property, Product, Case, etc.\* perspective: string; \*// e.g., "cashflow", "roadmap", "policy\\\_match"\* asOf: ISODateTime; \*// living markdown\* markdown: string; \*// lineage/traceability\* sources: UUID\\\[\\\]; \*// domain doc ids used\* } interface CollectionNarrativeUpsert { collectionId: UUID; name: string; \*// e.g., "CA Property Narrative 2025"\* criteria: Record\\<string, unknown\\>;\*// structured filter\* asOf: ISODateTime; members: Array\\<{ objectId: UUID; perspective: string; narrativeId: UUID }\\>; markdown: string; aggregates?: Record\\<string, unknown\\>; } \*/\\\*\\\* Discriminated union of all event payloads in the platform \\\*/\* type DomainEvent \\= | { etype: "DocumentUploaded"; payload: DocumentUploaded } | { etype: "DocumentClassified"; payload: DocumentClassified } | { etype: \\\`DomainStructured:${string}\\\`; payload: DomainStructured } | { etype: "DomainAssociated"; payload: DomainAssociated } | { etype: "PerspectiveNarrativeCreated" | "PerspectiveNarrativeUpdated"; payload: PerspectiveNarrativeUpsert } | { etype: "CollectionNarrativeCreated" | "CollectionNarrativeUpdated"; payload: CollectionNarrativeUpsert }; \*/\\\*\\\* \\---------- Event Bus (portable interface) \\---------- \\\*/\* type EventHandler \\= (evt: EventEnvelope\\<any\\>) \\=\\> Promise\\<void\\> | void; interface EventBus { publish: (evt: EventEnvelope\\<any\\>) \\=\\> Promise\\<void\\>; subscribe: (etype: string | RegExp, handler: EventHandler) \\=\\> void; } \*/\\\*\\\* Simple in-memory bus for testing the concept \\\*/\* class InMemoryBus implements EventBus { private handlers: Array\\<{ match: string | RegExp; handler: EventHandler }\\> \\= \\\[\\\]; subscribe(etype: string | RegExp, handler: EventHandler) { this.handlers.push({ match: etype, handler }); } async publish(evt: EventEnvelope\\<any\\>) { for (const { match, handler } of this.handlers) { const isMatch \\= typeof match \\=== "string" ? match \\=== evt.etype : match.test(evt.etype); if (isMatch) await handler(evt); } } } \*/\\\*\\\* \\---------- Base Agent (generic listener/producer) \\---------- \\\*/\* abstract class BaseAgent\\<TListen extends string\\> { constructor( protected readonly bus: EventBus, protected readonly name: string, protected readonly version: string \\= "v1" ) {} \*/\\\*\\\* Each agent declares which event types it listens to \\\*/\* abstract listens(): Array\\<TListen | RegExp\\>; \*/\\\*\\\* Main handler — implement the \\\*business\\\* description inside \\\*/\* abstract handle(evt: EventEnvelope\\<any\\>): Promise\\<void\\>; \*/\\\*\\\* Wire the agent to the bus \\\*/\* register() { for (const et of this.listens()) { this.bus.subscribe(et, async (evt) \\=\\> { if (this.isDuplicate(evt)) return; \*// naive idempotency gate\* await this.handle(evt); }); } } \*/\\\*\\\* Utility: publish with uniform envelope \\\*/\* protected async emit\\<T \\= any\\>(etype: string, payload: T, parents?: UUID\\\[\\\], opKey?: string) { const env: EventEnvelope\\<T\\> \\= { eid: cryptoRandom(), etype, ts: new Date().toISOString(), actor: { name: this.name, version: this.version }, parents, opKey, payload }; await this.bus.publish(env); } \*/\\\*\\\* Idempotency: replace with a proper store-backed check in prod \\\*/\* private seenKeys \\= new Set\\<string\\>(); protected isDuplicate(evt: EventEnvelope\\<any\\>): boolean { const key \\= evt.opKey ?? \\\`${evt.etype}:${evt.eid}\\\`; if (this.seenKeys.has(key)) return true; this.seenKeys.add(key); return false; } } \*/\\\*\\\* Utility: not-cryptographically-secure id generator for demo \\\*/\* function cryptoRandom(): UUID { return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/\\\[xy\\\]/g, c \\=\\> { const r \\= (Math.random() \\\* 16) | 0, v \\= c \\=== "x" ? r : (r & 0x3 | 0x8); return v.toString(16); }); } \*/\\\* \\============================================================ Foundational Agents (shared) \\============================================================ \\\*/\* \*/\\\*\\\* Classifier Agent: DocumentUploaded \\-\\> DocumentClassified \\\*/\* class ClassifierAgent extends BaseAgent\\<"DocumentUploaded"\\> { listens() { return \\\["DocumentUploaded"\\\]; } async handle(evt: EventEnvelope\\<DocumentUploaded\\>) { \*// Describe: detect domain \\+ doc type \\+ extract key business fields.\* \*// \\- Determine docType (e.g., "tax\\\_bill", "prd", "provider\\\_note").\* \*// \\- Pull keyFields (addresses, dates, amounts, ids) with page/section provenance.\* \*// \\- Compute routingKeys (e.g., \\\`property:{id}\\\`, \\\`product:{name}\\\`).\* \*// \\- Emit DocumentClassified with confidence score; low confidence flagged elsewhere.\* const classified: DocumentClassified \\= { docId: evt.payload.docId, domainHint: "TBD-by-classifier", docType: "TBD-doc-type", keyFields: {}, routingKeys: \\\[\\\], confidence: 0.9, provenance: \\\[\\\] }; await this.emit("DocumentClassified", classified, \\\[evt.eid\\\], \\\`classify:${evt.payload.docId}:${this.version}\\\`); } } \*/\\\* \\============================================================ DOMAIN 1 — Individual Real Estate Residential Investor \\============================================================ \\\*/\* \*/\\\*\\\* Tax Agent: DocumentClassified(tax\\\_bill) \\-\\> DomainStructured:TaxObligation \\\*/\* class TaxAgent extends BaseAgent\\<"DocumentClassified"\\> { listens() { return \\\["DocumentClassified"\\\]; } async handle(evt: EventEnvelope\\<DocumentClassified\\>) { if (evt.payload.docType \\!== "tax\\\_bill") return; \*// Describe: read classification fields (property, year, amount, due date).\* \*// Build a TaxObligation domain doc linked to the Property.\* const body \\= { \*/\\\* propertyId, taxYear, amountDue, dueDate, jurisdiction \\\*/\* }; const domain: DomainStructured\\<"TaxObligation", typeof body\\> \\= { docType: "TaxObligation", subjectId: "PROPERTY-ID-TBD", docId: cryptoRandom(), body }; await this.emit("DomainStructured:TaxObligation", domain, \\\[evt.eid\\\], \\\`tax:${evt.payload.docId}:${this.version}\\\`); } } \*/\\\*\\\* Property Association Agent: link domain docs to Property \\\*/\* class PropertyAssocAgent extends BaseAgent\\<RegExp\\> { listens() { return \\\[/^DomainStructured:/\\\]; } async handle(evt: EventEnvelope\\<DomainStructured\\>) { \*// Describe: attach domain doc to its Property; add derived\\\_from/source links.\* const assoc: DomainAssociated \\= { subjectId: evt.payload.subjectId, links: \\\[{ rel: "has\\\_domain\\\_doc", toId: evt.payload.docId }\\\] }; await this.emit("DomainAssociated", assoc, \\\[evt.eid\\\], \\\`assoc:${evt.payload.docId}:${this.version}\\\`); } } \*/\\\*\\\* Cashflow Agent: recompute derived cashflow view \\\*/\* class CashflowAgent extends BaseAgent\\<RegExp\\> { listens() { return \\\[/^DomainStructured:(RentSchedule|UtilityExpense|TaxObligation|LoanSchedule)$/\\\]; } async handle(evt: EventEnvelope\\<DomainStructured\\>) { \*// Describe: aggregate inflows/outflows for the Property; produce CashflowLedger.\* const body \\= { \*/\\\* monthly inflow/outflow lines, forecast, risk signals \\\*/\* }; const domain: DomainStructured\\<"CashflowLedger", typeof body\\> \\= { docType: "CashflowLedger", subjectId: evt.payload.subjectId, docId: cryptoRandom(), body }; await this.emit("DomainStructured:CashflowLedger", domain, \\\[evt.eid\\\], \\\`cashflow:${evt.payload.subjectId}:${this.version}\\\`); } } \*/\\\*\\\* Property Perspective Narrative Builder (living) \\\*/\* class PropertyNarrativeAgent extends BaseAgent\\<RegExp\\> { listens() { return \\\[/^DomainStructured:/, /^DomainAssociated$/\\\]; } async handle(evt: EventEnvelope\\<any\\>) { \*// Describe: gather relevant domain docs for a Property;\* \*// render markdown for each perspective (cashflow, compliance, tenant, maintenance);\* \*// upsert each narrative and emit ...Updated.\* const upsert: PerspectiveNarrativeUpsert \\= { narrativeId: cryptoRandom(), objectId: "PROPERTY-ID-TBD", perspective: "cashflow", asOf: new Date().toISOString(), markdown: "\\# Property Narrative (Cashflow)\\\\n\\\\n- …", sources: \\\[\*/\\\* domain doc ids used \\\*/\*\\\] }; await this.emit("PerspectiveNarrativeUpdated", upsert, \\\[evt.eid\\\], \\\`nar:prop:${upsert.objectId}:${upsert.perspective}\\\`); } } \*/\\\*\\\* Portfolio Collection Narrative Composer (living) \\\*/\* class PortfolioCollectionAgent extends BaseAgent\\<"PerspectiveNarrativeUpdated"\\> { listens() { return \\\["PerspectiveNarrativeUpdated"\\\]; } async handle(evt: EventEnvelope\\<PerspectiveNarrativeUpsert\\>) { \*// Describe: if narrative matches criteria (e.g., state=CA, year=2025),\* \*// recompute aggregates and upsert a named collection narrative.\* const upsert: CollectionNarrativeUpsert \\= { collectionId: "COL-CA-2025-01", name: "CA Property Narrative 2025", criteria: { state: "CA", year: 2025, perspective: "cashflow" }, asOf: new Date().toISOString(), members: \\\[{ objectId: evt.payload.objectId, perspective: evt.payload.perspective, narrativeId: evt.payload.narrativeId }\\\], markdown: "\\# CA Property Narrative 2025\\\\n\\\\n- …", aggregates: { \*/\\\* totals, medians, risks \\\*/\* } }; await this.emit("CollectionNarrativeUpdated", upsert, \\\[evt.eid\\\], \\\`col:CA-2025:${this.version}\\\`); } } \*/\\\* \\============================================================ DOMAIN 2 — Software Product Management \\============================================================ \\\*/\* \*/\\\*\\\* Roadmap Agent: PRD/RFC/Release Note \\-\\> Initiative/Release docs \\\*/\* class RoadmapAgent extends BaseAgent\\<"DocumentClassified"\\> { listens() { return \\\["DocumentClassified"\\\]; } async handle(evt: EventEnvelope\\<DocumentClassified\\>) { if (\\!\\\["prd", "rfc", "release\\\_note"\\\].includes(evt.payload.docType)) return; \*// Describe: interpret PRD/RFC/Release linkage and create Initiative/Release domain docs.\* const domain: DomainStructured\\<"Initiative", any\\> \\= { docType: "Initiative", subjectId: "PRODUCT-ID-TBD", docId: cryptoRandom(), body: { \*/\\\* title, goals, dependencies, release window \\\*/\* } }; await this.emit("DomainStructured:Initiative", domain, \\\[evt.eid\\\], \\\`roadmap:${evt.payload.docId}:${this.version}\\\`); } } \*/\\\*\\\* Product Perspective Narrative (living: roadmap, adoption, quality, customer\\\_voice) \\\*/\* class ProductNarrativeAgent extends BaseAgent\\<RegExp\\> { listens() { return \\\[/^DomainStructured:(Initiative|Release|QualitySignal|AdoptionMetric|CustomerTheme|ProductRisk)$/\\\]; } async handle(evt: EventEnvelope\\<DomainStructured\\>) { \*// Describe: synthesize per-product perspective markdown (e.g., Roadmap status with risks & deps).\* const upsert: PerspectiveNarrativeUpsert \\= { narrativeId: cryptoRandom(), objectId: "PRODUCT-ID-TBD", perspective: "roadmap", asOf: new Date().toISOString(), markdown: "\\# Product Roadmap Narrative\\\\n\\\\n- …", sources: \\\[evt.payload.docId\\\] }; await this.emit("PerspectiveNarrativeUpdated", upsert, \\\[evt.eid\\\], \\\`nar:prod:${upsert.objectId}:${upsert.perspective}\\\`); } } \*/\\\* \\============================================================ DOMAIN 3 — Medical Preauthorization \\============================================================ \\\*/\* \*/\\\*\\\* Policy Match Agent: policy/order \\-\\> PolicyCriteriaChecklist \\\*/\* class PolicyMatchAgent extends BaseAgent\\<"DocumentClassified"\\> { listens() { return \\\["DocumentClassified"\\\]; } async handle(evt: EventEnvelope\\<DocumentClassified\\>) { const { docType } \\= evt.payload; if (\\!\\\["payer\\\_policy", "plan\\\_document", "guideline", "order\\\_form"\\\].includes(docType)) return; \*// Describe: map requested service (CPT/ICD) to policy criteria; produce checklist.\* const domain: DomainStructured\\<"PolicyCriteriaChecklist", any\\> \\= { docType: "PolicyCriteriaChecklist", subjectId: "CASE-ID-TBD", docId: cryptoRandom(), body: { \*/\\\* criteria items, required evidence, status per item \\\*/\* } }; await this.emit("DomainStructured:PolicyCriteriaChecklist", domain, \\\[evt.eid\\\], \\\`policy:${evt.payload.docId}:${this.version}\\\`); } } \*/\\\*\\\* Case Perspective Narrative (living: clinical\\\_evidence, policy\\\_match, request\\\_status, timeliness) \\\*/\* class CaseNarrativeAgent extends BaseAgent\\<RegExp\\> { listens() { return \\\[/^DomainStructured:(PolicyCriteriaChecklist|EvidenceSummary|PreauthRequestPacket|Determination|PreauthTimeline|P2PBrief)$/\\\]; } async handle(evt: EventEnvelope\\<DomainStructured\\>) { \*// Describe: compile a case-specific narrative (e.g., Policy Match) with checklists and missing items.\* const upsert: PerspectiveNarrativeUpsert \\= { narrativeId: cryptoRandom(), objectId: "CASE-ID-TBD", perspective: "policy\\\_match", asOf: new Date().toISOString(), markdown: "\\# Case Narrative — Policy Match\\\\n\\\\n- …", sources: \\\[evt.payload.docId\\\] }; await this.emit("PerspectiveNarrativeUpdated", upsert, \\\[evt.eid\\\], \\\`nar:case:${upsert.objectId}:${upsert.perspective}\\\`); } } \*/\\\* \\============================================================ Wiring & Demo Harness \\============================================================ \\\*/\* function wireAgents(bus: EventBus) { \*// Foundational\* new ClassifierAgent(bus, "classifier").register(); \*// Domain 1: Real Estate\* new TaxAgent(bus, "tax-agent").register(); new PropertyAssocAgent(bus, "property-assoc").register(); new CashflowAgent(bus, "cashflow").register(); new PropertyNarrativeAgent(bus, "property-narratives").register(); new PortfolioCollectionAgent(bus, "portfolio-collection").register(); \*// Domain 2: Product Management\* new RoadmapAgent(bus, "roadmap").register(); new ProductNarrativeAgent(bus, "product-narratives").register(); \*// Domain 3: Medical Preauth\* new PolicyMatchAgent(bus, "policy-match").register(); new CaseNarrativeAgent(bus, "case-narratives").register(); } \*// Example bootstrap\* const bus \\= new InMemoryBus(); wireAgents(bus); \*// Seed a fake document upload to see the pipeline shape:\* bus.publish({ eid: cryptoRandom(), etype: "DocumentUploaded", ts: new Date().toISOString(), payload: { docId: cryptoRandom(), filename: "example.pdf" } });\](#cape-event-skeleton-typescript-generic-3-domain-samples------------core-event-types-generic-reusable------------type-uuid-string-type-isodatetime-string-a-normalized-envelope-all-events-travel-in-interface-eventenvelopetpayload-unknown-eid-uuid-etype-string-eg-documentuploaded-domainstructuredtaxobligation-ts-isodatetime-tenantid-string-actor-name-string-version-string-parents-uuid-opkey-string-idempotency-key-payload-tpayload-shared-document-seen-primitives-across-domains-interface-documentuploaded-docid-uuid-filename-string-sourceuri-string-hints-recordstring-string-interface-documentclassified-docid-uuid-domainhint-string-eg-real\_estate-product-preauth-doctype-string-eg-tax\_bill-prd-keyfields-recordstring-unknown-routingkeys-string-confidence-number-provenance-array-field-string-page-number-section-string-generic-a-domain-document-was-createdupdated-interface-domainstructuredtdoc-extends-string-string-tbody-unknown-doctype-tdoc-eg-taxobligation-subjectid-uuid-top-level-domain-object-property-product-case-docid-uuid-id-of-this-domain-doc-body-tbody-typed-per-doctype-in-domain-modules-domain-relationships-were-createdupdated-interface-domainassociated-subjectid-uuid-eg-property-id-links-array-rel-string-eg-has\_domain\_doc-derived\_from-toid-uuid-evidence-unknown-narratives-perspective-collection-interface-perspectivenarrativeupsert-narrativeid-uuid-objectid-uuid-a-property-product-case-etc-perspective-string-eg-cashflow-roadmap-policy\_match-asof-isodatetime-living-markdown-markdown-string-lineagetraceability-sources-uuid-domain-doc-ids-used-interface-collectionnarrativeupsert-collectionid-uuid-name-string-eg-ca-property-narrative-2025-criteria-recordstring-unknown-structured-filter-asof-isodatetime-members-array-objectid-uuid-perspective-string-narrativeid-uuid-markdown-string-aggregates-recordstring-unknown-discriminated-union-of-all-event-payloads-in-the-platform-type-domainevent-etype-documentuploaded-payload-documentuploaded-etype-documentclassified-payload-documentclassified-etype-domainstructuredstring-payload-domainstructured-etype-domainassociated-payload-domainassociated-etype-perspectivenarrativecreated-perspectivenarrativeupdated-payload-perspectivenarrativeupsert-etype-collectionnarrativecreated-collectionnarrativeupdated-payload-collectionnarrativeupsert------------event-bus-portable-interface------------type-eventhandler-evt-eventenvelopeany-promisevoid-void-interface-eventbus-publish-evt-eventenvelopeany-promisevoid-subscribe-etype-string-regexp-handler-eventhandler-void-simple-in-memory-bus-for-testing-the-concept-class-inmemorybus-implements-eventbus-private-handlers-array-match-string-regexp-handler-eventhandler-subscribeetype-string-regexp-handler-eventhandler-thishandlerspush-match-etype-handler-async-publishevt-eventenvelopeany-for-const-match-handler-of-thishandlers-const-ismatch-typeof-match-string-match-evtetype-matchtestevtetype-if-ismatch-await-handlerevt------------base-agent-generic-listenerproducer------------abstract-class-baseagenttlisten-extends-string-constructor-protected-readonly-bus-eventbus-protected-readonly-name-string-protected-readonly-version-string-v1-each-agent-declares-which-event-types-it-listens-to-abstract-listens-arraytlisten-regexp-main-handler-implement-the-business-description-inside-abstract-handleevt-eventenvelopeany-promisevoid-wire-the-agent-to-the-bus-register-for-const-et-of-thislistens-thisbussubscribeet-async-evt-if-thisisduplicateevt-return-naive-idempotency-gate-await-thishandleevt-utility-publish-with-uniform-envelope-protected-async-emitt-anyetype-string-payload-t-parents-uuid-opkey-string-const-env-eventenvelopet-eid-cryptorandom-etype-ts-new-datetoisostring-actor-name-thisname-version-thisversion-parents-opkey-payload-await-thisbuspublishenv-idempotency-replace-with-a-proper-store-backed-check-in-prod-private-seenkeys-new-setstring-protected-isduplicateevt-eventenvelopeany-boolean-const-key-evtopkey-evtetypeevteid-if-thisseenkeyshaskey-return-true-thisseenkeysaddkey-return-false-utility-not-cryptographically-secure-id-generator-for-demo-function-cryptorandom-uuid-return-xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxxreplacexyg-c-const-r-mathrandom-16-0-v-c-x-r-r-0x3-0x8-return-vtostring16-foundational-agents-shared-classifier-agent-documentuploaded---documentclassified-class-classifieragent-extends-baseagentdocumentuploaded-listens-return-documentuploaded-async-handleevt-eventenvelopedocumentuploaded-describe-detect-domain-doc-type-extract-key-business-fields---determine-doctype-eg-tax\_bill-prd-provider\_note---pull-keyfields-addresses-dates-amounts-ids-with-pagesection-provenance---compute-routingkeys-eg-propertyid-productname---emit-documentclassified-with-confidence-score-low-confidence-flagged-elsewhere-const-classified-documentclassified-docid-evtpayloaddocid-domainhint-tbd-by-classifier-doctype-tbd-doc-type-keyfields-routingkeys-confidence-09-provenance-await-thisemitdocumentclassified-classified-evteid-classifyevtpayloaddocidthisversion-domain-1-individual-real-estate-residential-investor-tax-agent-documentclassifiedtax\_bill---domainstructuredtaxobligation-class-taxagent-extends-baseagentdocumentclassified-listens-return-documentclassified-async-handleevt-eventenvelopedocumentclassified-if-evtpayloaddoctype-tax\_bill-return-describe-read-classification-fields-property-year-amount-due-date-build-a-taxobligation-domain-doc-linked-to-the-property-const-body-propertyid-taxyear-amountdue-duedate-jurisdiction-const-domain-domainstructuredtaxobligation-typeof-body-doctype-taxobligation-subjectid-property-id-tbd-docid-cryptorandom-body-await-thisemitdomainstructuredtaxobligation-domain-evteid-taxevtpayloaddocidthisversion-property-association-agent-link-domain-docs-to-property-class-propertyassocagent-extends-baseagentregexp-listens-return-domainstructured-async-handleevt-eventenvelopedomainstructured-describe-attach-domain-doc-to-its-property-add-derived\_fromsource-links-const-assoc-domainassociated-subjectid-evtpayloadsubjectid-links-rel-has\_domain\_doc-toid-evtpayloaddocid-await-thisemitdomainassociated-assoc-evteid-assocevtpayloaddocidthisversion-cashflow-agent-recompute-derived-cashflow-view-class-cashflowagent-extends-baseagentregexp-listens-return-domainstructuredrentscheduleutilityexpensetaxobligationloanschedule-async-handleevt-eventenvelopedomainstructured-describe-aggregate-inflowsoutflows-for-the-property-produce-cashflowledger-const-body-monthly-inflowoutflow-lines-forecast-risk-signals-const-domain-domainstructuredcashflowledger-typeof-body-doctype-cashflowledger-subjectid-evtpayloadsubjectid-docid-cryptorandom-body-await-thisemitdomainstructuredcashflowledger-domain-evteid-cashflowevtpayloadsubjectidthisversion-property-perspective-narrative-builder-living-class-propertynarrativeagent-extends-baseagentregexp-listens-return-domainstructured-domainassociated-async-handleevt-eventenvelopeany-describe-gather-relevant-domain-docs-for-a-property-render-markdown-for-each-perspective-cashflow-compliance-tenant-maintenance-upsert-each-narrative-and-emit-updated-const-upsert-perspectivenarrativeupsert-narrativeid-cryptorandom-objectid-property-id-tbd-perspective-cashflow-asof-new-datetoisostring-markdown-property-narrative-cashflownn--sources-domain-doc-ids-used-await-thisemitperspectivenarrativeupdated-upsert-evteid-narpropupsertobjectidupsertperspective-portfolio-collection-narrative-composer-living-class-portfoliocollectionagent-extends-baseagentperspectivenarrativeupdated-listens-return-perspectivenarrativeupdated-async-handleevt-eventenvelopeperspectivenarrativeupsert-describe-if-narrative-matches-criteria-eg-stateca-year2025-recompute-aggregates-and-upsert-a-named-collection-narrative-const-upsert-collectionnarrativeupsert-collectionid-col-ca-2025-01-name-ca-property-narrative-2025-criteria-state-ca-year-2025-perspective-cashflow-asof-new-datetoisostring-members-objectid-evtpayloadobjectid-perspective-evtpayloadperspective-narrativeid-evtpayloadnarrativeid-markdown-ca-property-narrative-2025nn--aggregates-totals-medians-risks-await-thisemitcollectionnarrativeupdated-upsert-evteid-colca-2025thisversion-domain-2-software-product-management-roadmap-agent-prdrfcrelease-note---initiativerelease-docs-class-roadmapagent-extends-baseagentdocumentclassified-listens-return-documentclassified-async-handleevt-eventenvelopedocumentclassified-if-prd-rfc-release\_noteincludesevtpayloaddoctype-return-describe-interpret-prdrfcrelease-linkage-and-create-initiativerelease-domain-docs-const-domain-domainstructuredinitiative-any-doctype-initiative-subjectid-product-id-tbd-docid-cryptorandom-body-title-goals-dependencies-release-window-await-thisemitdomainstructuredinitiative-domain-evteid-roadmapevtpayloaddocidthisversion-product-perspective-narrative-living-roadmap-adoption-quality-customer\_voice-class-productnarrativeagent-extends-baseagentregexp-listens-return-domainstructuredinitiativereleasequalitysignaladoptionmetriccustomerthemeproductrisk-async-handleevt-eventenvelopedomainstructured-describe-synthesize-per-product-perspective-markdown-eg-roadmap-status-with-risks-deps-const-upsert-perspectivenarrativeupsert-narrativeid-cryptorandom-objectid-product-id-tbd-perspective-roadmap-asof-new-datetoisostring-markdown-product-roadmap-narrativenn--sources-evtpayloaddocid-await-thisemitperspectivenarrativeupdated-upsert-evteid-narprodupsertobjectidupsertperspective-domain-3-medical-preauthorization-policy-match-agent-policyorder---policycriteriachecklist-class-policymatchagent-extends-baseagentdocumentclassified-listens-return-documentclassified-async-handleevt-eventenvelopedocumentclassified-const-doctype-evtpayload-if-payer\_policy-plan\_document-guideline-order\_formincludesdoctype-return-describe-map-requested-service-cpticd-to-policy-criteria-produce-checklist-const-domain-domainstructuredpolicycriteriachecklist-any-doctype-policycriteriachecklist-subjectid-case-id-tbd-docid-cryptorandom-body-criteria-items-required-evidence-status-per-item-await-thisemitdomainstructuredpolicycriteriachecklist-domain-evteid-policyevtpayloaddocidthisversion-case-perspective-narrative-living-clinical\_evidence-policy\_match-request\_status-timeliness-class-casenarrativeagent-extends-baseagentregexp-listens-return-domainstructuredpolicycriteriachecklistevidencesummarypreauthrequestpacketdeterminationpreauthtimelinep2pbrief-async-handleevt-eventenvelopedomainstructured-describe-compile-a-case-specific-narrative-eg-policy-match-with-checklists-and-missing-items-const-upsert-perspectivenarrativeupsert-narrativeid-cryptorandom-objectid-case-id-tbd-perspective-policy\_match-asof-new-datetoisostring-markdown-case-narrative-policy-matchnn--sources-evtpayloaddocid-await-thisemitperspectivenarrativeupdated-upsert-evteid-narcaseupsertobjectidupsertperspective-wiring-demo-harness-function-wireagentsbus-eventbus-foundational-new-classifieragentbus-classifierregister-domain-1-real-estate-new-taxagentbus-tax-agentregister-new-propertyassocagentbus-property-assocregister-new-cashflowagentbus-cashflowregister-new-propertynarrativeagentbus-property-narrativesregister-new-portfoliocollectionagentbus-portfolio-collectionregister-domain-2-product-management-new-roadmapagentbus-roadmapregister-new-productnarrativeagentbus-product-narrativesregister-domain-3-medical-preauth-new-policymatchagentbus-policy-matchregister-new-casenarrativeagentbus-case-narrativesregister-example-bootstrap-const-bus-new-inmemorybus-wireagentsbus-seed-a-fake-document-upload-to-see-the-pipeline-shape-buspublish-eid-cryptorandom-etype-documentuploaded-ts-new-datetoisostring-payload-docid-cryptorandom-filename-examplepdf) - \[\*\*How to use this skeleton\*\*\](#how-to-use-this-skeleton) - \[\*\*You said:\*\*\](#you-said) - \[\*\*ChatGPT said:\*\*\](#chatgpt-said) - \[\*\*0\\) Storage Contracts\*\*\](#0-storage-contracts) - \[\*\*Postgres (metadata) — suggested tables (high-level)\*\*\](#postgres-metadata-suggested-tables-high-level) - \[\*\*Blob filesystem (markdown)\*\*\](#blob-filesystem-markdown) - \[\*\*1\\) Repository Interfaces (DI-friendly)\*\*\](#1-repository-interfaces-di-friendly) - \[\*/\\\*\\\* Postgres metadata repo \\\*/\* export interface MetadataRepo { \*// Idempotency\* tryClaimOpKey(opKey: string): Promise\\<boolean\\>; \*// Event log (optional)\* persistEvent(env: EventEnvelope\\<any\\>): Promise\\<void\\>; \*// Documents & classification\* upsertDocument(doc: { docId: UUID; filename: string; sourceUri?: string }): Promise\\<void\\>; upsertClassification(c: DocumentClassified & { classifierVersion: string }): Promise\\<void\\>; \*// Domain docs & links\* upsertDomainDoc(d: { domainDocId: UUID; subjectId: UUID; docType: string; body: any; sourceDocId?: UUID; }): Promise\\<void\\>; upsertLink(l: { subjectId: UUID; rel: string; toId: UUID; evidence?: any }): Promise\\<void\\>; \*// Narratives (index only)\* upsertPerspectiveNarrative(n: { narrativeId: UUID; objectId: UUID; perspective: string; asOf: ISODateTime; blobUri: string; sources: UUID\\\[\\\]; }): Promise\\<void\\>; upsertCollectionNarrative(n: { collectionId: UUID; name: string; asOf: ISODateTime; criteria: any; members: Array\\<{ objectId: UUID; perspective: string; narrativeId: UUID }\\>; blobUri: string; aggregates?: any; }): Promise\\<void\\>; } \*/\\\*\\\* Blob store for markdown artifacts \\\*/\* export interface BlobStore { putMarkdown(path: string, markdown: string): Promise\\<{ uri: string }\\>; } \*/\\\*\\\* Simple clock & ids for testability \\\*/\* export interface Clock { nowIso(): ISODateTime; } export interface Ids { newId(): UUID; }\](#postgres-metadata-repo-export-interface-metadatarepo-idempotency-tryclaimopkeyopkey-string-promiseboolean-event-log-optional-persisteventenv-eventenvelopeany-promisevoid-documents-classification-upsertdocumentdoc-docid-uuid-filename-string-sourceuri-string-promisevoid-upsertclassificationc-documentclassified-classifierversion-string-promisevoid-domain-docs-links-upsertdomaindocd-domaindocid-uuid-subjectid-uuid-doctype-string-body-any-sourcedocid-uuid-promisevoid-upsertlinkl-subjectid-uuid-rel-string-toid-uuid-evidence-any-promisevoid-narratives-index-only-upsertperspectivenarrativen-narrativeid-uuid-objectid-uuid-perspective-string-asof-isodatetime-bloburi-string-sources-uuid-promisevoid-upsertcollectionnarrativen-collectionid-uuid-name-string-asof-isodatetime-criteria-any-members-array-objectid-uuid-perspective-string-narrativeid-uuid-bloburi-string-aggregates-any-promisevoid-blob-store-for-markdown-artifacts-export-interface-blobstore-putmarkdownpath-string-markdown-string-promise-uri-string-simple-clock-ids-for-testability-export-interface-clock-nowiso-isodatetime-export-interface-ids-newid-uuid) - \[\*\*2\\) Event Bus & Base Agent (updated to use Postgres \\+ Blobs)\*\*\](#2-event-bus-base-agent-updated-to-use-postgres-blobs) - \[export abstract class BaseAgent\\<TListen extends string\\> { constructor( protected readonly bus: EventBus, protected readonly meta: MetadataRepo, protected readonly blobs: BlobStore, protected readonly ids: Ids, protected readonly clock: Clock, protected readonly name: string, protected readonly version: string \\= "v1" ) {} abstract listens(): Array\\<TListen | RegExp\\>; abstract handle(evt: EventEnvelope\\<any\\>): Promise\\<void\\>; register() { for (const et of this.listens()) { this.bus.subscribe(et, async (evt) \\=\\> { \*// Idempotency gate based on opKey\* const key \\= evt.opKey ?? \\\`${evt.etype}:${evt.eid}\\\`; const claimed \\= await this.meta.tryClaimOpKey(\\\`${this.name}:${key}\\\`); if (\\!claimed) return; await this.meta.persistEvent(evt); \*// optional\* await this.handle(evt); }); } } protected async emit\\<T \\= any\\>(etype: string, payload: T, parents?: UUID\\\[\\\], opKey?: string) { const env: EventEnvelope\\<T\\> \\= { eid: this.ids.newId(), etype, ts: this.clock.nowIso(), actor: { name: this.name, version: this.version }, parents, opKey, payload }; await this.meta.persistEvent(env); \*// optional\* await this.bus.publish(env); } }\](#export-abstract-class-baseagenttlisten-extends-string-constructor-protected-readonly-bus-eventbus-protected-readonly-meta-metadatarepo-protected-readonly-blobs-blobstore-protected-readonly-ids-ids-protected-readonly-clock-clock-protected-readonly-name-string-protected-readonly-version-string-v1-abstract-listens-arraytlisten-regexp-abstract-handleevt-eventenvelopeany-promisevoid-register-for-const-et-of-thislistens-thisbussubscribeet-async-evt-idempotency-gate-based-on-opkey-const-key-evtopkey-evtetypeevteid-const-claimed-await-thismetatryclaimopkeythisnamekey-if-claimed-return-await-thismetapersisteventevt-optional-await-thishandleevt-protected-async-emitt-anyetype-string-payload-t-parents-uuid-opkey-string-const-env-eventenvelopet-eid-thisidsnewid-etype-ts-thisclocknowiso-actor-name-thisname-version-thisversion-parents-opkey-payload-await-thismetapersisteventenv-optional-await-thisbuspublishenv) - \[\*\*3\\) Foundational Agent: Classifier\*\*\](#3-foundational-agent-classifier) - \[export class ClassifierAgent extends BaseAgent\\<"DocumentUploaded"\\> { listens() { return \\\["DocumentUploaded"\\\]; } async handle(evt: EventEnvelope\\<DocumentUploaded\\>) { \*// Upsert the document shell (metadata in Postgres)\* await this.meta.upsertDocument({ docId: evt.payload.docId, filename: evt.payload.filename, sourceUri: evt.payload.sourceUri }); \*// Describe: detect docType/domainHint; extract key\\\_fields \\+ provenance.\* const classified: DocumentClassified & { classifierVersion: string } \\= { docId: evt.payload.docId, domainHint: "TBD-by-classifier", docType: "TBD-doc-type", keyFields: {}, routingKeys: \\\[\\\], confidence: 0.9, provenance: \\\[\\\], classifierVersion: this.version }; \*// Persist classification in Postgres\* await this.meta.upsertClassification(classified); \*// Emit for downstream domain agents\* await this.emit( "DocumentClassified", { ...classified }, \\\[evt.eid\\\], \\\`classify:${evt.payload.docId}:${this.version}\\\` ); } }\](#export-class-classifieragent-extends-baseagentdocumentuploaded-listens-return-documentuploaded-async-handleevt-eventenvelopedocumentuploaded-upsert-the-document-shell-metadata-in-postgres-await-thismetaupsertdocument-docid-evtpayloaddocid-filename-evtpayloadfilename-sourceuri-evtpayloadsourceuri-describe-detect-doctypedomainhint-extract-key\_fields-provenance-const-classified-documentclassified-classifierversion-string-docid-evtpayloaddocid-domainhint-tbd-by-classifier-doctype-tbd-doc-type-keyfields-routingkeys-confidence-09-provenance-classifierversion-thisversion-persist-classification-in-postgres-await-thismetaupsertclassificationclassified-emit-for-downstream-domain-agents-await-thisemit-documentclassified-classified-evteid-classifyevtpayloaddocidthisversion) - \[\*\*4\\) Domain Examples (3 domains) — agents now persist to Postgres and write narratives to blobs\*\*\](#4-domain-examples-3-domains-agents-now-persist-to-postgres-and-write-narratives-to-blobs) - \[\*\*4.1 Real Estate — TaxAgent, PropertyAssocAgent, PropertyNarrativeAgent, CA Collection\*\*\](#41-real-estate-taxagent-propertyassocagent-propertynarrativeagent-ca-collection) - \[\*\*4.2 Software Product Management — RoadmapAgent, ProductNarrativeAgent\*\*\](#42-software-product-management-roadmapagent-productnarrativeagent) - \[\*\*4.3 Medical Preauthorization — PolicyMatchAgent, CaseNarrativeAgent\*\*\](#43-medical-preauthorization-policymatchagent-casenarrativeagent) - \[export class PolicyMatchAgent extends BaseAgent\\<"DocumentClassified"\\> { listens() { return \\\["DocumentClassified"\\\]; } async handle(evt: EventEnvelope\\<DocumentClassified\\>) { const { docType } \\= evt.payload; if (\\!\\\["payer\\\_policy", "plan\\\_document", "guideline", "order\\\_form"\\\].includes(docType)) return; const subjectId \\= \*/\\\* Case ID \\\*/\* this.ids.newId(); const domainDocId \\= this.ids.newId(); const body \\= { \*/\\\* criteria items, required evidence, met/unmet \\\*/\* }; await this.meta.upsertDomainDoc({ domainDocId, subjectId, docType: "PolicyCriteriaChecklist", body, sourceDocId: evt.payload.docId }); await this.emit("DomainStructured:PolicyCriteriaChecklist", { docType: "PolicyCriteriaChecklist", subjectId, docId: domainDocId, body }, \\\[evt.eid\\\], \\\`policy:${evt.payload.docId}:${this.version}\\\` ); } } export class CaseNarrativeAgent extends BaseAgent\\<RegExp\\> { listens() { return \\\[/^DomainStructured:(PolicyCriteriaChecklist|EvidenceSummary|PreauthRequestPacket|Determination|PreauthTimeline|P2PBrief)$/\\\]; } async handle(evt: EventEnvelope\\<DomainStructured\\>) { const objectId \\= evt.payload.subjectId; const perspective \\= "policy\\\_match"; const markdown \\= \\\`\\# Case Narrative — Policy Match\\\\n\\\\n- Placeholder for case ${objectId}\\\`; const narrativeId \\= this.ids.newId(); const path \\= \\\`narratives/case/${objectId}/${perspective}/${narrativeId}.md\\\`; const { uri } \\= await this.blobs.putMarkdown(path, markdown); await this.meta.upsertPerspectiveNarrative({ narrativeId, objectId, perspective, asOf: this.clock.nowIso(), blobUri: uri, sources: \\\[evt.payload.docId\\\] }); await this.emit("PerspectiveNarrativeUpdated", { narrativeId, objectId, perspective, asOf: this.clock.nowIso(), markdown, sources: \\\[evt.payload.docId\\\] }, \\\[evt.eid\\\], \\\`nar:case:${objectId}:${perspective}\\\` ); } }\](#export-class-policymatchagent-extends-baseagentdocumentclassified-listens-return-documentclassified-async-handleevt-eventenvelopedocumentclassified-const-doctype-evtpayload-if-payer\_policy-plan\_document-guideline-order\_formincludesdoctype-return-const-subjectid-case-id-thisidsnewid-const-domaindocid-thisidsnewid-const-body-criteria-items-required-evidence-metunmet-await-thismetaupsertdomaindoc-domaindocid-subjectid-doctype-policycriteriachecklist-body-sourcedocid-evtpayloaddocid-await-thisemitdomainstructuredpolicycriteriachecklist-doctype-policycriteriachecklist-subjectid-docid-domaindocid-body-evteid-policyevtpayloaddocidthisversion-export-class-casenarrativeagent-extends-baseagentregexp-listens-return-domainstructuredpolicycriteriachecklistevidencesummarypreauthrequestpacketdeterminationpreauthtimelinep2pbrief-async-handleevt-eventenvelopedomainstructured-const-objectid-evtpayloadsubjectid-const-perspective-policy\_match-const-markdown-case-narrative-policy-matchnn--placeholder-for-case-objectid-const-narrativeid-thisidsnewid-const-path-narrativescaseobjectidperspectivenarrativeidmd-const-uri-await-thisblobsputmarkdownpath-markdown-await-thismetaupsertperspectivenarrative-narrativeid-objectid-perspective-asof-thisclocknowiso-bloburi-uri-sources-evtpayloaddocid-await-thisemitperspectivenarrativeupdated-narrativeid-objectid-perspective-asof-thisclocknowiso-markdown-sources-evtpayloaddocid-evteid-narcaseobjectidperspective) - \[\*\*5\\) Bootstrapping with Concrete Storage Adapters (stubs)\*\*\](#5-bootstrapping-with-concrete-storage-adapters-stubs) - \[\*// Minimal in-memory adapters for concept testing.\* \*// Replace with real Postgres (pg/knex/Prisma) and real S3/Azure SDK adapters.\* class InMemoryMetadataRepo implements MetadataRepo { private ops \\= new Set\\<string\\>(); async tryClaimOpKey(opKey: string) { if (this.ops.has(opKey)) return false; this.ops.add(opKey); return true; } async persistEvent(\\\_: EventEnvelope\\<any\\>) { \*/\\\* store in memory or noop \\\*/\* } private docs \\= new Map\\<string, any\\>(); private cls \\= new Map\\<string, any\\>(); private dd \\= new Map\\<string, any\\>(); private links \\= new Map\\<string, any\\>(); private pn \\= new Map\\<string, any\\>(); private cn \\= new Map\\<string, any\\>(); async upsertDocument(d: any) { this.docs.set(d.docId, d); } async upsertClassification(c: any) { this.cls.set(c.docId, c); } async upsertDomainDoc(d: any) { this.dd.set(d.domainDocId, d); } async upsertLink(l: any) { this.links.set(\\\`${l.subjectId}|${l.rel}|${l.toId}\\\`, l); } async upsertPerspectiveNarrative(n: any) { this.pn.set(n.narrativeId, n); } async upsertCollectionNarrative(n: any) { this.cn.set(n.collectionId, n); } } class InMemoryBlobStore implements BlobStore { private store \\= new Map\\<string, string\\>(); async putMarkdown(path: string, markdown: string) { this.store.set(path, markdown); return { uri: \\\`mem://${path}\\\` }; } } class SystemClock implements Clock { nowIso() { return new Date().toISOString(); } } class SimpleIds implements Ids { newId() { return cryptoRandom(); } }\](#minimal-in-memory-adapters-for-concept-testing-replace-with-real-postgres-pgknexprisma-and-real-s3azure-sdk-adapters-class-inmemorymetadatarepo-implements-metadatarepo-private-ops-new-setstring-async-tryclaimopkeyopkey-string-if-thisopshasopkey-return-false-thisopsaddopkey-return-true-async-persistevent\_-eventenvelopeany-store-in-memory-or-noop-private-docs-new-mapstring-any-private-cls-new-mapstring-any-private-dd-new-mapstring-any-private-links-new-mapstring-any-private-pn-new-mapstring-any-private-cn-new-mapstring-any-async-upsertdocumentd-any-thisdocssetddocid-d-async-upsertclassificationc-any-thisclssetcdocid-c-async-upsertdomaindocd-any-thisddsetddomaindocid-d-async-upsertlinkl-any-thislinkssetlsubjectidlrelltoid-l-async-upsertperspectivenarrativen-any-thispnsetnnarrativeid-n-async-upsertcollectionnarrativen-any-thiscnsetncollectionid-n-class-inmemoryblobstore-implements-blobstore-private-store-new-mapstring-string-async-putmarkdownpath-string-markdown-string-thisstoresetpath-markdown-return-uri-mempath-class-systemclock-implements-clock-nowiso-return-new-datetoisostring-class-simpleids-implements-ids-newid-return-cryptorandom) - \[\*\*6\\) Wiring\*\*\](#6-wiring) - \[const bus \\= new InMemoryBus(); const meta \\= new InMemoryMetadataRepo(); \*// swap with Postgres adapter\* const blobs \\= new InMemoryBlobStore(); \*// swap with S3/Azure adapter\* const clock \\= new SystemClock(); const ids \\= new SimpleIds(); \*// Foundational\* new ClassifierAgent(bus, meta, blobs, ids, clock, "classifier").register(); \*// Real Estate\* new TaxAgent(bus, meta, blobs, ids, clock, "tax-agent").register(); new PropertyAssocAgent(bus, meta, blobs, ids, clock, "property-assoc").register(); new PropertyNarrativeAgent(bus, meta, blobs, ids, clock, "property-narratives").register(); new PortfolioCollectionAgent(bus, meta, blobs, ids, clock, "portfolio-collection").register(); \*// Product Mgmt\* new RoadmapAgent(bus, meta, blobs, ids, clock, "roadmap").register(); new ProductNarrativeAgent(bus, meta, blobs, ids, clock, "product-narratives").register(); \*// Preauth\* new PolicyMatchAgent(bus, meta, blobs, ids, clock, "policy-match").register(); new CaseNarrativeAgent(bus, meta, blobs, ids, clock, "case-narratives").register(); \*// Example seed\* bus.publish({ eid: ids.newId(), etype: "DocumentUploaded", ts: clock.nowIso(), payload: { docId: ids.newId(), filename: "sample.pdf" } });\](#const-bus-new-inmemorybus-const-meta-new-inmemorymetadatarepo-swap-with-postgres-adapter-const-blobs-new-inmemoryblobstore-swap-with-s3azure-adapter-const-clock-new-systemclock-const-ids-new-simpleids-foundational-new-classifieragentbus-meta-blobs-ids-clock-classifierregister-real-estate-new-taxagentbus-meta-blobs-ids-clock-tax-agentregister-new-propertyassocagentbus-meta-blobs-ids-clock-property-assocregister-new-propertynarrativeagentbus-meta-blobs-ids-clock-property-narrativesregister-new-portfoliocollectionagentbus-meta-blobs-ids-clock-portfolio-collectionregister-product-mgmt-new-roadmapagentbus-meta-blobs-ids-clock-roadmapregister-new-productnarrativeagentbus-meta-blobs-ids-clock-product-narrativesregister-preauth-new-policymatchagentbus-meta-blobs-ids-clock-policy-matchregister-new-casenarrativeagentbus-meta-blobs-ids-clock-case-narrativesregister-example-seed-buspublish-eid-idsnewid-etype-documentuploaded-ts-clocknowiso-payload-docid-idsnewid-filename-samplepdf) - \[\*\*Notes / Next steps\*\*\](#notes-next-steps) - \[\*\*You said:\*\*\](#you-said) - \[\*\*ChatGPT said:\*\*\](#chatgpt-said) - \[Per your storage rule: all metadata in Postgres, all markdown in blobs (S3/Azure). Below is a clean, opinionated blueprint with TypeScript skeletons.\](#per-your-storage-rule-all-metadata-in-postgres-all-markdown-in-blobs-s3azure-below-is-a-clean-opinionated-blueprint-with-typescript-skeletons) - \[\*\*Domain Repo — Concept\*\*\](#domain-repo-concept) - \[\*\*Authoring & Generation flow\*\*\](#authoring-generation-flow) - \[\*\*Postgres schema (metadata)\*\*\](#postgres-schema-metadata) - \[markdown bodies go to blobs; Postgres stores URIs \\+ linkage. you’ll also keep your existing tables for documents, document\\\_classifications, domain\\\_documents, domain\\\_links, and narratives.\](#markdown-bodies-go-to-blobs-postgres-stores-uris-linkage-youll-also-keep-your-existing-tables-for-documents-document\_classifications-domain\_documents-domain\_links-and-narratives) - \[\*\*Domain Repo interfaces (TypeScript)\*\*\](#domain-repo-interfaces-typescript) - \[export interface DomainRepo { \*// domains\* getDomainByKey(key: string): Promise\\<Domain\\>; listAgents(domainId: UUID, onlyActive?: boolean): Promise\\<AgentDefinition\\\[\\\]\\>; getDomainDesignNote(domainId: UUID, version?: string): Promise\\<DesignNoteIndex | null\\>; upsertAgentDesignNote(idx: AgentDesignNoteIndex): Promise\\<void\\>; } export type Domain \\= { domainId: UUID; key: string; name: string; topObject: string; }; export type AgentDefinition \\= { agentId: UUID; domainId: UUID; key: string; \*// 'tax-agent'\* kind: "classifier" | "structurer" | "association" | "narrative" | "collection"; listens: string\\\[\\\]; \*// normalized expressions (regex or DSL)\* emits: string\\\[\\\]; \*// event types (exact or templated)\* docTypes?: string\\\[\\\]; subjectType?: string; perspective?: string; collectionName?: string; config?: Record\\<string, any\\>; active: boolean; }; export type DesignNoteIndex \\= { domainId: UUID; version: string; blobUri: string }; export type AgentDesignNoteIndex \\= { agentId: UUID; version: string; blobUri: string; generatedFrom: string; };\](#export-interface-domainrepo-domains-getdomainbykeykey-string-promisedomain-listagentsdomainid-uuid-onlyactive-boolean-promiseagentdefinition-getdomaindesignnotedomainid-uuid-version-string-promisedesignnoteindex-null-upsertagentdesignnoteidx-agentdesignnoteindex-promisevoid-export-type-domain-domainid-uuid-key-string-name-string-topobject-string-export-type-agentdefinition-agentid-uuid-domainid-uuid-key-string-tax-agent-kind-classifier-structurer-association-narrative-collection-listens-string-normalized-expressions-regex-or-dsl-emits-string-event-types-exact-or-templated-doctypes-string-subjecttype-string-perspective-string-collectionname-string-config-recordstring-any-active-boolean-export-type-designnoteindex-domainid-uuid-version-string-bloburi-string-export-type-agentdesignnoteindex-agentid-uuid-version-string-bloburi-string-generatedfrom-string) - \[\*\*Design Note generation\*\*\](#design-note-generation) - \[\*\*Generator responsibilities\*\*\](#generator-responsibilities) - \[\*\*Generator skeleton\*\*\](#generator-skeleton) - \[export class DesignNoteGenerator { constructor( private readonly repo: DomainRepo, private readonly blobs: BlobStore, private readonly clock: Clock, private readonly ids: Ids ) {} async generateForDomain(domainKey: string, domainMetaVersion: string, generatorVersion \\= "gen-v1") { const domain \\= await this.repo.getDomainByKey(domainKey); const domainNote \\= await this.repo.getDomainDesignNote(domain.domainId, domainMetaVersion); if (\\!domainNote) throw new Error("No domain meta note found"); const metaMarkdown \\= await this.readBlob(domainNote.blobUri); \*// helper to fetch blob\* const agents \\= await this.repo.listAgents(domain.domainId, true); for (const a of agents) { const markdown \\= this.renderAgentDesignNote(metaMarkdown, domain, a); const path \\= \\\`design-notes/${domain.key}/${a.key}/${generatorVersion}.md\\\`; const { uri } \\= await this.blobs.putMarkdown(path, markdown); await this.repo.upsertAgentDesignNote({ agentId: a.agentId, version: generatorVersion, blobUri: uri, generatedFrom: domainMetaVersion }); } } private renderAgentDesignNote(meta: string, domain: Domain, agent: AgentDefinition): string { \*// Describe: parse meta note; extract relevant sections for agent.kind.\* \*// Merge with agent.config (field dicts, schema URIs, criteria).\* \*// Produce markdown with: Intent, Inputs (events), Outputs (events), Field rules,\* \*// Validation, Idempotency, Error handling, Observability, Examples.\* return \\\[ \\\`\\# Agent Design Note — ${domain.name} / ${agent.key}\\\`, \\\`\\\`, \\\`\\\*\\\*Kind\\\*\\\*: ${agent.kind} \\\*\\\*Domain\\\*\\\*: ${domain.key} \\\*\\\*Top Object\\\*\\\*: ${domain.topObject}\\\`, \\\`\\\*\\\*Listens\\\*\\\*: ${agent.listens.join(", ")}\\\`, \\\`\\\*\\\*Emits\\\*\\\*: ${agent.emits.join(", ")}\\\`, agent.perspective ? \\\`\\\*\\\*Perspective\\\*\\\*: ${agent.perspective}\\\` : \\\`\\\`, agent.collectionName ? \\\`\\\*\\\*Collection\\\*\\\*: ${agent.collectionName}\\\` : \\\`\\\`, \\\`\\\`, \\\`\\#\\# Intent\\\`, \\\`Describe what this agent does in business terms.\\\`, \\\`\\\`, \\\`\\#\\# Inputs (Events)\\\`, \\\`- ${agent.listens.join("\\\\n- ")}\\\`, \\\`\\\`, \\\`\\#\\# Outputs (Events)\\\`, \\\`- ${agent.emits.join("\\\\n- ")}\\\`, \\\`\\\`, \\\`\\#\\# Field Rules (from Domain Meta)\\\`, \\\`- Define required/optional fields per docType or schema.\\\`, \\\`\\\`, \\\`\\#\\# Narrative Structure (if narrative agent)\\\`, \\\`- Sections, tables, links, provenance requirements.\\\`, \\\`\\\`, \\\`\\#\\# Idempotency & Versioning\\\`, \\\`- opKey \\= H(inputs, version, scope).\\\`, \\\`\\\`, \\\`\\#\\# Quality Gates\\\`, \\\`- confidence thresholds, validation checks.\\\`, \\\`\\\`, \\\`\\#\\# Observability\\\`, \\\`- record latency, counts, cost\\\_units.\\\`, \\\`\\\`, \\\`\\#\\# Examples\\\`, \\\`- Before/After illustrations.\\\`, \\\`\\\`, \\\].filter(Boolean).join("\\\\n"); } private async readBlob(uri: string): Promise\\<string\\> { \*// Implement via S3/Azure SDK (download text)\* return \\\`\\# Domain Meta Note placeholder for ${uri}\\\`; } }\](#export-class-designnotegenerator-constructor-private-readonly-repo-domainrepo-private-readonly-blobs-blobstore-private-readonly-clock-clock-private-readonly-ids-ids-async-generatefordomaindomainkey-string-domainmetaversion-string-generatorversion-gen-v1-const-domain-await-thisrepogetdomainbykeydomainkey-const-domainnote-await-thisrepogetdomaindesignnotedomaindomainid-domainmetaversion-if-domainnote-throw-new-errorno-domain-meta-note-found-const-metamarkdown-await-thisreadblobdomainnotebloburi-helper-to-fetch-blob-const-agents-await-thisrepolistagentsdomaindomainid-true-for-const-a-of-agents-const-markdown-thisrenderagentdesignnotemetamarkdown-domain-a-const-path-design-notesdomainkeyakeygeneratorversionmd-const-uri-await-thisblobsputmarkdownpath-markdown-await-thisrepoupsertagentdesignnote-agentid-aagentid-version-generatorversion-bloburi-uri-generatedfrom-domainmetaversion-private-renderagentdesignnotemeta-string-domain-domain-agent-agentdefinition-string-describe-parse-meta-note-extract-relevant-sections-for-agentkind-merge-with-agentconfig-field-dicts-schema-uris-criteria-produce-markdown-with-intent-inputs-events-outputs-events-field-rules-validation-idempotency-error-handling-observability-examples-return-agent-design-note-domainname-agentkey-kind-agentkind-domain-domainkey-top-object-domaintopobject-listens-agentlistensjoin-emits-agentemitsjoin-agentperspective-perspective-agentperspective-agentcollectionname-collection-agentcollectionname-intent-describe-what-this-agent-does-in-business-terms-inputs-events---agentlistensjoinn--outputs-events---agentemitsjoinn--field-rules-from-domain-meta---define-requiredoptional-fields-per-doctype-or-schema-narrative-structure-if-narrative-agent---sections-tables-links-provenance-requirements-idempotency-versioning---opkey-hinputs-version-scope-quality-gates---confidence-thresholds-validation-checks-observability---record-latency-counts-cost\_units-examples---beforeafter-illustrations-filterbooleanjoinn-private-async-readbloburi-string-promisestring-implement-via-s3azure-sdk-download-text-return-domain-meta-note-placeholder-for-uri) - \[\*\*Agent Factory — instantiate from the Domain Repo\*\*\](#agent-factory-instantiate-from-the-domain-repo) - \[type AgentInstance \\= BaseAgent\\<any\\>; export class AgentFactory { constructor( private readonly domainRepo: DomainRepo, private readonly meta: MetadataRepo, private readonly blobs: BlobStore, private readonly bus: EventBus, private readonly ids: Ids, private readonly clock: Clock ) {} async spawnDomain(domainKey: string): Promise\\<AgentInstance\\\[\\\]\\> { const domain \\= await this.domainRepo.getDomainByKey(domainKey); const defs \\= await this.domainRepo.listAgents(domain.domainId, true); const instances: AgentInstance\\\[\\\] \\= \\\[\\\]; for (const def of defs) { const design \\= await this.fetchLatestAgentDesignNote(def.agentId); const agent \\= this.instantiate(def, design?.markdown ?? ""); agent.register(); instances.push(agent); } return instances; } private async fetchLatestAgentDesignNote(agentId: UUID): Promise\\<{ markdown: string } | null\\> { \*// Query latest agent\\\_design\\\_notes row, then fetch blob content by uri\* return { markdown: "\\#\\# Instructions go here" }; } private instantiate(def: AgentDefinition, designMarkdown: string): AgentInstance { const baseArgs \\= \\\[this.bus, this.meta, this.blobs, this.ids, this.clock, def.key, "v1"\\\] as const; switch (def.kind) { case "classifier": return new (class extends BaseAgent\\<"DocumentUploaded"\\> { listens() { return \\\["DocumentUploaded"\\\]; } async handle(evt: EventEnvelope\\<any\\>) { \*// Use designMarkdown: guides extraction fields & routing.\* \*// Call MetadataRepo to upsert classification, then emit DocumentClassified.\* } })(...baseArgs); case "structurer": return new (class extends BaseAgent\\<"DocumentClassified" | RegExp\\> { listens() { \*// turn DSL to matchers; for demo, listen to DocumentClassified\* return \\\["DocumentClassified"\\\]; } async handle(evt: EventEnvelope\\<any\\>) { \*// Use designMarkdown \\+ def.docTypes to create DomainStructured:\\<DocType\\>\* } })(...baseArgs); case "association": return new (class extends BaseAgent\\<RegExp\\> { listens() { return \\\[/^DomainStructured:/\\\]; } async handle(evt: EventEnvelope\\<any\\>) { \*// Use designMarkdown to add graph links and emit DomainAssociated.\* } })(...baseArgs); case "narrative": return new (class extends BaseAgent\\<RegExp\\> { listens() { return \\\[/^DomainStructured:/, /^DomainAssociated$/\\\]; } async handle(evt: EventEnvelope\\<any\\>) { \*// Use designMarkdown to gather domain docs, render markdown, write to blob,\* \*// upsert narrative index in Postgres, emit PerspectiveNarrativeUpdated.\* } })(...baseArgs); case "collection": return new (class extends BaseAgent\\<"PerspectiveNarrativeUpdated"\\> { listens() { return \\\["PerspectiveNarrativeUpdated"\\\]; } async handle(evt: EventEnvelope\\<PerspectiveNarrativeUpsert\\>) { \*// Use designMarkdown \\+ def.config.criteria to select members,\* \*// compose markdown, write to blob, upsert, emit CollectionNarrativeUpdated.\* } })(...baseArgs); default: throw new Error(\\\`Unknown agent kind: ${def.kind}\\\`); } } }\](#type-agentinstance-baseagentany-export-class-agentfactory-constructor-private-readonly-domainrepo-domainrepo-private-readonly-meta-metadatarepo-private-readonly-blobs-blobstore-private-readonly-bus-eventbus-private-readonly-ids-ids-private-readonly-clock-clock-async-spawndomaindomainkey-string-promiseagentinstance-const-domain-await-thisdomainrepogetdomainbykeydomainkey-const-defs-await-thisdomainrepolistagentsdomaindomainid-true-const-instances-agentinstance-for-const-def-of-defs-const-design-await-thisfetchlatestagentdesignnotedefagentid-const-agent-thisinstantiatedef-designmarkdown-agentregister-instancespushagent-return-instances-private-async-fetchlatestagentdesignnoteagentid-uuid-promise-markdown-string-null-query-latest-agent\_design\_notes-row-then-fetch-blob-content-by-uri-return-markdown-instructions-go-here-private-instantiatedef-agentdefinition-designmarkdown-string-agentinstance-const-baseargs-thisbus-thismeta-thisblobs-thisids-thisclock-defkey-v1-as-const-switch-defkind-case-classifier-return-new-class-extends-baseagentdocumentuploaded-listens-return-documentuploaded-async-handleevt-eventenvelopeany-use-designmarkdown-guides-extraction-fields-routing-call-metadatarepo-to-upsert-classification-then-emit-documentclassified-baseargs-case-structurer-return-new-class-extends-baseagentdocumentclassified-regexp-listens-turn-dsl-to-matchers-for-demo-listen-to-documentclassified-return-documentclassified-async-handleevt-eventenvelopeany-use-designmarkdown-defdoctypes-to-create-domainstructureddoctype-baseargs-case-association-return-new-class-extends-baseagentregexp-listens-return-domainstructured-async-handleevt-eventenvelopeany-use-designmarkdown-to-add-graph-links-and-emit-domainassociated-baseargs-case-narrative-return-new-class-extends-baseagentregexp-listens-return-domainstructured-domainassociated-async-handleevt-eventenvelopeany-use-designmarkdown-to-gather-domain-docs-render-markdown-write-to-blob-upsert-narrative-index-in-postgres-emit-perspectivenarrativeupdated-baseargs-case-collection-return-new-class-extends-baseagentperspectivenarrativeupdated-listens-return-perspectivenarrativeupdated-async-handleevt-eventenvelopeperspectivenarrativeupsert-use-designmarkdown-defconfigcriteria-to-select-members-compose-markdown-write-to-blob-upsert-emit-collectionnarrativeupdated-baseargs-default-throw-new-errorunknown-agent-kind-defkind) - \[\*\*Minimal Domain Meta Note (markdown) — template\*\*\](#minimal-domain-meta-note-markdown-template) - \[and render a concrete Agent Design Note (markdown) instructing how to map fields, validate, and emit.\](#and-render-a-concrete-agent-design-note-markdown-instructing-how-to-map-fields-validate-and-emit) - \[\*\*Putting it together (3 domains to prove it)\*\*\](#putting-it-together-3-domains-to-prove-it) - \[\*\*You said:\*\*\](#you-said) - \[\*\*ChatGPT said:\*\*\](#chatgpt-said) - \[Here’s a long-form Markdown blueprint that pulls together everything we’ve been iterating on — the Core Agent Pattern for the Enterprise (CAPE), the Domain Repo, Agents & Events, Storage Contracts, and Generation Workflow — laid out like a professional architecture pattern doc.\](#heres-a-long-form-markdown-blueprint-that-pulls-together-everything-weve-been-iterating-on-the-core-agent-pattern-for-the-enterprise-cape-the-domain-repo-agents-events-storage-contracts-and-generation-workflow-laid-out-like-a-professional-architecture-pattern-doc) - \[\*\*🌐 Core Agent Patterns for the Enterprise (CAPE)\*\*\](#core-agent-patterns-for-the-enterprise-cape) - \[\*\*Pattern Name\*\*\](#pattern-name) - \[A pattern for transforming raw documents into structured domain knowledge and living narratives through an event-driven agent framework.\](#a-pattern-for-transforming-raw-documents-into-structured-domain-knowledge-and-living-narratives-through-an-event-driven-agent-framework) - \[\*\*✨ Intent\*\*\](#intent) - \[\*\*🏛️ Architectural Context\*\*\](#architectural-context) - \[\*\*🗃️ Storage Contract\*\*\](#storage-contract) - \[\*\*Tables (simplified)\*\*\](#tables-simplified) - \[\*\\-- Domains & design notes\* domains, domain\\\_design\\\_notes agent\\\_definitions, agent\\\_design\\\_notes \*\\-- Event \\+ doc processing\* domain\\\_events, documents, document\\\_classifications domain\\\_documents, domain\\\_links \*\\-- Narratives\* perspective\\\_narratives, collection\\\_narratives \*\\-- Idempotency\* op\\\_keys\](#domains-design-notes-domains-domain\_design\_notes-agent\_definitions-agent\_design\_notes----event-doc-processing-domain\_events-documents-document\_classifications-domain\_documents-domain\_links----narratives-perspective\_narratives-collection\_narratives----idempotency-op\_keys) - \[\*\*📦 Event Vocabulary\*\*\](#event-vocabulary) - \[\*\*⚙️ Domain Repo\*\*\](#domain-repo) - \[\*\*Purpose\*\*\](#purpose) - \[\*\*Tables\*\*\](#tables) - \[\*\*🧩 Design Note Workflow\*\*\](#design-note-workflow) - \[\*\*🧑‍💻 TypeScript Skeleton\*\*\](#typescript-skeleton) - \[\*// Base event envelope\* interface EventEnvelope\\<T=any\\> { eid: string; etype: string; ts: string; parents?: string\\\[\\\]; opKey?: string; actor?: { name: string; version?: string }; payload: T; } \*// Base agent\* abstract class BaseAgent\\<TListen extends string\\> { constructor( protected readonly bus: EventBus, protected readonly meta: MetadataRepo, protected readonly blobs: BlobStore, protected readonly ids: Ids, protected readonly clock: Clock, protected readonly name: string, protected readonly version \\= "v1" ) {} abstract listens(): Array\\<TListen|RegExp\\>; abstract handle(evt: EventEnvelope\\<any\\>): Promise\\<void\\>; register() { \*/\\\* subscribe logic \\\*/\* } protected async emit\\<T\\>(etype: string, payload: T, parents?: string\\\[\\\], opKey?: string) { \*/\\\* publish \\\*/\* } } \*// Example: Classifier Agent\* class ClassifierAgent extends BaseAgent\\<"DocumentUploaded"\\> { listens() { return \\\["DocumentUploaded"\\\]; } async handle(evt: EventEnvelope\\<DocumentUploaded\\>) { \*// Detect domain \\+ docType, extract key fields, provenance.\* \*// Persist classification (Postgres) and emit DocumentClassified.\* } }\](#base-event-envelope-interface-eventenvelopetany-eid-string-etype-string-ts-string-parents-string-opkey-string-actor-name-string-version-string-payload-t-base-agent-abstract-class-baseagenttlisten-extends-string-constructor-protected-readonly-bus-eventbus-protected-readonly-meta-metadatarepo-protected-readonly-blobs-blobstore-protected-readonly-ids-ids-protected-readonly-clock-clock-protected-readonly-name-string-protected-readonly-version-v1-abstract-listens-arraytlistenregexp-abstract-handleevt-eventenvelopeany-promisevoid-register-subscribe-logic-protected-async-emittetype-string-payload-t-parents-string-opkey-string-publish-example-classifier-agent-class-classifieragent-extends-baseagentdocumentuploaded-listens-return-documentuploaded-async-handleevt-eventenvelopedocumentuploaded-detect-domain-doctype-extract-key-fields-provenance-persist-classification-postgres-and-emit-documentclassified) - \[\*\*🧠 Agents by Kind\*\*\](#agents-by-kind) - \[\*\*Classifier\*\*\](#classifier) - \[\*\*Structurer\*\*\](#struct--- title: Quick Intro to Markdown and Pandoc tags: how-to, ppt description: A brief introduction presented by Nikhil Kandula. slideOptions: theme: solarized center: false --- <style> .reveal { font-size: 32px; } </style> # Introduction to Markdown and Pandoc <!-- Put the link to this slide here so people can follow --> > slide: https://hackmd.io/@casf/HJWuqWzaO --- # What is Markdown - Markdown is a light weight mark up language that you can use to add formatting elements to plain text documents - Can be coverted to into HTML, LaTeX, pdf and other formats - Main purpose is redability and ease of use --- # Markdown files - Saved as `.md`, `.markdown` files - Opened in your text editor of choice (VS code, Notepad ++, Vim, Emacs, Matlab editor, even MS Notepad) - Or use an online markdown editor and save file locally (see [stackedit.io](https://stackedit.io/app#)) --- - We Use Markdown because it gives a clean and organised look to our files. It allows for lots of options like check boxes and emojis. Markdown is very commonly used in writing research papers. --- # Syntax > > Markdown includes the most frequently used formatting of text: headings, bold, italics, items, enumeration, code blocks (including inline codes)... --- | Syntax | Output | -------- | -------- | | # Heading | <h1>Heading</h1> | |## Subheading |<h2>Subheading</h2> | |### Next heading level | <h3>Next heading level</h3> | After headings, paragraphs, other formatted blocks, **an empty space is important** --- # Inline formatting | *italics* `*italics*` | **bold** `**bold**` |~~strikeout~~`~~strikeout~~` |`inline code` (enclose code within 'backtics')| :exclamation: **Please note that if you intend to convert document to LaTeX, do not use unnecessary decorations like strikeout or emojis** --- # Lists, Tables and codes (code blocks) --- - `Append statements with +, -, *` to form a *continuous* list - `Append with 1. 2. 3.` for numbered lists - testing a nested list - use 'tab' indenting for nested lists --- --- # Nested lists Lists can be **nested** *for example* * Item 1. First Subitem 2. Second Subitem * Item - Subitem - Subitem * Item --- # Mathematical equations *for example an equation can be written as* $$x_{1,2} = \frac{-b \pm \sqrt{b^2-4ac}}{2b}.$$ $$k_{n+1}$$ $$\frac{n!}{k!(n-k)!}$$ $$ A+B=\begin{bmatrix} a_{11}+b_{11}&a_{12}+b_{12}&\dots&a_{1n}+b_{1n} \\ a_{21}+b_{21}&a_{22}+b_{22}&\dots&a_{2n}+b_{2n} \\ \vdots&\vdots&\ddots&\vdots \\a_{m1}+b_{m1}&a_{m2}+b_{m2}&\dots&a_{mn}+b_{mn} \end{bmatrix}\ $$ --- # Mathematical symbols $$n^2$$ $$k_n^2$$ $$\sqrt{k}$$ --- # Quoted line > First line example **This is a paragraph** > Another line > > > Nested line > > Last line **Conclusion** --- # Images *for example a image can be written as* ![image of a forest path](https://i.imgur.com/Mr7SdDf.jpg) # Links *for example a link can be written as* [link 1](https://google.com) <https://google.com> [link 1][1] [1]:<https://youtube.com> **These are the three ways you can represent the links** --- # Foot notes --- Here's a simple footnote - [^1] [^1]: This is a footnote This is another line --- --- # Tables To add a table, use three or more hyphens (---) to create each column’s header, and use pipes (|) to separate each column. You can optionally add pipes on either end of the table. | Syntax | Description | | ----------- | ----------- | | Header | Title | | Paragraph | Text | --- Cell widths can vary, as shown below. The rendered output will look the same. | Syntax | Description | | --- | ----------- | | Header | Title | | Paragraph | Text | --- # Alignment You can align text in the columns to the left, right, or center by adding a colon (:) to the left, right, or on both side of the hyphens within the header row. --- | Syntax | Description | Test Text | | :--- | :----: | ---: | | Header | Title | Text | | Paragraph | Text | Test | --- # check list - [ ] (for unchecked checkbox) - [x] (for checked checkbox) --- # Hackmd - Work on markdown documents with instant previews (side-by-side or full-screen) of markdown documents while editing. - Realtime collaboration - Export functions - Toolbar for easy access to formatting, images, links, tables. - Users may also leave comments like the *Review* functionality in word files. - Links to github repositories (sadly we use gitlab presently), but that's ok --- # Slides ## This presentation was made on hackmd. Sign up for hackmd. --- ## Pandoc Utility for converting markdown files to pdf, html, latex, and others (docx if necessary). See [Getting started with pandoc](https://pandoc.org/getting-started.html). For us it is important to be able to convert documents, reports to latex. --- - We can convert markdown to latex using pandoc in online with the following link https://pandoc.org/try/?text=&from=markdown&to=latex&standalone=0 --- ### Thank you! :clap: | Syntax | Description | Test Text | | :--- | :----: | ---: | | Header | Title | Text | | Paragraph | Text | Test | | row 4 | ff | ff |
{"metaMigratedAt":"2023-06-16T03:54:30.914Z","metaMigratedFrom":"YAML","title":"Quick Intro to Markdown and Pandoc","breaks":true,"description":"A brief introduction presented by Nikhil Kandula.","slideOptions":"{\"theme\":\"solarized\",\"center\":false}","contributors":"[{\"id\":\"98b1574d-f5ac-4c4d-b964-ed70e351bf2a\",\"add\":444,\"del\":0,\"latestUpdatedAt\":null},{\"id\":\"da510d01-dc76-4e53-92a6-6415b764b5cc\",\"add\":3166,\"del\":766},{\"id\":\"72ff1ced-fe04-4068-af98-73ddb5eb05c6\",\"add\":4669,\"del\":1964},{\"id\":\"0b74edd0-8ee0-4f66-a4e9-536186b8b11d\",\"add\":10,\"del\":0},{\"id\":\"3ec32e43-7b92-425f-ad6e-ae5abe91c756\",\"add\":0,\"del\":3},{\"id\":\"e19f9842-1c98-41d0-86f9-12809fa024b8\",\"add\":94664,\"del\":0,\"latestUpdatedAt\":1758597613276}]"}
    2606 views
   owned this note