Choose the Codex skill for the stage
These skills are the workflow entry points. Use them from the Investment repository root; Codex will inspect the ticker workspace, preserve source files, and resume existing state where possible.
| Skill | Use it for | Gate or output |
|---|---|---|
$analyze-equity | Start, resume, or validate the 14-step Phase 0 analysis. | Completed run validates as VALID. |
$equity-report | Turn a completed Phase 0 run into a cited private HTML report. | Requires a completed v2, v3, or v4 run; finishes as VALID REPORT. |
$kpi-handoff | Compile a completed v4 run into an internal handoff and a redacted public KPI projection. | Preview and validate before the explicit promote step. |
Use $analyze-equity to analyze <TICKER>. After it validates, ask separately for $equity-report or $kpi-handoff. Do not use the report skill to run analysis, or the KPI skill with an incomplete or pre-v4 run.
Quick start
-
Open the Investment workspace. Work from the repository root that contains
app/,stocks/, and.agents/skills/. -
Create the ticker workspace. Use the supported command; it copies the reviewed scaffold, initializes source state and a pending neutral report theme, then validates the folder contract:
python3 -B -m app.stock_workspace create <TICKER> \ --company "Company Name" --exchange "NASDAQ" -
Add source documents. Put them anywhere under
stocks/<TICKER>/sources/. Keep the raw files unchanged. -
Scan and ask Codex to run it.
python3 -B -m app.source_intake <TICKER> scan Use $analyze-equity to analyze <TICKER>For a fresh run, provide portfolio context when relevant. Without it, the manifest records clearly labeled Watching defaults.
- Let the workflow pass its gates. Codex reviews required visuals, locks canonical facts and core calculations, prepares v4 retrieval, and records cited support and counter-evidence for each step.
-
Confirm the analysis gate. The Phase 0 workflow is complete only when validation prints
VALID. Then choose the next artifact:Use $equity-report for <TICKER> Use $kpi-handoff for <TICKER>
What you need
| Requirement | Needed? | Purpose |
|---|---|---|
| Investment workspace | Required | Contains the skills, prompts, helper CLIs, ticker folders, and tests. |
| Python 3.9 or newer | Required | Runs source intake, Phase 0, report rendering, and KPI handoff validation. |
pypdf | Required for PDFs | Extracts text page by page without converting or rewriting the original PDF. |
Markdown | Required for HTML reports | Renders the cited report synthesis and accepted analysis appendix into standalone HTML. |
stocks/<TICKER>/sources/ | Required | The hard input contract. At least one usable source is the practical minimum for meaningful analysis. |
| Codex with local skills | Required for the guided workflow | Use $analyze-equity, then the separate report or KPI skill as needed. |
| Portfolio details | Optional | Personalizes Steps 12 and 13. Defaults are used and labeled when details are absent. |
Supported files
- Extracted: PDF, Markdown, plain text, HTML, and HTM.
- Cataloged for visual review: PNG, JPG, and JPEG.
- Unreadable files: recorded as source errors without aborting other usable sources.
- Discovery: recursive; nested folders are allowed and evidence remains isolated by ticker.
Folder structure
Investment/
├── .agents/skills/
│ ├── analyze-equity/ # Phase 0 analysis and validation
│ ├── equity-report/ # private HTML report
│ └── kpi-handoff/ # public-safe KPI projection
├── app/
│ ├── analysis_prompts/ # 14 numbered prompts
│ ├── phase0_analysis.py # prepare, retrieve, facts, calculate, validate
│ ├── equity_report.py # prepare, status, render, validate
│ ├── kpi_handoff.py # build and promote KPI artifacts
│ └── source_intake.py # initialize, scan, and mark source tracking
├── requirements.txt # pypdf and Markdown
└── stocks/
└── <TICKER>/
├── README.md
├── sources/
│ ├── quarterly/
│ ├── events/
│ ├── news/
│ └── analyst-research/
├── trackers/ # durable thesis and KPI pointers
└── outputs/
└── phase0/
└── <run-id>/
The source subfolders are a useful taxonomy, not a restriction. The helper inventories every supported file beneath sources/ and never moves, renames, converts, or overwrites it.
Recommended source packet
More evidence improves coverage, but the packet should stay current, relevant, and legally usable.
| Priority | Evidence | Main coverage |
|---|---|---|
| Core | Latest annual report or 10-K | Business model, financial history, risks, capital structure, headcount, and long-term economics. |
| Core | Latest quarterly report or 10-Q | Current growth, margins, liquidity, guidance, dilution, and balance-sheet changes. |
| Core | Earnings release and call transcript | Guidance, operating drivers, management explanations, catalysts, and current debates. |
| Recommended | Investor presentation or analyst day | Strategy, market opportunity, product roadmap, capital allocation, and KPI definitions. |
| Recommended | Relevant 8-Ks and event transcripts | Financing, restructuring, M&A, leadership, regulatory, and product developments. |
| Recommended | Proxy statement, ownership, and estimate evidence | Incentives, insider alignment, holder mix, revisions, and valuation context. |
| Optional | Legally usable market-data or research PDFs | Historical multiples, price context, consensus, peer comparisons, and sentiment. |
Phase 0 lifecycle
Codex normally runs these commands for you. They are documented here for inspection, recovery, and manual verification.
Run them from the Investment repository root. For a different checkout location, add --root /path/to/Investment before the ticker.
1. Scan source intake
python3 -B -m app.source_intake <TICKER> scan
Reports new or modified files without marking them. After a completed validated run, source intake can be marked through validate --mark-sources.
2. Prepare or resume
python3 -B -m app.phase0_analysis <TICKER> prepare
Builds the evidence catalog and chunks, then resumes the newest incomplete run. Use --new-run only when a fresh fingerprinted run is needed.
python3 -B -m app.phase0_analysis <TICKER> prepare --new-run
Optional portfolio context
python3 -B -m app.phase0_analysis <TICKER> prepare \
--position-status Holding \
--shares 125 \
--average-cost 42.50 \
--cost-currency USD \
--current-allocation 3 \
--target-allocation 5
Allowed position states are Watching and Holding. A holding requires shares, average cost, three-letter cost currency, current allocation, and target allocation. Without supplied context, the manifest records clearly labeled Watching defaults.
3. Review required visuals
python3 -B -m app.phase0_analysis <TICKER> review
python3 -B -m app.phase0_analysis <TICKER> review --mark <VISUAL-ID>
Inspect every listed preview before writing analysis. Mark only the visual IDs actually reviewed; do not begin the 14 steps while the run reports review_required.
4. Lock facts and core calculations
python3 -B -m app.phase0_analysis <TICKER> facts prepare
python3 -B -m app.phase0_analysis <TICKER> facts build
python3 -B -m app.phase0_analysis <TICKER> facts status
python3 -B -m app.phase0_analysis <TICKER> facts validate --lock
python3 -B -m app.phase0_analysis <TICKER> calculate core
Populate the fact candidates with source-backed assertions, preserve conflicts explicitly, and keep reported facts, guidance, estimates, market observations, and analyst assumptions distinct. Do not write Step 1 until facts and core calculations are locked.
5. Prepare deterministic v4 retrieval
python3 -B -m app.phase0_analysis <TICKER> retrieve prepare
python3 -B -m app.phase0_analysis <TICKER> retrieve plan --step <N>
python3 -B -m app.phase0_analysis <TICKER> retrieve search "<SUPPORT QUERY>" --step <N> --kind support --explain
python3 -B -m app.phase0_analysis <TICKER> retrieve search "<COUNTER QUERY>" --step <N> --kind counter --explain
python3 -B -m app.phase0_analysis <TICKER> retrieve validate --step <N>
For each step, satisfy the plan or record a gap, conflict, or review requirement. Register only material claims in the evidence sidecar and retain the counter-search trace even when it finds nothing.
6. Complete, calculate, and synchronize
python3 -B -m app.phase0_analysis <TICKER> status
python3 -B -m app.phase0_analysis <TICKER> calculate valuation
python3 -B -m app.phase0_analysis <TICKER> calculate decision
Write each numbered output from its prompt and cited evidence, starting at next_step. After Step 7, lock valuation assumptions and results; after Step 11, lock decision arithmetic before Step 12.
7. Validate the complete run
python3 -B -m app.phase0_analysis <TICKER> validate --mark-sources
Use --run-id <RUN_ID> to validate a non-default run. Completion requires VALID; accepted Markdown, evidence sidecars, retrieval traces, facts, and calculations are immutable.
The 14-step prompt sequence
The prompts run sequentially. They are not independent parallel reports: later judgments consume locked facts, calculations, retrieval evidence, and handoffs from earlier steps. The v4 run also accepts each Markdown output together with its step evidence sidecar and retrieval trace.
| Step | Analysis | Purpose |
|---|---|---|
| 01 | Business Phase | Classify the company from startup through decline and establish the phase used later. |
| 02 | Business Analysis | Explain the value proposition, revenue architecture, customer structure, pricing, and economics. |
| 03 | Moat | Assess switching costs, network effects, intangible assets, cost advantages, and counter-positioning. |
| 04 | Long-Term Growth Drivers | Separate funded growth from narrative growth across customer acquisition and expansion. |
| 05 | Phase-Specific Key Metrics | Score the metrics, ownership signals, estimates, and value creation appropriate to Step 1's phase. |
| 06 | Risk | Run a forensic pre-mortem covering concentration, financial, governance, and structural risks. |
| 07 | Phase-Appropriate Valuation Metrics | Select the correct valuation family for Step 1's phase and judge support versus history and peers. |
| 08 | Price and Sentiment | Connect one-year price action to catalysts, positioning, analyst views, and narrative shifts. |
| 09 | Antifragility | Stress liquidity, leverage, cash generation, asset quality, and survival under operating shocks. |
| 10 | Reverse DCF | Translate the market price into the growth and margin expectations it implies. |
| 11 | Intrinsic Valuation | Estimate value with explicit operating, discount-rate, terminal, and scenario assumptions. |
| 12 | Final Decision and Buy Plan | Synthesize Steps 10 and 11 with prior evidence and portfolio context into an action framework. |
| 13 | Behavioral Bias Check | Audit confirmation bias, overconfidence, herding, recency, and position-specific behavior. |
| 14 | Efficiency and AI Productivity | Test productivity claims using per-employee trends, peer comparison, and distortion checks. |
Required handoffs
- Facts and core calculations → Step 1 onward: use locked values and preserve their fact or result IDs alongside the original source citations.
- Step 1 → Steps 5 and 7: use the detected business phase.
- Step 7 → Steps 10 and 11: use one consistent valuation method, assumptions, and scenario inputs.
- Steps 10 and 11 → Step 12: explicitly synthesize market-implied expectations and intrinsic value.
- Portfolio manifest → Steps 12 and 13: use supplied position data or clearly labeled defaults.
- All prior steps → later steps: use concise cited handoffs instead of duplicating whole outputs; validate each v4 sidecar before status can accept it.
Private quality-gated HTML report
$equity-report is separate from $analyze-equity. It accepts a completed analysis-contract-v2, v3, or v4 run, preserves all 14 accepted outputs, and creates a cited synthesis plus a deterministic standalone HTML report. It never runs the analysis steps or publishes the private artifact for you.
Command lifecycle
python3 -B -m app.equity_report <TICKER> prepare [--run-id <RUN>]
python3 -B -m app.equity_report <TICKER> status [--run-id <RUN>]
python3 -B -m app.equity_report <TICKER> render [--run-id <RUN>]
python3 -B -m app.equity_report <TICKER> validate [--run-id <RUN>]
What the report contains
- A decision-first opening with dated market data, evidence confidence, underwriting status, and portfolio context.
- Thesis, variant perception, business quality, operating drivers, valuation scenarios, risks, catalysts, falsifiers, and monitoring triggers.
- A behavioral circuit breaker covering confirmation, overconfidence, herding, recency, sunk-cost or house-money effects, concentration, and cooling-off questions.
- An aggregate evidence-quality summary, explicit contradictions, unresolved gaps, linked source register, and all 14 accepted outputs in a navigable appendix.
Public-safe KPI handoff
$kpi-handoff connects a completed v4 analysis to a deterministic KPI dashboard without scraping a report or exposing portfolio context. It reads locked facts, calculation results, reviewed evidence, and approved selections.
Command lifecycle
python3 -B -m app.kpi_handoff <TICKER> prepare [--run-id <RUN>]
python3 -B -m app.kpi_handoff <TICKER> build [--run-id <RUN>]
python3 -B -m app.kpi_handoff <TICKER> preview [--run-id <RUN>]
python3 -B -m app.kpi_handoff <TICKER> validate [--run-id <RUN>]
python3 -B -m app.kpi_handoff <TICKER> promote [--run-id <RUN>]
- Prepare: select the newest completed v4 run unless a run ID is explicitly named.
- Curate: add stable KPI definitions, typed observations, thresholds, catalysts, risks, and monitoring triggers with lineage.
- Build and preview: compile the internal handoff and the redacted public projection; preview reads only the public projection.
- Validate: confirm hashes, source lineage, compatible periods and units, reviewed visuals, and absence of private fields.
- Promote: explicitly lock the validated run as
trackers/kpi_current.json. Promotion does not publish or modify the public Reports site by itself.
Public report and site bundle
The public full report is a separate artifact, not a copy of the personalized report. It requires a completed v4 analysis, a validated KPI handoff, and an official-source-verified company theme.
python3 -B -m app.public_equity_report <TICKER> prepare [--run-id <RUN>]
python3 -B -m app.public_equity_report <TICKER> status [--run-id <RUN>]
python3 -B -m app.public_equity_report <TICKER> render [--run-id <RUN>]
python3 -B -m app.public_equity_report <TICKER> validate [--run-id <RUN>]
python3 -B -m app.site_publication <TICKER> prepare [--run-id <RUN>]
python3 -B -m app.site_publication <TICKER> validate [--run-id <RUN>]
The bundle fingerprints the public report, KPI dashboard, verified theme, card metadata, and exact website destinations. Applying it requires the explicit --confirm-publication flag; it updates the local website checkout and rebuilds data/library.json, but never commits or pushes.
Outputs and resumable state
stocks/<TICKER>/outputs/phase0/<run-id>/
├── Step_01_Output.md
├── Step_02_Output.md
├── ...
├── Step_14_Output.md
├── step_evidence/ # v4 evidence sidecars
├── retrieval_traces/ # v4 retrieval traces
├── evidence_catalog.json
├── evidence_chunks.jsonl
├── evidence_blocks.jsonl
├── evidence_tables.jsonl
├── evidence_visuals/
├── facts_ledger.json # after facts validate --lock
├── calculation_results/ # after calculate stages
├── run_manifest.json
├── Report_Synthesis.md # after $equity-report
├── <TICKER>_Full_Report.html # private personalized report
├── report_manifest.json # independent report fingerprints
├── kpi_handoff_public.json # after $kpi-handoff build
├── KPI_Dashboard_Preview.html # after $kpi-handoff preview
├── Public_Report_Synthesis.md # curated public-only synthesis
├── <TICKER>_Public_Report.html # separate public report
├── public_report_manifest.json
└── publication_bundle.json # exact hashes and site destinations
run_manifest.jsonrecords the contract, status, detected phase, assumptions, prompt and source hashes, citations, web sources, timestamps, and failures.evidence_catalog.jsoninventories the usable sources, images requiring inspection, and isolated source errors.evidence_blocks.jsonl,evidence_tables.jsonl, andevidence_visuals/retain structured context for reliable review.- For v4, each accepted step hashes its Markdown output, evidence sidecar, and retrieval trace together.
- The newest incomplete run resumes by default. A completed run or explicit
--new-runcreates a new timestamped run. report_manifest.jsonfingerprints the accepted analysis, synthesis, styles, portfolio context, and rendered HTML without modifyingrun_manifest.json.- KPI handoff artifacts are fingerprinted separately; promotion writes only the validated run ID and hashes to
trackers/kpi_current.json.
Evidence and citation rules
- Prefer local evidence and read the original document when a search result needs surrounding context.
- Supplement only when required information is absent locally, using primary sources such as the SEC, company investor relations, official exchanges, or regulators.
- State an as-of date for web evidence.
- Mark unsupported, unavailable, or stale facts as evidence gaps rather than estimating them.
- Use the citation strings returned by evidence search. Never invent page numbers or chunk IDs.
- For v4, register every material local or web citation in the step evidence sidecar; IDs supplement citations and never replace them.
- Keep reported actuals, guidance, consensus estimates, market observations, and analyst assumptions distinct. Preserve conflicts instead of averaging them.
Local PDF: [[source:quarterly/example.pdf#page=12]]
Local text: [[source:events/example.md#chunk=0123456789abcdef]]
Primary web: [Company filing](https://example.com/filing), published YYYY-MM-DD
Every material factual paragraph or table row should be traceable, and each step must contain at least one machine-checkable citation. Quantitative claims must also resolve to a locked fact or calculation result when the contract requires it.
Troubleshooting
| Symptom | What to do |
|---|---|
pypdf is missing | Run python3 -m pip install -r requirements.txt, then repeat prepare. |
| A PDF or text file cannot be read | Inspect its entry in evidence_catalog.json. Usable sources continue; replace the file only outside the workflow if you have a lawful clean copy. |
| An image is cataloged but has no text | Visually inspect it before relying on it. Images are not OCR-converted by this workflow. |
| Visual review is required | Run review, inspect every listed preview, and mark only the visual IDs you actually reviewed before continuing. |
| Facts will not lock | Inspect unresolved conflicts, missing periods or units, and unreviewed visual values. Fix the authoring inputs, then run facts validate --lock again. |
status leaves a step pending | Repair the reported citation, sidecar, retrieval, placeholder, handoff, or length issue, then rerun status. |
| Retrieval validation fails | Run the step plan, satisfy each requirement or record an explicit gap/conflict/review status, register material claims, and rerun retrieve validate --step <N>. |
| A completed step needs substantive revision | Start a fresh run. Do not alter a completed hashed output. |
| The run was interrupted | Run prepare without --new-run; it resumes the newest incomplete run at the first pending step. |
| Validation reports an evidence gap | Add reliable evidence and start a fresh run, or retain the explicit gap when the fact is genuinely unavailable. |
| The report command rejects a run | Complete and validate a v2, v3, or v4 Phase 0 run first. Legacy or incomplete runs are intentionally not rendered. |
| The KPI handoff command rejects a run | Use a completed validated v4 run only; rebuild and validate the public projection before promotion. |
| The report is marked preliminary | Refresh missing current primary inputs in a new analysis run; do not fill valuation gaps with assumptions presented as facts. |
Publication safety
- Keep files beneath
sources/unchanged and outside the public site. - Publish only permitted derived analysis and citations—never licensed documents, credentials, private paths, portfolio details, raw evidence, or a personalized full report.
- Public KPI projections may retain only allowlisted values backed by dated primary HTTPS sources; withheld items must remain explicit gaps.
- Public reports use
Public_Report_Synthesis.mdand the public renderer; never copy the private<TICKER>_Full_Report.htmlinto the website. - Verify
trackers/report_theme.jsonagainst an official HTTPS source before creating a publication bundle. - Review generated output for sensitive information before publication and run browser checks at desktop and 390px mobile widths.