moshcode 0.25.1 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,23 @@
1
+ {
2
+ "$schema": "https://anthropic.com/claude-code/marketplace.schema.json",
3
+ "name": "moshcode",
4
+ "description": "moshcode's own Claude Code plugins — the pit's slash commands, in your engine",
5
+ "owner": {
6
+ "name": "moshcoder",
7
+ "url": "https://moshcode.sh"
8
+ },
9
+ "plugins": [
10
+ {
11
+ "name": "ticker",
12
+ "description": "Equity research slash commands backed by advis0r.com: scored reports, extracted signals, transcript search, company-name lookup, and ranked watchlists.",
13
+ "source": "./plugins/ticker",
14
+ "category": "productivity",
15
+ "author": {
16
+ "name": "moshcoder",
17
+ "url": "https://moshcode.sh"
18
+ },
19
+ "homepage": "https://github.com/moshcoder/moshcode#ticker",
20
+ "keywords": ["stocks", "equity", "research", "markets", "advis0r"]
21
+ }
22
+ ]
23
+ }
package/README.md CHANGED
@@ -46,6 +46,8 @@ or miss one that does. A test fails the build when it drifts.
46
46
  | `moshcode engines` | engines | list engines and installation status |
47
47
  | `moshcode tools` | tools | list workflow tools and installation status |
48
48
  | `moshcode trade` | tools | look up markets and trade through Alpaca |
49
+ | `moshcode ticker` <br>`advisor` | tools | equity research from advis0r.com |
50
+ | `moshcode plugin` <br>`plugins` | extend | install moshcode's slash commands into Claude Code |
49
51
  | `moshcode commands` | script | list built-in moshscript commands |
50
52
  | `moshcode completion` | extend | print a shell completion script |
51
53
  | `moshcode run` | script | run a moshscript |
@@ -211,6 +213,49 @@ Alpaca's CLI has no confirmation prompts; `--submit` intentionally removes
211
213
  MoshCode's preview guard. Live trading additionally requires Alpaca's `--live`
212
214
  opt-in or corresponding environment setting.
213
215
 
