A company-research dossier subject backend for
Animus, built on
@launchapp-dev/animus-plugin-sdk
(TypeScript, Zod-typed, protocol 1.x).
kind=company. One Markdown file per company: the YAML frontmatter holds the
structured dossier fields the orchestrator queries; the body is the free-form
prose thesis. Files live under a configurable root, so every dossier is
human-readable, diffable, and git-versioned alongside the rest of a research
firm's repo.
<root>/company/<TICKER>.md e.g. research/company/NVDA.md
| RPC | Behavior |
|---|---|
subject/list |
Walks <root>/<kind>/*.md, parses frontmatter, filters in-memory. |
subject/get |
Reads one .md at the deterministic path for the id. |
subject/create |
Allocates an id (ticker, else CO-NNNN), writes the file atomically. |
subject/update |
Read → merge patch (status/labels/dossier blocks) → atomic write. |
subject/status |
Convenience wrapper over subject/update with a status patch. |
subject/schema |
Field schema incl. the full dossier_fields map; supports_create. |
health/check |
Verifies the root directory exists and is writable. |
Legacy <kind>/<verb> routes (company/list, …) are advertised for older
daemon builds. The SDK handles the JSON-RPC loop, --manifest/--help,
initialize/$/ping/shutdown/exit, and validates inbound params with Zod.
The structured fields (frontmatter) and the prose (body):
- identity —
ticker,name,sector,cap_tier,adv(avg daily volume),price - discovery —
source(edgar-spinoff|edgar-form4|edgar-13d|social|theme|screen),detected_at,mention_velocity?,attention_vs_sentiment?,pump_flags? - special_situation —
type(spinoff|insider-cluster|13d|none),filing_url,trigger_state - theme —
secular_tailwind,edgar_penetration_pct,crowding_score(0–9),un_priced_optionality,steinhardt_trigger - valuation —
multiples_vs_sector,margin_of_safety_pct,quality_floor(roic/roe) - thesis —
bull/base/bear(+*_probprobabilities),variant_perception,value_trap_check,what_would_change_my_mind(exit triggers). The long-form prose lives in the markdown body. - setup —
type(52wk-high|rsi-200sma|pead-flag|leaps),entry,stop,target,r_multiple,ivr - horizon —
kind(swing|position),conviction(1–5) - risk —
position_size,settlement_state,notes - calibration —
conviction_pct,base_rate_ref,sources[](each withingested_at),outcome_embargo_until,outcome_actual,pnl_attributed - meta —
last_updated,by_agent,version_history[](dated)
The schema is defined once with zod in src/schema.ts and
is the single source of truth: subject/schema reflects it, the parser
validates against it, and the writer renders it back in a fixed field order.
---
id: company:NVDA
kind: company
title: NVIDIA
status: ready
priority: null
assignee: null
labels: []
created_at: 2026-06-13T00:00:00.000Z
updated_at: 2026-06-13T00:00:00.000Z
identity:
ticker: NVDA
sector: Semiconductors
...
theme:
crowding_score: 6
...
setup:
type: 52wk-high
entry: 120.0
...
meta:
last_updated: 2026-06-13T00:00:00.000Z
---
# NVIDIA — AI compute monopoly
Free-form prose thesis. Bull/base/bear narrative, variant perception,
what-would-change-my-mind. Agents read it, humans edit it in their IDE.- A company's natural key is its ticker:
subject/createwithcustom.ticker = "NVDA"writescompany/NVDA.mdand idcompany:NVDA. Tickers normalize to uppercase;BRK.B/RDS-Aare valid. - With no ticker, a monotonic sequence id is allocated (
company:CO-0001, scanned from existingCO-NNNN.mdfiles, gaps not filled).
| Variable | Default | Description |
|---|---|---|
ANIMUS_COMPANY_ROOT |
<cwd>/research |
Root directory for dossier files. |
ANIMUS_COMPANY_KINDS |
company |
Comma-separated subject kinds. |
ANIMUS_COMPANY_ID_PREFIX |
company: |
Id prefix on SubjectId values. |
This is a Node.js stdio plugin. npm run build (tsc) emits dist/; the
entrypoint dist/main.js carries a #!/usr/bin/env node shebang and is marked
executable, so the Animus daemon spawns it directly and speaks
newline-delimited JSON-RPC 2.0 on stdin/stdout. plugin.toml is the discovery
surface ([binary] default = "dist/main.js").
npm install
npm run build # tsc → dist/ (chmod +x dist/main.js)
node dist/main.js --manifest # prints the plugin manifest JSON (host install handshake)Point the backend at the firm repo's research/ directory so dossiers land in
version control:
# from the plugin checkout (after `npm install && npm run build`):
animus plugin install /path/to/animus-subject-company --project-root "$(pwd)"
# configure the root via env (workflow YAML daemon env, or process env):
export ANIMUS_COMPANY_ROOT="/path/to/firm-repo/research"
# then the unified subject surface routes kind=company here:
animus subject create --kind company --title "NVIDIA" \
--custom ticker=NVDA --description "AI compute thesis"
animus subject list --kind company
animus subject get --kind company --id company:NVDA
animus subject status --kind company --id company:NVDA --status in-progressnpm install
npm run build # tsc → dist/
npm run typecheck # strict tsc, incl. tests
npm test # vitestElastic License 2.0.