mirror of
https://github.com/tiennm99/tiennm99bot.git
synced 2026-10-17 00:15:04 +00:00
docs: remove completed implementation records
This commit is contained in:
1 parent
d14b34d8ce
commit
cc7dd4aa10
24 files changed
-1743
No files matched your search
@@ -1,31 +0,0 @@
|
||||
# Wheelofnames Command Journal
|
||||
|
||||
## Context
|
||||
|
||||
Executed plan `plans/260703-0404-wheelofnames-misc-command/plan.md`.
|
||||
|
||||
## What Changed
|
||||
|
||||
- Added public `/wheelofnames` command to `misc`.
|
||||
- Command parses comma-separated options, trims whitespace, ignores empty entries, and returns one random valid option.
|
||||
- Updated command registration tests and handler tests.
|
||||
- Updated `telegram-commands.json` and README command list.
|
||||
- Synced plan phases to completed.
|
||||
|
||||
## Decisions
|
||||
|
||||
- Plain text reply only; no HTML parse mode needed.
|
||||
- Non-cryptographic randomness acceptable for casual choice selection.
|
||||
- Duplicate options preserved, allowing intentional weighting.
|
||||
- No stats migration needed because command is additive.
|
||||
|
||||
## Validation
|
||||
|
||||
- `go test ./internal/modules/misc`
|
||||
- `go test ./cmd/server ./internal/modules/misc`
|
||||
- `go test ./...`
|
||||
- `go vet ./...`
|
||||
|
||||
## Unresolved Questions
|
||||
|
||||
None.
|
||||
@@ -1,34 +0,0 @@
|
||||
# Stock Dividend Command Naming Journal
|
||||
|
||||
## Context
|
||||
|
||||
Researched official VSDC dividend notices and brainstormed clearer stock command
|
||||
contracts for cash, share, and mixed dividend events.
|
||||
|
||||
## What Happened
|
||||
|
||||
- Approved `/stock_cash_dividend <vnd_per_share> <TICKER>` for cash dividends.
|
||||
- Approved `/stock_share_dividend <owned:new> <TICKER>` for share dividends.
|
||||
- Approved `/stock_dividend <vnd_per_share> <owned:new> <TICKER>` for mixed
|
||||
cash-and-share dividends.
|
||||
- Official examples support ratios such as `4:1` and `100:10`.
|
||||
- No implementation changes made yet.
|
||||
|
||||
## Decisions
|
||||
|
||||
- Share ratios use `owned:new`; both parts must be positive whole numbers.
|
||||
- New shares use integer floor division. Fractional entitlements discarded.
|
||||
- Cash input means VND paid per pre-event share.
|
||||
- Mixed dividends calculate cash and new shares from the same pre-event holding,
|
||||
then persist both results atomically.
|
||||
- Stats history needs a one-time, idempotent migration: existing
|
||||
`/stock_dividend` usage becomes `/stock_cash_dividend`, and `/stock_bonus`
|
||||
usage becomes `/stock_share_dividend`. The new mixed `/stock_dividend` starts
|
||||
with fresh stats.
|
||||
|
||||
## Next Steps
|
||||
|
||||
- Create an implementation plan covering handlers, registration, user-facing
|
||||
text, command menu, atomic storage behavior, stats migrations, and tests.
|
||||
- Implement the approved zero-result behavior: reject share-only payouts, but
|
||||
still credit cash and report zero new shares for mixed payouts.
|
||||
@@ -1,33 +0,0 @@
|
||||
# Stock Dividend Command Plan Journal
|
||||
|
||||
## Context
|
||||
|
||||
Created the implementation plan at
|
||||
`plans/260720-1616-stock-dividend-commands/` from the approved research and
|
||||
brainstorm decisions.
|
||||
|
||||
## What Happened
|
||||
|
||||
- Added three pending phases: implement ratio dividend commands, migrate command
|
||||
statistics, and verify user-facing contracts.
|
||||
- Planned `/stock_cash_dividend` with VND/share, `/stock_share_dividend` with an
|
||||
`owned:new` ratio, and combined `/stock_dividend` using both inputs.
|
||||
- Preserved floor rounding, pre-event holdings, and one atomic portfolio save.
|
||||
- Defined zero-share behavior: reject share-only events; combined events still
|
||||
credit cash.
|
||||
- Tightened migration design after review: each stats row gets a `prepared`
|
||||
checkpoint containing its exact final target count. Crash retries set that
|
||||
count instead of incrementing again.
|
||||
- Could not persist the active-plan selection because `CK_SESSION_ID` was unset.
|
||||
|
||||
## Status
|
||||
|
||||
- Plan: pending
|
||||
- Progress: 0/3 phases complete
|
||||
- Source implementation: not started
|
||||
|
||||
## Next Steps
|
||||
|
||||
- Execute the three planned phases, beginning with command contracts and tests.
|
||||
- Keep the stats migration before module registration so the reused
|
||||
`/stock_dividend` name cannot misattribute historical usage.
|
||||
@@ -1,31 +0,0 @@
|
||||
# Stock Dividend Plan Validation Journal
|
||||
|
||||
## Context
|
||||
|
||||
Validated `plans/260720-1616-stock-dividend-commands/plan.md` and its three
|
||||
pending phase documents before implementation.
|
||||
|
||||
## Validation Result
|
||||
|
||||
- Standard verification: 30 checked, 30 verified, 0 failed, 0 unverified.
|
||||
- Confirmed cash input is a positive whole VND amount per share.
|
||||
- Confirmed any positive whole-number `owned:new` ratio is accepted and echoed
|
||||
unreduced.
|
||||
- Confirmed repeated manual calls are allowed. No event ledger or duplicate-call
|
||||
restriction; caller owns correctness.
|
||||
- Confirmed permanent global and per-row migration markers. Incomplete runs
|
||||
resume from `prepared` checkpoints using their exact target counts.
|
||||
- Propagated these decisions through all three phase documents.
|
||||
- Whole-plan consistency sweep reconciled one stale float-acceptance reference
|
||||
with integer-input wording and found zero contradictions.
|
||||
|
||||
## Status
|
||||
|
||||
- Plan validation: complete
|
||||
- Plan implementation: not started
|
||||
- Source changes: none
|
||||
|
||||
## Next Steps
|
||||
|
||||
- Execute the validated phases in order: command behavior, stats migration, then
|
||||
user-contract and full-project verification.
|
||||
@@ -1,67 +0,0 @@
|
||||
# Stock Dividend Commands Journal
|
||||
|
||||
## Context
|
||||
|
||||
Implemented the validated stock-dividend plan: clearer manual commands,
|
||||
ratio-based share entitlement, and historical stats preservation.
|
||||
|
||||
## What Changed
|
||||
|
||||
- Added `/stock_cash_dividend <vnd_per_share> <TICKER>` for positive whole-VND
|
||||
cash credits.
|
||||
- Added `/stock_share_dividend <owned:new> <TICKER>` with unreduced ratio
|
||||
preservation and floor-rounded whole shares.
|
||||
- Changed `/stock_dividend <vnd_per_share> <owned:new> <TICKER>` to apply cash
|
||||
and shares from the same pre-event holding with one portfolio save.
|
||||
- Share-only zero entitlement rejects with the minimum holding; combined events
|
||||
still credit cash when shares round to zero.
|
||||
- Updated registration, command menu, usage text, README, and contract tests;
|
||||
removed `/stock_bonus` from active commands.
|
||||
|
||||
## Stats Migration
|
||||
|
||||
- Migrates `stock_dividend -> stock_cash_dividend` and
|
||||
`stock_bonus -> stock_share_dividend`, including anonymous and per-user rows.
|
||||
- Merges existing target counts without loss.
|
||||
- Permanent global and per-row markers retain migration history.
|
||||
- Each row stores a `prepared` exact target count before mutation. Retries set
|
||||
that count after any write-boundary failure, preventing double increments.
|
||||
|
||||
## Review Findings
|
||||
|
||||
- Guarded `strconv.ParseInt` range errors so its saturated return value cannot be
|
||||
accepted as valid input.
|
||||
- Added exact `int64` share formatting so quantities above `2^53` do not lose
|
||||
digits through `float64` conversion.
|
||||
- Enforced exact float-backed VND balance addition at the `2^53` boundary;
|
||||
inexact sums reject without saving.
|
||||
- Reviewer: 9/10, approve. Adversarial review: PASS; no disproven claims or
|
||||
reachable regressions.
|
||||
|
||||
## Decisions
|
||||
|
||||
- Ratios remain positive integer `owned:new` values and are echoed as entered;
|
||||
no normalization.
|
||||
- Commands are manual adjustments. Repeated calls remain allowed, with no event
|
||||
ledger or duplicate-call guard; caller owns correctness.
|
||||
- Overflow, exactness, ticker, and syntax validation remain mandatory despite
|
||||
the manual workflow.
|
||||
|
||||
## Verification
|
||||
|
||||
- Passed: `go test ./internal/modules/stock`
|
||||
- Passed: `go test ./internal/modules/stats`
|
||||
- Passed: `go test ./cmd/server`
|
||||
- Passed: `go test ./...`
|
||||
- Passed: `go vet ./...`
|
||||
- Passed: `telegram-commands.json` PowerShell `ConvertFrom-Json`
|
||||
- Passed: `git diff --check` (line-ending warnings only)
|
||||
- Skipped: Mongo-backed tests because `MONGODB_TEST_URL` was unset.
|
||||
- Skipped: `golangci-lint run` because the binary was not installed.
|
||||
|
||||
## Next Considerations
|
||||
|
||||
- Run Mongo-backed migration tests when a test database is available.
|
||||
- Run the lint gate when `golangci-lint` is installed.
|
||||
- After deployment, verify migrated counts and retained system markers before
|
||||
considering migration-runtime cleanup; keep historical stats and markers.
|
||||
@@ -1,47 +0,0 @@
|
||||
# Cross-Platform Go Workflow Journal
|
||||
|
||||
## Context
|
||||
|
||||
Removed Unix-oriented Make targets so Windows, macOS, and Linux contributors
|
||||
can use the same standard Go workflow with platform-specific environment syntax.
|
||||
|
||||
## What Changed
|
||||
|
||||
- Deleted `Makefile` and replaced its development shortcuts with documented
|
||||
`go test`, `go vet`, `go build`, `go run`, and direct Docker commands.
|
||||
- Documented Telegram webhook inspection and cleanup with PowerShell
|
||||
`Invoke-RestMethod` and POSIX `curl` examples.
|
||||
- Deleted `telegram-commands.json`; the runtime module registry already builds
|
||||
and registers the command menu on every startup, so the JSON duplicated the
|
||||
authoritative Go definitions.
|
||||
- Replaced Makefile linker flags with Go's embedded VCS build metadata and kept
|
||||
the existing seven-character commit SHA behavior for deploy notifications.
|
||||
- Updated CI and MongoDB test guidance to point contributors to the portable
|
||||
README workflow.
|
||||
|
||||
## Reflection
|
||||
|
||||
Removing the task wrapper makes the repository less convenient for habitual
|
||||
`make` users, but avoids maintaining shell-specific orchestration and duplicate
|
||||
command-menu data. Standard Go, Docker, and HTTP tools keep each operation
|
||||
explicit and work across supported development platforms.
|
||||
|
||||
## Decisions
|
||||
|
||||
- The Go module registry is the single source of truth for Telegram commands.
|
||||
- Local binaries obtain their short revision from Go build information; the
|
||||
deployment-provided `SOURCE_COMMIT` remains preferred at runtime.
|
||||
- Platform differences are documented only where shell syntax or HTTP tooling
|
||||
differs.
|
||||
|
||||
## Verification
|
||||
|
||||
- Passed: `go test ./...`
|
||||
- Passed: `go vet ./...`
|
||||
- Passed: `go build ./...`
|
||||
- Unavailable: `golangci-lint run` because the binary is not installed.
|
||||
|
||||
## Next Steps
|
||||
|
||||
- Run the lint gate when `golangci-lint` is available.
|
||||
- Keep command registration tests aligned with future public command changes.
|
||||
@@ -1,51 +0,0 @@
|
||||
# Testcontainers MongoDB Integration Journal
|
||||
|
||||
## Context
|
||||
|
||||
MongoDB integration tests previously depended on contributors manually starting
|
||||
a database and setting `MONGODB_TEST_URL`. The suite now provisions its own
|
||||
MongoDB 8 instances when Docker is available.
|
||||
|
||||
## What Changed
|
||||
|
||||
- Added Testcontainers Go and MongoDB module v0.43.0.
|
||||
- Added a shared lazy test manager that starts one `mongo:8` container per
|
||||
`storage`, `lol`, and `stats` package and terminates it after that package's
|
||||
suite.
|
||||
- Preserved `MONGODB_TEST_URL` as an external-database override.
|
||||
- Docker-unavailable environments emit an explicit warning and skip MongoDB
|
||||
tests; a regression test verifies both the warning and skip behavior.
|
||||
- Once the Docker provider is healthy, container startup and connection-string
|
||||
failures are fatal. Cleanup failures also make an otherwise passing suite
|
||||
fail.
|
||||
- Updated README and CI guidance so normal Go test commands exercise
|
||||
Testcontainers automatically.
|
||||
|
||||
## Reflection
|
||||
|
||||
Package-scoped lazy containers balance isolation and startup cost: packages do
|
||||
not share database processes, while tests inside a package avoid repeatedly
|
||||
starting MongoDB. Distinguishing an absent Docker daemon from a broken healthy
|
||||
provider keeps local no-Docker runs usable without hiding real infrastructure
|
||||
regressions.
|
||||
|
||||
## Decisions
|
||||
|
||||
- Pin tests and local setup guidance to MongoDB 8.
|
||||
- Keep explicit external MongoDB support for constrained or pre-provisioned
|
||||
environments.
|
||||
- Treat lifecycle failures as test failures whenever Docker is available.
|
||||
|
||||
## Verification
|
||||
|
||||
- Passed: `go test ./...`
|
||||
- Passed: `go vet ./...`
|
||||
- Passed: `go build ./...`
|
||||
- Passed: `golangci-lint run`
|
||||
- Passed: `go mod tidy` with no residual module diff.
|
||||
- Three real MongoDB containers ran, one for each integration-test package, and
|
||||
all three were cleaned up successfully.
|
||||
|
||||
## Next Steps
|
||||
|
||||
- Monitor CI duration and container startup reliability after rollout.
|
||||
@@ -1,64 +0,0 @@
|
||||
# Telegram Command Discovery Journal
|
||||
|
||||
> Historical note: the later command-parameter convention simplifies
|
||||
> `<options(comma-separated)>` to `<option,...>`, keeping the literal delimiter
|
||||
> visible without prose inside the placeholder. See
|
||||
> `docs/command-parameter-conventions.md`.
|
||||
|
||||
## Context
|
||||
|
||||
Telegram's native command menu and `/help` exposed only short descriptions,
|
||||
leaving users to discover parameters through failed invocations or source
|
||||
documentation.
|
||||
|
||||
## What Changed
|
||||
|
||||
- Extended the shared command registration with `Parameters` metadata and
|
||||
presentation helpers used by both discovery surfaces.
|
||||
- Added metadata for all 40 public commands, including the exact stats grammar:
|
||||
`[users | user <username> | cmd <command_name>]`.
|
||||
- Normalized placeholders to lowercase descriptive names, including meaningful
|
||||
units or currencies; `[...]` marks optional input, `...` remaining free text,
|
||||
and parentheses structured input.
|
||||
- Normalized `/wheelofnames` to `<options(comma-separated)>` across metadata,
|
||||
usage text, and tests.
|
||||
- Finalized dividend placeholders as `<vnd_per_share> <ticker>`,
|
||||
`<ratio(owned:new)> <ticker>`, and
|
||||
`<vnd_per_share> <ratio(owned:new)> <ticker>` for cash, share, and combined
|
||||
commands. Parsing remains unchanged.
|
||||
- Native menu descriptions show parameters followed by the summary, while
|
||||
`/help` renders the complete invocation followed by the summary. Neither
|
||||
discovery surface includes example invocations. Dynamic fields are
|
||||
HTML-escaped in `/help`.
|
||||
- Registration validation rejects multiline metadata and public descriptions
|
||||
over Telegram's 256-character limit.
|
||||
- Updated user and deployment documentation for the shared registry behavior.
|
||||
|
||||
## Reflection
|
||||
|
||||
Keeping syntax beside each handler registration prevents the native menu,
|
||||
`/help`, and implementation from drifting independently. Both discovery
|
||||
surfaces stay compact without sacrificing safe HTML rendering in `/help`.
|
||||
|
||||
## Decisions
|
||||
|
||||
- Existing command names, handlers, parsers, and persisted data remain
|
||||
unchanged; normalization is presentation-only.
|
||||
- No command was added, renamed, or deleted, so no stats migration is needed.
|
||||
- Discovery surfaces intentionally omit example invocations; handler usage
|
||||
errors may still include focused examples.
|
||||
- The complete `/help` output remains within Telegram's 4,096-character limit.
|
||||
|
||||
## Verification
|
||||
|
||||
- Passed: command presentation, validation, menu, and `/help` tests for all 40
|
||||
public commands.
|
||||
- Passed: `go test ./...`, including real MongoDB Testcontainers suites.
|
||||
- Passed: `go vet ./...`
|
||||
- Passed: `go build ./...`
|
||||
- Passed: `golangci-lint run`
|
||||
|
||||
## Next Steps
|
||||
|
||||
- Require parameter metadata updates alongside future public command contract
|
||||
changes.
|
||||
@@ -1,44 +0,0 @@
|
||||
# Command Parameter Conventions Journal
|
||||
|
||||
## Context
|
||||
|
||||
Command parameter labels had grown organically, especially for comma-separated
|
||||
arguments. Researched common CLI notation to establish a minimal display syntax
|
||||
for Telegram's native menu, `/help`, and handler usage text.
|
||||
|
||||
## What Changed
|
||||
|
||||
- Added the evergreen `docs/command-parameter-conventions.md` reference with
|
||||
concise rules for required, optional, variadic, alternative, and structured
|
||||
parameters.
|
||||
- Recorded the user-selected `<option,...>` notation for required
|
||||
comma-separated values.
|
||||
- Updated `/random` and `/wheelofnames` metadata, usage text, and contract tests
|
||||
from `<options(comma-separated)>` to `<option,...>`.
|
||||
- Linked project guidance and README command-discovery documentation to the
|
||||
shared convention reference.
|
||||
|
||||
## Reflection
|
||||
|
||||
The compact notation communicates both one-or-more values and the literal comma
|
||||
separator without turning display metadata into a schema language. Keeping the
|
||||
rules in an evergreen document avoids repeating policy in project instructions
|
||||
and feature docs.
|
||||
|
||||
## Decisions
|
||||
|
||||
- Parameter strings remain presentation-only; handlers own validation.
|
||||
- `/random` and `/wheelofnames` parsing and runtime behavior remain unchanged.
|
||||
- Metadata, usage errors, and tests must use the same exact notation.
|
||||
|
||||
## Verification
|
||||
|
||||
- Passed: focused command-presentation and misc tests.
|
||||
- Passed: `go test ./...`
|
||||
- Passed: `go vet ./...`
|
||||
- Passed: `go build ./...`
|
||||
- Passed: `golangci-lint run`
|
||||
|
||||
## Next Steps
|
||||
|
||||
- Apply the evergreen conventions whenever command parameters change.
|
||||
@@ -1,59 +0,0 @@
|
||||
# Stock and Coin Cost Basis P&L Journal
|
||||
|
||||
## Context
|
||||
|
||||
Stock and coin portfolios tracked account funding and holdings but not the
|
||||
remaining acquisition cost of each position, so they could not distinguish
|
||||
realized sale results from unrealized open-position performance.
|
||||
|
||||
## What Changed
|
||||
|
||||
- Added persisted per-symbol total remaining `costBasis` to stock and coin
|
||||
portfolios, with invariant checks on load, update, and save paths.
|
||||
- Buys add actual spend; partial sells remove proportional weighted-average
|
||||
basis and report realized P&L; full sells remove the position and its basis.
|
||||
- Portfolio views now show average entry price and per-position unrealized P&L.
|
||||
Account P&L remains total account value minus top-ups and is withheld when
|
||||
missing quotes make valuation partial.
|
||||
- Stock share dividends preserve total basis while increasing quantity; cash
|
||||
dividends and top-ups remain outside position basis.
|
||||
- Sorted, bounded portfolio replies retain summaries while omitting excess
|
||||
position lines before Telegram's message limit.
|
||||
|
||||
## Migration Safety
|
||||
|
||||
- Enabled modules scan every portfolio before handlers are installed on every
|
||||
boot, even when a completion marker already exists.
|
||||
- Missing legacy basis is initialized from a complete current quote set, giving
|
||||
each migrated position zero initial unrealized P&L without repricing rows that
|
||||
already have basis.
|
||||
- Versioned writes retry conflicts; the shared `system` marker is written only
|
||||
after all rows succeed and remains an audit record rather than a scan bypass.
|
||||
- A two-minute overall deadline bounds startup. Invalid data, noncanonical
|
||||
symbols, missing quotes, exhausted conflicts, or storage failures abort
|
||||
startup instead of allowing trades with unknown basis.
|
||||
|
||||
## Decisions
|
||||
|
||||
- Persist total remaining cost, deriving average entry price as basis divided by
|
||||
held quantity; do not persist trade lots or cumulative realized P&L.
|
||||
- Migrate only loaded modules, so disabled-module data waits until re-enabled.
|
||||
- Preserve all command names, parameter contracts, and existing portfolio data.
|
||||
|
||||
## Verification
|
||||
|
||||
- Passed: focused stock and coin accounting, migration, output, and reply-budget
|
||||
tests.
|
||||
- Passed: MongoDB 8 Testcontainers migration and idempotency coverage.
|
||||
- Passed: `go test ./...`
|
||||
- Passed: `go vet ./...`
|
||||
- Passed: `go build ./...`
|
||||
- Passed: `golangci-lint run`
|
||||
|
||||
## Operational Impact
|
||||
|
||||
- Deployments with legacy holdings may perform market-price lookups and writes
|
||||
during startup; a required provider or database failure intentionally keeps
|
||||
the bot offline until initialization can complete safely.
|
||||
- Subsequent healthy boots still verify invariants but do not reprice completed
|
||||
positions.
|
||||
@@ -1,87 +0,0 @@
|
||||
---
|
||||
type: technical-journal
|
||||
topic: dividend-api-and-migration-cleanup
|
||||
conducted_at: 2026-07-21T17:04:00+07:00
|
||||
status: complete
|
||||
---
|
||||
|
||||
# Dividend API and Migration Cleanup Journal
|
||||
|
||||
## Context
|
||||
|
||||
Portfolio schema migrations were verified complete in production, so their
|
||||
compatibility code had become permanent startup and maintenance overhead. Coin
|
||||
positions also inherited a stock-only dividend cursor with no valid use.
|
||||
Separately, research was needed before designing automatic discovery of
|
||||
Vietnamese stock dividend events.
|
||||
|
||||
## What Happened
|
||||
|
||||
- Removed `dividendCheckedAt` from coin positions, validation, buy behavior,
|
||||
and tests. Stock retains the cursor because dividend events apply there.
|
||||
- Retired completed stock and coin portfolio migrations plus the completed
|
||||
stats command-renaming migration and their migration-only tests.
|
||||
- Preserved recurring startup maintenance: stats query indexes and the LoL
|
||||
match-cache TTL index remain idempotently initialized and tested.
|
||||
- Preserved historical migration records in MongoDB's `system` collection and
|
||||
kept the reusable `internal/systemstate` helper for future migrations.
|
||||
- Removed legacy numeric-position JSON/BSON decoders after production schema
|
||||
completion was confirmed. Current models now describe only the supported
|
||||
nested asset schema.
|
||||
- Accepted lazy cleanup of stale coin cursor fields. BSON decoding ignores the
|
||||
old unknown field, and the next portfolio mutation uses versioned
|
||||
`ReplaceOne`, rewriting that portfolio in the current shape without a new
|
||||
one-time migration.
|
||||
|
||||
## Dividend API Research
|
||||
|
||||
SSI iBoard's corporate-actions endpoint is the recommended initial source. It
|
||||
currently returns anonymous JSON with ticker/date filters, pagination, stable
|
||||
`CorId` values, cash amounts, ratios, and event dates. It covered verified cash
|
||||
and share dividend examples.
|
||||
|
||||
The endpoint is undocumented and has no published SLA, rate limit, or stability
|
||||
contract. Any implementation should therefore isolate it behind a replaceable
|
||||
provider, validate and locally classify events, deduplicate by `CorId`, and ask
|
||||
the user to confirm before changing a portfolio. VSDC remains the authoritative
|
||||
notice source; a licensed FiinGroup feed is the stronger future option if this
|
||||
becomes production-critical.
|
||||
|
||||
## Decisions
|
||||
|
||||
- Keep dividend state stock-only; coin assets persist only `quantity` and
|
||||
total remaining `base`.
|
||||
- Remove completed one-time runtime code rather than continuing to scan already
|
||||
migrated portfolios on every boot.
|
||||
- Do not delete system history or general migration infrastructure.
|
||||
- Do not introduce a cleanup migration solely for stale coin BSON fields;
|
||||
normal writes remove them safely over time.
|
||||
- Treat SSI iBoard as a replaceable prototype provider, not a guaranteed public
|
||||
API contract.
|
||||
|
||||
## Verification
|
||||
|
||||
- Passed focused tests:
|
||||
`go test -count=1 ./internal/modules/coin ./internal/modules/stock ./internal/modules/stats ./cmd/server`
|
||||
- Passed full suite: `go test -count=1 ./...`
|
||||
- MongoDB 8 tests executed and passed for stats indexes and the LoL TTL index.
|
||||
- Passed: `go vet ./...`
|
||||
- Passed: `go build ./...`
|
||||
- Passed with zero issues: `golangci-lint run`
|
||||
- Passed: `git diff --check` (expected LF/CRLF working-copy warnings only).
|
||||
- Independent tester, debugger, and reviewer found no defects.
|
||||
|
||||
## Reflection
|
||||
|
||||
Migration code is operationally valuable only while incompatible data can
|
||||
still exist. Removing it after verification narrows startup failure modes and
|
||||
makes the active persistence contract explicit. Lazy removal is appropriate
|
||||
for an ignored field because it does not affect reads or correctness; structural
|
||||
schema changes still require guarded migrations.
|
||||
|
||||
## Next
|
||||
|
||||
Design the Telegram interaction for listing SSI dividend events, including date
|
||||
windows, pagination, exact ratio conversion, ambiguity handling, and explicit
|
||||
user confirmation. Preserve manual dividend commands and keep automatic event
|
||||
application out of scope until that interaction is approved.
|
||||
@@ -1,73 +0,0 @@
|
||||
---
|
||||
type: technical-journal
|
||||
topic: stock-dividend-event-buttons
|
||||
conducted_at: 2026-07-21T18:15:00+07:00
|
||||
status: complete
|
||||
---
|
||||
|
||||
# Stock Dividend Event Buttons Journal
|
||||
|
||||
## Context
|
||||
|
||||
`/stock_portfolio` needed to surface recent dividend events for held tickers
|
||||
without obscuring the portfolio or silently changing financial state. SSI
|
||||
iBoard was selected as a best-effort discovery source, while the existing
|
||||
manual dividend commands remain available.
|
||||
|
||||
## What Happened
|
||||
|
||||
- The portfolio response is sent first. Each discovered cash or explicit share
|
||||
dividend follows in its own message with an `Apply dividend` button; a ticker
|
||||
with no relevant event produces no extra message.
|
||||
- Added a replaceable SSI provider with pagination, local event classification,
|
||||
stable event IDs, deduplication, and exact ratio handling.
|
||||
- Added callback registration to the shared module framework and persisted
|
||||
short-lived pending actions separately from portfolios.
|
||||
- Successful checks advance `dividendCheckedAt`; failed checks leave the cursor
|
||||
unchanged and never prevent the portfolio from being displayed.
|
||||
- Added `openedAt` to distinguish the holding lifecycle and retained applied SSI
|
||||
event identities for auditability and replay protection.
|
||||
|
||||
SSI discovery accepts only day-granularity date windows. Queries therefore use
|
||||
a cursor overlap at the lower boundary, then locally filter and deduplicate the
|
||||
returned events. This avoids missing events around a date boundary while stable
|
||||
SSI event IDs prevent overlap from producing repeated actionable suggestions.
|
||||
|
||||
## Key Decisions
|
||||
|
||||
- Callback data carries an opaque random token, not trusted dividend values.
|
||||
Pending actions expire after 24 hours and are bound to the requesting
|
||||
Telegram user, originating chat, and event message.
|
||||
- A callback reloads the current portfolio and calculates from the holding at
|
||||
click time. Another group member, an expired action, or a holding sold and
|
||||
reopened after suggestion creation cannot apply it.
|
||||
- Applied SSI event IDs are recorded atomically with the portfolio mutation, so
|
||||
duplicate clicks and retries cannot apply the same provider event twice.
|
||||
- Event fetches occur outside the per-user mutation lock. Cursor persistence
|
||||
reloads and merges under that lock, preserving concurrent buys, sells, and
|
||||
manual dividends without holding a lock across network calls.
|
||||
- Notification or provider failures do not advance the affected cursor. A later
|
||||
portfolio request can safely retry rather than lose an event.
|
||||
|
||||
## Verification
|
||||
|
||||
- Focused stock and module tests passed.
|
||||
- Full suite passed: `go test -count=1 ./...`.
|
||||
- Stock race tests and 20-iteration concurrency stress tests passed.
|
||||
- `go vet ./...` and `go build ./...` passed.
|
||||
- `golangci-lint run` completed with zero issues.
|
||||
- Independent testing, debugging, and code review found no blockers.
|
||||
|
||||
## Risks and Limitations
|
||||
|
||||
- SSI iBoard is undocumented and has no published stability or availability
|
||||
guarantee; the provider can require replacement if its contract changes.
|
||||
- The portfolio has no dated transaction lots, so current quantity is not proof
|
||||
of record-date entitlement. Users must verify the issuer notice.
|
||||
- Manual commands do not record an SSI event ID. Applying manually and later
|
||||
accepting the related button can count the same dividend twice.
|
||||
|
||||
## Next
|
||||
|
||||
Observe SSI response stability and callback behavior in real use. Commit these
|
||||
changes only if the user requests it.
|
||||
Reference in new issue
Block a user