216
+ ### Equity research (`moshcode ticker`)
217
+
218
+ Where `trade` is Alpaca's order book, `ticker` is the research desk:
219
+ [advis0r.com](https://advis0r.com/api)'s public read-only API, rendered in the
220
+ pit. No key, no login, no write routes, no binary to install:
221
+
222
+ ```sh
223
+ moshcode ticker NVDA # score, technicals, fundamentals, thesis, signals
224
+ moshcode ticker lookup rivian # company name → RIVN
225
+ moshcode ticker signals AAPL # what was said, quoted and sourced
226
+ moshcode ticker search "data center" # across every indexed transcript
227
+ moshcode ticker reports --limit 10 # the stored index, best score first
228
+ moshcode ticker discover fusion # a ranked watchlist (slow — analyzes each candidate)
229
+ moshcode ticker open NVDA # the shareable report page
230
+ ```
231
+
232
+ Add `--json` to any of them for the raw response. The same facade is `/ticker …`
233
+ in the pit, and `MOSHCODE_ADVISOR_URL` points it at another instance.
234
+
235
+ Reports are **stored snapshots**, not live quotes: every response carries
236
+ `reportGeneratedAt` and every renderer prints it, alongside whether the price is
237
+ delayed and which feed produced it. Scores labelled `offline` come from
238
+ deterministic rules rather than a model. It is a research aid, not advice, and
239
+ nothing under `ticker` can place an order.
240
+
241
+ ### Social posting from the pit
242
+
243
+ The pit can hand a prepared post to Bluesky or Nostr without storing either
244
+ account's credentials in MoshCode:
245
+
246
+ ```text
247
+ /socials
248
+ /post bsky "shipped it 🤘"
249
+ /post nostr "shipped it 🤘"
250
+ ```
251
+
252
+ Bluesky opens its official compose intent. Nostr opens the MoshCode composer,
253
+ connects to a NIP-07 browser signer (or a NIP-46 bunker through
254
+ [`window.nostr.js`](https://github.com/fiatjaf/window.nostr.js)), signs a kind-1
255
+ event, and publishes it to the displayed relays. Both flows leave the final
256
+ confirmation in the browser. If the pit is remote or headless, `/post` prints
257
+ the composer URL instead.
258
+
214
259
  ## Browser terminal (`moshcode console`)
215
260
 
216
261
  A real terminal in the browser — arrow keys, history, full-screen TUIs — because
@@ -287,6 +332,34 @@ from and five to rotate. Porkbun's API access is off by default and enabled
287
332
  per-domain — and its documentation tools work with no keys at all, which is a
288
333
  sensible way to try the server before trusting it with DNS writes.
289
334
 
335
+ ## Claude Code plugins
336
+
337
+ MoshCode publishes its own plugin marketplace, so the pit's slash commands work
338
+ inside your engine too:
339
+
340
+ ```sh
341
+ moshcode plugin list # what the marketplace ships, and who can take it
342
+ moshcode plugin install # add the marketplace + install `ticker`
343
+ moshcode plugin remove ticker # take it back off
344
+ ```
345
+
346
+ `ticker@moshcode` adds `/ticker`, `/signals`, `/research`, `/lookup`,
347
+ `/reports`, and `/discover` — the same advis0r research surface described above,
348
+ driven from inside a coding session. Restart the engine afterwards; a newly
349
+ installed plugin is not live in a session that is already running.
350
+
351
+ The equivalent by hand:
352
+
353
+ ```sh
354
+ claude plugin marketplace add moshcoder/moshcode
355
+ claude plugin install ticker@moshcode
356
+ ```
357
+
358
+ Claude Code is currently the only engine with a plugin primitive. The others are
359
+ reported as skipped with a reason, the same way they are for skills, rather than
360
+ being left out of the summary. `MOSHCODE_PLUGIN_SOURCE=.` installs from a local
361
+ checkout instead of GitHub, which is how you try an unreleased plugin.
362
+
290
363
  ## Upgrade everything
291
364
 
292
365
  ```sh
package/bin/moshcode.mjs CHANGED
@@ -19,7 +19,9 @@ import { tradeArgs, tradeUsage } from "../src/trade.mjs";
19
19
  import { runUpgrade } from "../src/upgrade.mjs";
20
20
  import { selfUpdateCommand } from "../src/selfupdate.mjs";
21
21
  import { describeUninstall, uninstallPlan } from "../src/uninstall.mjs";
22
- import { mcpCommand, skillCommand } from "../src/integrations.mjs";
22
+ import { mcpCommand, pluginCommand, skillCommand } from "../src/integrations.mjs";
23
+ import { tickerCommand } from "../src/advisor.mjs";
24
+ import { canOpenBrowser, openBrowser } from "../src/open-url.mjs";
23
25
  import { locate, tilde } from "../src/pwd.mjs";
24
26
  import { createPrd, listPrds, authoringPrompt } from "../src/prd.mjs";
25
27
  import { loginAuto, whoami, logout } from "../src/auth.mjs";
@@ -344,6 +346,18 @@ async function main() {
344
346
  propagateExit(r.code, r.signal);
345
347
  return;
346
348
  }
349
+ if (cmd === "ticker" || cmd === "advisor") {
350
+ const code = await tickerCommand(rest, {
351
+ openUrl: (url) => canOpenBrowser() && openBrowser(url),
352
+ });
353
+ if (code) process.exitCode = code;
354
+ return;
355
+ }
356
+ if (cmd === "plugin" || cmd === "plugins") {
357
+ const code = await pluginCommand(rest);
358
+ if (code) process.exitCode = code;
359
+ return;
360
+ }
347
361
  if (cmd === "console") {
348
362
  const code = await consoleCommand(rest);
349
363
  if (code) process.exitCode = code;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "moshcode",
3
- "version": "0.25.1",
3
+ "version": "0.26.0",
4
4
  "type": "module",
5
5
  "description": "moshcode — a metal wrapper for coding engines and native UGig/CoinPay workflow CLIs, with OpenPRD and moshscript",
6
6
  "repository": {
@@ -25,6 +25,8 @@
25
25
  "src",
26
26
  "examples",
27
27
  "prd",
28
+ ".claude-plugin",
29
+ "plugins",
28
30
  "install.sh",
29
31
  "README.md"
30
32
  ],
@@ -0,0 +1,13 @@
1
+ {
2
+ "$schema": "https://anthropic.com/claude-code/plugin.schema.json",
3
+ "name": "ticker",
4
+ "description": "Equity research slash commands backed by advis0r.com: scored reports, extracted signals, transcript search, company-name lookup, and ranked watchlists.",
5
+ "version": "0.1.0",
6
+ "author": {
7
+ "name": "moshcoder",
8
+ "url": "https://moshcode.sh"
9
+ },
10
+ "homepage": "https://github.com/moshcoder/moshcode#ticker",
11
+ "license": "MIT",
12
+ "keywords": ["stocks", "equity", "research", "markets", "advis0r"]
13
+ }
@@ -0,0 +1,49 @@
1
+ # ticker — equity research in your engine 🤘
2
+
3
+ Slash commands backed by [advis0r.com](https://advis0r.com/api): scored research
4
+ reports, extracted signals with sources, transcript search, company-name lookup,
5
+ and ranked watchlists.
6
+
7
+ | command | what it does |
8
+ | --- | --- |
9
+ | `/ticker NVDA` | score, technicals, fundamentals, thesis, signals, sources |
10
+ | `/signals AAPL` | what was actually said, quoted and sourced |
11
+ | `/research data center` | full-text search across every indexed transcript |
12
+ | `/lookup rivian` | company name → `RIVN` |
13
+ | `/reports` | every stored report, best score first |
14
+ | `/discover fusion` | a ranked watchlist for a topic (slow) |
15
+
16
+ ## Install
17
+
18
+ ```bash
19
+ moshcode plugin install
20
+ ```
21
+
22
+ Or straight from Claude Code:
23
+
24
+ ```bash
25
+ claude plugin marketplace add moshcoder/moshcode
26
+ claude plugin install ticker@moshcode
27
+ ```
28
+
29
+ Restart the engine afterwards — a newly installed plugin is not live in a
30
+ session that is already running.
31
+
32
+ ## How it works
33
+
34
+ Each command shells out to `moshcode ticker …`, which calls advis0r's public,
35
+ read-only API. No key, no login, no write routes. With `moshcode` absent, every
36
+ command falls back to `curl` against the same endpoints.
37
+
38
+ Point the commands at another instance with `MOSHCODE_ADVISOR_URL`.
39
+
40
+ ## What this is not
41
+
42
+ A research aid, not advice. Reports are **stored snapshots** — every response
43
+ carries `reportGeneratedAt`, and every command is instructed to print it, because
44
+ a stale price presented as a live one is the one failure mode that actually costs
45
+ someone money. Scores marked `offline` come from deterministic rules, not a model.
46
+
47
+ Trading lives behind a different verb: `moshcode trade` wraps Alpaca, previews
48
+ orders by default, and requires an explicit `--submit`. Nothing in this plugin
49
+ can place an order.
@@ -0,0 +1,37 @@
1
+ ---
2
+ description: Build a ranked watchlist for a topic (slow — it analyzes each candidate).
3
+ argument-hint: "[topic]"
4
+ allowed-tools: Bash(moshcode ticker:*), Bash(curl -sS https://advis0r.com/api/:*)
5
+ ---
6
+
7
+ ## Task
8
+
9
+ Rank candidates for `$ARGUMENTS` (no topic → the default watchlist).
10
+
11
+ ```bash
12
+ moshcode ticker discover $ARGUMENTS --limit 10 --json
13
+ ```
14
+
15
+ Fallback: `curl -sS --max-time 180 "https://advis0r.com/api/discover?topic=<url-encoded>&provider=offline&horizon=2&limit=10"`
16
+
17
+ **This route runs an analysis per candidate and can take minutes.** Tell the
18
+ user it is working before you start, and do not retry on a timeout — re-running
19
+ it costs the same minutes again.
20
+
21
+ ## Reading the response
22
+
23
+ `candidates` is ranked, each with `rank`, `ticker`, `companyName`, `lastPrice`,
24
+ `overallScore`, `confidence`, `classification`, `thesis`, `primaryCatalyst`,
25
+ `mainRisk`, `independentConfirmation`, plus liquidity fields
26
+ (`bidAskSpreadPercent`, `avgVolume`, `float`, `marketCap`).
27
+
28
+ ## Rules
29
+
30
+ - Lead with `rank`, `ticker`, `overallScore`, and `classification`.
31
+ - **Print `mainRisk` next to every thesis.** A ranked list that shows only the
32
+ bull case is a pitch, not research.
33
+ - `provider: offline` means these scores are deterministic rules, not a model.
34
+ Say which provider produced the ranking.
35
+ - Flag illiquidity: a wide `bidAskSpreadPercent` or thin `avgVolume` matters
36
+ more than the score for anything small-cap.
37
+ - End with the response's own `disclaimer`.
@@ -0,0 +1,27 @@
1
+ ---
2
+ description: Find a ticker symbol by company name (rivian → RIVN).
3
+ argument-hint: <company name>
4
+ allowed-tools: Bash(moshcode ticker:*), Bash(curl -sS https://advis0r.com/api/:*)
5
+ ---
6
+
7
+ ## Task
8
+
9
+ Resolve `$ARGUMENTS` to a ticker symbol.
10
+
11
+ ```bash
12
+ moshcode ticker lookup $ARGUMENTS --limit 10 --json
13
+ ```
14
+
15
+ Fallback: `curl -sS "https://advis0r.com/api/lookup?q=<url-encoded>&limit=10"`
16
+
17
+ ## Reading the response
18
+
19
+ `matches` is a list of `{ symbol, name, exchange, hasReport }`.
20
+ `hasReport: true` means advis0r already has a stored research snapshot.
21
+
22
+ ## Rules
23
+
24
+ - Show every match with its exchange — "Delta" is an airline and a faucet company.
25
+ - Mark which ones have a report, and offer `/ticker <SYMBOL>` for those.
26
+ - One unambiguous match: say the symbol and go straight to offering the report.
27
+ - No match: say the *directory* has no match, and do not invent a symbol.
@@ -0,0 +1,30 @@
1
+ ---
2
+ description: Every stored advis0r research report, best score first.
3
+ argument-hint: "[--limit n] [--sort recent|score|ticker]"
4
+ allowed-tools: Bash(moshcode ticker:*), Bash(curl -sS https://advis0r.com/api/:*)
5
+ ---
6
+
7
+ ## Task
8
+
9
+ List the stored reports.
10
+
11
+ ```bash
12
+ moshcode ticker reports $ARGUMENTS --json
13
+ ```
14
+
15
+ Fallback: `curl -sS "https://advis0r.com/api/reports?sort=score&limit=25"`
16
+
17
+ ## Reading the response
18
+
19
+ `reports` is a list of `{ ticker, companyName, lastPrice, overallScore,
20
+ confidence, classification, aiProvider, aiModel, sourceCount, signalCount,
21
+ generatedAt }`, and `total` is how many exist.
22
+
23
+ ## Rules
24
+
25
+ - Render as a table: ticker, score, classification, price, generated-at.
26
+ - **`generatedAt` per row, always.** These are snapshots taken at different
27
+ times; a table that hides that reads as one consistent as-of date.
28
+ - A row with no `aiProvider` was scored deterministically, not by a model.
29
+ - Offer `/ticker <SYMBOL>` for anything worth a closer look.
30
+ - This is a coverage list, not a recommendation list. Rank order is score order.
@@ -0,0 +1,29 @@
1
+ ---
2
+ description: Full-text search across every indexed earnings transcript and article.
3
+ argument-hint: <words to search for>
4
+ allowed-tools: Bash(moshcode ticker:*), Bash(curl -sS https://advis0r.com/api/:*)
5
+ ---
6
+
7
+ ## Task
8
+
9
+ Search the transcript index for `$ARGUMENTS`.
10
+
11
+ ```bash
12
+ moshcode ticker search $ARGUMENTS --limit 20 --json
13
+ ```
14
+
15
+ Fallback: `curl -sS "https://advis0r.com/api/search?q=<url-encoded>&limit=20"`
16
+
17
+ ## Reading the response
18
+
19
+ `results` is a list of segments: `text`, `speaker`, `ticker`, `event_date`.
20
+ The API tries full-text search first and falls back to a substring scan, so a
21
+ hit is a hit — but relevance is not ranked. Read before summarizing.
22
+
23
+ ## Rules
24
+
25
+ - Cluster the hits by ticker and say which companies came up, with dates.
26
+ - Quote sparingly and attribute each quote to its speaker and ticker.
27
+ - If nothing matches, say the *index* has no match — this searches advis0r's
28
+ indexed corpus, not the whole web. Suggest `/lookup` if the query looks like
29
+ a company name.
@@ -0,0 +1,30 @@
1
+ ---
2
+ description: What was actually said about a ticker — extracted signals with quotes and sources.
3
+ argument-hint: <SYMBOL>
4
+ allowed-tools: Bash(moshcode ticker:*), Bash(curl -sS https://advis0r.com/api/:*)
5
+ ---
6
+
7
+ ## Task
8
+
9
+ List the extracted signals for `$ARGUMENTS`.
10
+
11
+ ```bash
12
+ moshcode ticker signals $ARGUMENTS --json
13
+ ```
14
+
15
+ Fallback: `curl -sS "https://advis0r.com/api/signals?ticker=$ARGUMENTS"`
16
+
17
+ ## Reading the response
18
+
19
+ Each signal carries `signal_type`, `direction` (positive/negative/neutral),
20
+ `strength`, `specificity`, `quote`, `event_date`, `speaker`, `speaker_title`,
21
+ `source_url`, and `source_tier`.
22
+
23
+ ## Rules
24
+
25
+ - Group by direction and lead with the most recent. Note the positive/negative split.
26
+ - **Every claim keeps its `source_url`.** These are extracted quotes from
27
+ transcripts and articles — a signal repeated without its source is a rumor.
28
+ - `strength` and `specificity` are the extractor's confidence, not the market's.
29
+ A strong signal from a low `source_tier` is still a low-tier source; say so.
30
+ - End with the response's own `disclaimer`.
@@ -0,0 +1,42 @@
1
+ ---
2
+ description: Research one ticker — score, technicals, fundamentals, thesis, signals, and sources.
3
+ argument-hint: <SYMBOL>
4
+ allowed-tools: Bash(moshcode ticker:*), Bash(curl -sS https://advis0r.com/api/:*)
5
+ ---
6
+
7
+ ## Task
8
+
9
+ Pull the stored research report for `$ARGUMENTS` and summarize it for the user.
10
+
11
+ Run:
12
+
13
+ ```bash
14
+ moshcode ticker $ARGUMENTS --json
15
+ ```
16
+
17
+ If `moshcode` is not installed, fall back to the API directly:
18
+
19
+ ```bash
20
+ curl -sS "https://advis0r.com/api/ticker?symbol=$ARGUMENTS"
21
+ ```
22
+
23
+ ## Reading the response
24
+
25
+ - `overallScore` (0–100), `confidence`, and `classification` are the headline. A
26
+ low score is a *finding*, not a failure to report.
27
+ - `aiAnalysis.analysis.thesis` is a hosted-model take; `analysis.thesis` is a
28
+ deterministic offline one. Say which you are quoting — they carry different weight.
29
+ - `technical` holds rsi14 / sma / macd / atr / relativeVolume.
30
+ - `facts` holds SEC fundamentals; `facts.source === "unavailable"` means the
31
+ fundamentals section is missing, not that the company has none.
32
+ - `signals` are extracted quotes with `direction` and `source_url`.
33
+ - `sources` are the documents behind them.
34
+
35
+ ## Rules
36
+
37
+ - **`reportGeneratedAt` is when this snapshot was built.** State it. The price in
38
+ a stored report is not a live quote, and must never be presented as one.
39
+ - If the response is a 400 with `didYouMean`, the user typed a company name
40
+ rather than a symbol — re-run against the suggested symbol and say you did.
41
+ - End with the response's own `disclaimer`. This is research, not advice.
42
+ - Link the shareable report: `https://advis0r.com/ticker/<SYMBOL>`.
@@ -0,0 +1,130 @@
1
+ ---
2
+ openprd: "0.2"
3
+ id: "0008"
4
+ title: "Bring equity research into the pit, and ship the pit's slash commands as a plugin"
5
+ status: Draft
6
+ authors:
7
+ - anthony@profullstack.com
8
+ created: 2026-08-06
9
+ updated: 2026-08-06
10
+ repo: https://github.com/moshcoder/moshcode
11
+ discussion:
12
+ implementation:
13
+ tags:
14
+ - research
15
+ - plugins
16
+ - advis0r
17
+ supersedes:
18
+ superseded-by:
19
+ ---
20
+
21
+ ## Problem
22
+
23
+ `moshcode trade` can look up a quote and place an order. It cannot answer the
24
+ question that comes before either one — *is this worth buying?* Everything that
25
+ would inform that lives in [advis0r.com](https://advis0r.com/api): indexed
26
+ earnings transcripts and news, extracted signals with sources, SEC fundamentals,
27
+ technicals, and a composite score. Today that means leaving the pit for a
28
+ browser, and it means an agent working in a session has no path to it at all.
29
+
30
+ Two separate gaps, one cause:
31
+
32
+ 1. **In the pit.** There is no research verb. `/trade quote AAPL` returns a
33
+ price and nothing about why it is that price.
34
+ 2. **In the engine.** moshcode already fans MCP servers and Agent Skills out
35
+ across engines, but it publishes no commands of its own. A slash command that
36
+ exists at the mosh prompt does not exist inside Claude Code, and there is no
37
+ mechanism by which it could.
38
+
39
+ ## Goals
40
+
41
+ - Research a ticker without leaving the terminal, in one short command.
42
+ - An agent mid-session can pull sourced evidence about a company rather than
43
+ recalling it from training data.
44
+ - moshcode's own slash commands become installable into the engines it drives,
45
+ through the engines' native plugin mechanism rather than a moshcode-specific one.
46
+ - A stored snapshot is never mistaken for a live quote.
47
+
48
+ ## Non-Goals
49
+
50
+ - Placing orders. `trade` owns that, with its preview-by-default guard; nothing
51
+ under `ticker` writes anything anywhere.
52
+ - Reimplementing advis0r. Every route used is public, read-only, and unauthenticated;
53
+ scoring, ingestion, and analysis stay server-side.
54
+ - Authentication. The routes that need a sign-in (`/api/digest`,
55
+ `/api/report/regenerate`) are deliberately out of scope — adding credentials
56
+ would make this the first moshcode verb that holds one.
57
+ - A general plugin framework. One marketplace, one plugin, extended by adding a
58
+ directory.
59
+
60
+ ## Users
61
+
62
+ - Someone in the pit deciding what to look at before opening the trading CLI.
63
+ - A coding agent asked about a company, which should cite indexed sources rather
64
+ than assert from memory.
65
+
66
+ ## Requirements
67
+
68
+ - R1 [P0] `moshcode ticker <SYMBOL>` prints the stored report: score, confidence,
69
+ classification, technicals, fundamentals, thesis, recent signals, and sources.
70
+ - R2 [P0] Verbs for the rest of the surface: `signals`, `search`, `lookup`,
71
+ `reports`, `discover`, `tickers`, `stats`, `open`. A first argument that is not
72
+ a verb is a symbol; `report` is the unambiguous spelling for a symbol that
73
+ collides with one.
74
+ - R3 [P0] Every rendered report states `reportGeneratedAt`, whether the price is
75
+ delayed, and which feed produced it. A stored price must never render as a live one.
76
+ - R4 [P0] Every substantive response carries the API's own `disclaimer` through
77
+ to the output.
78
+ - R5 [P0] `--json` on any verb prints the raw response, so scripts and agents get
79
+ the full document rather than the rendered subset.
80
+ - R6 [P0] The same surface is `/ticker …` at the mosh prompt.
81
+ - R7 [P1] A non-symbol argument is refused with the `lookup` that resolves it,
82
+ and a 400 carrying `didYouMean` surfaces the suggestion.
83
+ - R8 [P0] `.claude-plugin/marketplace.json` publishes a `ticker` plugin providing
84
+ `/ticker`, `/signals`, `/research`, `/lookup`, `/reports`, `/discover`.
85
+ - R9 [P0] `moshcode plugin install` adds the marketplace and installs the plugin,
86
+ fanning out across engines and reporting every engine without a plugin
87
+ primitive as skipped — the same contract as 0003 R8 for skills.
88
+ - R10 [P1] `MOSHCODE_ADVISOR_URL` and `MOSHCODE_PLUGIN_SOURCE` redirect the API
89
+ and the marketplace, so both are testable against a checkout.
90
+ - R11 [P1] The verb table in the schema and the parser's own list are checked
91
+ against each other, so a verb cannot complete and then fail.
92
+
93
+ ## UX Notes
94
+
95
+ `ticker` renders in-process rather than handing the terminal to a tool, because
96
+ unlike every other entry in `tools`, there is no advis0r binary — only an HTTP
97
+ API. That makes it the first moshcode verb that formats a remote response itself,
98
+ so the rendering rules matter more than usual:
99
+
100
+ - Direction is colour: acid for positive signals, red for negative.
101
+ - A model-written thesis is labelled with its provider and model; a
102
+ deterministic one is labelled `offline`. They carry different weight and must
103
+ not look alike.
104
+ - Optional sections (fundamentals, technicals, analysis) are genuinely absent
105
+ when SEC or the market feed rate-limits. A missing section degrades the report;
106
+ it never prevents one.
107
+ - `discover` ranks by analyzing each candidate and legitimately takes minutes. It
108
+ gets a longer timeout than the row-read routes, and says so up front.
109
+
110
+ ## Success Metrics
111
+
112
+ - `/ticker <SYMBOL>` answers in one line of input, with sources.
113
+ - The plugin installs into Claude Code and its six commands appear, verified by
114
+ `claude plugin validate` and an end-to-end install.
115
+ - No rendered output anywhere presents a stored price as a live quote.
116
+
117
+ ## Risks & Open Questions
118
+
119
+ - **Scored equity research one verb away from an order-placing CLI.** The
120
+ mitigation is structural rather than advisory: `ticker` has no write path,
121
+ `trade` keeps its preview guard, and the disclaimer travels with the data.
122
+ - **Snapshot staleness.** advis0r rebuilds a report when it is missing or when a
123
+ watchlist member asks; moshcode cannot trigger a rebuild without
124
+ authentication. Printing the generated-at stamp is the honest answer, not a
125
+ workaround.
126
+ - Single upstream: if advis0r is down, the verb is down. Acceptable — it is a
127
+ research aid, not a dependency of anything else in moshcode.
128
+ - Open: whether `plugin` should later fan out to other engines as they gain
129
+ plugin primitives, or stay Claude-specific. The plan structure already allows
130
+ the first without a rewrite.
package/prd/README.md CHANGED
@@ -23,4 +23,5 @@ Start one with `moshcode prd "<idea>"` (TUI: `/prd`).
23
23
  | [0005](0005-hosted-moshpit-resolver.md) | A hosted Moshpit resolver, for the devices that cannot run the bridge | Draft |
24
24
  | [0006](0006-help.md) | --help | Draft |
25
25
  | [0007](0007-profullstack-site-init.md) | Generate batteries-included Profullstack sites for Moshpit names | Draft |
26
+ | [0008](0008-ticker-research-and-plugin-marketplace.md) | Bring equity research into the pit, and ship the pit's slash commands as a plugin | Draft |
26
27
  <!-- PRD-INDEX:END -->