mirror of
https://github.com/tiennm99/miti99bot.git
synced 2026-09-04 04:18:08 +00:00
docs(stock): add stock-events plan artifacts
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
---
|
||||
phase: 1
|
||||
title: Extend SSI Corporate Events
|
||||
status: completed
|
||||
priority: P2
|
||||
dependencies: []
|
||||
---
|
||||
|
||||
# Phase 1: Extend SSI Corporate Events
|
||||
|
||||
## Overview
|
||||
Add an additive SSI corporate-action fetch path for read-only event listing. Preserve the current dividend-specific contract used by `/stock_portfolio` and retained dividend history.
|
||||
|
||||
## Requirements
|
||||
- Functional: fetch all SSI corporate-action rows for one normalized symbol in `(after, through]`, with the same one-day Asia/Saigon overlap and provider page caps already enforced in `C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\stock\dividend_events_ssi.go:23` and `C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\stock\dividend_events_ssi.go:113`.
|
||||
- Functional: deduplicate by SSI `CorId`, then return deterministic chronological order by `PublishedAt`, tie-broken by provider ID as today’s dividend path does at `C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\stock\dividend_events_ssi.go:160`.
|
||||
- Functional: preserve SSI raw display fields for the generic command path: symbol, provider ID, SSI type code/label, title/description/name, published/ex/record/payment strings, value, ratio, and source URL.
|
||||
- Functional: use a private cursor timestamp only for filtering and sorting; do not replace the raw SSI date strings with normalized event dates in the display model.
|
||||
- Functional: keep `FetchDividendEvents` behavior unchanged for dividend discovery and `/stock_portfolio` notifications (`C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\stock\dividend_events.go:12`, `C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\stock\dividend_notifications.go:204`).
|
||||
- Non-functional: no persistence, no callback/button work, no schema/index/system-state changes.
|
||||
|
||||
## Architecture
|
||||
`SSIDividendProvider` already owns SSI HTTP access, page fetches, date parsing, and source-link generation in `C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\stock\dividend_events_ssi.go:92`, `C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\stock\dividend_events_ssi.go:172`, `C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\stock\dividend_events_ssi.go:247`, and `C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\stock\dividend_events_ssi.go:309`. Phase 1 adds a parallel generic event model plus an additive fetch method that reuses those helpers, but does not widen `DividendEvent` validation.
|
||||
|
||||
Data flow:
|
||||
1. Symbol and time window enter the generic provider.
|
||||
2. SSI pages are fetched with the existing timeout/cap logic.
|
||||
3. Each raw SSI row is copied into a generic display model with minimal validation: matching symbol, valid provider ID, and a private cursor timestamp via `publicDate` or the existing fallback chain.
|
||||
4. Generic rows are sorted and returned to the command layer with raw SSI strings intact; dividend-only normalization remains on the separate `FetchDividendEvents` path.
|
||||
|
||||
## Related Code Files
|
||||
- Create: `C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\stock\stock_events.go` — introduce the generic stock-event model and provider interface shared by the SSI provider and command handler.
|
||||
- Modify: `C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\stock\dividend_events_ssi.go` — add the additive generic SSI fetch method and generic row normalizer while keeping dividend normalization intact.
|
||||
- Modify: `C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\stock\dividend_events_ssi_test.go` — cover generic pagination/dedup/range/order behavior and explicit dividend-regression expectations.
|
||||
|
||||
## Implementation Steps
|
||||
1. Define a generic read-only event type and provider interface separate from `DividendEvent` so `/stock_portfolio` persistence rules are not broadened.
|
||||
2. Add an additive SSI fetch method that reuses `fetchPage`, `startOfSaigonDay`, `parseSSIOptionalDate`, `parseSSIDate`, and `eventSourceURL` instead of introducing a second transport/client stack.
|
||||
3. Normalize every matching SSI row into a generic display model with title fallback order `EventTitle -> EventDescription -> EventName -> EventListCode`, while requiring only data needed for chronological display.
|
||||
4. Keep `FetchDividendEvents` and `normalizeEvent` behavior additive-only: no relaxed dividend validation for value/ratio fields, no changes to portfolio history serialization.
|
||||
5. Add provider tests for cross-page deduplication, one-day overlap filtering, deterministic ordering, generic inclusion of non-dividend corporate actions, and a regression assertion that dividend discovery still excludes non-dividend rows.
|
||||
|
||||
## Success Criteria
|
||||
- [x] Generic SSI fetch returns all eligible corporate actions in deterministic chronological order for one ticker and lookback window.
|
||||
- [x] Generic fetch propagates upstream/paging/decode errors to the caller instead of silently succeeding with partial pages.
|
||||
- [x] Existing dividend-provider tests still pass with no behavior drift in `/stock_portfolio` discovery.
|
||||
|
||||
## Risk Assessment
|
||||
- High: weakening dividend validation would change `/stock_portfolio` suggestions and history merges. Mitigation: additive generic method only; keep dividend-specific tests green before Phase 2.
|
||||
- Medium: malformed SSI rows could create unstable or unsortable output. Mitigation: require a usable publish timestamp and provider ID; skip rows that cannot be placed chronologically.
|
||||
- Medium: over-refactoring the proven dividend loop increases blast radius. Mitigation: reuse helper functions first; duplicate only the page-scan control flow if that keeps the dividend path unchanged.
|
||||
- Rollback: revert the generic provider additions and tests only. No stored data or public command contract exists yet, so rollback is code-only and isolated.
|
||||
@@ -0,0 +1,59 @@
|
||||
---
|
||||
phase: 2
|
||||
title: "Add Telegram Command"
|
||||
status: completed
|
||||
priority: P2
|
||||
dependencies: [1]
|
||||
---
|
||||
|
||||
# Phase 2: Add Telegram Command
|
||||
|
||||
## Overview
|
||||
Expose `/stock_events <ticker> [days]` as a public, read-only Telegram command. Keep it independent from sender-specific portfolio state and produce deterministic, Telegram-safe SSI event output.
|
||||
|
||||
## Requirements
|
||||
- Functional: register public command metadata in `C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\stock\stock.go:13` with exact parameters `<ticker> [days]` and a concise description compatible with `/help` and Telegram’s native menu (`C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\command_presentation.go:6`, `C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\validate.go:14`).
|
||||
- Functional: accept exactly 1 required arg plus 1 optional days arg; default days to 30; allow only whole numbers `1..90`; reject missing or extra args with exact usage text.
|
||||
- Functional: normalize ticker with `normalizeStockSymbol` at `C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\stock\symbols.go:18`; surface the same unknown-ticker wording used by current stock handlers at `C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\stock\handlers.go:93`.
|
||||
- Functional: do not require `senderInfo`, `LoadPortfolio`, `PendingDividendStore`, or any write path from `C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\stock\handlers.go:59` and `C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\stock\portfolio.go:64`.
|
||||
- Functional: respond cleanly for no events, upstream/provider failure, and parse failure.
|
||||
- Non-functional: preserve provider order, bound every message below the repo’s 4000-char Telegram safety margin used at `C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\stock\handlers.go:480` and `C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\stats\views.go:17`.
|
||||
|
||||
## Architecture
|
||||
Data flow:
|
||||
1. Dispatcher routes the public command to `handleStockEvents`.
|
||||
2. The handler parses args, defaults/validates `days`, normalizes the ticker, and computes `after = now - days*24h`, `through = now`.
|
||||
3. The handler calls the generic SSI provider from Phase 1 and receives chronologically sorted corporate actions.
|
||||
4. Each event becomes a plain-text block with symbol, SSI type, bounded title, populated dates, and `SSI event: <id>` plus the raw source URL when present.
|
||||
5. Blocks are packed into `<=4000`-char replies without splitting an event block; multi-message output adds deterministic part numbering. If one block still exceeds budget after field truncation, hard-truncate the final line with `…(truncated)`.
|
||||
|
||||
Formatting strategy:
|
||||
- Reuse the package-level rune-safe truncation helper from `C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\stock\dividend_notifications.go:363` for long titles and labels.
|
||||
- Prefer plain-text replies via `chathelper.Reply` instead of HTML tables so raw SSI URLs stay visible and chunking stays simple.
|
||||
- Keep chronological ordering exactly as returned by the provider; do not re-sort by type or date label in the handler.
|
||||
|
||||
## Related Code Files
|
||||
- Modify: `C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\stock\handlers.go` — add state access to the generic provider if needed, but keep sender/store logic untouched for this command.
|
||||
- Modify: `C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\stock\stock.go` — register `/stock_events` metadata and handler.
|
||||
- Modify: `C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\stock\stock_events.go` — implement args parsing, provider call, event formatting, and reply chunking.
|
||||
- Modify: `C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\stock\handlers_test.go` — add registration, usage, validation, no-sender, no-events, upstream-error, and chunking coverage.
|
||||
|
||||
## Implementation Steps
|
||||
1. Wire the state to a generic stock-event provider with a zero-write fallback path suitable for tests that do not initialize stores or sender data.
|
||||
2. Register `stock_events` as `VisibilityPublic` with exact metadata: `Parameters: "<ticker> [days]"`, description concise enough to stay well under the 256-rune menu limit.
|
||||
3. Implement the command parser so `/stock_events TCB`, `/stock_events TCB 7`, and only those shapes succeed; anything else returns exact usage or range errors.
|
||||
4. Implement the read-only handler using `s.now()` and the provider from Phase 1. Do not touch portfolio/dividend history, pending buttons, or locks.
|
||||
5. Format one event block per SSI row with only required fields. Include date labels only when present so missing `RecordDate` or `PaymentDate` does not generate noisy placeholders.
|
||||
6. Pack reply blocks into bounded Telegram messages, preserve order across chunks, and keep no-events/failure replies single-message and deterministic.
|
||||
7. Add handler tests for default 30-day behavior, explicit day range, invalid day values, extra args, senderless execution, provider window propagation, empty results, provider error mapping, and over-budget output chunking.
|
||||
|
||||
## Success Criteria
|
||||
- [x] `/stock_events <ticker> [days]` is publicly registered with exact parameters/usage text and no sender requirement.
|
||||
- [x] The handler produces deterministic chronological output, friendly empty/error replies, and message chunks below the Telegram safety budget.
|
||||
- [x] The command path is provably read-only: no portfolio loads, pending-action writes, or dividend-history mutations are required for success.
|
||||
|
||||
## Risk Assessment
|
||||
- High: oversized replies can be rejected by Telegram or split mid-event. Mitigation: chunk by whole event blocks against a 4000-char budget and add an oversized synthetic test.
|
||||
- Medium: introducing a hidden sender or store dependency would break channel/anonymized use. Mitigation: add a senderless test case and keep the handler isolated from `senderInfo`.
|
||||
- Medium: metadata drift between handler usage and registration breaks `/help` and the native menu. Mitigation: assert the exact `Parameters` string and usage text in tests.
|
||||
- Rollback: remove the new command registration and `stock_events` handler changes. Phase 1’s additive provider can remain unused or be reverted separately without data cleanup.
|
||||
@@ -0,0 +1,53 @@
|
||||
---
|
||||
phase: 3
|
||||
title: "Verify and Document"
|
||||
status: completed
|
||||
priority: P2
|
||||
dependencies: [1, 2]
|
||||
---
|
||||
|
||||
# Phase 3: Verify and Document
|
||||
|
||||
## Overview
|
||||
Lock the public contract, prove dividend behavior did not regress, and update user-facing docs. This phase is the quality gate before implementation is considered done.
|
||||
|
||||
## Requirements
|
||||
- Functional: document `/stock_events <ticker> [days]`, default 30 days, valid range `1..90`, and read-only SSI behavior in `C:\Users\miti99\Workspaces\tiennm99\miti99bot\README.md:22`.
|
||||
- Functional: keep existing dividend event behavior unchanged for `/stock_portfolio`, including SSI overlap/refetch behavior already covered in `C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\stock\dividend_flow_test.go:94`, `C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\stock\dividend_flow_test.go:154`, and `C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\stock\dividend_flow_test.go:491`.
|
||||
- Non-functional: run the repo gates required by `AGENTS.md`: `gofmt`, focused stock tests, `go test ./...`, `go vet ./...`, `go build ./...`, and `golangci-lint run` when the binary is available.
|
||||
|
||||
## Architecture
|
||||
This phase does not introduce runtime behavior. It validates that:
|
||||
1. command metadata matches handler usage and README wording;
|
||||
2. the new generic SSI path did not alter dividend discovery or notification flows;
|
||||
3. repo-wide compilation, tests, and vet/lint still pass after the additive command lands.
|
||||
|
||||
Test matrix:
|
||||
- Unit: generic SSI normalization/order tests, days parser, reply chunking.
|
||||
- Integration: registration metadata, handler no-events/error/senderless behavior, provider window propagation.
|
||||
- Regression: dividend SSI/provider tests plus `dividend_flow_test.go` scenarios.
|
||||
- Repository: full `go test ./...`, `go vet ./...`, `go build ./...`, optional `golangci-lint run`.
|
||||
|
||||
## Related Code Files
|
||||
- Modify: `C:\Users\miti99\Workspaces\tiennm99\miti99bot\README.md` — add the new command contract beside the stock command documentation.
|
||||
- Verify: `C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\stock\handlers_test.go` — command registration/usage/read-only coverage.
|
||||
- Verify: `C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\stock\dividend_events_ssi_test.go` — generic SSI fetch plus dividend-regression coverage.
|
||||
- Verify: `C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\stock\dividend_flow_test.go` — unchanged `/stock_portfolio` dividend notifications.
|
||||
|
||||
## Implementation Steps
|
||||
1. Update the README stock section with the exact command syntax, default day window, allowed range, and SSI-source caveat so docs match the public command contract.
|
||||
2. Run focused stock-module tests first to catch fast feedback on provider normalization, handler parsing, chunking, and dividend regressions.
|
||||
3. Run `gofmt` on touched Go files, then execute `go test ./...`, `go vet ./...`, and `go build ./...`.
|
||||
4. Run `golangci-lint run` if the binary is available locally; if it is unavailable, record that explicitly rather than silently skipping it.
|
||||
5. If any gate fails because of the new command/provider work, fix the owning phase before marking this plan complete.
|
||||
|
||||
## Success Criteria
|
||||
- [x] README, command metadata, and handler usage text all match `/stock_events <ticker> [days]` exactly.
|
||||
- [x] Focused stock tests cover the new command and confirm `/stock_portfolio` dividend behavior is unchanged.
|
||||
- [x] Repo-wide test, vet, and build gates pass; lint status is either passing or explicitly reported as unavailable/pre-existing.
|
||||
|
||||
## Risk Assessment
|
||||
- Medium: docs can drift from the exact `Parameters` string and create `/help` confusion. Mitigation: compare README text against the registered `Parameters` and handler usage string before closing.
|
||||
- Medium: additive SSI changes can still regress dividend behavior indirectly. Mitigation: rerun the provider/dividend-flow suites, not just the new command tests.
|
||||
- Low: repo-wide gates may surface unrelated pre-existing failures. Mitigation: separate new failures from baseline issues and avoid hiding them behind the feature summary.
|
||||
- Rollback: revert the README and command changes if validation reveals an unacceptable regression. No data migration or cleanup step is needed.
|
||||
@@ -0,0 +1,59 @@
|
||||
---
|
||||
title: Stock Events Command
|
||||
description: >-
|
||||
Add a public /stock_events command for read-only SSI corporate action lookup
|
||||
with bounded Telegram output.
|
||||
status: completed
|
||||
priority: P2
|
||||
effort: 8h
|
||||
branch: main
|
||||
tags:
|
||||
- feature
|
||||
- backend
|
||||
- telegram
|
||||
- stock
|
||||
blockedBy: []
|
||||
blocks: []
|
||||
created: 2026-07-23T00:00:00.000Z
|
||||
---
|
||||
|
||||
# Stock Events Command
|
||||
|
||||
## Overview
|
||||
|
||||
Add public `/stock_events <ticker> [days]` for read-only SSI corporate-action lookup. Reuse SSI pagination helpers from `C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\stock\dividend_events_ssi.go:113` without changing the dividend-history path used by `/stock_portfolio` (`C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\stock\dividend_notifications.go:56`).
|
||||
|
||||
## Scope Challenge
|
||||
|
||||
- Existing code: command metadata/help comes from `C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\stock\stock.go:13`, `C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\command_presentation.go:6`, and `C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\validate.go:14`; ticker normalization already exists at `C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\stock\symbols.go:18`.
|
||||
- Minimum change: add one parallel read-only SSI event path plus one public command; no portfolio writes, no dividend buttons, no stats/storage migration.
|
||||
- Complexity: 7 touched files, 1 new command, 0 schema changes, 3 sequential phases.
|
||||
|
||||
## Phases
|
||||
|
||||
| Phase | Name | Status |
|
||||
|-------|------|--------|
|
||||
| 1 | [Extend SSI Corporate Events](./phase-01-extend-ssi-corporate-events.md) | Completed |
|
||||
| 2 | [Add Telegram Command](./phase-02-add-telegram-command.md) | Completed |
|
||||
| 3 | [Verify and Document](./phase-03-verify-and-document.md) | Completed |
|
||||
|
||||
## Dependencies
|
||||
|
||||
- Cross-plan: None. `plans\260722-1114-compact-portfolio-numbers\plan.md`, `plans\260722-1356-per-user-dividend-history\plan.md`, `plans\260722-1705-mobile-portfolio-columns\plan.md`, and `plans\260722-1843-retire-stock-dividend-command\plan.md` are already completed.
|
||||
- Phase 2 depends on Phase 1's additive SSI corporate-action fetch contract.
|
||||
- Phase 3 depends on Phases 1-2 for command behavior, regression tests, and docs alignment.
|
||||
|
||||
## Compatibility
|
||||
|
||||
- Keep dividend-only contracts unchanged: `DividendEventProvider` stays specific to `/stock_portfolio` at `C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\stock\dividend_events.go:12`, retained history stays under `Portfolio.Dividends` at `C:\Users\miti99\Workspaces\tiennm99\miti99bot\internal\modules\stock\portfolio.go:44`.
|
||||
- No Mongo/index/system-state/stats work. Out-of-scope items remain untouched.
|
||||
|
||||
## Validation
|
||||
|
||||
- Unit: SSI generic normalization, overlap/date filtering, deterministic order, days parsing, and reply chunking/truncation.
|
||||
- Integration: command registration metadata, usage/error replies, senderless read-only execution, no-events path, upstream failure path, and dividend regressions.
|
||||
- Repo gate: `gofmt`, focused stock tests, `go test ./...`, `go vet ./...`, `go build ./...`, and `golangci-lint run` when available.
|
||||
|
||||
## Open Questions
|
||||
|
||||
None.
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"decision": "PASS",
|
||||
"disprovenClaims": [],
|
||||
"unverifiedClaims": [
|
||||
"The implementation cannot prove that every production SSI corporate-action variant remains representable because the endpoint is undocumented. The raw DTO path copies every decoded eventListCode and optional display field without a dividend-type filter (internal/modules/stock/dividend_events_ssi.go:147-180,227-263), while README.md:42-47 correctly limits the promise to eligible, best-effort SSI rows. Fixtures exercise AGM, ISS, OTHER, FALLBACK, and DIV shapes, including malformed optional dates and raw decimal fields (internal/modules/stock/dividend_events_ssi_test.go:82-144), but they are not an authoritative enumeration of SSI's live schema."
|
||||
],
|
||||
"missingProof": [],
|
||||
"reachableRegressions": []
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"skill": "ck:cook",
|
||||
"mode": "interactive",
|
||||
"task": "Add /stock_events <ticker> [days] for read-only SSI corporate-action lookup",
|
||||
"acceptanceCriteria": [
|
||||
"default lookback is 30 days and an explicit whole-number lookback from 1 through 90 is accepted",
|
||||
"all eligible SSI corporate actions for the ticker are returned for the exact (after, through] interval",
|
||||
"raw SSI event name, title, description, date strings, value, and ratio are preserved for display without dividend normalization",
|
||||
"a malformed optional date remains displayable, a malformed non-empty publicDate is rejected, and a missing publicDate uses the first parseable optional date only as its filter/order cursor",
|
||||
"SSI pagination is complete, CorId values are deduplicated, and output order is deterministic by publication time then provider ID",
|
||||
"the command is senderless and read-only, with friendly usage, empty-result, and upstream-error replies",
|
||||
"every Telegram reply stays below the 4000-character safety budget without reordering events",
|
||||
"existing dividend normalization, portfolio discovery, retained history, and callback behavior remain unchanged",
|
||||
"README, command metadata, usage text, registration tests, help/menu discovery, and server expectations remain exact"
|
||||
],
|
||||
"touchpoints": [
|
||||
"internal/modules/stock/dividend_events_ssi.go",
|
||||
"internal/modules/stock/stock_events.go",
|
||||
"internal/modules/stock/handlers.go",
|
||||
"internal/modules/stock/stock.go",
|
||||
"internal/modules/stock/dividend_events_ssi_test.go",
|
||||
"internal/modules/stock/stock_events_test.go",
|
||||
"internal/modules/stock/handlers_test.go",
|
||||
"cmd/server/command_menu_test.go",
|
||||
"README.md"
|
||||
],
|
||||
"publicContracts": [
|
||||
"Telegram command: /stock_events <ticker> [days]",
|
||||
"default days: 30; accepted explicit range: 1..90",
|
||||
"SSIStockEventProvider.FetchStockEvents(ctx, symbol, after, through)",
|
||||
"DividendEventProvider.FetchDividendEvents(ctx, symbol, after, through) remains unchanged"
|
||||
],
|
||||
"blastRadius": [
|
||||
"stock command registration and dispatch",
|
||||
"Telegram native command menu and /help presentation",
|
||||
"shared SSI corporate-action HTTP pagination used by stock-event and dividend discovery",
|
||||
"stock portfolio dividend notification discovery",
|
||||
"user-facing README contract"
|
||||
],
|
||||
"scoutSummary": "The re-review traced raw SSI fields through pagination, copyStockEvent, cursor selection, formatting, chunking, module registration, help/menu metadata, server discovery, and the unchanged strict dividend caller. Generic events retain malformed optional date strings for display. Non-empty publicDate must parse and cannot fall back; when publicDate is absent, the first parseable optional date is used only for exact interval filtering and deterministic ordering. The command remains senderless, store-free, and concurrency-safe, and no reachable dividend or portfolio regression was found."
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"decision": "PASS",
|
||||
"score": 9.6,
|
||||
"criticalCount": 0,
|
||||
"acceptanceCoverage": [
|
||||
"default 30-day and explicit 1..90 parsing are covered by stock_events_test.go",
|
||||
"exact (after, through] filtering, pagination, CorId deduplication, and deterministic ordering are covered by dividend_events_ssi_test.go",
|
||||
"senderless execution, empty results, upstream failures, registration metadata, and bounded reply chunking are covered by stock_events_test.go",
|
||||
"native menu metadata is covered by cmd/server/command_menu_test.go",
|
||||
"README and handler usage match /stock_events <ticker> [days]",
|
||||
"raw name, title, description, dates, value, and ratio are copied and rendered without dividend normalization",
|
||||
"provider fixtures prove malformed optional dates remain raw/displayable, malformed non-empty publicDate is rejected, and missing publicDate uses a parseable optional cursor"
|
||||
],
|
||||
"regressionProof": [
|
||||
"the shared FetchDividendEvents contract remains signature-compatible and the strict normalizeEvent plus parseSSIDividendDates block is byte-for-byte unchanged from HEAD",
|
||||
"the generic provider test verifies non-dividend rows do not leak into dividend discovery",
|
||||
"focused stock and server tests passed",
|
||||
"the full repository test suite passed",
|
||||
"the stock package race test passed",
|
||||
"vet, build, lint, and diff checks passed"
|
||||
],
|
||||
"contractStatus": "CHANGED",
|
||||
"blockingReasons": []
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"highRisk": true,
|
||||
"reasons": [
|
||||
"an intentional new public Telegram command contract was added",
|
||||
"the implementation refactors SSI pagination shared with existing dividend discovery"
|
||||
],
|
||||
"autoStopRequired": true,
|
||||
"humanApproved": true,
|
||||
"largeDiff": true
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"commands": [
|
||||
{
|
||||
"command": "go test -count=1 ./internal/modules/stock ./cmd/server",
|
||||
"status": "pass",
|
||||
"exitCode": 0,
|
||||
"timestamp": "2026-07-23T02:54:30.893Z",
|
||||
"summary": "Focused stock-module and server command-discovery tests passed."
|
||||
},
|
||||
{
|
||||
"command": "go test -count=1 ./...",
|
||||
"status": "pass",
|
||||
"exitCode": 0,
|
||||
"timestamp": "2026-07-23T02:54:30.893Z",
|
||||
"summary": "The complete Go test suite passed with no package failures."
|
||||
},
|
||||
{
|
||||
"command": "go test -race -count=1 ./internal/modules/stock",
|
||||
"status": "pass",
|
||||
"exitCode": 0,
|
||||
"timestamp": "2026-07-23T02:54:30.893Z",
|
||||
"summary": "The stock package passed under the Go race detector."
|
||||
},
|
||||
{
|
||||
"command": "go vet ./...",
|
||||
"status": "pass",
|
||||
"exitCode": 0,
|
||||
"timestamp": "2026-07-23T02:54:30.893Z",
|
||||
"summary": "Go vet completed without findings."
|
||||
},
|
||||
{
|
||||
"command": "go build ./...",
|
||||
"status": "pass",
|
||||
"exitCode": 0,
|
||||
"timestamp": "2026-07-23T02:54:30.893Z",
|
||||
"summary": "All Go packages built successfully."
|
||||
},
|
||||
{
|
||||
"command": "golangci-lint run",
|
||||
"status": "pass",
|
||||
"exitCode": 0,
|
||||
"timestamp": "2026-07-23T02:54:30.893Z",
|
||||
"summary": "golangci-lint reported zero issues."
|
||||
},
|
||||
{
|
||||
"command": "git diff --check",
|
||||
"status": "pass",
|
||||
"exitCode": 0,
|
||||
"timestamp": "2026-07-23T02:54:30.893Z",
|
||||
"summary": "No whitespace errors were found; Git emitted only line-ending conversion notices."
|
||||
},
|
||||
{
|
||||
"command": "go test -count=1 -cover ./internal/modules/stock",
|
||||
"status": "pass",
|
||||
"exitCode": 0,
|
||||
"timestamp": "2026-07-23T02:54:30.893Z",
|
||||
"summary": "The stock package passed with 80.7% statement coverage."
|
||||
}
|
||||
],
|
||||
"beforeAfter": {
|
||||
"before": "No public stock corporate-action lookup command existed.",
|
||||
"after": "The command, metadata, raw SSI provider path, tests, and README are present; malformed optional dates remain displayable, cursor validation is isolated from raw output, and all automated gates pass."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
# PM Completion Report
|
||||
|
||||
Plan: `plans/260723-0852-stock-events-command`
|
||||
|
||||
## Phases
|
||||
|
||||
- Phase 1 `Extend SSI Corporate Events`: completed
|
||||
- Phase 2 `Add Telegram Command`: completed
|
||||
- Phase 3 `Verify and Document`: completed
|
||||
|
||||
## Tests
|
||||
|
||||
- Focused stock tests: pass
|
||||
- Command menu discovery test: pass
|
||||
- `go test -count=1 ./...`: pass
|
||||
- `go test -race -count=1 ./internal/modules/stock`: pass
|
||||
- `go vet ./...`: pass
|
||||
- `go build ./...`: pass
|
||||
- `golangci-lint run`: pass
|
||||
- `git diff --check`: pass
|
||||
|
||||
## Docs
|
||||
|
||||
- `README.md` updated for `/stock_events <ticker> [days]`
|
||||
- Plan text updated to reflect raw SSI display fields and private cursor handling
|
||||
- Phase checklists and status synced to completed
|
||||
|
||||
## Limitation
|
||||
|
||||
- SSI lookup remains best-effort because the upstream corporate-actions endpoint is undocumented and can change without notice.
|
||||
|
||||
## Blockers
|
||||
|
||||
- None
|
||||
|
||||
## Open Questions
|
||||
|
||||
- None
|
||||
|
||||
## Mappings
|
||||
|
||||
- No unresolved task-to-phase mappings.
|
||||
Reference in New Issue
Block a user