Skip to content

feat(solana): core::arg_rendering + Marginfi preset; bootstrap-only solana-add-idl skill#375

Open
shahan-khatchadourian-anchorage wants to merge 1 commit into
mainfrom
shahankhatch/373-validate-solana-add-idl-skill
Open

feat(solana): core::arg_rendering + Marginfi preset; bootstrap-only solana-add-idl skill#375
shahan-khatchadourian-anchorage wants to merge 1 commit into
mainfrom
shahankhatch/373-validate-solana-add-idl-skill

Conversation

@shahan-khatchadourian-anchorage

@shahan-khatchadourian-anchorage shahan-khatchadourian-anchorage commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Summary

Single, additive PR consolidating the solana-add-idl skill work (supersedes #401, closed into this).

  • core::arg_rendering — adds format_arg_value (+ charset_safe, bytes_as_hex): a charset-safe, single-field-per-arg renderer (byte arrays -> 0x hex). New presets import it from crate::core; existing presets are left untouched.
  • Marginfi preset — new IDL-based preset, auto-registered via build.rs, as a live validation of the skill.
  • SKILL.md — Sonnet-subagent dispatch (model enforced at the API layer) + compare mode; import format_arg_value from crate::core; bootstrap-only scope (scaffold a new preset, never regenerate an existing one); subtitle convention; surfpool live-fuzz validation; and an "Improving this skill" section with two non-destructive validation loops (corpus diff + model compare).

No existing preset is modified — clean on main.

Test plan

  • cargo clippy -p visualsign-solana --all-targets -- -D warnings
  • cargo clippy -p visualsign-solana --features diagnostics --all-targets -- -D warnings
  • cargo test -p visualsign-solana — 270 passed
  • cargo test -p visualsign-solana --features diagnostics
  • Add surfpool label to run live fuzz CI (incl. Marginfi)

Closes #397

@shahan-khatchadourian-anchorage

Copy link
Copy Markdown
Contributor Author

Finding from commit 3 (regeneration test): config.rs template prescribes HashMap but SolanaIntegrationConfigData uses BTreeMap

The skill's config.rs template currently has:

use std::collections::HashMap;
// ...
let mut programs = HashMap::new();
let mut instructions = HashMap::new();

But SolanaIntegrationConfigData is defined as:

pub struct SolanaIntegrationConfigData {
    pub programs: BTreeMap<&'static str, BTreeMap<&'static str, Vec<&'static str>>>,
}

A contributor following the template verbatim would get a type mismatch compile error. The template needs to be updated to BTreeMap throughout — both the use line and both ::new() calls.

@shahan-khatchadourian-anchorage

Copy link
Copy Markdown
Contributor Author

Finding from commit 3 (regeneration test): Step 4 of the skill is stale — presets/mod.rs is auto-generated, do not edit

Step 4 currently says:

Add pub mod {snake_name}; to src/chain_parsers/visualsign-solana/src/presets/mod.rs. Keep entries in alphabetical order.

But presets/mod.rs contains only:

//! ... Do NOT edit this file — it has no hand-maintained content.
include!(concat!(env!(\OUT_DIR\), \/generated_presets_mod.rs\));

build.rs auto-discovers any {PascalName}Visualizer struct under src/presets/. Step 4 should be replaced with a note explaining this — creating the directory with mod.rs + config.rs is all that's needed; no manual module registration.

@shahan-khatchadourian-anchorage

Copy link
Copy Markdown
Contributor Author

Finding from commit 3 (regeneration test): skill requires InstructionView in crate::core, which only lands via PR #367

The updated skill prescribes:

use crate::core::{
    InstructionView, ...
};
// ...
let view = InstructionView::from_context(context);

InstructionView does not exist on main yet — it's introduced in PR #367 (fix/362-idl-preset-alt-accounts). Any contributor running the skill against main today will get a compile error. This PR is stacked on #367 for that reason.

The skill should document this precondition — either a note at the top ("requires PR #367 / the InstructionView struct in core") or, once #367 merges, this becomes a non-issue. If the skill is intended to always reflect merged state, add a note that it tracks main and should not be used on branches predating the InstructionView introduction.

@shahan-khatchadourian-anchorage

Copy link
Copy Markdown
Contributor Author

Comparison: generated vs prior neutral_trade and onre_app implementation (template gap fix)

Finding that triggered this commit: the generated template was missing Program: {display_name} as the first field in expanded_fields for both build_parsed_fields and build_fallback_fields. The condensed view already had it correctly. The prior hand-written implementations had this field in the expanded view.

Fix applied:

  • neutral_trade/mod.rs: added create_text_field("Program", "Neutral Trade") as first expanded field in both functions
  • onre_app/mod.rs: added create_text_field("Program", "Onre App") as first expanded field in both functions
  • SKILL.md: template note added to Step 3 prescribing this pattern for all future presets

After fix, the generated expanded view is now consistent with the prior implementations on this point, while still being strictly better on: OnceLock caching, recursive push_arg_fields, BTreeMap for named_accounts, Remaining Account N handling, and InstructionView pattern.

shahan-khatchadourian-anchorage added a commit that referenced this pull request Jun 17, 2026
…y-name subtitle in neutral_trade and onre_app

Code review (PR #375) identified that regenerated neutral_trade and
onre_app silently regressed from the display-name subtitle to an empty
string, because the dflow_aggregator template (which always had an empty
subtitle) was used verbatim. Fix: add subtitle as a gathered input in
Step 1 (defaulting to display_name), template it in Step 3, and restore
"Neutral Trade" / "Onre App" in the affected presets.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
shahan-khatchadourian-anchorage added a commit that referenced this pull request Jun 17, 2026
…p; expand skill required-tests list

Code review (PR #375) identified that neutral_trade and onre_app were
missing the six rendering tests present in dflow_aggregator. Backfill
push_arg_fields (scalars, arrays, objects, empty collections),
build_named_accounts_surfaces_extra_accounts, and
remaining_account_label_is_human_readable into both presets.

Also update SKILL.md: expand required-tests list to include all ten
tests, add field_label_value and serde_json/IdlSource imports to the
prescribed test helpers, and document the build_named_accounts signature
with argument order.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Validates and updates the solana-add-idl scaffolding skill by regenerating multiple Solana IDL-based presets to match the newer InstructionView::from_context() pattern (graceful handling for v0 + ALT / unresolved accounts), plus aligning config generation and test-helper conventions.

Changes:

  • Regenerated onre_app, neutral_trade, and dflow_aggregator preset implementations to use InstructionView, IDL caching via OnceLock, BTreeMap named accounts, and dummy_account_strings test helpers.
  • Improved expanded/fallback field rendering consistency (e.g., ensuring expanded views include a human-readable Program field).
  • Updated .claude/skills/solana-add-idl/SKILL.md to document the new patterns (BTreeMap config, no manual presets/mod.rs registration, additional tests, etc.).

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/chain_parsers/visualsign-solana/src/presets/onre_app/mod.rs Regenerated IDL visualizer using InstructionView, cached IDL, fallback rendering, recursive arg field rendering, and expanded “Remaining Account N” support + tests.
src/chain_parsers/visualsign-solana/src/presets/onre_app/config.rs Simplifies config map construction (type inference) while keeping BTreeMap backing.
src/chain_parsers/visualsign-solana/src/presets/neutral_trade/mod.rs Regenerated visualizer and tests in the same InstructionView/fallback/recursive-args pattern.
src/chain_parsers/visualsign-solana/src/presets/dflow_aggregator/mod.rs Small regeneration deltas: formatting, expanded/fallback “Program” field, and test helper conversion to dummy_account_strings.
.claude/skills/solana-add-idl/SKILL.md Updates skill instructions to match current preset patterns (InstructionView, BTreeMap config, no manual module registration, extended required tests).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .claude/skills/solana-add-idl/SKILL.md Outdated
Comment on lines +128 to +134
**Subtitle field uses `{subtitle_text}`.** In the `preview_layout` construction inside `visualize_tx_commands`, set the subtitle to the value gathered in Step 1:
```rust
subtitle: Some(SignablePayloadFieldTextV2 {
text: "{subtitle_text}".to_string(),
}),
```
If the user provided no subtitle (or said to leave it empty), use `String::new()` instead.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 76e32a3 — replaced the single "{subtitle_text}".to_string() placeholder with two explicit forms: one showing a custom subtitle as a string literal with .to_string(), and one showing the empty-default case as String::new() directly. This matches what the generated presets actually emit.

@shahan-khatchadourian-anchorage

Copy link
Copy Markdown
Contributor Author

Review summary

Stacked on: #367 (fix/362-idl-preset-alt-accounts — introduces InstructionView)

What this PR does

Validates the solana-add-idl scaffolding skill by running it in Validation Mode: delete three existing preset implementations (dflow_aggregator, neutral_trade, onre_app), regenerate them from scratch using the skill as the spec, compare against the prior implementations, and fold every gap back into the skill template.

Skill changes (SKILL.md)

  • Two-mode orientation at the top — "Adding a new program" vs "Validation Mode" are now named explicitly so first-time readers don't have to reach the end to discover the distinction
  • Step 1 now asks for a subtitle (default: empty, matching the corpus-wide convention for IDL presets; the prior hand-written neutral_trade/onre_app used the display name as subtitle, which was an inconsistency — the title already contains the program name)
  • config.rs template corrected from HashMap to BTreeMapSolanaIntegrationConfigData.programs requires BTreeMap
  • Step 3 now documents the exact build_named_accounts signature (data, idl, accounts order) and the subtitle two-form template (custom string vs String::new() — fixes a Copilot finding where the prior placeholder would have generated literal text)
  • Step 4 corrected — presets/mod.rs is fully auto-generated by build.rs; no manual pub mod line is needed
  • Step 6 added InstructionView::from_context as the prescribed account-resolution pattern, with security-asymmetry note explaining why resolve_accounts()? is kept only in token_2022
  • Step 7 (new) — compare generated output against prior implementation, post a structured PR comment; skip for new programs with no prior implementation
  • Required tests expanded from 4 to 10: added push_arg_fields (scalars, arrays, objects, empty collections), build_named_accounts_surfaces_extra_accounts, and remaining_account_label_is_human_readable, plus field_label_value and serde_json/IdlSource import prescriptions
  • Validation Mode section (formerly "When validating…") — iterative loop diagram, per-finding PR comment guidance, "the skill is the artifact" principle

Generated preset changes vs prior implementations

All three presets are strictly better than the hand-written versions they replace:

Prior Generated
IDL caching Per-call decode_idl_data OnceLock<Option<Idl>> (once at startup)
Account resolution resolve_accounts()? (fails on ALT) InstructionView::from_context (infallible)
Extra accounts Silently dropped Surfaced as "Remaining Account N"
Arg rendering Flat format_arg_value Recursive push_arg_fields (handles nested objects/arrays)
Named accounts map Vec<(String,String)> or HashMap BTreeMap (deterministic order)
Test helpers Vec<AccountMeta> Vec<String> via dummy_account_strings
Tests per preset 4 10

Strengths

  • The delete→regenerate→compare loop is a rigorous validation methodology — findings surface as PR comments immediately rather than being batched, and each one closes with a skill fix + re-regeneration confirmation
  • The skill is now self-referential: the Validation Mode section describes how to improve the skill itself, so the next round of preset additions will benefit from all lessons learned here
  • The corpus subtitle survey (24/26 presets use String::new()) resolved an ambiguity that would otherwise have required a judgement call on every new preset

Base automatically changed from fix/362-idl-preset-alt-accounts to main June 18, 2026 06:44
@prasanna-anchorage prasanna-anchorage force-pushed the shahankhatch/373-validate-solana-add-idl-skill branch from 684ae17 to 41c82e4 Compare June 18, 2026 17:33
prasanna-anchorage pushed a commit that referenced this pull request Jun 18, 2026
…y-name subtitle in neutral_trade and onre_app

Code review (PR #375) identified that regenerated neutral_trade and
onre_app silently regressed from the display-name subtitle to an empty
string, because the dflow_aggregator template (which always had an empty
subtitle) was used verbatim. Fix: add subtitle as a gathered input in
Step 1 (defaulting to display_name), template it in Step 3, and restore
"Neutral Trade" / "Onre App" in the affected presets.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
prasanna-anchorage pushed a commit that referenced this pull request Jun 18, 2026
…p; expand skill required-tests list

Code review (PR #375) identified that neutral_trade and onre_app were
missing the six rendering tests present in dflow_aggregator. Backfill
push_arg_fields (scalars, arrays, objects, empty collections),
build_named_accounts_surfaces_extra_accounts, and
remaining_account_label_is_human_readable into both presets.

Also update SKILL.md: expand required-tests list to include all ten
tests, add field_label_value and serde_json/IdlSource imports to the
prescribed test helpers, and document the build_named_accounts signature
with argument order.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@prasanna-anchorage

Copy link
Copy Markdown
Contributor

Rebased onto main (in a worktree) now that #367 is merged. Because #367 was squash-merged, its commits still appeared on this branch and inflated the diff to 21 files with 3 conflicting presets. Rebased with git rebase --onto main 7936534 to drop the now-merged #367 commits and replay only this PR's 13 commits; the delete-then-regenerate sequence resolved the 3 preset conflicts cleanly. Force-pushed as 41c82e4.

The diff is now just the real change — 5 files: SKILL.md + the 3 regenerated presets (dflow_aggregator, neutral_trade, onre_app) + onre_app/config.rs.

Verified locally against the merged baseline:

  • cargo clippy -p visualsign-solana --all-targets -- -D warnings — clean
  • cargo clippy -p visualsign-solana --features diagnostics --all-targets -- -D warnings — clean
  • cargo test -p visualsign-solana — 266 lib + 59 integration tests pass, 0 failures

Ready for re-review.

…ly skill

Additive only -- no existing preset is modified. Consolidates the
solana-add-idl skill work into a single PR.

Code:
- Add `core::arg_rendering::format_arg_value` (+ charset_safe, bytes_as_hex):
  a charset-safe, single-field-per-arg renderer (byte arrays -> 0x hex) for
  IDL-based presets. New presets import it from crate::core; existing presets
  keep their current renderers untouched.
- Add Marginfi IDL-based preset as a live validation of the skill;
  auto-registered via build.rs.

Skill (SKILL.md):
- Dispatch scaffolding as a Sonnet subagent (model enforced at the API
  layer); compare mode dispatches Sonnet + Opus and diffs outputs.
- Import format_arg_value from crate::core rather than embedding it.
- Bootstrap-only scope: scaffold a NEW preset; never regenerate an existing
  one.
- Subtitle convention (Step 1 + preview_layout emission).
- Live-fuzz validation via the surfpool label (Step 3).
- "Improving this skill": two non-destructive validation loops -- corpus
  diff (regenerate to a scratch dir, diff vs committed, fix the skill) and
  Sonnet-vs-Opus model compare. Neither overwrites a committed preset.

Closes #397

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@shahan-khatchadourian-anchorage shahan-khatchadourian-anchorage force-pushed the shahankhatch/373-validate-solana-add-idl-skill branch from 41c82e4 to 3cc61da Compare June 26, 2026 17:52
@shahan-khatchadourian-anchorage shahan-khatchadourian-anchorage changed the title test(solana): validate solana-add-idl skill with preset regeneration (InstructionView) feat(solana): core::arg_rendering + Marginfi preset; bootstrap-only solana-add-idl skill Jun 26, 2026
@shahan-khatchadourian-anchorage

Copy link
Copy Markdown
Contributor Author

Consolidating the solana-add-idl skill work into this single PR and making it purely additive — heads-up since you rebased this branch.

What changed in approach: we're dropping the regenerate-existing-presets validation (the delete+regenerate of dflow/neutral_trade/onre_app) in favor of bootstrap-then-own: the skill scaffolds a new preset and never regenerates an owned one. Net effect here is additive only — core::arg_rendering (your #387 renderer, lifted verbatim into crate::core) + a new Marginfi preset + the skill doc. Your #387 dflow is untouched, so the #394 nested renderer still stacks on top exactly as planned.

Preserved from the prior branch: the regeneration-loop framing you'd added (reframed non-destructive — regenerate to a scratch dir, diff vs committed, fix the skill), plus the subtitle convention and surfpool live-fuzz docs. Added the Sonnet-subagent dispatch + compare mode (closes #397).

Follow-up (separate issue, not this PR): neutral_trade + onre_app still use the buggy push_arg_fields on main — same charset/field-explosion bug #387 fixed for dflow; tracked for a focused fix.

Tests: 270/270, clippy clean (default + diagnostics). Requesting your review given the merge-approval policy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(skills): set a fixed default model for solana-add-idl

3 participants