@mrc2204/agent-smart-memo 5.0.2 → 5.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/README.md +209 -375
  2. package/bin/asm.mjs +365 -0
  3. package/bin/opencode-mcp-server.mjs +320 -0
  4. package/dist/core/contracts/adapter-contracts.d.ts +1 -1
  5. package/dist/core/contracts/adapter-contracts.d.ts.map +1 -1
  6. package/dist/core/contracts/change-overlay-contracts.d.ts +69 -0
  7. package/dist/core/contracts/change-overlay-contracts.d.ts.map +1 -0
  8. package/dist/core/contracts/change-overlay-contracts.js +2 -0
  9. package/dist/core/contracts/change-overlay-contracts.js.map +1 -0
  10. package/dist/core/contracts/feature-pack-contracts.d.ts +37 -0
  11. package/dist/core/contracts/feature-pack-contracts.d.ts.map +1 -0
  12. package/dist/core/contracts/feature-pack-contracts.js +8 -0
  13. package/dist/core/contracts/feature-pack-contracts.js.map +1 -0
  14. package/dist/core/contracts/project-query-contracts.d.ts +84 -0
  15. package/dist/core/contracts/project-query-contracts.d.ts.map +1 -0
  16. package/dist/core/contracts/project-query-contracts.js +2 -0
  17. package/dist/core/contracts/project-query-contracts.js.map +1 -0
  18. package/dist/core/graph/code-graph-model.d.ts +9 -0
  19. package/dist/core/graph/code-graph-model.d.ts.map +1 -0
  20. package/dist/core/graph/code-graph-model.js +70 -0
  21. package/dist/core/graph/code-graph-model.js.map +1 -0
  22. package/dist/core/graph/code-graph-populator.d.ts +20 -0
  23. package/dist/core/graph/code-graph-populator.d.ts.map +1 -0
  24. package/dist/core/graph/code-graph-populator.js +760 -0
  25. package/dist/core/graph/code-graph-populator.js.map +1 -0
  26. package/dist/core/graph/contracts.d.ts +29 -0
  27. package/dist/core/graph/contracts.d.ts.map +1 -0
  28. package/dist/core/graph/contracts.js +47 -0
  29. package/dist/core/graph/contracts.js.map +1 -0
  30. package/dist/core/ingest/contracts.d.ts +44 -0
  31. package/dist/core/ingest/contracts.d.ts.map +1 -0
  32. package/dist/core/ingest/contracts.js +2 -0
  33. package/dist/core/ingest/contracts.js.map +1 -0
  34. package/dist/core/ingest/ids.d.ts +5 -0
  35. package/dist/core/ingest/ids.d.ts.map +1 -0
  36. package/dist/core/ingest/ids.js +17 -0
  37. package/dist/core/ingest/ids.js.map +1 -0
  38. package/dist/core/ingest/ingest-pipeline.d.ts +4 -0
  39. package/dist/core/ingest/ingest-pipeline.d.ts.map +1 -0
  40. package/dist/core/ingest/ingest-pipeline.js +105 -0
  41. package/dist/core/ingest/ingest-pipeline.js.map +1 -0
  42. package/dist/core/ingest/semantic-block-extractor.d.ts +9 -0
  43. package/dist/core/ingest/semantic-block-extractor.d.ts.map +1 -0
  44. package/dist/core/ingest/semantic-block-extractor.js +171 -0
  45. package/dist/core/ingest/semantic-block-extractor.js.map +1 -0
  46. package/dist/core/usecases/default-memory-usecase-port.d.ts +38 -0
  47. package/dist/core/usecases/default-memory-usecase-port.d.ts.map +1 -1
  48. package/dist/core/usecases/default-memory-usecase-port.js +1686 -12
  49. package/dist/core/usecases/default-memory-usecase-port.js.map +1 -1
  50. package/dist/db/graph-db.d.ts +24 -0
  51. package/dist/db/graph-db.d.ts.map +1 -1
  52. package/dist/db/graph-db.js +81 -2
  53. package/dist/db/graph-db.js.map +1 -1
  54. package/dist/db/slot-db.d.ts +235 -2
  55. package/dist/db/slot-db.d.ts.map +1 -1
  56. package/dist/db/slot-db.js +840 -18
  57. package/dist/db/slot-db.js.map +1 -1
  58. package/dist/index.d.ts +7 -247
  59. package/dist/index.d.ts.map +1 -1
  60. package/dist/index.js +32 -119
  61. package/dist/index.js.map +1 -1
  62. package/dist/shared/asm-config.d.ts +82 -0
  63. package/dist/shared/asm-config.d.ts.map +1 -0
  64. package/dist/shared/asm-config.js +254 -0
  65. package/dist/shared/asm-config.js.map +1 -0
  66. package/dist/shared/slotdb-path.d.ts +4 -3
  67. package/dist/shared/slotdb-path.d.ts.map +1 -1
  68. package/dist/shared/slotdb-path.js +15 -6
  69. package/dist/shared/slotdb-path.js.map +1 -1
  70. package/dist/tools/graph-tools.d.ts.map +1 -1
  71. package/dist/tools/graph-tools.js +131 -0
  72. package/dist/tools/graph-tools.js.map +1 -1
  73. package/dist/tools/project-tools.d.ts.map +1 -1
  74. package/dist/tools/project-tools.js +543 -0
  75. package/dist/tools/project-tools.js.map +1 -1
  76. package/openclaw.plugin.json +5 -164
  77. package/package.json +61 -26
  78. package/scripts/init-openclaw.mjs +727 -0
