captable_analysis · git:20260908.8b8c750 · 2026-09-08 · sha256 bbeeb91ae05ce3e6
captable_analysis git:20260908.8b8c750A
Immutable. This exact content is served forever at /api/v1/blob/bbeeb91ae05ce3e6.
--- name: captable_analysis description: Compute conversion scenarios, stamp duty and red-flag findings over a stored cap-table snapshot, plus a deterministic HTML one-pager. Use after captable_build. --- # captable_analysis Analyzes a cap-table snapshot stored by `captable_build` (issue #17, skill 2). All numbers are computed deterministically in `lib/captable/model.py` and `lib/captable/rubric.py`; the LLM's only job is to phrase a narrative over the computed JSON — it may not compute or invent any figure. ## Usage ```bash # via the command harness (agents; returns the narrative). All options are # optional; round parameters default from the data and are recorded as # assumptions: python -m skills.harness /captable_analysis synthcap python -m skills.harness -- /captable_analysis synthcap --as-of 2026-06-30 --pre-money 8000000 --investment 2000000 --fx-rate USD=0.88 --currency CHF # or the CLI (also writes analysis_scenarios.json): python -m skills.captable_analysis run --startup synthcap python -m skills.captable_analysis run --startup synthcap --as-of 2026-06-30 --pre-money 8000000 --investment 2000000 --fx-rate USD=0.88 --currency CHF ``` `synthcap` is the synthetic fixture dataset; substitute your startup's dataset slug. Reads `insights/captable/latest.json` (or the named snapshot), then: - accrues each executed CLA's loan balance to the analysis date under its extracted day-count and compounding (unstated → act/365 simple, recorded as an assumption; the accrual date vs the snapshot's as-of date is always disclosed); safe-harbor-capped loans accrue at the documented safe-harbor rate rather than the stated ceiling — an unquantified cap falls back to the ceiling with a loud overstatement disclosure, - reports a `maturity_conversion_at_fixed_price` block whenever a CLA fixes a per-share price for post-maturity conversion (implied shares at the accrued balance, and the company value that price implies over the current fully-diluted count — the discount/cap scenario prices apply to round conversions only), - keeps every loan in its own currency (`note_currencies`) and expresses the scenarios in ONE currency (`currency`: the loans' common currency, else CHF, or `--currency`). A loan in another currency needs `--fx-rate CUR=RATE` (units of the scenario currency per 1 CUR; balance, cap and floor convert at that rate, recorded as an assumption). Without a rate the scenarios and the stamp-duty estimate are **not computed** and a high-severity `mixed_currencies` scenario flag names the loans — a CHF and a USD loan are never summed into one figure, - computes conversion scenarios for a hypothetical round under all three market methods (`pre_money` / `percentage_ownership` / `dollars_invested`), side by side — CLAs are usually silent on the method, so no method is ever silently chosen; round parameters default from the data (largest cap, QEFR minimum) and are always recorded as assumptions, - reports `founders_post_round_pct` per scenario and raises a structured `scenario_flags` entry (`founder_majority_post_round`) when founders fall below 50% in every modelled scenario, - estimates the 1% issuance stamp duty as a structured `stamp_duty` block (estimate, CHF 1M lifetime exemption, remaining exemption) — only when the scenario currency is CHF; otherwise `estimate_chf` is null with a note, - applies the red-flag rubric (founder majority, investor dominance, dead equity, fully-diluted-definition ambiguity) — explicitly scoped to the snapshot date via `rubric_scope_note`, never to the post-round state, - labels reserved positions as `[reserved pool] …` in scenario ownership so pools are never listed as shareholders. ## Rendering (`render`) ```bash python -m skills.captable_analysis render --startup synthcap python -m skills.captable_analysis render --startup synthcap --as-of 2026-06-30 ``` Renders the snapshot as a self-contained HTML one-pager — **no LLM call**: every number is copied verbatim from the validated snapshot (ownership bar by role, holder table with classification badges, share classes, pools, CLA overhang with maturity/e-sign status, validation traffic lights), so the visual a reviewer looks at can never drift from the stored data. Percentages use the same denominator as `rubric.ownership_by_role`. When `analysis_scenarios.json` exists AND was computed over the same snapshot state — same as-of date AND same content fingerprint (`snapshot_fingerprint`, a hash of the snapshot minus its generation timestamp) — the conversion-scenario table is included. Scenarios from another as-of, or from an earlier build of the same as-of whose content has since changed, are skipped and the page says so (re-run the analysis to refresh them). Written to `insights/captable/captable.html` (or `snapshots/<as_of>.html`); `captable_build` also writes it automatically on every build. ## Outputs - `insights/captable/analysis_scenarios.json` — the computed JSON (prices rounded to 4 decimals, percentages to 2). - The narrative, stored through the repository's `InsightFile` convention (`captable-analysis-<dataset>-<model-slug>.md`, manifest-tracked) since it is model-dependent. Requires a snapshot: run `python -m skills.captable_build build` first. ## Reuse and contracts `captable_analysis` returns `list[InsightFile]`. The explicit `analyze` adapter also returns computed data, narrative, insight path and the selected insight; for a manual narrative its computed data is `None` and no snapshot is read. Manual narratives win first. Generated reuse uses the shared insight lifecycle, indexed startup revision and a key covering the computed scenarios (including snapshot fingerprint, accrual date and round/FX inputs), prompt and tool version. A new analysis date therefore invalidates accrued-interest results. The run CLI uses the same adapter; `--startup` is canonical and `--dataset`/`-d` remain aliases. Snapshots containing failed CLA extractions are rejected for analysis/rendering; rebuild them first. Conversion prices honor each loan's stated issued/outstanding or fully diluted cap/floor denominator. An unstated basis is disclosed as a fully diluted assumption. Dollars-invested scenarios fix post-money at pre-money plus new investment plus converting balances, including discount dilution in pricing.