Analysis workflow

Move from a grounded local source packet to a cited, resumable 14-step equity analysis, a private full report, and—when the run is v4—a public-safe KPI handoff. The workflow keeps raw sources unchanged and validates every derived artifact before it can be used.

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.

SkillUse it forGate or output
$analyze-equityStart, resume, or validate the 14-step Phase 0 analysis.Completed run validates as VALID.
$equity-reportTurn a completed Phase 0 run into a cited private HTML report.Requires a completed v2, v3, or v4 run; finishes as VALID REPORT.
$kpi-handoffCompile a completed v4 run into an internal handoff and a redacted public KPI projection.Preview and validate before the explicit promote step.
Typical request: 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

  1. Open the Investment workspace. Work from the repository root that contains app/, stocks/, and .agents/skills/.
  2. 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"
  3. Add source documents. Put them anywhere under stocks/<TICKER>/sources/. Keep the raw files unchanged.
  4. 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.

  5. 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.
  6. 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 Codex handles: workspace validation, source inventory, extraction, visual-review tracking, fact and calculation locks, hybrid retrieval, sequential prompt execution, citations, resumable state, private report synthesis, public-safe KPI projection, deterministic rendering, and final validation.

What you need

RequirementNeeded?Purpose
Investment workspaceRequiredContains the skills, prompts, helper CLIs, ticker folders, and tests.
Python 3.9 or newerRequiredRuns source intake, Phase 0, report rendering, and KPI handoff validation.
pypdfRequired for PDFsExtracts text page by page without converting or rewriting the original PDF.
MarkdownRequired for HTML reportsRenders the cited report synthesis and accepted analysis appendix into standalone HTML.
stocks/<TICKER>/sources/RequiredThe hard input contract. At least one usable source is the practical minimum for meaningful analysis.
Codex with local skillsRequired for the guided workflowUse $analyze-equity, then the separate report or KPI skill as needed.
Portfolio detailsOptionalPersonalizes 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.

PriorityEvidenceMain coverage
CoreLatest annual report or 10-KBusiness model, financial history, risks, capital structure, headcount, and long-term economics.
CoreLatest quarterly report or 10-QCurrent growth, margins, liquidity, guidance, dilution, and balance-sheet changes.
CoreEarnings release and call transcriptGuidance, operating drivers, management explanations, catalysts, and current debates.
RecommendedInvestor presentation or analyst dayStrategy, market opportunity, product roadmap, capital allocation, and KPI definitions.
RecommendedRelevant 8-Ks and event transcriptsFinancing, restructuring, M&A, leadership, regulatory, and product developments.
RecommendedProxy statement, ownership, and estimate evidenceIncentives, insider alignment, holder mix, revisions, and valuation context.
OptionalLegally usable market-data or research PDFsHistorical multiples, price context, consensus, peer comparisons, and sentiment.
Do not publish licensed source documents, private source paths, credentials, or raw evidence. Public outputs should contain only permitted analysis and citations.

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.

StepAnalysisPurpose
01Business PhaseClassify the company from startup through decline and establish the phase used later.
02Business AnalysisExplain the value proposition, revenue architecture, customer structure, pricing, and economics.
03MoatAssess switching costs, network effects, intangible assets, cost advantages, and counter-positioning.
04Long-Term Growth DriversSeparate funded growth from narrative growth across customer acquisition and expansion.
05Phase-Specific Key MetricsScore the metrics, ownership signals, estimates, and value creation appropriate to Step 1's phase.
06RiskRun a forensic pre-mortem covering concentration, financial, governance, and structural risks.
07Phase-Appropriate Valuation MetricsSelect the correct valuation family for Step 1's phase and judge support versus history and peers.
08Price and SentimentConnect one-year price action to catalysts, positioning, analyst views, and narrative shifts.
09AntifragilityStress liquidity, leverage, cash generation, asset quality, and survival under operating shocks.
10Reverse DCFTranslate the market price into the growth and margin expectations it implies.
11Intrinsic ValuationEstimate value with explicit operating, discount-rate, terminal, and scenario assumptions.
12Final Decision and Buy PlanSynthesize Steps 10 and 11 with prior evidence and portfolio context into an action framework.
13Behavioral Bias CheckAudit confirmation bias, overconfidence, herding, recency, and position-specific behavior.
14Efficiency and AI ProductivityTest 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.
Evidence confidence is not the same as investability. If current price, capitalization, share count, or valuation inputs are incomplete, the affected conclusion remains explicitly preliminary.

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>]
  1. Prepare: select the newest completed v4 run unless a run ID is explicitly named.
  2. Curate: add stable KPI definitions, typed observations, thresholds, catalysts, risks, and monitoring triggers with lineage.
  3. Build and preview: compile the internal handoff and the redacted public projection; preview reads only the public projection.
  4. Validate: confirm hashes, source lineage, compatible periods and units, reviewed visuals, and absence of private fields.
  5. Promote: explicitly lock the validated run as trackers/kpi_current.json. Promotion does not publish or modify the public Reports site by itself.
Public KPI output keeps only dated primary HTTPS evidence. Licensed, private, local-path, portfolio, and unsourced observations become explicit gaps instead of being copied into the public projection.

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.

Review the exact bundle and rendered pages first. Publication remains a separate approval: the tooling does not commit or push to GitHub automatically.

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.json records the contract, status, detected phase, assumptions, prompt and source hashes, citations, web sources, timestamps, and failures.
  • evidence_catalog.json inventories the usable sources, images requiring inspection, and isolated source errors.
  • evidence_blocks.jsonl, evidence_tables.jsonl, and evidence_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-run creates a new timestamped run.
  • report_manifest.json fingerprints the accepted analysis, synthesis, styles, portfolio context, and rendered HTML without modifying run_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

SymptomWhat to do
pypdf is missingRun python3 -m pip install -r requirements.txt, then repeat prepare.
A PDF or text file cannot be readInspect 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 textVisually inspect it before relying on it. Images are not OCR-converted by this workflow.
Visual review is requiredRun review, inspect every listed preview, and mark only the visual IDs you actually reviewed before continuing.
Facts will not lockInspect unresolved conflicts, missing periods or units, and unreviewed visual values. Fix the authoring inputs, then run facts validate --lock again.
status leaves a step pendingRepair the reported citation, sidecar, retrieval, placeholder, handoff, or length issue, then rerun status.
Retrieval validation failsRun 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 revisionStart a fresh run. Do not alter a completed hashed output.
The run was interruptedRun prepare without --new-run; it resumes the newest incomplete run at the first pending step.
Validation reports an evidence gapAdd reliable evidence and start a fresh run, or retain the explicit gap when the fact is genuinely unavailable.
The report command rejects a runComplete 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 runUse a completed validated v4 run only; rebuild and validate the public projection before promotion.
The report is marked preliminaryRefresh 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.md and the public renderer; never copy the private <TICKER>_Full_Report.html into the website.
  • Verify trackers/report_theme.json against 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.
This workflow supports investment research and decision discipline. It does not provide personalized investment advice, guarantee data completeness, or replace independent verification.