@@ -106,6 +106,41 @@ export function registerProjectTools(api, options) {
106
106
  }
107
107
  },
108
108
  });
109
+ api.registerTool({
110
+ name: "project_binding_preview",
111
+ label: "Project Binding Preview",
112
+ description: "Read-only OpenCode-style project binding preview. Resolves active project by project_id/project_alias/repo_root/session alias, blocks ambiguous multi-project binding unless cross-project is explicit.",
113
+ parameters: {
114
+ type: "object",
115
+ properties: {
116
+ project_id: { type: "string" },
117
+ project_alias: { type: "string" },
118
+ repo_root: { type: "string" },
119
+ session_project_alias: { type: "string" },
120
+ allow_cross_project: { type: "boolean" },
121
+ },
122
+ },
123
+ async execute(_id, params, ctx) {
124
+ try {
125
+ const sessionKey = getSessionKey(ctx);
126
+ const { userId, agentId } = parseOpenClawSessionIdentity(sessionKey);
127
+ const useCasePort = getMemoryUseCasePortForContext(ctx);
128
+ const data = await useCasePort.run("project.binding_preview", {
129
+ context: { userId, agentId },
130
+ payload: params,
131
+ meta: {
132
+ source: "openclaw",
133
+ toolName: "project_binding_preview",
134
+ requestId: _id,
135
+ },
136
+ });
137
+ return createResult(JSON.stringify(data, null, 2));
138
+ }
139
+ catch (error) {
140
+ return createResult(`Error: ${error instanceof Error ? error.message : String(error)}`, true);
141
+ }
142
+ },
143
+ });
109
144
  api.registerTool({
110
145
  name: "project_registration_state_set",
111
146
  label: "Project Registration State Set",
@@ -332,6 +367,7 @@ export function registerProjectTools(api, options) {
332
367
  checksum: { type: "string" },
333
368
  module: { type: "string" },
334
369
  language: { type: "string" },
370
+ content: { type: "string" },
335
371
  },
336
372
  required: ["relative_path"],
337
373
  },
@@ -360,6 +396,197 @@ export function registerProjectTools(api, options) {
360
396
  }
361
397
  },
362
398
  });
