Skip to main content

agentstatedeveloper_mcp/
mcp_params.rs

1//! MCP tool parameter types (Plan M t-002, 1.0.92).
2//!
3//! Extracted from `mcp_server.rs` to make the handler file scannable.
4//! Each struct is a typed shape for one MCP tool's arguments —
5//! `Deserialize` so rmcp can parse the incoming JSON, `JsonSchema` so
6//! rmcp can serve the tool's parameter schema to the agent.
7//!
8//! Naming-convention notes preserved at the bottom of this file
9//! (was at the same position in mcp_server.rs).
10//!
11//! No behavior change in this extraction; pure relocation.
12
13use schemars::JsonSchema;
14use serde::Deserialize;
15
16#[derive(Deserialize, JsonSchema)]
17pub struct CodeQueryParams {
18    /// Substring match on qualified name.
19    pub name_contains: Option<String>,
20    /// Filter by symbol kind: module, function, method, class, variable.
21    pub kind: Option<String>,
22    /// Filter by language (e.g. "python").
23    pub language: Option<String>,
24    /// Max results to return (default: 50).
25    #[serde(default = "default_limit")]
26    pub limit: u32,
27}
28
29#[derive(Deserialize, JsonSchema)]
30pub struct CodeSearchParams {
31    /// Concept or keyword(s) to search for. BM25-ranked via FTS5.
32    /// Supports inline exclusion syntax: "drift playhead -sample -waveform".
33    pub query: String,
34    /// Filter by symbol kind: module, function, method, class, variable.
35    pub kind: Option<String>,
36    /// Filter by language (e.g. "swift", "python", "typescript", "rust").
37    pub language: Option<String>,
38    /// Max results to return (default: 20).
39    #[serde(default = "default_search_limit")]
40    pub limit: u32,
41    /// Include test-file symbols in results (default: false — tests excluded so
42    /// production entry points rank first).
43    #[serde(default)]
44    pub include_tests: bool,
45    /// Restrict to test symbols only. Overrides include_tests when true.
46    /// Use when classifying test coverage or auditing test layout.
47    #[serde(default)]
48    pub tests_only: bool,
49    /// Comma-separated terms to exclude (e.g. "sample editor,waveform").
50    pub exclude: Option<String>,
51    /// Comma-separated glob patterns to restrict to specific paths (e.g. "App/**/DriftPad*").
52    pub paths: Option<String>,
53    /// Named scope alias from .asd/scopes.toml (e.g. "drift-pad").
54    pub scope: Option<String>,
55}
56
57fn default_search_limit() -> u32 {
58    20
59}
60
61#[derive(Deserialize, JsonSchema)]
62pub struct ReferencesParams {
63    /// Symbol name to find references for. Pass a qname (e.g. `pkg.mod.Type`)
64    /// for exact definition lookup, or a bare identifier (e.g. `MasterBusParams`)
65    /// to match any symbol whose qname ends with `.<name>` plus all literal
66    /// text occurrences in the worktree.
67    pub name: String,
68    /// Project root for the rg scan. Defaults to the current directory.
69    pub path: Option<String>,
70    /// Cap the number of occurrences returned (default: 500, 0 = unlimited).
71    #[serde(default = "default_references_limit")]
72    pub limit: u32,
73    /// Optional rg `--glob` filter, e.g. "**/*.swift". Comma-separated for multiple.
74    pub globs: Option<String>,
75}
76
77fn default_references_limit() -> u32 {
78    500
79}
80
81#[derive(Deserialize, JsonSchema)]
82pub struct ConclusionsListParams {
83    /// Restrict to one conclusion class: decisions | classifications |
84    /// mappings | hazards | recipes | followups. Omit to list all six.
85    pub class: Option<String>,
86    /// Restrict to one symbol qname. Omit to list across all symbols.
87    pub symbol: Option<String>,
88}
89
90#[derive(Deserialize, JsonSchema)]
91pub struct ConclusionsExportParams {
92    /// Output directory for the JSONL files. Defaults to `.asd/conclusions/`
93    /// relative to the database parent directory.
94    pub out: Option<String>,
95}
96
97#[derive(Deserialize, JsonSchema)]
98pub struct ConclusionsImportParams {
99    /// Input directory containing `*.jsonl` files. Defaults to
100    /// `.asd/conclusions/` relative to the database parent directory.
101    #[serde(rename = "in")]
102    pub in_dir: Option<String>,
103}
104
105#[derive(Deserialize, JsonSchema)]
106pub struct RecipeClassifyTestMigrationParams {
107    /// Search query — finds candidate test symbols.
108    pub query: String,
109    /// Max candidates to classify (default: 50).
110    #[serde(default = "default_recipe_limit")]
111    pub limit: u32,
112}
113
114fn default_recipe_limit() -> u32 {
115    50
116}
117
118// -- Plan G t-003: agent-thinking write surface ------------------------------
119
120#[derive(Deserialize, JsonSchema)]
121pub struct ThinkSpeculateParams {
122    pub qname: String,
123    /// Confidence in [0.0, 1.0]. Below 0.3 is excluded from prior_thinking
124    /// auto-surface by default.
125    pub confidence: f64,
126    pub summary: String,
127    pub body: Option<String>,
128}
129
130#[derive(Deserialize, JsonSchema)]
131pub struct ThinkModelParams {
132    pub name: String,
133    /// Comma-separated qnames the model spans (first is anchor).
134    pub symbols: String,
135    pub summary: String,
136}
137
138#[derive(Deserialize, JsonSchema)]
139pub struct ThinkFailedParams {
140    pub qname: String,
141    pub tried: String,
142    pub because: String,
143}
144
145#[derive(Deserialize, JsonSchema)]
146pub struct ThinkQuestionParams {
147    pub qname: String,
148    pub question: String,
149}
150
151#[derive(Deserialize, JsonSchema)]
152pub struct ThinkListParams {
153    /// Filter to one thinking kind: hypothesis | mental_model |
154    /// failed_attempt | open_question.
155    pub kind: Option<String>,
156    pub symbol: Option<String>,
157}
158
159#[derive(Deserialize, JsonSchema)]
160pub struct InvestigateParams {
161    /// Natural-language or keyword query.
162    /// Supports inline exclusion syntax: "drift playhead -sample -waveform".
163    pub query: String,
164    /// Number of top entry-point symbols to fully expand (default: 5).
165    #[serde(default = "default_investigate_depth")]
166    pub depth: u32,
167    /// Filter by symbol kind: module, function, method, class, variable.
168    pub kind: Option<String>,
169    /// Filter by language (e.g. "swift", "python", "typescript", "rust").
170    pub language: Option<String>,
171    /// Include test-file symbols as entry-point candidates (default: false).
172    #[serde(default)]
173    pub include_tests: bool,
174    /// Adjust output ordering and guidance for a specific intent.
175    /// Values: bugfix, feature, refactor, test, architecture, ui.
176    pub intent: Option<String>,
177    /// Comma-separated terms to exclude (e.g. "sample editor,waveform").
178    pub exclude: Option<String>,
179    /// Comma-separated glob patterns to restrict to specific paths.
180    pub paths: Option<String>,
181    /// Named scope alias from .asd/scopes.toml.
182    pub scope: Option<String>,
183}
184
185fn default_investigate_depth() -> u32 {
186    10
187}
188fn default_impact_depth() -> u32 {
189    3
190}
191fn default_git_depth() -> u32 {
192    20
193}
194fn default_checklist_depth() -> u32 {
195    10
196}
197fn default_test_depth() -> u32 {
198    2
199}
200fn default_prepare_depth() -> u32 {
201    10
202}
203fn default_prepare_git_depth() -> u32 {
204    10
205}
206
207#[derive(Deserialize, JsonSchema)]
208pub struct PrepareChangeParams {
209    /// Free-form description of the intended change (treated as a search query).
210    /// Supports inline exclusion syntax: "drift playhead -sample -waveform".
211    pub description: String,
212    /// Number of top entry-point symbols to expand (default: 7).
213    #[serde(default = "default_prepare_depth")]
214    pub depth: u32,
215    /// Filter by symbol kind.
216    pub kind: Option<String>,
217    /// Filter by language.
218    pub language: Option<String>,
219    /// Include test-file symbols as entry-point candidates (default: false).
220    #[serde(default)]
221    pub include_tests: bool,
222    /// Adjust output for a specific intent.
223    /// Values: bugfix, feature, refactor, test, architecture, ui.
224    pub intent: Option<String>,
225    /// BFS depth for finding affected tests from the top entry point (default: 2).
226    #[serde(default = "default_test_depth")]
227    pub test_depth: u32,
228    /// Number of recent git commits to scan per file (default: 10).
229    #[serde(default = "default_prepare_git_depth")]
230    pub git_depth: u32,
231    /// Comma-separated terms to exclude (e.g. "sample editor,waveform").
232    pub exclude: Option<String>,
233    /// Comma-separated glob patterns to restrict to specific paths.
234    pub paths: Option<String>,
235    /// Named scope alias from .asd/scopes.toml.
236    pub scope: Option<String>,
237    /// Active task context to enrich the query (e.g. a CTX task description).
238    /// Tokens are appended to the description before candidate scoring so the
239    /// result set is biased toward symbols relevant to the current task.
240    pub task_context: Option<String>,
241}
242
243#[derive(Deserialize, JsonSchema)]
244pub struct ChecklistParams {
245    /// Natural-language or keyword query.
246    /// Supports inline exclusion syntax: "drift playhead -sample -waveform".
247    pub query: String,
248    /// Number of top entry-point symbols to analyse (default: 5).
249    #[serde(default = "default_checklist_depth")]
250    pub depth: u32,
251    /// Filter by symbol kind.
252    pub kind: Option<String>,
253    /// Filter by language.
254    pub language: Option<String>,
255    /// Include test-file symbols as entry-point candidates (default: false).
256    #[serde(default)]
257    pub include_tests: bool,
258    /// Adjust checklist framing for a specific intent.
259    /// Values: bugfix, feature, refactor, test, architecture, ui.
260    pub intent: Option<String>,
261    /// Caller BFS depth for finding affected tests (default: 2).
262    #[serde(default = "default_test_depth")]
263    pub test_depth: u32,
264    /// Comma-separated terms to exclude (e.g. "sample editor,waveform").
265    pub exclude: Option<String>,
266    /// Comma-separated glob patterns to restrict to specific paths.
267    pub paths: Option<String>,
268    /// Named scope alias from .asd/scopes.toml.
269    pub scope: Option<String>,
270}
271
272#[derive(Deserialize, JsonSchema)]
273pub struct ImpactParams {
274    /// Fully-qualified symbol name to analyse.
275    pub qname: String,
276    /// Caller-graph traversal depth (default: 3).
277    #[serde(default = "default_impact_depth")]
278    pub depth: u32,
279    /// Number of recent git commits to look back per touched file (default: 20).
280    #[serde(default = "default_git_depth")]
281    pub git_depth: u32,
282}
283
284#[derive(Deserialize, JsonSchema)]
285pub struct HelpParams {
286    /// Feature name (e.g. "impact") or a phrase (e.g. "blast radius") to
287    /// fuzzy-match. Omit to get the full grouped catalog of every feature.
288    #[serde(default)]
289    pub topic: Option<String>,
290}
291
292#[derive(Deserialize, JsonSchema)]
293pub struct ArchitectureParams {
294    /// How many packages, hotspots, and clusters to list (default: 12).
295    #[serde(default = "default_arch_top")]
296    pub top: usize,
297}
298
299fn default_arch_top() -> usize {
300    12
301}
302
303#[derive(Deserialize, JsonSchema)]
304pub struct DeadCodeParams {
305    /// Max candidates to list; the total count is always reported (default: 50).
306    #[serde(default = "default_dead_limit")]
307    pub limit: usize,
308    /// Include test functions (excluded by default).
309    #[serde(default)]
310    pub include_tests: bool,
311}
312
313fn default_dead_limit() -> usize {
314    50
315}
316
317#[derive(Deserialize, JsonSchema)]
318pub struct SinceParams {
319    /// Base commit SHA (or branch/tag) to diff against HEAD.
320    pub sha: String,
321    /// Caller-graph BFS depth for blast radius (default: 3).
322    #[serde(default = "default_impact_depth")]
323    pub depth: u32,
324    /// Number of recent git commits to scan per changed file (default: 10).
325    #[serde(default = "default_since_git_depth")]
326    pub git_depth: u32,
327}
328
329fn default_since_git_depth() -> u32 {
330    10
331}
332
333#[derive(Deserialize, JsonSchema)]
334pub struct InvariantAddParams {
335    /// Fully-qualified symbol name.
336    pub qname: String,
337    /// One-line invariant summary.
338    pub summary: String,
339    /// Author identifier (default: "asd-mcp-agent").
340    #[serde(default = "default_author_id")]
341    pub author_id: String,
342}
343
344#[derive(Deserialize, JsonSchema)]
345pub struct InvariantListParams {
346    /// Filter to a single symbol's invariants. Omit to list all.
347    pub qname: Option<String>,
348}
349
350#[derive(Deserialize, JsonSchema)]
351pub struct FeedbackMarkParams {
352    /// The search query that produced this result.
353    pub query: String,
354    /// Fully-qualified symbol name being rated.
355    pub qname: String,
356    /// Verdict: "useful", "noisy", "missing", "wrong_layer",
357    /// "already_covered" (Plan C t-005), or "diagnostic_only" (Plan C t-005).
358    pub verdict: String,
359    /// Optional free-text note explaining the verdict.
360    pub note: Option<String>,
361    /// Agent/author identifier (default: "asd-mcp-agent").
362    #[serde(default = "default_author_id")]
363    pub author_id: String,
364    /// Plan E t-009: when verdict is "already_covered", the qname of
365    /// the symbol whose behavior covers this one. Auto-writes a paired
366    /// Mapping ledger entry alongside the FeedbackEntry.
367    pub covered_by: Option<String>,
368    /// Plan J t-014: optional expiry in days from now. After `now + N
369    /// days` the entry no longer influences ranking. Useful for
370    /// false-positive marks that should auto-decay.
371    pub ttl_days: Option<i64>,
372}
373
374#[derive(Deserialize, JsonSchema)]
375pub struct FeedbackListParams {
376    /// Filter to feedback for a specific symbol qname. Omit to list all.
377    pub qname: Option<String>,
378}
379
380#[derive(Deserialize, JsonSchema)]
381pub struct FeedbackWithdrawParams {
382    /// Entry id to retract, from `feedback_list`.
383    pub entry_id: String,
384    /// Who is retracting it. Recorded on the entry.
385    pub by: Option<String>,
386    /// Why. Free text, stored with the withdrawal.
387    pub reason: Option<String>,
388}
389
390#[derive(Deserialize, JsonSchema)]
391pub struct FeedbackPromoteParams {
392    /// Fully-qualified symbol name to promote.
393    pub qname: String,
394    /// The domain concept this symbol is the source-of-truth for (e.g. "Drift Pad playhead").
395    pub concept: String,
396    /// Agent/author identifier (default: "asd-mcp-agent").
397    #[serde(default = "default_author_id")]
398    pub author_id: String,
399}
400
401#[derive(Deserialize, JsonSchema)]
402pub struct CodeReadParams {
403    /// Fully-qualified symbol name.
404    pub qname: String,
405}
406
407#[derive(Deserialize, JsonSchema)]
408pub struct EffectsOfParams {
409    /// Fully-qualified symbol name.
410    pub qname: String,
411}
412
413#[derive(Deserialize, JsonSchema)]
414pub struct CallersOfParams {
415    /// Fully-qualified symbol name.
416    pub qname: String,
417}
418
419#[derive(Deserialize, JsonSchema)]
420pub struct CalleesOfParams {
421    /// Fully-qualified symbol name.
422    pub qname: String,
423}
424
425#[derive(Deserialize, JsonSchema)]
426pub struct LedgerGetParams {
427    /// Fully-qualified symbol name.
428    pub qname: String,
429    /// Include entries that have been superseded (default: false).
430    #[serde(default)]
431    pub include_superseded: bool,
432}
433
434#[derive(Deserialize, JsonSchema)]
435pub struct LedgerFindParams {
436    /// Filter by ledger kind (decision, assumption, constraint, rationale, hazard, tradeoff).
437    pub kind: Option<String>,
438    /// Filter by tag (must be present on entry).
439    pub tag: Option<String>,
440    /// Filter by author id.
441    pub author_id: Option<String>,
442    /// Max results to return (default: 50).
443    #[serde(default = "default_limit")]
444    pub limit: u32,
445}
446
447#[derive(Deserialize, JsonSchema)]
448pub struct LedgerAppendParams {
449    /// Fully-qualified symbol name this entry attaches to.
450    pub qname: String,
451    /// Ledger entry kind.
452    pub kind: String,
453    /// One-line summary.
454    pub summary: String,
455    /// Optional free-form body (markdown ok).
456    pub body: Option<String>,
457    /// Optional tags.
458    pub tags: Option<Vec<String>>,
459    /// Author kind: "agent" or "human" (default: "agent").
460    #[serde(default = "default_author_kind")]
461    pub author_kind: String,
462    /// Author id (default: "asd-mcp").
463    #[serde(default = "default_author_id")]
464    pub author_id: String,
465    /// Plan B t-002: optional classification role/intent tag
466    /// (e.g. "diagnostic-test", "fast-test", "fixture-path").
467    pub role: Option<String>,
468    /// Plan B t-002: optional canonical reproduction or validation command
469    /// (e.g. "swift test --filter SongPlayersTests").
470    pub command: Option<String>,
471}
472
473#[derive(Deserialize, JsonSchema)]
474pub struct LedgerApproveParams {
475    /// Entry id (returned by a prior `ledger_append` call).
476    pub entry_id: String,
477    /// Approver identifier — recorded on the entry as `approved-by:<id>`.
478    pub approver: String,
479    /// Approver kind. Must match an `approver:*` tag on the original
480    /// entry (e.g., "human", "senior_agent") unless `approver` itself
481    /// matches directly.
482    #[serde(default = "default_approver_kind_mcp")]
483    pub approver_kind: String,
484    /// Optional approver rationale — appended to the entry body as an
485    /// "Approver note" section.
486    #[serde(default)]
487    pub message: Option<String>,
488}
489
490#[derive(Deserialize, JsonSchema)]
491pub struct LedgerRejectParams {
492    /// Entry id to reject.
493    pub entry_id: String,
494    /// Reviewer id — recorded as `rejected-by:<id>`.
495    pub reviewer: String,
496    /// Reviewer kind. Same approver-match rule as approve.
497    #[serde(default = "default_approver_kind_mcp")]
498    pub reviewer_kind: String,
499    /// Rejection reason (required). Appended to the entry body.
500    pub reason: String,
501}
502
503#[derive(Deserialize, JsonSchema)]
504pub struct LedgerWithdrawParams {
505    /// Entry id to withdraw.
506    pub entry_id: String,
507    /// Author id — must match the original `entry.author.id`.
508    pub author_id: String,
509}
510
511#[derive(Deserialize, JsonSchema)]
512pub struct LedgerSupersedeParams {
513    /// Qname the new entry attaches to.
514    pub qname: String,
515    /// Entry ids superseded by the new entry.
516    pub supersedes: Vec<String>,
517    /// Ledger kind for the new entry (decision, rationale, hazard, …).
518    pub kind: String,
519    /// One-line summary.
520    pub summary: String,
521    /// Optional body.
522    #[serde(default)]
523    pub body: Option<String>,
524    /// Author kind (default: "agent").
525    #[serde(default = "default_author_kind")]
526    pub author_kind: String,
527    /// Author id (default: "asd-mcp").
528    #[serde(default = "default_author_id")]
529    pub author_id: String,
530}
531
532fn default_approver_kind_mcp() -> String {
533    "human".to_string()
534}
535
536#[derive(Deserialize, JsonSchema)]
537pub struct TracesOfParams {
538    /// Fully-qualified symbol name.
539    pub qname: String,
540    /// Maximum number of trace records to return (default 20).
541    #[serde(default)]
542    pub limit: Option<usize>,
543}
544
545#[derive(Deserialize, JsonSchema)]
546pub struct ReindexParams {
547    /// Absolute or relative path to a source file or directory to reindex.
548    /// Relative paths are resolved from the process working directory.
549    pub path: String,
550}
551
552#[derive(Deserialize, JsonSchema)]
553pub struct SyncParams {
554    /// Project root to sync into (`.asd/v1/` is appended). Defaults to the
555    /// directory of the active db.
556    #[serde(default)]
557    pub dir: Option<String>,
558    /// Also remove orphaned sidecar files for symbols that no longer exist.
559    #[serde(default)]
560    pub prune: bool,
561}
562
563#[derive(Deserialize, JsonSchema)]
564pub struct TestSummaryParams {
565    /// Raw test-runner output to summarize (cargo/pytest auto-detected; others
566    /// via a generic scan).
567    pub output: String,
568}
569
570#[derive(Deserialize, JsonSchema)]
571pub struct MapParams {
572    /// Return the summary without writing any Ownership ledger entries.
573    #[serde(default)]
574    pub dry_run: bool,
575}
576
577#[derive(Deserialize, JsonSchema)]
578pub struct LedgerRebindParams {
579    /// symbol_id of the old symbol whose ledger entries should be re-parented.
580    pub from_symbol_id: String,
581    /// Fully-qualified name of the new symbol to resolve and bind to.
582    pub to_qname: String,
583    /// Agent or user performing the rebind.
584    #[serde(default = "default_author_id")]
585    pub agent_id: String,
586}
587
588#[derive(Deserialize, JsonSchema)]
589pub struct AuditTailParams {
590    /// Substring match on event_type (e.g., `ledger.approve`,
591    /// `ledger.` for all ledger events).
592    #[serde(default)]
593    pub event_type: Option<String>,
594    /// Return only events AFTER this `event_id` (exclusive). Use for
595    /// incremental polling.
596    #[serde(default)]
597    pub since: Option<String>,
598    /// Exact match on actor_id.
599    #[serde(default)]
600    pub actor: Option<String>,
601    /// Exact match on outcome.
602    #[serde(default)]
603    pub outcome: Option<String>,
604    /// Max events to return (default 200, max 1000).
605    #[serde(default)]
606    pub limit: Option<u32>,
607}
608
609#[derive(Deserialize, JsonSchema)]
610pub struct EffectDeclareParams {
611    /// Fully-qualified symbol name.
612    pub qname: String,
613    /// List of declared effects. Each element is a JSON object matching the
614    /// `Effect` schema: `{ "effect": "<category>", "qualifiers": ..., "note": ... }`.
615    pub declared: Vec<serde_json::Value>,
616    /// Author id (default: "asd-mcp"). Surfaced to the policy gate so rules
617    /// can scope by agent identity.
618    #[serde(default = "default_author_id")]
619    pub author_id: String,
620}
621
622fn default_limit() -> u32 {
623    50
624}
625fn default_author_kind() -> String {
626    "agent".to_string()
627}
628fn default_author_id() -> String {
629    "asd-mcp".to_string()
630}
631
632// -- Scratch parameter types ------------------------------------------------
633
634#[derive(Deserialize, JsonSchema)]
635pub struct ScratchWriteParams {
636    /// Working notes content (markdown OK).
637    pub content: String,
638    /// Optional: qualified name of the symbol to attach this note to.
639    /// In planning mode, the symbol does not need to exist yet.
640    #[serde(default)]
641    pub symbol: Option<String>,
642    /// Optional: named investigation context (e.g. "tracing-sync-bug").
643    #[serde(default)]
644    pub workflow: Option<String>,
645    /// Optional: time-to-live in hours. When not set, no expiry.
646    #[serde(default)]
647    pub ttl_hours: Option<i64>,
648    /// Optional: freeform tags.
649    #[serde(default)]
650    pub tags: Option<Vec<String>>,
651    /// When true, marks this entry as pre-implementation planning notes.
652    /// Adds the "planning" tag automatically. Unresolved symbol names are
653    /// stored as-is rather than causing an error — useful for naming planned
654    /// symbols that do not exist in the index yet.
655    #[serde(default)]
656    pub planning: Option<bool>,
657}
658
659#[derive(Deserialize, JsonSchema)]
660pub struct ScratchListParams {
661    /// Filter by symbol qualified name.
662    #[serde(default)]
663    pub symbol: Option<String>,
664    /// Filter by workflow name.
665    #[serde(default)]
666    pub workflow: Option<String>,
667    /// Filter by session/agent_id.
668    #[serde(default)]
669    pub session: Option<String>,
670    /// Filter by status: "draft", "promoted", "discarded". Defaults to "draft".
671    #[serde(default)]
672    pub status: Option<String>,
673    /// Max results to return (default: 50).
674    #[serde(default = "default_limit")]
675    pub limit: u32,
676}
677
678#[derive(Deserialize, JsonSchema)]
679pub struct ScratchReadParams {
680    /// Scratch entry ID (`scr_…`).
681    pub scratch_id: String,
682}
683
684#[derive(Deserialize, JsonSchema)]
685pub struct ScratchUpdateParams {
686    /// Scratch entry ID to update.
687    pub scratch_id: String,
688    /// Replacement content (replaces previous content entirely).
689    pub content: String,
690}
691
692#[derive(Deserialize, JsonSchema)]
693pub struct ScratchDiscardParams {
694    /// Scratch entry ID to discard.
695    pub scratch_id: String,
696}
697
698#[derive(Deserialize, JsonSchema)]
699pub struct ScratchPromoteParams {
700    /// Scratch entry ID to promote.
701    pub scratch_id: String,
702    /// Ledger kind: decision, assumption, constraint, rationale, hazard, tradeoff, invariant, ownership, proof, validation_scenario, known_bug, concept.
703    pub kind: String,
704    /// Symbol qualified name. Required if the scratch entry has no symbol attached.
705    #[serde(default)]
706    pub qname: Option<String>,
707    /// One-line summary. Defaults to the first non-empty line of the scratch content.
708    #[serde(default)]
709    pub summary: Option<String>,
710}
711
712#[derive(Deserialize, JsonSchema)]
713pub struct ScratchCleanParams {
714    /// Delete entries older than this many hours. Required.
715    pub older_than_hours: u32,
716    /// Comma-separated statuses to clean: "discarded,promoted" (default).
717    #[serde(default = "default_scratch_clean_statuses")]
718    pub statuses: String,
719    /// When true, report what would be deleted without removing anything.
720    #[serde(default)]
721    pub dry_run: bool,
722}
723
724fn default_scratch_clean_statuses() -> String {
725    "discarded,promoted".to_string()
726}
727
728// -- New tool parameter types -----------------------------------------------
729
730#[derive(Deserialize, JsonSchema)]
731pub struct SearchParams {
732    /// Concept or keyword(s) to search for.
733    pub query: String,
734    /// Filter by symbol kind.
735    pub kind: Option<String>,
736    /// Filter by language.
737    pub language: Option<String>,
738    /// Max results (default: 20).
739    #[serde(default = "default_search_limit")]
740    pub limit: u32,
741    /// Include test-file symbols (default: false).
742    #[serde(default)]
743    pub include_tests: bool,
744    /// Adjust guidance for a specific intent (bugfix, feature, refactor, test, architecture, ui).
745    pub intent: Option<String>,
746    /// Named scope alias from .asd/scopes.toml.
747    pub scope: Option<String>,
748    /// Comma-separated glob patterns to restrict to specific paths.
749    pub paths: Option<String>,
750    /// Comma-separated exclusion terms.
751    pub exclude: Option<String>,
752    /// Skip document index; return symbol hits only (default: false).
753    #[serde(default)]
754    pub symbols_only: bool,
755    /// Agent token budget (default: 8000).
756    #[serde(default = "default_agent_budget")]
757    pub agent_budget: u32,
758}
759
760fn default_agent_budget() -> u32 {
761    8000
762}
763
764#[derive(Deserialize, JsonSchema)]
765pub struct ContextForParams {
766    /// Comma-separated fully-qualified symbol names.
767    pub qnames: String,
768    /// Token budget for the output.
769    pub budget_tokens: Option<u32>,
770    /// Include full source body (default: false).
771    #[serde(default)]
772    pub include_body: bool,
773}
774
775#[derive(Deserialize, JsonSchema)]
776pub struct TaskCloseParams {
777    /// Free-text proof of completion (default: "task completed").
778    pub proof: Option<String>,
779    /// Comma-separated qnames to annotate. If omitted, resolved from git HEAD changed files.
780    pub symbols: Option<String>,
781    /// Mark the task as validated.
782    #[serde(default)]
783    pub validated: bool,
784    /// Validation note (used when validated = true).
785    pub validation_note: Option<String>,
786    /// Reference to validation evidence (file, URL, or test name).
787    pub evidence: Option<String>,
788    /// CTX plan ID.
789    pub plan: Option<String>,
790    /// CTX task ID.
791    pub task: Option<String>,
792    /// Author id (default: "asd-task-close").
793    #[serde(default = "default_task_close_author")]
794    pub author: String,
795}
796
797fn default_task_close_author() -> String {
798    "asd-task-close".to_string()
799}
800
801#[derive(Deserialize, JsonSchema)]
802pub struct VerifyEffectsParams {
803    /// Fully-qualified symbol name.
804    pub qname: String,
805    /// Write verification result back to the store (default: false).
806    #[serde(default)]
807    pub write: bool,
808}
809
810#[derive(Deserialize, JsonSchema)]
811pub struct StatusParams {
812    /// Show source files modified since last commit (default: false).
813    #[serde(default)]
814    pub show_dirty: bool,
815}
816
817#[derive(Deserialize, JsonSchema)]
818pub struct ScorecardParams {
819    /// Named scope alias.
820    pub scope: Option<String>,
821    /// Comma-separated glob patterns.
822    pub paths: Option<String>,
823    /// Drill-down dimension: "truth", "feedback", "change", "uncertainty", "workflow".
824    pub drill_down: Option<String>,
825    /// Max symbols shown in drill-down (default: 10).
826    #[serde(default = "default_scorecard_limit")]
827    pub limit: u32,
828}
829
830fn default_scorecard_limit() -> u32 {
831    10
832}
833
834#[derive(Deserialize, JsonSchema)]
835pub struct AnnotateCommitParams {
836    /// Git commit SHA (default: "HEAD").
837    pub sha: Option<String>,
838    /// Actually write entries (default: false — dry-run).
839    #[serde(default)]
840    pub write: bool,
841    /// Author id (defaults to git user.name).
842    pub author: Option<String>,
843    /// Additional task context appended to commit body for annotation extraction.
844    pub task_description: Option<String>,
845    /// CTX task ID — written as ctx:task:<id> provenance tag.
846    pub ctx_task: Option<String>,
847    /// CTX plan ID — written as ctx:plan:<id> provenance tag.
848    pub ctx_plan: Option<String>,
849}
850
851// -- Tool implementations ---------------------------------------------------
852//
853// MCP tool naming conventions (see CLI parity audit):
854// - Tools that mirror a CLI verb 1:1 use the same name (search, callers, callees,
855//   impact, since, investigate, prepare_change, ...).
856// - `code_*` prefix is used for tools whose bare CLI name would collide in the
857//   flat MCP namespace shared with other servers: `code_search`, `code_read`,
858//   `code_query` — CLI equivalents are `asd search` and `asd read`.
859// - Subcommand-style CLI verbs are flattened with an underscore in MCP because
860//   MCP has no nested-command concept: MCP `ledger_append` = CLI `asd ledger append`,
861//   MCP `scratch_write` = CLI `asd scratch write`, and so on for feedback_*,
862//   invariant_*, audit_*.
863// - No `_of` suffix: use bare names (callers, callees, effects, traces).