Next.js 15 + TypeScript app implementing the fully-specced first change. Pipeline: resolve -> market data -> pure evaluation engine -> budget guard -> analysis agent -> report. - market-data: DataProvider interface, offline FixtureProvider (DE/SPY seeded from the reference example), FmpProvider (FMP free tier), TTL cache + retry. - technicals: pure MA/volatility/swing/52-week math. - evaluation: instrument-aware pure engine; equity branch built, ETF gated to "not yet supported". Reproduces the DE example (P/E 34.5, fwd 29.3, $167.6B). - agent: AnalysisAgent interface; default Claude Code CLI transport (headless, subscription-backed, web-grounded), Anthropic API alternate via config. - cost-controls: price table, spend store, monthly budget guard. - UI: ticker search + deep-dive toggle, report view, price chart with marked entry/exit/stop levels, cost/budget display, ETF/not-found states. 31 vitest tests, typecheck, production build, and lint all pass. Verified end-to-end via the API for DE, SPY, and an unknown ticker. Live Claude CLI agent test is the documented pick-up point (see README). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
5.9 KiB
ADDED Requirements
Requirement: Provider-agnostic analysis-agent interface
The system SHALL define an AnalysisAgent interface that accepts a structured
evaluation object and returns a written analysis. Consumers MUST depend only on
this interface so the underlying model provider can change without affecting the
evaluation engine or UI.
Scenario: Agent invoked through the interface
- WHEN an evaluation object is passed to the configured analysis agent
- THEN the agent returns a written analysis produced through the interface
Scenario: Alternate implementation can be registered
- WHEN a different agent implementation is configured
- THEN the system uses it without changes to evaluation or UI code
Requirement: Default agent via Claude Code CLI; API as swappable alternate
The system SHALL ship a default AnalysisAgent that invokes the local Claude
Code CLI in headless mode (claude -p --output-format json), which runs on the
operator's existing Claude authentication (e.g. subscription) rather than a metered
API key. The system SHALL also ship an alternate implementation backed by the
Anthropic API (@anthropic-ai/sdk), selectable via configuration without changes
in consumers. Either way, the default model SHALL be Claude Opus 4.8 (CLI alias
opus) and a per-request "deep dive" option SHALL escalate to Claude Fable 5
(CLI alias fable); the model SHALL be selectable per evaluation. Structured
narrative output SHALL be requested via the CLI --json-schema option (or the
equivalent structured-output mechanism on the API alternate). Any API key used by
the alternate SHALL be loaded from configuration and never hard-coded or committed.
Scenario: Claude Code CLI produces the written thesis
- WHEN the CLI agent is configured and an evaluation is submitted
- THEN the system runs
claude -pwith model aliasopusand returns the written thesis parsed from the CLI JSON output
Scenario: Deep-dive escalates to Fable 5
- WHEN an evaluation is requested with the deep-dive option enabled
- THEN the agent runs the CLI with model alias
fablefor that request - AND requests without the option continue to use
opus
Scenario: API alternate selected via configuration
- WHEN the agent transport is configured to the API alternate with a valid key
- THEN evaluations are served through
@anthropic-ai/sdkinstead of the CLI - AND no changes to evaluation or UI code are required
Scenario: Secrets sourced from configuration
- WHEN the API alternate reads its configuration
- THEN the Anthropic API key is loaded from environment/config, not source code
Requirement: Live web grounding
The agent SHALL be able to retrieve current information via its web search and
web fetch capability — the Claude Code CLI's WebSearch/WebFetch tools for the
default transport, or Anthropic's server-side web tools for the API alternate — to
source macro and news-driven facts the structured data layer does not provide:
tariff/rate developments, analyst rating and price-target changes, management
commentary, peer read-throughs, and dated catalysts. Facts drawn from the web SHALL
carry their source so the output can attribute them, and grounding SHALL be scoped
to the ticker under evaluation.
Scenario: Web-sourced facts are attributed
- WHEN the agent uses a web-sourced fact in the analysis (e.g. an analyst target change or a catalyst date)
- THEN the output attributes that fact to its source
Scenario: Grounding degrades gracefully
- WHEN web search or fetch is unavailable or returns an error
- THEN the agent still produces the analysis from the structured evaluation
- AND notes that live macro/news grounding was unavailable
Requirement: Grounded, structured written analysis
The agent SHALL base its narrative on the supplied evaluation data plus attributed web-sourced facts, and SHALL NOT invent figures. It SHALL produce the narrative sections reflected in the example evaluation: current standing, earnings recap and quality-of-earnings caveats, valuation with explicit over/undervalued reasoning, macro factors, timing, entry/exit/stop-loss rationale, bull-versus-bear, and an actionable plan. When a data caveat or discrepancy is present in the input, the agent SHALL preserve it.
Scenario: Narrative grounded in provided data
- WHEN the agent writes the analysis
- THEN every figure it cites is either present in the supplied evaluation object or attributed to a web source it retrieved
Scenario: Data caveats preserved
- WHEN the evaluation object flags a discrepancy or one-time item
- THEN the written analysis surfaces that caveat rather than omitting it
Scenario: Disclaimer preserved in narrative
- WHEN the agent returns its analysis
- THEN the analysis-not-advice disclaimer is present
Requirement: Graceful degradation without an available agent
The system SHALL, when no analysis agent is available (the Claude Code CLI is not installed or not authenticated, or the configured API alternate has no key), still return the full structured evaluation and clearly indicate that the written narrative is unavailable and how to enable it.
Scenario: Agent unavailable
- WHEN an evaluation is requested and no agent transport is available
- THEN the structured evaluation is returned
- AND the response indicates the written analysis is unavailable and how to enable it (authenticate the CLI, or configure an API key)
Requirement: Agent error handling
The system SHALL handle agent failures (auth errors, rate limits, timeouts) by returning a typed error and the underlying structured evaluation, without losing the data already computed.
Scenario: Agent call fails
- WHEN the agent call errors after retries
- THEN the system returns the structured evaluation plus a typed agent error
- AND the computed data is not discarded