399
+ api.registerTool({
400
+ name: "project_deindex",
401
+ label: "Project Deindex",
402
+ description: "Mark a project as deindexed (non-destructive): keep registry identity but tombstone indexed artifacts so retrieval/search no longer returns them.",
403
+ parameters: {
404
+ type: "object",
405
+ properties: {
406
+ project_id: { type: "string" },
407
+ reason: { type: "string" },
408
+ },
409
+ required: ["project_id"],
410
+ },
411
+ async execute(_id, params, ctx) {
412
+ try {
413
+ const sessionKey = getSessionKey(ctx);
414
+ const { userId, agentId } = parseOpenClawSessionIdentity(sessionKey);
415
+ const useCasePort = getMemoryUseCasePortForContext(ctx);
416
+ const data = await useCasePort.run("project.deindex", {
417
+ context: { userId, agentId },
418
+ payload: params,
419
+ meta: {
420
+ source: "openclaw",
421
+ toolName: "project_deindex",
422
+ requestId: _id,
423
+ },
424
+ });
425
+ return createResult(JSON.stringify(data, null, 2));
426
+ }
427
+ catch (error) {
428
+ return createResult(`Error: ${error instanceof Error ? error.message : String(error)}`, true);
429
+ }
430
+ },
431
+ });
432
+ api.registerTool({
433
+ name: "project_detach",
434
+ label: "Project Detach",
435
+ description: "Detach a project from active bindings (aliases/repo/tracker) after deindex safety step. Non-purge and reversible via re-register.",
436
+ parameters: {
437
+ type: "object",
438
+ properties: {
439
+ project_ref: {
440
+ type: "object",
441
+ properties: {
442
+ project_id: { type: "string" },
443
+ project_alias: { type: "string" },
444
+ },
445
+ },
446
+ reason: { type: "string" },
447
+ },
448
+ required: ["project_ref"],
449
+ },
450
+ async execute(_id, params, ctx) {
451
+ try {
452
+ const sessionKey = getSessionKey(ctx);
453
+ const { userId, agentId } = parseOpenClawSessionIdentity(sessionKey);
454
+ const useCasePort = getMemoryUseCasePortForContext(ctx);
455
+ const data = await useCasePort.run("project.detach", {
456
+ context: { userId, agentId },
457
+ payload: params,
458
+ meta: {
459
+ source: "openclaw",
460
+ toolName: "project_detach",
461
+ requestId: _id,
462
+ },
463
+ });
464
+ return createResult(JSON.stringify(data, null, 2));
465
+ }
466
+ catch (error) {
467
+ return createResult(`Error: ${error instanceof Error ? error.message : String(error)}`, true);
468
+ }
469
+ },
470
+ });
471
+ api.registerTool({
472
+ name: "project_unregister",
473
+ label: "Project Unregister",
474
+ description: "Safe unregister lifecycle step: requires explicit confirm=true, deindexes first, then disables project and detaches active bindings without destructive purge.",
475
+ parameters: {
476
+ type: "object",
477
+ properties: {
478
+ project_ref: {
479
+ type: "object",
480
+ properties: {
481
+ project_id: { type: "string" },
482
+ project_alias: { type: "string" },
483
+ },
484
+ },
485
+ confirm: { type: "boolean" },
486
+ mode: { type: "string", enum: ["safe"] },
487
+ reason: { type: "string" },
488
+ },
489
+ required: ["project_ref", "confirm"],
490
+ },
491
+ async execute(_id, params, ctx) {
492
+ try {
493
+ const sessionKey = getSessionKey(ctx);
494
+ const { userId, agentId } = parseOpenClawSessionIdentity(sessionKey);
495
+ const useCasePort = getMemoryUseCasePortForContext(ctx);
496
+ const data = await useCasePort.run("project.unregister", {
497
+ context: { userId, agentId },
498
+ payload: params,
499
+ meta: {
500
+ source: "openclaw",
501
+ toolName: "project_unregister",
502
+ requestId: _id,
503
+ },
504
+ });
505
+ return createResult(JSON.stringify(data, null, 2));
506
+ }
507
+ catch (error) {
508
+ return createResult(`Error: ${error instanceof Error ? error.message : String(error)}`, true);
509
+ }
510
+ },
511
+ });
512
+ api.registerTool({
513
+ name: "project_purge_preview",
514
+ label: "Project Purge Preview",
515
+ description: "Preview destructive purge impact with guardrails. Purge is only allowed when lifecycle_status=disabled and still requires explicit confirm in the purge call.",
516
+ parameters: {
517
+ type: "object",
518
+ properties: {
519
+ project_ref: {
520
+ type: "object",
521
+ properties: {
522
+ project_id: { type: "string" },
523
+ project_alias: { type: "string" },
524
+ },
525
+ },
526
+ },
527
+ required: ["project_ref"],
528
+ },
529
+ async execute(_id, params, ctx) {
530
+ try {
531
+ const sessionKey = getSessionKey(ctx);
532
+ const { userId, agentId } = parseOpenClawSessionIdentity(sessionKey);
533
+ const useCasePort = getMemoryUseCasePortForContext(ctx);
534
+ const data = await useCasePort.run("project.purge_preview", {
535
+ context: { userId, agentId },
536
+ payload: params,
537
+ meta: {
538
+ source: "openclaw",
539
+ toolName: "project_purge_preview",
540
+ requestId: _id,
541
+ },
542
+ });
543
+ return createResult(JSON.stringify(data, null, 2));
544
+ }
545
+ catch (error) {
546
+ return createResult(`Error: ${error instanceof Error ? error.message : String(error)}`, true);
547
+ }
548
+ },
549
+ });
550
+ api.registerTool({
551
+ name: "project_purge",
552
+ label: "Project Purge",
553
+ description: "Destructive lifecycle endpoint. Requires project to be disabled first and explicit confirm=true. Use project_purge_preview before execution.",
554
+ parameters: {
555
+ type: "object",
556
+ properties: {
557
+ project_ref: {
558
+ type: "object",
559
+ properties: {
560
+ project_id: { type: "string" },
561
+ project_alias: { type: "string" },
562
+ },
563
+ },
564
+ confirm: { type: "boolean" },
565
+ reason: { type: "string" },
566
+ },
567
+ required: ["project_ref", "confirm"],
568
+ },
569
+ async execute(_id, params, ctx) {
570
+ try {
571
+ const sessionKey = getSessionKey(ctx);
572
+ const { userId, agentId } = parseOpenClawSessionIdentity(sessionKey);
573
+ const useCasePort = getMemoryUseCasePortForContext(ctx);
574
+ const data = await useCasePort.run("project.purge", {
575
+ context: { userId, agentId },
576
+ payload: params,
577
+ meta: {
578
+ source: "openclaw",
579
+ toolName: "project_purge",
580
+ requestId: _id,
581
+ },
582
+ });
583
+ return createResult(JSON.stringify(data, null, 2));
584
+ }
585
+ catch (error) {
586
+ return createResult(`Error: ${error instanceof Error ? error.message : String(error)}`, true);
587
+ }
588
+ },
589
+ });
363
590
  api.registerTool({
364
591
  name: "project_telegram_onboarding",
365
592
  label: "Project Telegram Onboarding",
@@ -420,6 +647,7 @@ export function registerProjectTools(api, options) {
420
647
  checksum: { type: "string" },
421
648
  module: { type: "string" },
422
649
  language: { type: "string" },
650
+ content: { type: "string" },
423
651
  },
424
652
  required: ["relative_path"],
425
653
  },
@@ -448,6 +676,77 @@ export function registerProjectTools(api, options) {
448
676
  }
449
677
  },
