combustion.acoustics.spray.fluids
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Owners
        • Signed-in users
        • Everyone
        Owners Signed-in users Everyone
      • Write
        • Owners
        • Signed-in users
        • Everyone
        Owners Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Versions and GitHub Sync Note Insights Sharing URL Help
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Owners
  • Owners
  • Signed-in users
  • Everyone
Owners Signed-in users Everyone
Write
Owners
  • Owners
  • Signed-in users
  • Everyone
Owners Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       owned this note    owned this note      
    Published Linked with GitHub
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    \--- 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 |

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully