docs: record wheelofnames implementation

This commit is contained in:
2026-07-03 11:12:49 +07:00
parent d375029214
commit 9308358a23
6 changed files with 336 additions and 0 deletions
@@ -0,0 +1,31 @@
# 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.
@@ -0,0 +1,86 @@
---
phase: 1
title: Implement command
status: completed
priority: P2
dependencies: []
---
# Phase 1: Implement command
## Overview
Add the `/wheelofnames` command inside `internal/modules/misc/misc.go`, using the current misc module pattern: small command factory returning `modules.Command`, `chathelper.ArgAfterCommand` for parsing, and `chathelper.Reply` for plain text response.
## Requirements
- Functional: parse text after `/wheelofnames` as comma-separated options.
- Functional: trim whitespace and drop empty options.
- Functional: reply usage when no valid options exist.
- Functional: randomly pick one option from valid entries; preserve duplicates as weighting.
- Non-functional: keep implementation local to misc; no storage dependency; no new module.
## Architecture
Flow:
```text
Telegram update
-> dispatcher matches wheelofnames
-> wheelOfNamesCommand handler
-> chathelper.ArgAfterCommand
-> splitWheelOptions
-> math/rand/v2 rand.N(len(options))
-> chathelper.Reply
```
Use a tiny pure helper for parsing:
```go
func splitWheelOptions(arg string) []string {
parts := strings.Split(arg, ",")
out := make([]string, 0, len(parts))
for _, part := range parts {
if s := strings.TrimSpace(part); s != "" {
out = append(out, s)
}
}
return out
}
```
No crypto-grade randomness required; this is a casual selection command, not auth, payment, or security behavior.
## Related Code Files
- Modify: `/config/workspace/tiennm99/miti99bot/internal/modules/misc/misc.go`
- Create: none
- Delete: none
## Implementation Steps
1. Add `math/rand/v2` import, unless existing Go version/toolchain rejects it; fallback to standard `math/rand` only if needed.
2. Update package comment to include `/wheelofnames`.
3. Add `wheelOfNamesUsage` constant, e.g. `Usage: /wheelofnames <option1>, <option2>, ...`.
4. Add `wheelOfNamesCommand()` returning public `modules.Command`.
5. Add command to `New()` after other public misc commands or near `/ping`.
6. Add `splitWheelOptions(arg string) []string` helper near the command.
7. Handler:
- return nil for nil message
- parse args with `chathelper.ArgAfterCommand(update.Message.Text)`
- reply usage if parsed options length is zero
- pick `options[rand.N(len(options))]`
- reply selected option as plain text
## Success Criteria
- [x] `misc.New` registers `wheelofnames` as public command.
- [x] Handler replies usage for missing/empty option list.
- [x] Handler never returns an empty option.
- [x] Handler uses plain text reply, preserving forum topic behavior through `chathelper.Reply`.
## Risk Assessment
Main risk: flaky tests if randomness is asserted too strictly. Mitigate by testing deterministic one-option input and set membership for multi-option input.
Security: no HTML parse mode; user-supplied option text is plain text, so no HTML escaping needed.
@@ -0,0 +1,54 @@
---
phase: 2
title: Update command surfaces
status: completed
priority: P2
dependencies:
- 1
---
# Phase 2: Update command surfaces
## Overview
Update all user-facing command surfaces required by `AGENTS.md` for a new Telegram command. This is an additive command, so no stats migration is needed.
## Requirements
- Functional: command appears in `/help` because it is public and registered in the misc module.
- Functional: command appears in `telegram-commands.json` for Telegram command menu setup.
- Functional: README misc module summary reflects the new command.
- Non-functional: no command rename/delete, so preserve stats behavior by doing nothing special.
## Architecture
The source of runtime behavior is `internal/modules/misc/misc.go`. `telegram-commands.json` is a manual Telegram command menu source, and `README.md` is the human-facing module overview.
Stats compatibility note:
- Adding `/wheelofnames` creates new command usage rows naturally when the stats hook records invocations.
- No existing stats rows need migration because no command is renamed or deleted.
## Related Code Files
- Modify: `/config/workspace/tiennm99/miti99bot/telegram-commands.json`
- Modify: `/config/workspace/tiennm99/miti99bot/README.md`
- Create: none
- Delete: none
## Implementation Steps
1. Add command entry to `telegram-commands.json` near other misc commands:
- `command`: `wheelofnames`
- `description`: concise public description, e.g. `Pick one random comma-separated option`
2. Update README Modules table for `misc` to include `/wheelofnames`.
3. Do not update stats migrations or system state; this is add-only behavior.
## Success Criteria
- [x] `telegram-commands.json` remains valid JSON.
- [x] README `misc` command list includes `/wheelofnames`.
- [x] No migration or legacy stats marker added.
## Risk Assessment
Risk: runtime registration and manual command menu source drift. Mitigate by updating both `misc.go` and `telegram-commands.json` in same implementation.
@@ -0,0 +1,68 @@
---
phase: 3
title: Validate behavior
status: completed
priority: P2
dependencies:
- 1
- 2
---
# Phase 3: Validate behavior
## Overview
Add focused tests for the new handler and run command-surface validation required for command changes.
## Requirements
- Functional: tests cover registration, usage reply, one-option selection, trimming, and empty segment handling.
- Non-functional: run focused tests first, then full suite and vet because command/menu/shared behavior changed.
## Architecture
Use existing misc test harness:
- `installMisc` in `internal/modules/misc/handlers_test.go` wires the misc module to `testutil.RecordingBot`.
- `TestNew_RegistersExpectedCommands` in `internal/modules/misc/misc_test.go` locks command names and visibility.
Avoid brittle randomness assertions:
- Single-option input should return that option exactly.
- Multi-option input should assert the reply is one of the non-empty trimmed options.
## Related Code Files
- Modify: `/config/workspace/tiennm99/miti99bot/internal/modules/misc/misc_test.go`
- Modify: `/config/workspace/tiennm99/miti99bot/internal/modules/misc/handlers_test.go`
- Create: none
- Delete: none
## Implementation Steps
1. Update `TestNew_RegistersExpectedCommands` expected map:
- add `wheelofnames: modules.VisibilityPublic`
2. Add handler tests:
- `/wheelofnames` returns usage.
- `/wheelofnames , ,` returns usage.
- `/wheelofnames Alice` returns `Alice`.
- `/wheelofnames Alice, Bob, Carol` returns one of those exact strings.
- `/wheelofnames , Alice , , Bob ,` returns `Alice` or `Bob`, never empty/spaced.
3. Run formatting and focused tests:
- `gofmt -w internal/modules/misc/misc.go internal/modules/misc/misc_test.go internal/modules/misc/handlers_test.go`
- `go test ./internal/modules/misc`
4. Run broader validation because command menu/user-facing contract changes:
- `go test ./cmd/server ./internal/modules/misc`
- `go test ./...`
- `go vet ./...`
## Success Criteria
- [x] Focused misc tests pass.
- [x] Command menu/server tests pass.
- [x] Full `go test ./...` passes.
- [x] Full `go vet ./...` passes.
## Risk Assessment
Risk: random selection makes tests nondeterministic. Mitigate by avoiding exact expected value for multi-option tests.
Rollback: remove `wheelOfNamesCommand`, helper, tests, README entry, and `telegram-commands.json` entry.
@@ -0,0 +1,63 @@
---
title: Wheel of Names Misc Command
description: >-
Add public /wheelofnames command to pick one random comma-separated option in
the misc module.
status: completed
priority: P2
branch: main
tags:
- feature
- backend
blockedBy: []
blocks: []
created: '2026-07-03T04:04:35.848Z'
createdBy: 'ck:plan'
source: skill
---
# Wheel of Names Misc Command
## Overview
Add `/wheelofnames` to the existing `misc` module. The command accepts comma-separated options after the command text, trims whitespace, ignores empty entries, then replies with one randomly selected option. No storage, migrations, auth changes, or new module needed.
Assumptions:
- Public command, visible in `/help` and Telegram command menu.
- Usage reply when no valid comma-separated entries remain.
- One valid entry is allowed and returns that entry.
- Duplicate entries stay duplicated, so users can weight an option intentionally.
## Phases
| Phase | Name | Status |
|-------|------|--------|
| 1 | [Implement command](./phase-01-implement-command.md) | Completed |
| 2 | [Update command surfaces](./phase-02-update-command-surfaces.md) | Completed |
| 3 | [Validate behavior](./phase-03-validate-behavior.md) | Completed |
## Cross-Plan Dependencies
None. No unfinished project plans found under `plans/`.
## Key Files
| File | Action |
|------|--------|
| `internal/modules/misc/misc.go` | Add command registration, parser/helper, handler |
| `internal/modules/misc/misc_test.go` | Update registration expectations |
| `internal/modules/misc/handlers_test.go` | Add handler behavior tests |
| `telegram-commands.json` | Add public Telegram command menu entry |
| `README.md` | Update misc module command list |
## Acceptance Criteria
- `/wheelofnames a, b, c` replies with exactly one trimmed item from `a`, `b`, `c`.
- `/wheelofnames` and `/wheelofnames , ,` reply with usage text.
- Empty comma segments do not appear as choices.
- Command is public and included in module registration, `/help`, and `telegram-commands.json`.
- Focused tests pass, then full `go test ./...` and `go vet ./...` pass.
## Unresolved Questions
None.
@@ -0,0 +1,34 @@
# Plan Complete: Wheel of Names Misc Command
## Summary
| Field | Value |
|---|---|
| Plan | `plans/260703-0404-wheelofnames-misc-command/plan.md` |
| Status | completed |
| Phases | 3/3 |
| Files changed | 5 implementation/docs files + plan files |
| Tests | `go test ./internal/modules/misc`, `go test ./cmd/server ./internal/modules/misc`, `go test ./...`, `go vet ./...` |
## Work Completed
- [x] Added public `/wheelofnames` command in `misc`.
- [x] Parses comma-separated options, trims whitespace, ignores empty entries.
- [x] Replies usage when no valid option exists.
- [x] Picks one valid option with casual randomness.
- [x] Updated README and `telegram-commands.json`.
- [x] Added focused handler and registration tests.
## Documentation Updates
- README module command list updated.
- No `docs/` update needed; no architecture, setup, security, or deploy behavior changed.
## Known Limitations
- Randomness is non-cryptographic by design.
- Duplicate options are preserved as weighting.
## Unresolved Questions
None.