450
678
  });
679
+ api.registerTool({
680
+ name: "project_index_event",
681
+ label: "Project Index Event",
682
+ description: "Event-driven partial project reindex using explicit changed/deleted file lists from git hooks or local automation.",
683
+ parameters: {
684
+ type: "object",
685
+ properties: {
686
+ project_id: { type: "string" },
687
+ repo_root: { type: "string" },
688
+ source_rev: { type: "string" },
689
+ event_type: { type: "string", enum: ["post_commit", "post_merge", "post_rewrite", "manual"] },
690
+ changed_files: { type: "array", items: { type: "string" } },
691
+ deleted_files: { type: "array", items: { type: "string" } },
692
+ trusted_sync: { type: "boolean" },
693
+ full_snapshot: { type: "boolean" },
694
+ },
695
+ required: ["project_id"],
696
+ },
697
+ async execute(_id, params, ctx) {
698
+ try {
699
+ const sessionKey = getSessionKey(ctx);
700
+ const { userId, agentId } = parseOpenClawSessionIdentity(sessionKey);
701
+ const useCasePort = getMemoryUseCasePortForContext(ctx);
702
+ const data = await useCasePort.run("project.index_event", {
703
+ context: { userId, agentId },
704
+ payload: params,
705
+ meta: {
706
+ source: "openclaw",
707
+ toolName: "project_index_event",
708
+ requestId: _id,
709
+ },
710
+ });
711
+ return createResult(JSON.stringify(data, null, 2));
712
+ }
713
+ catch (error) {
714
+ return createResult(`Error: ${error instanceof Error ? error.message : String(error)}`, true);
715
+ }
716
+ },
717
+ });
718
+ api.registerTool({
719
+ name: "project_install_hooks",
720
+ label: "Project Install Hooks",
721
+ description: "Install local git hooks for an already-registered project so commit/merge events auto-trigger ASM indexing.",
722
+ parameters: {
723
+ type: "object",
724
+ properties: {
725
+ project_id: { type: "string" },
726
+ },
727
+ required: ["project_id"],
728
+ },
729
+ async execute(_id, params, ctx) {
730
+ try {
731
+ const sessionKey = getSessionKey(ctx);
732
+ const { userId, agentId } = parseOpenClawSessionIdentity(sessionKey);
733
+ const useCasePort = getMemoryUseCasePortForContext(ctx);
734
+ const data = await useCasePort.run("project.install_hooks", {
735
+ context: { userId, agentId },
736
+ payload: params,
737
+ meta: {
738
+ source: "openclaw",
739
+ toolName: "project_install_hooks",
740
+ requestId: _id,
741
+ },
742
+ });
743
+ return createResult(JSON.stringify(data, null, 2));
744
+ }
745
+ catch (error) {
746
+ return createResult(`Error: ${error instanceof Error ? error.message : String(error)}`, true);
747
+ }
748
+ },
749
+ });
451
750
  api.registerTool({
452
751
  name: "project_index_watch_get",
453
752
  label: "Project Index Watch Get",
@@ -596,6 +895,249 @@ export function registerProjectTools(api, options) {
596
895
  }
597
896
  },
598
897
  });
