diff --git a/KHADHROONY_BOT3_MIGRATION_CLOSURE_TODO.md b/KHADHROONY_BOT3_MIGRATION_CLOSURE_TODO.md index a99a571..35d329b 100644 --- a/KHADHROONY_BOT3_MIGRATION_CLOSURE_TODO.md +++ b/KHADHROONY_BOT3_MIGRATION_CLOSURE_TODO.md @@ -1,5 +1,5 @@ - + # Checklist détaillée de clôture de la migration `khadhroony-bot3` @@ -105,15 +105,16 @@ - [x] Garder Program ID librement éditable. - [x] Ajouter un autocomplétion non bloquant depuis le registre public `kb-program-ids`. +- [ ] Ajouter le même autocomplétion Program ID au filtre « programme déjà indexé » d’Extraction core. - [ ] Ajouter ultérieurement les autocomplétions Token et Pool lorsque leurs tables de référence existeront. ### 2.4 Journaux généraux et viewers - [x] Vérifier Backfill HTTP en runtime. -- [ ] Vérifier Extraction core en runtime après correction du gabarit pleine largeur. +- [x] Vérifier Extraction core en runtime après correction du gabarit pleine largeur. - [ ] Vérifier Exécution Solana Core. - [ ] Vérifier Exécution SPL. -- [ ] Vérifier Decode replay. +- [x] Vérifier Decode replay en runtime et conserver les échecs Loader/Metaplex comme anomalies fonctionnelles à corriger. - [x] Vérifier HTTP en runtime. - [x] Vérifier WebSocket en runtime. - [x] Placer les paramètres d’Extraction core dans les accordéons. @@ -125,6 +126,12 @@ ### 2.5 Fenêtres SQL +- [x] Relever temporairement le plafond de résultats de 5 000 à 100 000 pour les campagnes de migration. +- [ ] Ajouter ultérieurement une pagination SQL/IPC serveur avant les volumes massifs. +- [x] Écrire les CSV dans `/data/exports_csv`, indépendamment du répertoire courant Tauri. +- [ ] Corriger la valeur de repli TypeScript `maximumReplayCandidateLimit = 5_000` vers `100_000`. +- [x] Valider qu’un export produit `data/exports_csv/replay_transactions.csv`. + - [ ] Mettre toutes les fenêtres SQL, sauf Replay Candidates, sur une seule colonne pleine largeur. - [ ] Mettre les tables sur toute la largeur. - [ ] Limiter le scroll horizontal au wrapper de table. @@ -210,7 +217,7 @@ - [x] Charger et valider la configuration. - [x] Initialiser le logging. - [x] Initialiser le pool HTTP. -- [ ] Se connecter à PostgreSQL. +- [x] Se connecter à PostgreSQL et confirmer la disponibilité du profil `mainnet_research`. - [x] Appeler `initialize_postgres_schema_for_startup` après disponibilité du frontend splash. - [x] Appeler `emit_sql_startup_table_report`. - [x] Relier `emit_sql_startup_error`. @@ -221,27 +228,39 @@ - [x] Rendre les zones du splash scrollables sans afficher leurs barres de défilement. - [x] Garder automatiquement le dernier log et le dernier message visibles. - [x] Afficher connexion, schéma, nombre de tables, tables manquantes et statut final. -- [ ] Valider visuellement le fade-in, les messages intermédiaires, le fade-out et l’ouverture de `main` sur le workspace réel. +- [ ] Supprimer l’écrasement artificiel de `auto_initialize_schema` à `false` dans le chemin du splash et respecter la valeur du profil actif. +- [x] Valider visuellement les messages intermédiaires, l’ouverture de `main`, l’absence de scrollbar visible et l’auto-scroll ; conserver le fade CSS Tauri/Linux comme limitation visuelle non bloquante. ## 8. Purge contrôlée des données dérivées -- [ ] Inventorier les tables via `kb-store`. -- [ ] Classer chaque table en raw, nécessaire au replay, dérivée ou ambiguë. -- [ ] Bloquer la purge tant qu’une table reste ambiguë. -- [ ] Créer un script SQL versionné et idempotent. -- [ ] Conserver transactions, signatures et payloads RPC raw. -- [ ] Conserver toutes les données nécessaires à l’extraction et au replay. -- [ ] Purger core dérivé, décodage, observations, coverage, diagnostics et états de replay dérivés. -- [ ] Purger annotations, événements matérialisés, token accounts, lifecycle, admin, fees, risk, compliance et staking dérivés. -- [ ] Exécuter la purge dans une transaction. -- [ ] Ajouter des vérifications avant/après. -- [ ] Documenter précisément les tables conservées. -- [ ] Relancer l’extraction core. +- [x] Inventorier les tables via les migrations `kb-store` 0001 à 0004. +- [x] Classer `kb_sol_raw_transactions` et `kb_sol_obs_transaction_observations` comme acquisition raw ; classer core, ledger, decode, coverage et matérialisation comme dérivés reconstructibles. +- [x] Confirmer qu’aucune table actuellement définie par `kb-store` ne reste ambiguë pour cette reconstruction. +- [x] Confirmer que le schéma courant est initialisé par les listes SQL idempotentes de `kb-store` et non par une table `_sqlx_migrations` active. +- [ ] Corriger `kb-store/maintenance/reset_derived_store_keep_raw.sql` pour conserver explicitement les deux tables d’acquisition et utiliser une stratégie `TRUNCATE ... RESTART IDENTITY` pour les tables dérivées. +- [x] Conserver `kb_sol_raw_transactions` avec 4 574 transactions et remettre tous les `processing_state` à `received`. +- [ ] Restaurer ou accepter explicitement la perte des anciennes lignes de `kb_sol_obs_transaction_observations` supprimées pendant la reconstruction manuelle. +- [x] Recréer manuellement toutes les tables manquantes depuis les scripts SQL de `kb-store`. +- [x] Vérifier avant reprise que toutes les tables Core contiennent zéro ligne. +- [x] Vérifier avant reprise que `kb_sol_ops_processing_ledger` est vide. +- [x] Vérifier avant reprise que les 4 574 raws sont sélectionnables avec l’état `received`. +- [x] Purger les tables core, ledger, decode, coverage et matérialisation dérivées. +- [x] Encadrer la reconstruction manuelle par une démarche contrôlée sans toucher aux transactions raw. +- [x] Ajouter des vérifications avant reprise : compteurs raw, Core et ledger. +- [ ] Documenter précisément les tables conservées et la politique de reconstruction dans `kb-store/maintenance/README.md`. +- [ ] Relancer l’extraction core sur les 4 574 raws. - [ ] Relancer tous les décodeurs. - [ ] Relancer la matérialisation. - [ ] Valider les compteurs et erreurs. - [ ] Contrôler la reconstruction de chaque projection attendue. +### 8.1 Anomalies observées avant reconstruction + +- [ ] Auditer les instructions Loader immuables/v4 d’un octet qui échouent actuellement comme `*_tag_truncated`, notamment lorsque la transaction porte `UnsupportedProgramId`. +- [ ] Décider, signature réelle à l’appui, si ces formes doivent être `Unsupported`/`Ignored` plutôt que `Failed`. +- [ ] Auditer les flags signer/writable Metaplex réels avant d’assouplir les contrats de comptes. +- [ ] Comparer les signatures Metaplex en échec avec Bot2 `0.4.7-pre.035` et le contrat officiel. + ## 9. Jalon fonctionnel Bot2 `0.4.6` - [ ] Solana Core équivalent et validé. @@ -345,7 +364,7 @@ - [x] `cargo check --workspace`. - [ ] `cargo test --workspace`. - [x] `python3 scripts/audit_rust_workspace_rules.py` après `pre.058-fix-002`. -- [ ] `cargo tauri dev -c kb-app-demo-desktop/tauri.conf.json`. +- [x] `cargo tauri dev -c kb-app-demo-desktop/tauri.conf.json` : démarrage, splash, PostgreSQL, fenêtres et export CSV validés. - [ ] `cargo clippy --all-targets` en dernier. ## 16. Critères de clôture diff --git a/kb-app-demo-desktop/frontend/demo_decode_replay.html b/kb-app-demo-desktop/frontend/demo_decode_replay.html index 091d418..9064c61 100644 --- a/kb-app-demo-desktop/frontend/demo_decode_replay.html +++ b/kb-app-demo-desktop/frontend/demo_decode_replay.html @@ -1,5 +1,5 @@ - + @@ -39,7 +39,8 @@
- + +
diff --git a/kb-app-demo-desktop/frontend/demo_sql_replay_candidates.html b/kb-app-demo-desktop/frontend/demo_sql_replay_candidates.html index 5df1b35..8a4fa5d 100644 --- a/kb-app-demo-desktop/frontend/demo_sql_replay_candidates.html +++ b/kb-app-demo-desktop/frontend/demo_sql_replay_candidates.html @@ -1,5 +1,5 @@ - + @@ -131,7 +131,7 @@
- +
@@ -206,7 +206,7 @@
- +
@@ -264,7 +264,7 @@
- +
@@ -322,7 +322,7 @@
- +
@@ -380,7 +380,7 @@
- +
diff --git a/kb-app-demo-desktop/frontend/ts/demo_decode_replay.ts b/kb-app-demo-desktop/frontend/ts/demo_decode_replay.ts index b5e8315..b2a6711 100644 --- a/kb-app-demo-desktop/frontend/ts/demo_decode_replay.ts +++ b/kb-app-demo-desktop/frontend/ts/demo_decode_replay.ts @@ -1,5 +1,5 @@ // file: kb-app-demo-desktop/frontend/ts/demo_decode_replay.ts -// version: 5 +// version: 6 import * as bootstrap from "bootstrap"; import "simplebar"; @@ -279,6 +279,14 @@ async function loadOptions(): Promise { element("#decodeReplayVersionBadge").textContent = `Pipeline ${options.pipelineVersion}`; element("#decodeReplayLimitInput").value = String(options.defaultLimit); element("#decodeReplayConcurrencyInput").value = String(options.defaultMaxConcurrentInputs); + const programOptions = element("#decodeReplayProgramIdOptions"); + programOptions.replaceChildren(); + for (const program of options.programs) { + const option = document.createElement("option"); + option.value = program.programId; + option.label = program.code; + programOptions.append(option); + } const container = element("#decodeReplayDecoderList"); container.innerHTML = ""; for (const decoder of options.decoders) { diff --git a/kb-app-demo-desktop/frontend/ts/demo_sql_replay_candidates.ts b/kb-app-demo-desktop/frontend/ts/demo_sql_replay_candidates.ts index 265da3f..77becc7 100644 --- a/kb-app-demo-desktop/frontend/ts/demo_sql_replay_candidates.ts +++ b/kb-app-demo-desktop/frontend/ts/demo_sql_replay_candidates.ts @@ -94,7 +94,7 @@ let mintTable: Api | null = null; let ownerTable: Api | null = null; let accountTable: Api | null = null; let busyOperationCount = 0; -let maximumReplayCandidateLimit = 5_000; +let maximumReplayCandidateLimit = 100_000; function element(selector: string): T { const value = document.querySelector(selector); diff --git a/kb-app-demo-desktop/src/demo_decode_replay.rs b/kb-app-demo-desktop/src/demo_decode_replay.rs index 99ec7ff..2473514 100644 --- a/kb-app-demo-desktop/src/demo_decode_replay.rs +++ b/kb-app-demo-desktop/src/demo_decode_replay.rs @@ -1,5 +1,5 @@ // file: kb-app-demo-desktop/src/demo_decode_replay.rs -// version: 29 +// version: 30 //! Tauri commands and UI payloads for contextual instruction decode replay. @@ -22,6 +22,20 @@ pub(crate) struct DemoDecodeReplayDecoderOption { pub(crate) program_ids: std::vec::Vec, } +/// One known program suggested by the free-form Program ID field. +#[derive(Clone, Debug, serde::Serialize, TS)] +#[serde(rename_all = "camelCase")] +#[ts( + export, + export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_decode_replay/DemoDecodeReplayProgramOption.ts" +)] +pub(crate) struct DemoDecodeReplayProgramOption { + /// Stable program code. + pub(crate) code: std::string::String, + /// Canonical program identifier. + pub(crate) program_id: std::string::String, +} + /// Initial options shown by the contextual decode replay demo. #[derive(Clone, Debug, serde::Serialize, TS)] #[serde(rename_all = "camelCase")] @@ -36,6 +50,8 @@ pub(crate) struct DemoDecodeReplayOptionsPayload { pub(crate) decoders: std::vec::Vec, /// Stable names of materializers currently registered by the demo. pub(crate) materializer_names: std::vec::Vec, + /// Known programs offered as non-blocking autocomplete suggestions. + pub(crate) programs: std::vec::Vec, /// Default bounded selection limit. pub(crate) default_limit: u32, /// Default maximum concurrent contextual inputs. diff --git a/kb-app-demo-desktop/src/demo_sql_replay_candidates.rs b/kb-app-demo-desktop/src/demo_sql_replay_candidates.rs index bf56ab2..fbcd144 100644 --- a/kb-app-demo-desktop/src/demo_sql_replay_candidates.rs +++ b/kb-app-demo-desktop/src/demo_sql_replay_candidates.rs @@ -1,5 +1,5 @@ // file: kb-app-demo-desktop/src/demo_sql_replay_candidates.rs -// version: 7 +// version: 8 //! Read-only SQL replay candidate browser commands. @@ -266,18 +266,6 @@ pub(crate) fn validated_csv_file_name( }; } -pub(crate) fn csv_export_directory_from_current_dir( - current_dir: &std::path::Path, -) -> std::path::PathBuf { - let current_name = current_dir.file_name().and_then(std::ffi::OsStr::to_str); - if let (std::option::Option::Some("kb_app_demo_desktop"), std::option::Option::Some(parent)) = - (current_name, current_dir.parent()) - { - return parent.join("data").join("exports_csv"); - } - return current_dir.join("data").join("exports_csv"); -} - pub(crate) async fn available_csv_export_path( export_dir: &std::path::Path, file_name: &str, @@ -373,13 +361,6 @@ mod tests { assert!(result.is_err()); } - #[test] - fn csv_export_directory_uses_workspace_root_from_demo_crate() { - let current_dir = std::path::Path::new("/tmp/khadhroony-bot2/kb_app_demo_desktop"); - let result = crate::csv_export_directory_from_current_dir(current_dir); - assert_eq!(result, std::path::Path::new("/tmp/khadhroony-bot2/data/exports_csv")); - } - #[test] fn csv_file_name_accepts_split_entity_exports() { let mint_result = crate::validated_csv_file_name("replay_mints.csv"); diff --git a/kb-app-demo-desktop/src/lib.rs b/kb-app-demo-desktop/src/lib.rs index 13ca5b1..f9ebfb9 100644 --- a/kb-app-demo-desktop/src/lib.rs +++ b/kb-app-demo-desktop/src/lib.rs @@ -1,5 +1,5 @@ // file: kb-app-demo-desktop/src/lib.rs -// version: 10 +// version: 11 //! Tauri desktop demo application for `khadhroony-bot3`. @@ -95,6 +95,8 @@ pub(crate) use self::demo_decode_replay::DemoDecodeReplayDecoderOption; pub(crate) use self::demo_decode_replay::DemoDecodeReplayObserver; /// Internal demo decode replay item. pub(crate) use self::demo_decode_replay::DemoDecodeReplayOptionsPayload; +/// One known program suggested by the free-form Program ID field. +pub(crate) use self::demo_decode_replay::DemoDecodeReplayProgramOption; /// Internal demo decode replay item. pub(crate) use self::demo_decode_replay::DemoDecodeReplayProgressPayload; /// Internal demo decode replay item. @@ -267,8 +269,6 @@ pub(crate) use self::demo_sql_replay_candidates::DemoSqlReplayTransactionRequest pub(crate) use self::demo_sql_replay_candidates::DemoSqlReplayTransactionRow; /// Resolves an available CSV path. pub(crate) use self::demo_sql_replay_candidates::available_csv_export_path; -/// Resolves the CSV export directory. -pub(crate) use self::demo_sql_replay_candidates::csv_export_directory_from_current_dir; /// Parses an entity-kind code. pub(crate) use self::demo_sql_replay_candidates::entity_kind_from_code; /// Converts a PostgreSQL entity row. diff --git a/kb-app-demo-desktop/src/tauri.rs b/kb-app-demo-desktop/src/tauri.rs index 9568eab..f24b935 100644 --- a/kb-app-demo-desktop/src/tauri.rs +++ b/kb-app-demo-desktop/src/tauri.rs @@ -1,5 +1,5 @@ // file: kb-app-demo-desktop/src/tauri.rs -// version: 14 +// version: 15 //! Tauri runtime assembly and private command wrappers. @@ -270,6 +270,15 @@ fn demo_decode_replay_options( return format!("{}@{}", identity.name, identity.version); }) .collect::>(); + let programs = kb_program_ids::registered_program_ids() + .iter() + .map(|entry| { + return crate::DemoDecodeReplayProgramOption { + code: entry.code().to_string(), + program_id: entry.program_id().to_string(), + }; + }) + .collect(); let running = state.demo_decode_replay_running().load(std::sync::atomic::Ordering::Acquire); tracing::debug!( target: crate::TRACING_TARGET, @@ -286,6 +295,7 @@ fn demo_decode_replay_options( pipeline_version: kb_pipeline::DECODE_PIPELINE_VERSION.to_string(), decoders: decoder_options, materializer_names, + programs, default_limit: 100, default_max_concurrent_inputs: 4, running, @@ -915,14 +925,7 @@ async fn export_demo_sql_replay_csv( std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; - let current_dir_result = std::env::current_dir(); - let current_dir = match current_dir_result { - std::result::Result::Ok(value) => value, - std::result::Result::Err(error) => { - return std::result::Result::Err(format!("cannot resolve current directory: {error}")); - }, - }; - let export_dir = crate::csv_export_directory_from_current_dir(¤t_dir); + let export_dir = crate::workspace_root_dir().join("data").join("exports_csv"); let create_result = tokio::fs::create_dir_all(&export_dir).await; if let std::result::Result::Err(error) = create_result { return std::result::Result::Err(format!("cannot create CSV export directory: {error}")); diff --git a/kb-store/maintenance/reset_derived_store_keep_raw.sql b/kb-store/maintenance/reset_derived_store_keep_raw.sql new file mode 100644 index 0000000..b374caa --- /dev/null +++ b/kb-store/maintenance/reset_derived_store_keep_raw.sql @@ -0,0 +1,25 @@ +-- file: kb-store/maintenance/reset_derived_store_keep_raw.sql +-- version: 1 + +-- Reset every derived Solana table while preserving canonical raw acquisition data. +-- Intended for controlled local/research rebuilds only. +-- Preserved tables: +-- - kb_sol_raw_transactions +-- - kb_sol_obs_transaction_observations +-- No CASCADE is used: unexpected dependencies fail loudly. + +BEGIN; + +DROP TABLE IF EXISTS kb_sol_mat_events; +DROP TABLE IF EXISTS kb_sol_decode_coverage_observations; +DROP TABLE IF EXISTS kb_sol_decode_coverage_declarations; +DROP TABLE IF EXISTS kb_sol_decode_events; +DROP TABLE IF EXISTS kb_sol_ops_processing_ledger; +DROP TABLE IF EXISTS kb_sol_core_balance_changes; +DROP TABLE IF EXISTS kb_sol_core_logs; +DROP TABLE IF EXISTS kb_sol_core_inner_instructions; +DROP TABLE IF EXISTS kb_sol_core_instructions; +DROP TABLE IF EXISTS kb_sol_core_account_keys; +DROP TABLE IF EXISTS kb_sol_core_transactions; + +COMMIT; diff --git a/kb-store/src/postgres/replay_candidates.rs b/kb-store/src/postgres/replay_candidates.rs index 5ca4cc6..8de07a4 100644 --- a/kb-store/src/postgres/replay_candidates.rs +++ b/kb-store/src/postgres/replay_candidates.rs @@ -1,10 +1,10 @@ // file: kb-store/src/postgres/replay_candidates.rs -// version: 1 +// version: 2 //! Read-only replay candidate filters and PostgreSQL result rows. /// Maximum number of rows returned by one replay candidate query. -pub const MAX_REPLAY_CANDIDATE_ROWS: u32 = 5_000; +pub const MAX_REPLAY_CANDIDATE_ROWS: u32 = 100_000; /// Program occurrence scope used while filtering replay candidates. #[derive(Clone, Copy, Debug, Eq, PartialEq)] diff --git a/prompts/KHADHROONY_BOT3_MIGRATION_CONTINUATION_PROMPT_REORDERED.md b/prompts/KHADHROONY_BOT3_MIGRATION_CONTINUATION_PROMPT_REORDERED.md index 1b08829..0f1ce72 100644 --- a/prompts/KHADHROONY_BOT3_MIGRATION_CONTINUATION_PROMPT_REORDERED.md +++ b/prompts/KHADHROONY_BOT3_MIGRATION_CONTINUATION_PROMPT_REORDERED.md @@ -280,6 +280,14 @@ Sauf Replay Candidates : --- + +### État `pre.060` des outils de replay + +- plafond temporaire des listes SQL : `100000`; +- vraie pagination SQL/IPC reportée mais obligatoire avant les volumes massifs; +- export CSV ancré sur `/data/exports_csv`; +- Program ID de Decode replay libre avec autocomplétion issue de `kb-program-ids`. + ## 7. `.env` et configuration `kb-config` doit rester seul responsable de :