mirror of
https://github.com/panatgithub/AnkiHeadingSync.git
synced 2026-07-22 06:51:43 +00:00
docs(audit): review plugin improvement opportunities
中文: 基于真实代码审查整理插件可完善方向、风险点和后续开发优先级。 English: Reviews plugin improvement opportunities, risks, and prioritized next steps based on real code inspection.
This commit is contained in:
parent
c0c2551753
commit
771cf9c0cb
3 changed files with 1235 additions and 0 deletions
257
docs/plugin-improvement-audit-architecture-map.md
Normal file
257
docs/plugin-improvement-audit-architecture-map.md
Normal file
|
|
@ -0,0 +1,257 @@
|
|||
# Plugin Improvement Audit Architecture Map
|
||||
|
||||
## Scope
|
||||
|
||||
This map is based on the current production runtime path in the repository as inspected on 2026-04-26. It focuses on active code, active wiring, and code paths that materially affect user-visible sync behavior.
|
||||
|
||||
## 1. Active Entry Points
|
||||
|
||||
### Runtime entry
|
||||
|
||||
- `main.ts`
|
||||
- Exports `src/presentation/AnkiHeadingSyncPlugin.ts` as the plugin entry.
|
||||
|
||||
### Plugin composition root
|
||||
|
||||
- `src/presentation/AnkiHeadingSyncPlugin.ts :: onload()`
|
||||
- Creates persistence adapters:
|
||||
- `src/infrastructure/obsidian/ObsidianPluginDataStore.ts`
|
||||
- `src/infrastructure/persistence/DataJsonPluginConfigRepository.ts`
|
||||
- `src/infrastructure/persistence/DataJsonPluginStateRepository.ts`
|
||||
- Creates external gateways:
|
||||
- `src/infrastructure/anki/AnkiConnectGateway.ts`
|
||||
- `src/infrastructure/obsidian/ObsidianVaultGateway.ts`
|
||||
- Creates main use cases:
|
||||
- `ManualSyncCurrentFileUseCase`
|
||||
- `ManualSyncVaultUseCase`
|
||||
- `RebuildCardIndexUseCase`
|
||||
- `ClearCurrentFileSyncedCardsUseCase`
|
||||
- `CleanupEmptyDecksUseCase`
|
||||
- Registers commands through `src/presentation/commands/registerCommands.ts`
|
||||
- Registers the settings UI through `src/presentation/settings/PluginSettingTab.ts`
|
||||
|
||||
### User-visible command surface
|
||||
|
||||
- `src/presentation/commands/registerCommands.ts`
|
||||
- Registers 4 commands:
|
||||
- sync current file
|
||||
- sync vault
|
||||
- clear current file synced cards
|
||||
- cleanup empty decks
|
||||
|
||||
### User-visible settings surface
|
||||
|
||||
- `src/presentation/settings/PluginSettingTab.ts`
|
||||
- Active cards:
|
||||
- card types
|
||||
- sync content
|
||||
- deck
|
||||
- scope
|
||||
- commands
|
||||
|
||||
## 2. Active Runtime Layers
|
||||
|
||||
### Presentation
|
||||
|
||||
- `src/presentation/AnkiHeadingSyncPlugin.ts`
|
||||
- Plugin lifecycle, command callbacks, notices, settings update entry.
|
||||
- `src/presentation/settings/PluginSettingTab.ts`
|
||||
- Settings rendering, note-type cache loading, field-mapping editing, folder-scope editing, deck template insertion button.
|
||||
- `src/presentation/notices/NoticeService.ts`
|
||||
- User-facing success/error summaries.
|
||||
- `src/presentation/modals/EmptyDeckSelectionModal.ts`
|
||||
- Deck cleanup modal.
|
||||
- `src/presentation/i18n/*`
|
||||
- Locale detection and message lookup.
|
||||
|
||||
### Application
|
||||
|
||||
- `src/application/use-cases/*`
|
||||
- Thin user-action entry points over services.
|
||||
- `src/application/services/ManualSyncService.ts`
|
||||
- Main orchestration service for file sync, vault sync, and rebuild index.
|
||||
- `src/application/services/FileIndexerService.ts`
|
||||
- Scope filtering, incremental scan decisions, state-assisted restore of unchanged cards.
|
||||
- `src/application/services/AnkiBatchExecutor.ts`
|
||||
- Batched Anki note create/update/model-migrate/tag-sync/deck-change/media-upload.
|
||||
- `src/application/services/QaGroupSyncService.ts`
|
||||
- QA Group note sync, slot preservation, model mismatch handling, GI marker generation.
|
||||
- `src/application/services/MarkdownWriteBackService.ts`
|
||||
- File-grouped marker writes, conflict capture, pending write-back generation.
|
||||
- `src/application/services/RenderConfigService.ts`
|
||||
- Deck resolution, note-model selection, render-config hashing.
|
||||
- `src/application/services/NoteFieldMappingService.ts`
|
||||
- Saved mapping validation and rendered-field projection.
|
||||
- `src/application/services/QaGroupFieldMappingService.ts`
|
||||
- QA Group slot derivation and validation.
|
||||
|
||||
### Domain
|
||||
|
||||
- `src/domain/manual-sync/services/CardIndexingService.ts`
|
||||
- Heading scanning, card-type detection, ID/GI marker recovery, QA Group and semantic QA parsing.
|
||||
- `src/domain/manual-sync/services/DiffPlannerService.ts`
|
||||
- Create/update/change-deck/rewrite-marker/orphan planning.
|
||||
- `src/domain/manual-sync/services/CardMarkerService.ts`
|
||||
- Card ID marker parse/create/validate/apply.
|
||||
- `src/domain/manual-sync/services/GroupMarkerService.ts`
|
||||
- GI marker parse/create/validate/apply.
|
||||
- `src/domain/manual-sync/services/DeckExtractionService.ts`
|
||||
- YAML/body deck declaration parsing.
|
||||
- `src/domain/manual-sync/services/DeckResolutionService.ts`
|
||||
- Folder/file/default deck resolution and warning generation.
|
||||
- `src/domain/manual-sync/services/QaGroupBlockParser.ts`
|
||||
- QA Group block parsing.
|
||||
- `src/domain/manual-sync/services/SemanticQaListParser.ts`
|
||||
- Semantic QA list parsing.
|
||||
|
||||
### Infrastructure
|
||||
|
||||
- `src/infrastructure/anki/AnkiConnectGateway.ts`
|
||||
- AnkiConnect HTTP adapter and `multi` request batching.
|
||||
- `src/infrastructure/obsidian/ObsidianVaultGateway.ts`
|
||||
- Vault reads, compare-and-swap writes, folder tree, backlinks, media resolution.
|
||||
- `src/infrastructure/persistence/DataJsonPluginConfigRepository.ts`
|
||||
- Settings load/save normalization and validation.
|
||||
- `src/infrastructure/persistence/DataJsonPluginStateRepository.ts`
|
||||
- Plugin state load/save and migration.
|
||||
|
||||
## 3. Main Data Flow
|
||||
|
||||
### Manual sync: current file
|
||||
|
||||
1. Command callback in `registerCommands()` calls `AnkiHeadingSyncPlugin.runSyncCurrentFile()`.
|
||||
2. `ManualSyncCurrentFileUseCase.execute()` forwards to `ManualSyncService.syncFile()`.
|
||||
3. `ManualSyncService.syncFile()` validates settings and scope, then loads plugin state.
|
||||
4. `FileIndexerService.indexFile()` reads the target Markdown file and delegates parsing to `CardIndexingService.index()`.
|
||||
5. `DiffPlannerService.plan()` compares indexed cards with persisted state.
|
||||
6. `AnkiBatchExecutor.execute()` syncs ordinary/basic/cloze/semantic cards.
|
||||
7. `QaGroupSyncService.sync()` syncs QA Group blocks separately.
|
||||
8. `MarkdownWriteBackService.write()` writes card ID markers and GI markers back into Markdown.
|
||||
9. `ManualSyncService.buildNextState()` saves files/cards/groupBlocks/pending write-back into plugin state.
|
||||
10. `NoticeService.showSyncSummary()` renders a localized summary.
|
||||
|
||||
### Manual sync: vault
|
||||
|
||||
1. `ManualSyncVaultUseCase.execute()` forwards to `ManualSyncService.syncVault()`.
|
||||
2. `FileIndexerService.indexVault()` uses `ScanScopeService` plus `ObsidianVaultGateway.listMarkdownFileRefs()` to enumerate in-scope files.
|
||||
3. Incremental decisions are made per file using file stamp, deck-rule fingerprint, missing known cards, and pending write-back state.
|
||||
4. Remaining flow matches current-file sync.
|
||||
|
||||
### Rebuild index
|
||||
|
||||
1. `RebuildCardIndexUseCase.execute()` forwards to `ManualSyncService.rebuildIndex()`.
|
||||
2. Vault is reindexed with `forceReadAll = true`.
|
||||
3. No Anki note create/update occurs.
|
||||
4. Existing markers can still be rewritten if enough identity exists.
|
||||
5. Persisted state is rebuilt from indexed files plus recovered QA Group state.
|
||||
|
||||
### Clear current file synced cards
|
||||
|
||||
1. `ClearCurrentFileSyncedCardsUseCase.hasTrackedCards()` checks local state for current file.
|
||||
2. `execute()` loads note IDs/group IDs from local state.
|
||||
3. Anki notes are deleted through `AnkiGateway.deleteNotes()`.
|
||||
4. Markdown markers are removed through `MarkdownSyncedMarkerRemovalService`.
|
||||
5. Local state is rewritten without that file’s cards/groups.
|
||||
|
||||
## 4. Critical State Objects
|
||||
|
||||
### Settings
|
||||
|
||||
- `src/application/config/PluginSettings.ts :: PluginSettings`
|
||||
- Controls note-type selection, field mapping caches, deck logic, scope logic, backlink behavior, tag sync, and AnkiConnect URL.
|
||||
- Contains both current `cardTypeConfigs` and legacy mirrored note-type fields.
|
||||
|
||||
### Persisted plugin state
|
||||
|
||||
- `src/domain/manual-sync/entities/PluginState.ts :: PluginState`
|
||||
- `files`
|
||||
- Per-file index metadata: `fileHash`, `fileStamp`, `deckRulesFingerprint`, `noteIds`, `groupIds`.
|
||||
- `cards`
|
||||
- Per-note synced card snapshot keyed by note ID.
|
||||
- `groupBlocks`
|
||||
- Per-QA-group synced snapshot keyed by group ID.
|
||||
- `pendingWriteBack`
|
||||
- Deferred marker writes intended for conflict recovery.
|
||||
|
||||
### Scan-time objects
|
||||
|
||||
- `IndexedCard`
|
||||
- `IndexedGroupCardBlock`
|
||||
- `IndexedFile`
|
||||
|
||||
### Plan-time objects
|
||||
|
||||
- `src/domain/manual-sync/value-objects/ManualSyncPlan.ts :: ManualSyncPlan`
|
||||
- `toCreate`
|
||||
- `toUpdate`
|
||||
- `toVerifyDeck`
|
||||
- `toChangeDeck`
|
||||
- `toRewriteMarker`
|
||||
- `toOrphan`
|
||||
|
||||
## 5. Main External API Boundaries
|
||||
|
||||
### Obsidian APIs
|
||||
|
||||
- `Plugin.loadData()` / `Plugin.saveData()` through `ObsidianPluginDataStore`
|
||||
- Vault file enumeration through `ObsidianVaultGateway.listMarkdownFileRefs()`
|
||||
- Compare-and-swap write boundary through `ObsidianVaultGateway.replaceMarkdownFile()`
|
||||
- Metadata and tag extraction through `getAllTags()` and cached metadata
|
||||
- Obsidian notices and settings controls in presentation layer
|
||||
|
||||
### AnkiConnect
|
||||
|
||||
- All network calls are centralized in `AnkiConnectGateway.invoke()` / `invokeMulti()`.
|
||||
- The adapter uses AnkiConnect action names directly (`modelNames`, `deckNamesAndIds`, `getDeckStats`, `addNote`, `updateNoteFields`, `changeDeck`, `deleteDecks`, `storeMediaFile`, `multi`, etc.).
|
||||
|
||||
## 6. Active Code vs Likely Legacy / Dormant Remnants
|
||||
|
||||
### Clearly active
|
||||
|
||||
- `main.ts`
|
||||
- `src/presentation/AnkiHeadingSyncPlugin.ts`
|
||||
- `src/presentation/settings/PluginSettingTab.ts`
|
||||
- `src/application/services/ManualSyncService.ts`
|
||||
- `src/application/services/FileIndexerService.ts`
|
||||
- `src/application/services/AnkiBatchExecutor.ts`
|
||||
- `src/application/services/QaGroupSyncService.ts`
|
||||
- `src/infrastructure/anki/AnkiConnectGateway.ts`
|
||||
- `src/infrastructure/obsidian/ObsidianVaultGateway.ts`
|
||||
|
||||
### Generated or packaging artifacts
|
||||
|
||||
- `main.js`
|
||||
- Root-level generated bundle copy written by `esbuild.config.mjs`.
|
||||
- `dist/plugin/*`
|
||||
- Staged package output used for release/manual sync.
|
||||
|
||||
### Debug / manual inspection scripts
|
||||
|
||||
- `query_note.js`
|
||||
- `query_notes.js`
|
||||
- Direct HTTP scripts with hard-coded note IDs and no repository call sites.
|
||||
|
||||
### Likely dormant or legacy architectural branches
|
||||
|
||||
- `src/application/services/QaGroupModelService.ts`
|
||||
- `src/application/services/QaGroupModelDefinition.ts`
|
||||
- `src/application/config/ManagedNoteModels.ts`
|
||||
- These define and test a managed `ObsiAnki QA Group 12` model, but no production runtime call site invokes `QaGroupModelService.ensureModel()`.
|
||||
- The active runtime QA Group path instead uses user-selected note types plus `QaGroupFieldMappingService`.
|
||||
|
||||
- `src/presentation/AnkiHeadingSyncPlugin.ts :: runRebuildCardIndex()`
|
||||
- Wired in plugin initialization, but not surfaced by `registerCommands()` and not listed in the settings command card.
|
||||
|
||||
- Legacy mirrored settings fields in `PluginSettings`
|
||||
- `qaHeadingLevel`, `clozeHeadingLevel`, `qaGroupMarker`, `qaNoteType`, `clozeNoteType`, `semanticQaMarker`, `semanticQaNoteType`
|
||||
- Still exist and are derived from `cardTypeConfigs`, which indicates an unfinished migration rather than a clean single source of truth.
|
||||
|
||||
## 7. Audit Notes
|
||||
|
||||
- The active sync engine is stateful and layered.
|
||||
- The highest-value audit attention should stay on:
|
||||
- pending write-back persistence
|
||||
- QA Group authority split
|
||||
- semantic QA runtime/UI parity
|
||||
- AnkiConnect failure handling
|
||||
- hidden rebuild/recovery surface
|
||||
632
docs/plugin-improvement-audit-report.md
Normal file
632
docs/plugin-improvement-audit-report.md
Normal file
|
|
@ -0,0 +1,632 @@
|
|||
# Plugin Improvement Audit Report
|
||||
|
||||
## 1. Executive summary
|
||||
|
||||
This plugin is in a solid middle stage: the core sync engine is better structured than many Obsidian plugins, but product surface and failure recovery are still uneven.
|
||||
|
||||
- Overall maturity
|
||||
- Medium to high for core sync architecture.
|
||||
- Medium for user-facing completeness.
|
||||
- Medium-low for failure recovery resilience across restarts and AnkiConnect outages.
|
||||
|
||||
- Strongest parts
|
||||
- Layered runtime composition.
|
||||
- State-aware incremental indexing.
|
||||
- Explicit marker conflict detection instead of blind overwrite.
|
||||
- Rich parser and sync-path test coverage for core card types.
|
||||
|
||||
- Highest-risk parts
|
||||
- Pending write-back recovery is discarded on load.
|
||||
- Destructive reset paths and batch sync are not transaction-safe.
|
||||
- Runtime feature surface and settings surface are not aligned.
|
||||
- QA Group note-model strategy is split between active user-model sync and dormant managed-model code.
|
||||
|
||||
- Next 3 most valuable improvements
|
||||
1. Persist `pendingWriteBack` correctly across plugin reloads and add restart-recovery tests.
|
||||
2. Add explicit AnkiConnect timeout/health-check handling and friendlier offline UX.
|
||||
3. Unify runtime product authority: semantic QA visibility, QA Group model strategy, and note-type source of truth.
|
||||
|
||||
- Validation baseline observed during this audit run
|
||||
- `git status --short`: clean.
|
||||
- `npm run lint`: passed.
|
||||
- `npm test`: failing in current baseline; failures cluster in `FileIndexerService`, `ManualSyncService`, and `ClearCurrentFileSyncedCardsUseCase` tests.
|
||||
|
||||
## 2. Architecture map
|
||||
|
||||
See [plugin-improvement-audit-architecture-map.md](plugin-improvement-audit-architecture-map.md).
|
||||
|
||||
In short, the active runtime path is:
|
||||
|
||||
`main.ts` -> `AnkiHeadingSyncPlugin.onload()` -> use cases -> `ManualSyncService` / cleanup use cases -> domain services + infrastructure gateways -> persisted plugin state + markdown write-back.
|
||||
|
||||
## 3. Confirmed strengths
|
||||
|
||||
### 3.1 Clear runtime composition and layer boundaries
|
||||
|
||||
- Evidence
|
||||
- `src/presentation/AnkiHeadingSyncPlugin.ts :: onload()` wires repositories, gateways, use cases, and the setting tab in one place.
|
||||
- Domain parsing and marker logic live outside presentation code.
|
||||
- AnkiConnect calls are centralized in `src/infrastructure/anki/AnkiConnectGateway.ts`.
|
||||
- Why this is strong
|
||||
- It keeps plugin lifecycle, orchestration, parsing, and I/O mostly separated.
|
||||
- It makes future refactors possible without rewriting the whole plugin.
|
||||
|
||||
### 3.2 Incremental indexing is state-aware, not brute-force only
|
||||
|
||||
- Evidence
|
||||
- `src/application/services/FileIndexerService.ts :: indexRefs()` skips rereads when `fileStamp`, `deckRulesFingerprint`, and known-card presence still match.
|
||||
- The same path restores cards and group blocks from persisted state for unchanged files.
|
||||
- Why this is strong
|
||||
- Large-vault behavior is already being treated as an engineering problem.
|
||||
- Re-indexing work is avoided when nothing relevant changed.
|
||||
|
||||
### 3.3 Marker write-back uses optimistic concurrency instead of blind overwrite
|
||||
|
||||
- Evidence
|
||||
- `src/infrastructure/obsidian/ObsidianVaultGateway.ts :: replaceMarkdownFile()` reads current content and throws `MarkdownWriteConflictError` if it no longer matches the scanned content.
|
||||
- `src/application/services/MarkdownWriteBackService.ts :: write()` collects `conflictFiles` and `pendingEntries` instead of silently overwriting.
|
||||
- Why this is strong
|
||||
- This prevents silent file corruption when a note changes after scan but before marker write-back.
|
||||
|
||||
### 3.4 Card and QA Group identity recovery paths are explicit
|
||||
|
||||
- Evidence
|
||||
- `src/domain/manual-sync/services/CardIndexingService.ts :: resolveIdentity()` recovers by marker, by state, and by pending write-back.
|
||||
- `src/domain/manual-sync/services/CardIndexingService.ts :: resolveGroupIdentity()` recovers QA Group notes by GI marker, by `src`, or by block hash.
|
||||
- Why this is strong
|
||||
- Sync identity is not tied to a single fragile marker path.
|
||||
- The design anticipates marker deletion and partial state recovery.
|
||||
|
||||
### 3.5 Saved field mappings are validated against live model fields
|
||||
|
||||
- Evidence
|
||||
- `src/application/services/NoteFieldMappingService.ts :: validateMapping()` rejects missing or stale fields.
|
||||
- `src/application/services/QaGroupFieldMappingService.ts :: validateMapping()` rejects missing QA Group fields, duplicate usage, and stale slot references.
|
||||
- Why this is strong
|
||||
- The plugin does not blindly trust stale settings.
|
||||
- Model drift is surfaced as a user-facing problem instead of silently writing wrong fields.
|
||||
|
||||
### 3.6 User-facing error and i18n plumbing is centralized
|
||||
|
||||
- Evidence
|
||||
- `src/application/errors/PluginUserError.ts` separates internal errors from localized user messages.
|
||||
- `src/presentation/notices/NoticeService.ts` consolidates summary rendering.
|
||||
- `src/presentation/i18n/index.ts` and `src/presentation/i18n/messages/*` provide a real translation dictionary instead of ad hoc strings.
|
||||
- Why this is strong
|
||||
- Error surfaces are at least architecturally prepared for consistent UX.
|
||||
|
||||
### 3.7 Core sync modules have non-trivial targeted tests
|
||||
|
||||
- Evidence
|
||||
- `src/application/services/ManualSyncService.test.ts`
|
||||
- `src/application/services/QaGroupSyncService.test.ts`
|
||||
- `src/infrastructure/anki/AnkiConnectGateway.test.ts`
|
||||
- `src/presentation/settings/PluginSettingTab.test.ts`
|
||||
- Why this is strong
|
||||
- The repository is not relying only on smoke tests or manual validation.
|
||||
|
||||
## 4. Confirmed problems
|
||||
|
||||
### 4.1 Pending write-back recovery is discarded on every load
|
||||
|
||||
- Severity: high
|
||||
- Area: sync correctness
|
||||
- Evidence from real code
|
||||
- `src/application/services/MarkdownWriteBackService.ts :: write()` creates `pendingEntries` when marker write-back conflicts or fails.
|
||||
- `src/application/services/FileIndexerService.ts :: indexRefs()` explicitly consumes `state.pendingWriteBack` to force reread/recovery.
|
||||
- `src/infrastructure/persistence/DataJsonPluginStateRepository.ts :: migratePluginState()` always returns `pendingWriteBack: []`, even when loading an existing `PluginState`.
|
||||
- `src/infrastructure/persistence/DataJsonPluginStateRepository.test.ts` currently asserts this behavior by expecting `loaded.pendingWriteBack` to equal `[]`.
|
||||
- Why it matters
|
||||
- The codebase already models deferred marker recovery, but restart/load drops that state.
|
||||
- A user who hits a write conflict, closes Obsidian, then retries loses the recovery queue.
|
||||
- Recommended fix
|
||||
- Preserve modern `pendingWriteBack` entries on load.
|
||||
- Keep legacy migration handling separate from modern-state passthrough.
|
||||
- Add explicit schema-versioned migration logic if needed.
|
||||
- Estimated implementation size: M
|
||||
- Risk level: medium
|
||||
- Suggested test coverage
|
||||
- Persist and reload modern `pendingWriteBack` entries unchanged.
|
||||
- Restart after write conflict should still re-attempt marker repair.
|
||||
|
||||
### 4.2 Semantic QA is active in runtime but hidden in settings
|
||||
|
||||
- Severity: high
|
||||
- Area: UX
|
||||
- Evidence from real code
|
||||
- `src/application/config/PluginSettings.ts` includes `semantic-qa` in `CARD_TYPE_CONFIG_IDS` and requires `semanticQaNoteType`.
|
||||
- `src/domain/manual-sync/services/CardIndexingService.ts` actively parses semantic QA blocks.
|
||||
- `src/application/services/RenderConfigService.ts :: resolve()` actively selects a semantic QA note type.
|
||||
- `src/presentation/settings/PluginSettingTab.ts` hardcodes `VISIBLE_CARD_TYPE_CONFIG_IDS = ["basic", "qa-group", "cloze"]`.
|
||||
- `src/presentation/settings/PluginSettingTab.test.ts` explicitly expects semantic QA controls not to exist.
|
||||
- Why it matters
|
||||
- Users can hit runtime semantic QA behavior without being able to fully configure, disable, or map it from the settings page.
|
||||
- This is a product-surface mismatch, not just a code-style issue.
|
||||
- Recommended fix
|
||||
- Either surface semantic QA as a first-class configurable card type, or remove/disable the parser until a proper UI exists.
|
||||
- Estimated implementation size: M
|
||||
- Risk level: medium
|
||||
- Suggested test coverage
|
||||
- Settings UI coverage for semantic QA controls.
|
||||
- End-to-end semantic QA sync with explicit note-type and field-mapping selection.
|
||||
|
||||
### 4.3 Rebuild index exists but is not exposed to users
|
||||
|
||||
- Severity: medium
|
||||
- Area: UX
|
||||
- Evidence from real code
|
||||
- `src/presentation/AnkiHeadingSyncPlugin.ts :: onload()` instantiates `RebuildCardIndexUseCase`.
|
||||
- `src/presentation/AnkiHeadingSyncPlugin.ts :: runRebuildCardIndex()` implements user-facing handling and notices.
|
||||
- `src/presentation/commands/registerCommands.ts` registers only 4 commands and does not register rebuild.
|
||||
- `src/presentation/settings/PluginSettingTab.ts :: renderCommandsCard()` lists only the 4 registered commands.
|
||||
- Why it matters
|
||||
- A recovery-oriented feature exists in code but is unavailable in normal user flows.
|
||||
- That increases support burden and leaves state-recovery capability effectively dormant.
|
||||
- Recommended fix
|
||||
- Add a command and a clearly labeled UI entry for rebuild index.
|
||||
- Document what rebuild does and does not do.
|
||||
- Estimated implementation size: S
|
||||
- Risk level: low
|
||||
- Suggested test coverage
|
||||
- Command registration test.
|
||||
- Settings/UI test for rebuild trigger visibility.
|
||||
|
||||
### 4.4 QA Group model authority is split between active user-model sync and dormant managed-model code
|
||||
|
||||
- Severity: medium
|
||||
- Area: architecture
|
||||
- Evidence from real code
|
||||
- Active runtime QA Group sync uses `src/application/services/QaGroupSyncService.ts` plus `settings.cardTypeConfigs["qa-group"].noteType` and `QaGroupFieldMappingService`.
|
||||
- `src/application/services/QaGroupModelService.ts`, `src/application/services/QaGroupModelDefinition.ts`, and `src/application/config/ManagedNoteModels.ts` implement managed model creation for `ObsiAnki QA Group 12`.
|
||||
- Repository-wide search shows `QaGroupModelService` is only referenced by its own tests, not by production runtime.
|
||||
- `src/presentation/i18n/messages/en.ts` and `zh.ts` still describe QA Group as syncing into `ObsiAnki QA Group 12`.
|
||||
- Why it matters
|
||||
- The repository currently carries two different product stories for QA Group.
|
||||
- That makes maintenance, documentation, and future migration decisions harder than necessary.
|
||||
- Recommended fix
|
||||
- Decide one authority model:
|
||||
- fully user-selected QA Group models, or
|
||||
- plugin-managed QA Group model.
|
||||
- Remove or archive the losing branch.
|
||||
- Update settings copy accordingly.
|
||||
- Estimated implementation size: M
|
||||
- Risk level: medium
|
||||
- Suggested test coverage
|
||||
- Remove dead branch tests or convert them into migration tests.
|
||||
- One integration path from settings to sync for the chosen authority model.
|
||||
|
||||
### 4.5 Settings UI is carrying too much stateful business logic in one file
|
||||
|
||||
- Severity: medium
|
||||
- Area: architecture
|
||||
- Evidence from real code
|
||||
- `src/presentation/settings/PluginSettingTab.ts` is roughly 1900 lines and owns:
|
||||
- note type cache loading
|
||||
- field cache hydration
|
||||
- QA Group derivation logic
|
||||
- debounced persistence
|
||||
- folder tree load/cache/expansion
|
||||
- card rendering and rerendering
|
||||
- The same class directly calls `plugin.updateSettings()` from many render-time control handlers.
|
||||
- Why it matters
|
||||
- The file is already large enough that small changes can easily affect unrelated behavior.
|
||||
- UI, cache, mapping, and persistence concerns are mixed.
|
||||
- Recommended fix
|
||||
- Split the setting tab into smaller card-focused modules and move mapping/cache orchestration into dedicated presenter/service helpers.
|
||||
- Estimated implementation size: L
|
||||
- Risk level: medium
|
||||
- Suggested test coverage
|
||||
- Preserve existing UI tests while splitting into smaller component-level tests.
|
||||
- Add a render-count or localized-rerender test for card-scoped updates.
|
||||
|
||||
### 4.6 Legacy mirrored note-type fields still act as a shadow configuration path
|
||||
|
||||
- Severity: medium
|
||||
- Area: architecture
|
||||
- Evidence from real code
|
||||
- `src/application/config/PluginSettings.ts` stores both `cardTypeConfigs[*].noteType` and legacy fields such as `qaNoteType`, `clozeNoteType`, and `semanticQaNoteType`.
|
||||
- `normalizePluginSettings()` derives the legacy fields back from `cardTypeConfigs`.
|
||||
- `src/application/services/RenderConfigService.ts :: resolveNoteModel()` reads the legacy fields instead of `cardTypeConfigs`.
|
||||
- Why it matters
|
||||
- There are two representations for the same concept.
|
||||
- The code currently avoids divergence only by normalization discipline, which is weaker than having one source of truth.
|
||||
- Recommended fix
|
||||
- Make `cardTypeConfigs` the only runtime authority.
|
||||
- Relegate legacy fields to one-way migration only.
|
||||
- Estimated implementation size: M
|
||||
- Risk level: medium
|
||||
- Suggested test coverage
|
||||
- Migration tests from old settings snapshots.
|
||||
- Runtime note-model resolution tests that use only `cardTypeConfigs`.
|
||||
|
||||
### 4.7 AnkiConnect failures are not classified into health-check/offline UX
|
||||
|
||||
- Severity: medium
|
||||
- Area: UX
|
||||
- Evidence from real code
|
||||
- `src/infrastructure/anki/AnkiConnectGateway.ts :: invoke()` calls `requestUrl()` without an explicit timeout parameter.
|
||||
- `src/presentation/AnkiHeadingSyncPlugin.ts :: runSyncCurrentFile()` and `runSyncVault()` catch generic errors and pass them through `renderUnknownUserFacingError()`.
|
||||
- `src/application/errors/PluginUserError.ts :: toUserFacingMessage()` falls back to raw error text for ordinary `Error` instances.
|
||||
- Why it matters
|
||||
- “Anki is not running”, “wrong URL”, “timed out”, and “AnkiConnect returned an action error” are different user problems but converge to a generic failure path.
|
||||
- This weakens first-run UX and troubleshooting.
|
||||
- Recommended fix
|
||||
- Add a dedicated gateway health-check method, explicit timeout handling, and user-facing offline messaging.
|
||||
- Surface that in settings as a check button or status line.
|
||||
- Estimated implementation size: M
|
||||
- Risk level: low
|
||||
- Suggested test coverage
|
||||
- Gateway timeout test.
|
||||
- Plugin-level offline error rendering test.
|
||||
- Settings health-check UI test.
|
||||
|
||||
### 4.8 Clear-current-file reset deletes remote notes before markdown cleanup succeeds
|
||||
|
||||
- Severity: high
|
||||
- Area: sync correctness
|
||||
- Evidence from real code
|
||||
- `src/application/use-cases/ClearCurrentFileSyncedCardsUseCase.ts :: execute()` deletes note IDs through `ankiGateway.deleteNotes(noteIds)` before calling `markdownMarkerRemovalService.remove(...)`.
|
||||
- The result can still contain `conflictFiles` and `failureFiles`, meaning markdown cleanup can fail after remote deletion has already happened.
|
||||
- Why it matters
|
||||
- A user can end up with deleted Anki notes but stale markers/local traces in Markdown.
|
||||
- There is no rollback path.
|
||||
- Recommended fix
|
||||
- Make reset more recoverable:
|
||||
- either remove local markers/state first and mark remote deletion as pending,
|
||||
- or add a two-phase result model with resumable cleanup.
|
||||
- Estimated implementation size: M
|
||||
- Risk level: high
|
||||
- Suggested test coverage
|
||||
- Conflict during marker removal after remote deletion.
|
||||
- Restart/resume after partial reset.
|
||||
|
||||
### 4.9 Batch sync is non-transactional across create/update/tag/deck/media phases
|
||||
|
||||
- Severity: high
|
||||
- Area: sync correctness
|
||||
- Evidence from real code
|
||||
- `src/application/services/AnkiBatchExecutor.ts :: execute()` performs deck ensure, media upload, note create, note update, model migration, tag sync, and deck migration in separate phases.
|
||||
- There is no rollback or checkpoint reconciliation when a later phase fails after earlier remote mutations already succeeded.
|
||||
- Why it matters
|
||||
- Partial AnkiConnect failure can leave the remote state ahead of the local marker/state write-back pipeline.
|
||||
- The plugin already tries to recover marker writes, but not the whole multi-phase sync transaction.
|
||||
- Recommended fix
|
||||
- Introduce a resumable execution journal or a narrower phase-by-phase recovery strategy.
|
||||
- At minimum, classify remote progress in the saved state when later phases fail.
|
||||
- Estimated implementation size: L
|
||||
- Risk level: high
|
||||
- Suggested test coverage
|
||||
- Partial failure after note creation but before tag/deck sync.
|
||||
- Partial failure after model migration.
|
||||
|
||||
### 4.10 Test doubles are too optimistic for real Anki multi-request failure behavior
|
||||
|
||||
- Severity: medium
|
||||
- Area: testing
|
||||
- Evidence from real code
|
||||
- `src/test-support/manualSyncFakes.ts :: FakeManualSyncAnkiGateway` batch methods (`addNotes`, `updateNotes`, `changeDecks`, `storeMediaFiles`) always succeed and do not simulate per-item or top-level multi failures.
|
||||
- The real adapter in `src/infrastructure/anki/AnkiConnectGateway.ts` uses `multi` requests and already contains per-item error parsing logic for some actions.
|
||||
- Why it matters
|
||||
- Service-level tests can pass while still underrepresenting real-world failure modes.
|
||||
- This is one reason the code has many happy-path tests but weaker evidence around partial remote failures.
|
||||
- Recommended fix
|
||||
- Add failure-capable fake gateways or integration-style adapter fixtures that can simulate:
|
||||
- top-level `multi` errors
|
||||
- partial per-action failures
|
||||
- timeouts / transport errors
|
||||
- Estimated implementation size: M
|
||||
- Risk level: low
|
||||
- Suggested test coverage
|
||||
- `AnkiBatchExecutor` partial failure cases.
|
||||
- `ManualSyncService` recovery after transport failure.
|
||||
|
||||
## 5. Improvement backlog
|
||||
|
||||
### P0: must fix soon
|
||||
|
||||
- Persist `pendingWriteBack` on load and restart.
|
||||
- Harden destructive reset so remote deletion cannot silently outrun local cleanup.
|
||||
- Add AnkiConnect timeout/health classification and user-facing offline guidance.
|
||||
- Add at least one resumable or checkpointed strategy for partial remote sync failure.
|
||||
|
||||
### P1: high value
|
||||
|
||||
- Resolve semantic QA runtime/UI mismatch.
|
||||
- Unify QA Group model authority and remove dormant managed-model branch or fully adopt it.
|
||||
- Collapse note-model authority onto `cardTypeConfigs` only.
|
||||
- Expose rebuild index or remove the dormant entry point.
|
||||
- Refactor `PluginSettingTab` into smaller modules.
|
||||
- Improve failure-capable test doubles and add failure-path integration tests.
|
||||
|
||||
### P2: nice to have
|
||||
|
||||
- Improve locale handling so `zh-*` variants do not fall back to English by design.
|
||||
- Move `query_note.js` and `query_notes.js` into an explicit debug/scripts area or remove them.
|
||||
- Simplify build/release documentation around root `main.js` vs `dist/plugin/main.js`.
|
||||
- Add a small settings-page connection test/diagnostic panel.
|
||||
|
||||
### P3: later exploration
|
||||
|
||||
- Dry-run or preview mode before sync.
|
||||
- Richer conflict explanation UI for marker-write conflicts.
|
||||
- Lightweight performance telemetry for large-vault scans.
|
||||
|
||||
## 6. Recommended next development plans
|
||||
|
||||
### Module 1: Persist pending write-back across restart
|
||||
|
||||
- Goal
|
||||
- Make marker conflict recovery survive plugin reloads.
|
||||
- Why it matters
|
||||
- The current design already depends on `pendingWriteBack`, but load discards it.
|
||||
- Files likely to change
|
||||
- `src/infrastructure/persistence/DataJsonPluginStateRepository.ts`
|
||||
- `src/infrastructure/persistence/DataJsonPluginStateRepository.test.ts`
|
||||
- Possibly `src/domain/manual-sync/entities/PluginState.ts`
|
||||
- Implementation outline
|
||||
- Distinguish legacy migration from modern-state passthrough.
|
||||
- Preserve modern `pendingWriteBack` entries.
|
||||
- Validate marker kinds and required fields on load.
|
||||
- Tests to add
|
||||
- Save/load round-trip for modern pending entries.
|
||||
- Recovery after conflict across repository reload.
|
||||
- Risk
|
||||
- Medium
|
||||
- Suggested prompt title
|
||||
- `Persist Pending Writeback Recovery`
|
||||
|
||||
### Module 2: Add Anki health check and timeout-aware UX
|
||||
|
||||
- Goal
|
||||
- Turn Anki offline/slow scenarios into clear, recoverable UX.
|
||||
- Why it matters
|
||||
- Current transport errors are too generic for first-run and troubleshooting.
|
||||
- Files likely to change
|
||||
- `src/infrastructure/anki/AnkiConnectGateway.ts`
|
||||
- `src/presentation/AnkiHeadingSyncPlugin.ts`
|
||||
- `src/presentation/settings/PluginSettingTab.ts`
|
||||
- `src/presentation/i18n/messages/en.ts`
|
||||
- `src/presentation/i18n/messages/zh.ts`
|
||||
- Implementation outline
|
||||
- Add ping/health-check action.
|
||||
- Add explicit timeout handling.
|
||||
- Surface health result in settings and sync command failures.
|
||||
- Tests to add
|
||||
- Gateway timeout/offline tests.
|
||||
- Settings health-check UI tests.
|
||||
- Plugin command offline-notice tests.
|
||||
- Risk
|
||||
- Low
|
||||
- Suggested prompt title
|
||||
- `AnkiConnect Health Check UX`
|
||||
|
||||
### Module 3: Bring semantic QA to product parity
|
||||
|
||||
- Goal
|
||||
- Stop having semantic QA exist only half-way between runtime and settings.
|
||||
- Why it matters
|
||||
- Users need explicit control over all active sync-capable card types.
|
||||
- Files likely to change
|
||||
- `src/presentation/settings/PluginSettingTab.ts`
|
||||
- `src/presentation/settings/PluginSettingTab.test.ts`
|
||||
- `src/application/config/PluginSettings.ts`
|
||||
- `src/application/services/NoteFieldMappingService.ts`
|
||||
- `src/application/services/RenderConfigService.ts`
|
||||
- Implementation outline
|
||||
- Expose semantic QA in settings with note-type and field mapping.
|
||||
- Or gate parser/runtime support behind explicit availability.
|
||||
- Tests to add
|
||||
- Settings rendering and persistence tests.
|
||||
- Semantic QA sync path with configured mapping.
|
||||
- Risk
|
||||
- Medium
|
||||
- Suggested prompt title
|
||||
- `Semantic QA Settings Parity`
|
||||
|
||||
### Module 4: Harden clear-current-file reset
|
||||
|
||||
- Goal
|
||||
- Make reset resumable and safer under write conflicts or partial failures.
|
||||
- Why it matters
|
||||
- Current order can delete remote data before local cleanup finishes.
|
||||
- Files likely to change
|
||||
- `src/application/use-cases/ClearCurrentFileSyncedCardsUseCase.ts`
|
||||
- `src/application/services/MarkdownSyncedMarkerRemovalService.ts`
|
||||
- `src/infrastructure/persistence/DataJsonPluginStateRepository.ts`
|
||||
- `src/application/use-cases/ClearCurrentFileSyncedCardsUseCase.test.ts`
|
||||
- Implementation outline
|
||||
- Add staged reset state or reorder the operation with recovery markers.
|
||||
- Preserve enough local state to retry cleanup safely.
|
||||
- Tests to add
|
||||
- Conflict after remote delete.
|
||||
- Retry after restart.
|
||||
- Risk
|
||||
- High
|
||||
- Suggested prompt title
|
||||
- `Harden Clear Current File Reset`
|
||||
|
||||
### Module 5: Unify QA Group model authority
|
||||
|
||||
- Goal
|
||||
- Remove the split between user-selected QA Group models and dormant managed-model infrastructure.
|
||||
- Why it matters
|
||||
- One codebase should tell one consistent QA Group story.
|
||||
- Files likely to change
|
||||
- `src/application/services/QaGroupModelService.ts`
|
||||
- `src/application/services/QaGroupModelDefinition.ts`
|
||||
- `src/application/config/ManagedNoteModels.ts`
|
||||
- `src/application/services/QaGroupSyncService.ts`
|
||||
- `src/presentation/settings/PluginSettingTab.ts`
|
||||
- `src/presentation/i18n/messages/en.ts`
|
||||
- `src/presentation/i18n/messages/zh.ts`
|
||||
- Implementation outline
|
||||
- Decide whether the plugin owns a managed QA Group model.
|
||||
- Remove or fully integrate the losing branch.
|
||||
- Tests to add
|
||||
- End-to-end QA Group path for the chosen authority model.
|
||||
- Copy and settings tests matching the chosen UX.
|
||||
- Risk
|
||||
- Medium
|
||||
- Suggested prompt title
|
||||
- `Unify QA Group Model Authority`
|
||||
|
||||
### Module 6: Make `cardTypeConfigs` the sole note-model authority
|
||||
|
||||
- Goal
|
||||
- Complete the settings migration instead of keeping mirrored legacy fields alive.
|
||||
- Why it matters
|
||||
- Shadow settings make future bugs more likely.
|
||||
- Files likely to change
|
||||
- `src/application/config/PluginSettings.ts`
|
||||
- `src/application/services/RenderConfigService.ts`
|
||||
- `src/infrastructure/persistence/DataJsonPluginConfigRepository.ts`
|
||||
- `src/application/config/PluginSettings.test.ts`
|
||||
- Implementation outline
|
||||
- Read note-model names directly from `cardTypeConfigs`.
|
||||
- Keep legacy values only for load-time migration.
|
||||
- Tests to add
|
||||
- Old snapshot migration tests.
|
||||
- RenderConfigService tests for all card types.
|
||||
- Risk
|
||||
- Medium
|
||||
- Suggested prompt title
|
||||
- `Retire Legacy Note Type Mirrors`
|
||||
|
||||
### Module 7: Split the settings page by card and service
|
||||
|
||||
- Goal
|
||||
- Reduce the size and cognitive load of `PluginSettingTab.ts`.
|
||||
- Why it matters
|
||||
- The settings page is now one of the main maintenance hotspots.
|
||||
- Files likely to change
|
||||
- `src/presentation/settings/PluginSettingTab.ts`
|
||||
- New helpers/components under `src/presentation/settings/`
|
||||
- `src/presentation/settings/PluginSettingTab.test.ts`
|
||||
- Implementation outline
|
||||
- Extract card-type card, deck card, scope card, and cache/mapping orchestration helpers.
|
||||
- Keep public UI behavior stable first.
|
||||
- Tests to add
|
||||
- Preserve existing behavior with smaller focused tests.
|
||||
- Risk
|
||||
- Medium
|
||||
- Suggested prompt title
|
||||
- `Refactor Settings Page Cards`
|
||||
|
||||
## 7. Product suggestions
|
||||
|
||||
- Simplify settings mental model
|
||||
- Make every active sync-capable card type visible and configurable from one consistent card-type surface.
|
||||
|
||||
- Improve onboarding
|
||||
- Add a first-run AnkiConnect health check and a “what still needs configuration” summary.
|
||||
|
||||
- Add sync preview or dry-run mode
|
||||
- The existing plan/build architecture is already close to supporting a non-destructive preview step.
|
||||
|
||||
- Make error recovery explicit
|
||||
- Marker-write conflicts should tell the user what happened, what was already synced remotely, and how to retry safely.
|
||||
|
||||
- Add mapping confidence cues
|
||||
- Show whether a mapping is from live cache, stale cache, manual override, or incomplete selection.
|
||||
|
||||
- Explain conflicts in UI
|
||||
- Deck fallback warnings and mapping staleness already exist in code; present them earlier in settings or pre-sync diagnostics.
|
||||
|
||||
- Stop hardcoding old QA Group product language in user copy
|
||||
- Current strings still refer to `ObsiAnki QA Group 12` even though runtime sync now follows user-selected models.
|
||||
|
||||
## 8. Technical suggestions
|
||||
|
||||
- Tighten service boundaries
|
||||
- Move settings-page cache and mapping orchestration out of `PluginSettingTab`.
|
||||
|
||||
- Finish config migration
|
||||
- Keep one note-model authority path and one QA Group model strategy.
|
||||
|
||||
- Strengthen state invariants
|
||||
- `pendingWriteBack` should be durable, validated, and part of the explicit recovery model.
|
||||
|
||||
- Harden gateway contracts
|
||||
- Distinguish transport failure, top-level AnkiConnect error, and per-action multi failure.
|
||||
|
||||
- Clean dead or dormant branches
|
||||
- Remove unmanaged remnants like unused managed QA Group runtime services if they are not the chosen direction.
|
||||
|
||||
- Add lightweight performance instrumentation
|
||||
- File scan counts, skipped counts, and marker-conflict counts are already available and could be logged or surfaced in debug mode.
|
||||
|
||||
## 9. Testing suggestions
|
||||
|
||||
### Parser
|
||||
|
||||
- Add more pathological QA Group and semantic QA markdown cases:
|
||||
- mixed fences
|
||||
- repeated labels
|
||||
- ambiguous indentation
|
||||
- empty answer edge cases
|
||||
|
||||
### Mapping
|
||||
|
||||
- Add stale-field and partially renamed-field tests for basic, cloze, semantic QA, and QA Group mappings.
|
||||
- Add tests for semantic QA settings once surfaced.
|
||||
|
||||
### Sync execution
|
||||
|
||||
- Add partial failure tests after remote note creation but before local write-back.
|
||||
- Add restart/retry tests using persisted `pendingWriteBack`.
|
||||
|
||||
### Anki gateway
|
||||
|
||||
- Add timeout/offline tests.
|
||||
- Add explicit `multi` partial failure tests for more actions than model-field loading.
|
||||
|
||||
### Settings UI
|
||||
|
||||
- Add tests for semantic QA controls if kept active.
|
||||
- Add health-check and stale-cache status tests.
|
||||
|
||||
### Persistence / migration
|
||||
|
||||
- Add save/load tests that preserve `pendingWriteBack`.
|
||||
- Add versioned migration tests for old settings snapshots after legacy field cleanup.
|
||||
|
||||
### Failure paths
|
||||
|
||||
- Add reset-conflict tests where remote deletion succeeds but local cleanup fails.
|
||||
- Add deck cleanup partial-failure tests with mixed deletion outcomes.
|
||||
|
||||
### E2E / manual validation
|
||||
|
||||
- Validate against a real Anki instance for:
|
||||
- Anki offline
|
||||
- changed note model fields
|
||||
- QA Group model mismatch
|
||||
- marker conflict after editing the file between scan and write-back
|
||||
|
||||
## 10. Risks and non-goals
|
||||
|
||||
- Do not rewrite the whole plugin.
|
||||
- Do not add more settings before fixing the current runtime/UI mismatches.
|
||||
- Do not keep both user-selected QA Group models and dormant managed QA Group model code long term.
|
||||
- Do not hide AnkiConnect transport errors under vague generic notices.
|
||||
- Do not overfit field mapping heuristics to one language or one note template.
|
||||
- Do not treat generated `main.js` or `dist/plugin/*` as the primary design surface.
|
||||
|
||||
## 11. Quick wins
|
||||
|
||||
- Add a rebuild-index command and list it in the settings command card.
|
||||
- Treat `zh-CN` / `zh-TW` style locales as Chinese instead of falling back to English.
|
||||
- Move `query_note.js` and `query_notes.js` under a `scripts/debug/` convention or delete them.
|
||||
- Update QA Group settings copy to match the actual chosen product model.
|
||||
- Add a settings-page “Check Anki connection” button.
|
||||
|
||||
## 12. Suggested implementation order
|
||||
|
||||
1. Persist `pendingWriteBack` correctly across save/load/restart.
|
||||
2. Add AnkiConnect timeout + health-check + offline UX.
|
||||
3. Harden clear-current-file reset against partial failure.
|
||||
4. Resolve semantic QA runtime/UI mismatch.
|
||||
5. Unify QA Group model authority.
|
||||
6. Retire legacy note-type mirrors and make `cardTypeConfigs` authoritative.
|
||||
7. Improve failure-capable test doubles and add partial-failure integration coverage.
|
||||
8. Split the settings page into smaller card-scoped modules.
|
||||
346
docs/plugin-improvement-next-prompts.md
Normal file
346
docs/plugin-improvement-next-prompts.md
Normal file
|
|
@ -0,0 +1,346 @@
|
|||
# Plugin Improvement Next Prompts
|
||||
|
||||
The following prompts are ready-to-use implementation prompts for the top 5 follow-up tasks from the audit. Each prompt is written for a deep implementation run and assumes the agent must inspect real code first.
|
||||
|
||||
## 1. Persist Pending Writeback Recovery
|
||||
|
||||
### Prompt title
|
||||
|
||||
`pending-writeback-persistence`
|
||||
|
||||
### Prompt
|
||||
|
||||
```text
|
||||
Use the attached request as the primary reference for this task.
|
||||
|
||||
Repository: Anki Heading Sync Obsidian plugin.
|
||||
|
||||
Goal:
|
||||
Persist pending markdown write-back recovery across plugin reloads/restarts.
|
||||
|
||||
Important instructions:
|
||||
- Do a real code review first. Do not guess.
|
||||
- Start from the actual current implementation of pending write-back:
|
||||
- src/application/services/MarkdownWriteBackService.ts
|
||||
- src/application/services/FileIndexerService.ts
|
||||
- src/infrastructure/persistence/DataJsonPluginStateRepository.ts
|
||||
- src/infrastructure/persistence/DataJsonPluginStateRepository.test.ts
|
||||
- Verify how pendingWriteBack is produced, consumed, saved, and loaded.
|
||||
- Minimize source changes. Do not rewrite unrelated persistence code.
|
||||
|
||||
Required workflow:
|
||||
1. Inspect the real repository code in depth.
|
||||
2. Write a gap report to:
|
||||
docs/pending-writeback-persistence-gap-report.md
|
||||
3. Write a decisions doc to:
|
||||
docs/pending-writeback-persistence-decisions.md
|
||||
4. Implement the fix.
|
||||
5. Add or update tests.
|
||||
6. Run validation:
|
||||
- npm run lint
|
||||
- npm test
|
||||
7. If validation passes, run build and sync built plugin artifacts to the Obsidian plugin directory.
|
||||
8. Commit the work with a bilingual commit message.
|
||||
|
||||
Implementation requirements:
|
||||
- Preserve modern pendingWriteBack entries on load.
|
||||
- Keep any required legacy migration behavior explicit and isolated.
|
||||
- Ensure restart/reload does not silently discard recovery entries.
|
||||
- Do not modify production behavior outside this slice unless required by the fix.
|
||||
|
||||
Validation requirements:
|
||||
- Add at least one round-trip persistence test for pendingWriteBack.
|
||||
- Add at least one recovery-oriented test proving the loaded state is usable.
|
||||
|
||||
Build and sync requirements:
|
||||
- After passing lint/tests, run the project build.
|
||||
- Sync only built plugin files:
|
||||
- main.js
|
||||
- manifest.json
|
||||
- styles.css if present
|
||||
- Do not delete or overwrite data.json.
|
||||
|
||||
Commit requirements:
|
||||
- Commit only the relevant source/test/docs changes for this task.
|
||||
- Use a bilingual commit message.
|
||||
|
||||
Final response format:
|
||||
1. gap summary
|
||||
2. decisions made
|
||||
3. files changed
|
||||
4. tests added/updated
|
||||
5. commands run and results
|
||||
6. final commit hash
|
||||
7. final bilingual commit message
|
||||
8. whether plugin artifacts were synced
|
||||
9. known risks
|
||||
```
|
||||
|
||||
## 2. Add AnkiConnect Health Check and Timeout UX
|
||||
|
||||
### Prompt title
|
||||
|
||||
`anki-health-check-timeout-ux`
|
||||
|
||||
### Prompt
|
||||
|
||||
```text
|
||||
Use the attached request as the primary reference for this task.
|
||||
|
||||
Repository: Anki Heading Sync Obsidian plugin.
|
||||
|
||||
Goal:
|
||||
Add explicit AnkiConnect health-check and timeout-aware offline UX.
|
||||
|
||||
Important instructions:
|
||||
- Review the real repository code before making recommendations or edits.
|
||||
- Start from these files:
|
||||
- src/infrastructure/anki/AnkiConnectGateway.ts
|
||||
- src/presentation/AnkiHeadingSyncPlugin.ts
|
||||
- src/presentation/settings/PluginSettingTab.ts
|
||||
- src/application/errors/PluginUserError.ts
|
||||
- src/presentation/i18n/messages/en.ts
|
||||
- src/presentation/i18n/messages/zh.ts
|
||||
- Do not add generic status UI. Make it fit the existing plugin architecture.
|
||||
|
||||
Required workflow:
|
||||
1. Inspect the real code path for current sync failures and settings UI.
|
||||
2. Write a gap report to:
|
||||
docs/anki-health-check-timeout-gap-report.md
|
||||
3. Write a decisions doc to:
|
||||
docs/anki-health-check-timeout-decisions.md
|
||||
4. Implement the feature.
|
||||
5. Add tests.
|
||||
6. Run validation:
|
||||
- npm run lint
|
||||
- npm test
|
||||
7. If validation passes, run build and sync built plugin files.
|
||||
8. Commit with a bilingual commit message.
|
||||
|
||||
Implementation requirements:
|
||||
- Add an explicit gateway-level health-check path.
|
||||
- Add timeout-aware handling for slow/offline AnkiConnect behavior.
|
||||
- Surface a user-facing check in settings and improve sync error messages.
|
||||
- Keep the UI concise and aligned with the current settings page.
|
||||
|
||||
Testing requirements:
|
||||
- Add gateway tests for timeout/offline behavior.
|
||||
- Add plugin/settings tests for the user-facing health-check or error surface.
|
||||
|
||||
Build and sync requirements:
|
||||
- Sync only main.js, manifest.json, and styles.css if present.
|
||||
- Never overwrite or delete data.json.
|
||||
|
||||
Final response format:
|
||||
1. gap summary
|
||||
2. decisions made
|
||||
3. files changed
|
||||
4. UX changes delivered
|
||||
5. tests added/updated
|
||||
6. commands run and results
|
||||
7. final commit hash
|
||||
8. final bilingual commit message
|
||||
9. whether plugin artifacts were synced
|
||||
10. known follow-ups
|
||||
```
|
||||
|
||||
## 3. Bring Semantic QA to Settings Parity
|
||||
|
||||
### Prompt title
|
||||
|
||||
`semantic-qa-settings-parity`
|
||||
|
||||
### Prompt
|
||||
|
||||
```text
|
||||
Use the attached request as the primary reference for this task.
|
||||
|
||||
Repository: Anki Heading Sync Obsidian plugin.
|
||||
|
||||
Goal:
|
||||
Resolve the mismatch where semantic QA is active in runtime but not surfaced in the settings UI.
|
||||
|
||||
Important instructions:
|
||||
- Inspect the real repository code first.
|
||||
- Start from:
|
||||
- src/application/config/PluginSettings.ts
|
||||
- src/domain/manual-sync/services/CardIndexingService.ts
|
||||
- src/application/services/RenderConfigService.ts
|
||||
- src/application/services/NoteFieldMappingService.ts
|
||||
- src/presentation/settings/PluginSettingTab.ts
|
||||
- src/presentation/settings/PluginSettingTab.test.ts
|
||||
- Decide whether semantic QA should be fully exposed or intentionally gated/disabled, but justify the decision from real code.
|
||||
|
||||
Required workflow:
|
||||
1. Inspect the actual runtime and settings code.
|
||||
2. Write a gap report to:
|
||||
docs/semantic-qa-settings-parity-gap-report.md
|
||||
3. Write a decisions doc to:
|
||||
docs/semantic-qa-settings-parity-decisions.md
|
||||
4. Implement the chosen direction.
|
||||
5. Add tests.
|
||||
6. Run validation:
|
||||
- npm run lint
|
||||
- npm test
|
||||
7. If validation passes, run build and sync built plugin files.
|
||||
8. Commit with a bilingual commit message.
|
||||
|
||||
Implementation requirements:
|
||||
- If semantic QA remains active runtime behavior, users must be able to configure it coherently.
|
||||
- If semantic QA is intentionally not ready, runtime behavior must not silently remain active and unconfigurable.
|
||||
- Preserve existing behavior for basic, cloze, and QA Group paths.
|
||||
|
||||
Testing requirements:
|
||||
- Add settings UI coverage for semantic QA.
|
||||
- Add runtime sync coverage for the chosen semantic QA behavior.
|
||||
|
||||
Build and sync requirements:
|
||||
- Sync only built plugin files.
|
||||
- Do not overwrite data.json.
|
||||
|
||||
Final response format:
|
||||
1. gap summary
|
||||
2. decision taken and why
|
||||
3. files changed
|
||||
4. UX impact
|
||||
5. tests added/updated
|
||||
6. commands run and results
|
||||
7. final commit hash
|
||||
8. final bilingual commit message
|
||||
9. whether plugin artifacts were synced
|
||||
10. known tradeoffs
|
||||
```
|
||||
|
||||
## 4. Harden Clear Current File Reset
|
||||
|
||||
### Prompt title
|
||||
|
||||
`clear-current-file-reset-hardening`
|
||||
|
||||
### Prompt
|
||||
|
||||
```text
|
||||
Use the attached request as the primary reference for this task.
|
||||
|
||||
Repository: Anki Heading Sync Obsidian plugin.
|
||||
|
||||
Goal:
|
||||
Make “clear current file synced cards” safer under marker conflicts and partial failure.
|
||||
|
||||
Important instructions:
|
||||
- Review the real code before changing anything.
|
||||
- Start from:
|
||||
- src/application/use-cases/ClearCurrentFileSyncedCardsUseCase.ts
|
||||
- src/application/services/MarkdownSyncedMarkerRemovalService.ts
|
||||
- src/infrastructure/persistence/DataJsonPluginStateRepository.ts
|
||||
- src/application/use-cases/ClearCurrentFileSyncedCardsUseCase.test.ts
|
||||
- Keep the change narrowly scoped to reset safety and recoverability.
|
||||
|
||||
Required workflow:
|
||||
1. Inspect the real destructive path and its current tests.
|
||||
2. Write a gap report to:
|
||||
docs/clear-current-file-reset-hardening-gap-report.md
|
||||
3. Write a decisions doc to:
|
||||
docs/clear-current-file-reset-hardening-decisions.md
|
||||
4. Implement the hardening.
|
||||
5. Add tests.
|
||||
6. Run validation:
|
||||
- npm run lint
|
||||
- npm test
|
||||
7. If validation passes, run build and sync built plugin files.
|
||||
8. Commit with a bilingual commit message.
|
||||
|
||||
Implementation requirements:
|
||||
- Avoid ending in a state where remote notes are deleted but local cleanup cannot be resumed safely.
|
||||
- If a staged or pending reset state is needed, make it explicit.
|
||||
- Preserve existing user-facing command behavior unless the safety fix requires improved messaging.
|
||||
|
||||
Testing requirements:
|
||||
- Add tests for marker conflict or cleanup failure after remote deletion would otherwise occur.
|
||||
- Add retry/resume coverage if new state is introduced.
|
||||
|
||||
Build and sync requirements:
|
||||
- Sync only built plugin files.
|
||||
- Do not overwrite data.json.
|
||||
|
||||
Final response format:
|
||||
1. gap summary
|
||||
2. decisions made
|
||||
3. files changed
|
||||
4. safety behavior changed
|
||||
5. tests added/updated
|
||||
6. commands run and results
|
||||
7. final commit hash
|
||||
8. final bilingual commit message
|
||||
9. whether plugin artifacts were synced
|
||||
10. residual risks
|
||||
```
|
||||
|
||||
## 5. Unify QA Group Model Authority
|
||||
|
||||
### Prompt title
|
||||
|
||||
`qa-group-authority-unification`
|
||||
|
||||
### Prompt
|
||||
|
||||
```text
|
||||
Use the attached request as the primary reference for this task.
|
||||
|
||||
Repository: Anki Heading Sync Obsidian plugin.
|
||||
|
||||
Goal:
|
||||
Unify the QA Group note-model strategy so the plugin no longer carries both an active user-selected path and a dormant managed-model branch.
|
||||
|
||||
Important instructions:
|
||||
- Inspect the real code first.
|
||||
- Start from:
|
||||
- src/application/services/QaGroupSyncService.ts
|
||||
- src/application/services/QaGroupFieldMappingService.ts
|
||||
- src/application/services/QaGroupModelService.ts
|
||||
- src/application/services/QaGroupModelDefinition.ts
|
||||
- src/application/config/ManagedNoteModels.ts
|
||||
- src/presentation/settings/PluginSettingTab.ts
|
||||
- src/presentation/i18n/messages/en.ts
|
||||
- src/presentation/i18n/messages/zh.ts
|
||||
- Decide one product authority model and remove or fully integrate the other.
|
||||
|
||||
Required workflow:
|
||||
1. Inspect the real production call sites and tests.
|
||||
2. Write a gap report to:
|
||||
docs/qa-group-authority-unification-gap-report.md
|
||||
3. Write a decisions doc to:
|
||||
docs/qa-group-authority-unification-decisions.md
|
||||
4. Implement the chosen authority model.
|
||||
5. Add tests.
|
||||
6. Run validation:
|
||||
- npm run lint
|
||||
- npm test
|
||||
7. If validation passes, run build and sync built plugin files.
|
||||
8. Commit with a bilingual commit message.
|
||||
|
||||
Implementation requirements:
|
||||
- The final codebase should tell one coherent QA Group story.
|
||||
- Align settings copy, tests, and runtime behavior with that story.
|
||||
- Remove or archive dead production code if it is no longer part of the chosen path.
|
||||
|
||||
Testing requirements:
|
||||
- Add or update tests so the chosen QA Group authority path is fully covered.
|
||||
- Remove misleading tests that only validate dead code paths.
|
||||
|
||||
Build and sync requirements:
|
||||
- Sync only built plugin files.
|
||||
- Do not overwrite data.json.
|
||||
|
||||
Final response format:
|
||||
1. gap summary
|
||||
2. authority model chosen and why
|
||||
3. files changed
|
||||
4. runtime/UI alignment changes
|
||||
5. tests added/updated
|
||||
6. commands run and results
|
||||
7. final commit hash
|
||||
8. final bilingual commit message
|
||||
9. whether plugin artifacts were synced
|
||||
10. follow-up migration tasks
|
||||
```
|
||||
Loading…
Reference in a new issue