898
+ api.registerTool({
899
+ name: "project_change_overlay_query",
900
+ label: "Project Change Overlay Query",
901
+ description: "Query ASM-94 change-aware overlay with explicit selector (task/tracker) and optional feature filter.",
902
+ parameters: {
903
+ type: "object",
904
+ properties: {
905
+ project_id: { type: "string" },
906
+ task_id: { type: "string" },
907
+ tracker_issue_key: { type: "string" },
908
+ task_title: { type: "string" },
909
+ feature_key: {
910
+ type: "string",
911
+ enum: [
912
+ "project_onboarding_registration_indexing",
913
+ "code_aware_retrieval",
914
+ "heartbeat_health_runtime_integrity",
915
+ "change_aware_impact",
916
+ "post_entry_review_decision_support",
917
+ ],
918
+ },
919
+ feature_name: { type: "string" },
920
+ include_related: { type: "boolean" },
921
+ include_parent_chain: { type: "boolean" },
922
+ },
923
+ required: ["project_id"],
924
+ },
925
+ async execute(_id, params, ctx) {
926
+ try {
927
+ const sessionKey = getSessionKey(ctx);
928
+ const { userId, agentId } = parseOpenClawSessionIdentity(sessionKey);
929
+ const useCasePort = getMemoryUseCasePortForContext(ctx);
930
+ const data = await useCasePort.run("project.change_overlay.query", {
931
+ context: { userId, agentId },
932
+ payload: params,
933
+ meta: {
934
+ source: "openclaw",
935
+ toolName: "project_change_overlay_query",
936
+ requestId: _id,
937
+ },
938
+ });
939
+ return createResult(JSON.stringify(data, null, 2));
940
+ }
941
+ catch (error) {
942
+ return createResult(`Error: ${error instanceof Error ? error.message : String(error)}`, true);
943
+ }
944
+ },
945
+ });
946
+ api.registerTool({
947
+ name: "project_feature_pack_generate",
948
+ label: "Project Feature Pack Generate",
949
+ description: "Generate a minimal feature/capability pack for a registered project flow. ASM-93 Slice 2 supports multiple priority feature packs.",
950
+ parameters: {
951
+ type: "object",
952
+ properties: {
953
+ project_id: { type: "string" },
954
+ project_alias: { type: "string" },
955
+ feature_key: {
956
+ type: "string",
957
+ enum: [
958
+ "project_onboarding_registration_indexing",
959
+ "code_aware_retrieval",
960
+ "heartbeat_health_runtime_integrity",
961
+ "change_aware_impact",
962
+ "post_entry_review_decision_support",
963
+ ],
964
+ },
965
+ },
966
+ },
967
+ async execute(_id, params, ctx) {
968
+ try {
969
+ const sessionKey = getSessionKey(ctx);
970
+ const { userId, agentId } = parseOpenClawSessionIdentity(sessionKey);
971
+ const useCasePort = getMemoryUseCasePortForContext(ctx);
972
+ const data = await useCasePort.run("project.feature_pack.generate", {
973
+ context: { userId, agentId },
974
+ payload: params,
975
+ meta: {
976
+ source: "openclaw",
977
+ toolName: "project_feature_pack_generate",
978
+ requestId: _id,
979
+ },
980
+ });
981
+ return createResult(JSON.stringify(data, null, 2));
982
+ }
983
+ catch (error) {
984
+ return createResult(`Error: ${error instanceof Error ? error.message : String(error)}`, true);
985
+ }
986
+ },
987
+ });
988
+ api.registerTool({
989
+ name: "project_feature_pack_query",
990
+ label: "Project Feature Pack Query",
991
+ description: "Query feature pack by feature_key or feature name (human-friendly) for a registered project.",
992
+ parameters: {
993
+ type: "object",
994
+ properties: {
995
+ project_id: { type: "string" },
996
+ project_alias: { type: "string" },
997
+ feature_key: {
998
+ type: "string",
999
+ enum: [
1000
+ "project_onboarding_registration_indexing",
1001
+ "code_aware_retrieval",
1002
+ "heartbeat_health_runtime_integrity",
1003
+ "change_aware_impact",
1004
+ "post_entry_review_decision_support",
1005
+ ],
1006
+ },
1007
+ feature_name: { type: "string" },
1008
+ },
1009
+ },
1010
+ async execute(_id, params, ctx) {
1011
+ try {
1012
+ const sessionKey = getSessionKey(ctx);
1013
+ const { userId, agentId } = parseOpenClawSessionIdentity(sessionKey);
1014
+ const useCasePort = getMemoryUseCasePortForContext(ctx);
1015
+ const data = await useCasePort.run("project.feature_pack.query", {
1016
+ context: { userId, agentId },
1017
+ payload: params,
1018
+ meta: {
1019
+ source: "openclaw",
1020
+ toolName: "project_feature_pack_query",
1021
+ requestId: _id,
1022
+ },
1023
+ });
1024
+ return createResult(JSON.stringify(data, null, 2));
1025
+ }
1026
+ catch (error) {
1027
+ return createResult(`Error: ${error instanceof Error ? error.message : String(error)}`, true);
1028
+ }
1029
+ },
1030
+ });
1031
+ api.registerTool({
1032
+ name: "project_opencode_search",
1033
+ label: "Project OpenCode Search",
1034
+ description: "Read-only OpenCode retrieval surface. Resolves project binding first, then runs project-scoped developer query. Cross-project behavior requires explicit opt-in.",
1035
+ parameters: {
1036
+ type: "object",
1037
+ properties: {
1038
+ query: { type: "string" },
1039
+ limit: { type: "number" },
1040
+ project_id: { type: "string" },
1041
+ project_alias: { type: "string" },
1042
+ repo_root: { type: "string" },
1043
+ session_project_alias: { type: "string" },
1044
+ explicit_project_id: { type: "string" },
1045
+ explicit_project_alias: { type: "string" },
1046
+ explicit_cross_project: { type: "boolean" },
1047
+ },
1048
+ required: ["query"],
1049
+ },
1050
+ async execute(_id, params, ctx) {
1051
+ try {
1052
+ const sessionKey = getSessionKey(ctx);
1053
+ const { userId, agentId } = parseOpenClawSessionIdentity(sessionKey);
1054
+ const useCasePort = getMemoryUseCasePortForContext(ctx);
1055
+ const data = await useCasePort.run("project.opencode_search", {
1056
+ context: { userId, agentId },
1057
+ payload: params,
1058
+ meta: {
1059
+ source: "openclaw",
1060
+ toolName: "project_opencode_search",
1061
+ requestId: _id,
1062
+ },
1063
+ });
1064
+ return createResult(JSON.stringify(data, null, 2));
1065
+ }
1066
+ catch (error) {
1067
+ return createResult(`Error: ${error instanceof Error ? error.message : String(error)}`, true);
1068
+ }
1069
+ },
1070
+ });
1071
+ api.registerTool({
1072
+ name: "project_developer_query",
1073
+ label: "Project Developer Query",
1074
+ description: "ASM-112 typed developer query parser surface with deterministic intent/selector normalization over existing hybrid_search/feature_pack/change_overlay capabilities.",
1075
+ parameters: {
1076
+ type: "object",
1077
+ properties: {
1078
+ project_id: { type: "string" },
1079
+ project_alias: { type: "string" },
1080
+ query: { type: "string" },
1081
+ intent: {
1082
+ type: "string",
1083
+ enum: [
1084
+ "locate_symbol",
1085
+ "locate_file",
1086
+ "feature_lookup",
1087
+ "change_lookup",
1088
+ "locate",
1089
+ "trace_flow",
1090
+ "impact",
1091
+ "impact_analysis",
1092
+ "change_aware_lookup",
1093
+ "feature_understanding",
1094
+ ],
1095
+ },
1096
+ limit: { type: "number" },
1097
+ symbol_name: { type: "string" },
1098
+ relative_path: { type: "string" },
1099
+ route_path: { type: "string" },
1100
+ tracker_issue_key: { type: "string" },
1101
+ task_id: { type: "string" },
1102
+ task_title: { type: "string" },
1103
+ tracker_issue_keys: { type: "array", items: { type: "string" } },
1104
+ task_ids: { type: "array", items: { type: "string" } },
1105
+ route_paths: { type: "array", items: { type: "string" } },
1106
+ feature_key: {
1107
+ type: "string",
1108
+ enum: [
1109
+ "project_onboarding_registration_indexing",
1110
+ "code_aware_retrieval",
1111
+ "heartbeat_health_runtime_integrity",
1112
+ "change_aware_impact",
1113
+ "post_entry_review_decision_support",
1114
+ ],
1115
+ },
1116
+ feature_name: { type: "string" },
1117
+ },
1118
+ required: [],
1119
+ },
1120
+ async execute(_id, params, ctx) {
1121
+ try {
1122
+ const sessionKey = getSessionKey(ctx);
1123
+ const { userId, agentId } = parseOpenClawSessionIdentity(sessionKey);
1124
+ const useCasePort = getMemoryUseCasePortForContext(ctx);
1125
+ const data = await useCasePort.run("project.developer_query", {
1126
+ context: { userId, agentId },
1127
+ payload: params,
1128
+ meta: {
1129
+ source: "openclaw",
1130
+ toolName: "project_developer_query",
1131
+ requestId: _id,
1132
+ },
1133
+ });
1134
+ return createResult(JSON.stringify(data, null, 2));
1135
+ }
1136
+ catch (error) {
1137
+ return createResult(`Error: ${error instanceof Error ? error.message : String(error)}`, true);
1138
+ }
1139
+ },
1140
+ });
599
1141
  api.registerTool({
600
1142
  name: "project_hybrid_search",
601
1143
  label: "Project Hybrid Search",
@@ -606,6 +1148,7 @@ export function registerProjectTools(api, options) {
606
1148
  project_id: { type: "string" },
607
1149
  query: { type: "string" },
608
1150
  limit: { type: "number" },
1151
+ debug: { type: "boolean", description: "Return candidate-generation and ranking debug info for conformance/debugging." },
609
1152
  path_prefix: { type: "array", items: { type: "string" } },
610
1153
  module: { type: "array", items: { type: "string" } },
611
1154
  language: { type: "array", items: { type: "string" } },