@tomingtoming/kioq 0.9.0 → 0.9.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.
package/dist/src/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ import path from "node:path";
1
2
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
3
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
4
  import { z } from "zod";
@@ -114,11 +115,14 @@ function appendBoundaryWarnings(lines, warnings) {
114
115
  lines.push(` suggestion: ${warning.suggestion}`);
115
116
  });
116
117
  }
117
- function appendScopeLabel(lines, scopeLabel) {
118
- lines.push(`scope_label: ${scopeLabel}`);
118
+ function appendScopeLabel(_lines, _scopeLabel) {
119
+ // Removed: scope_label duplicates tool name, adds no value for AI
119
120
  }
120
121
  function appendResponsibilityWarning(lines, warnings) {
121
- lines.push(`responsibility_warning: ${responsibilityWarningCode(warnings)}`);
122
+ const code = responsibilityWarningCode(warnings);
123
+ if (code === "none")
124
+ return;
125
+ lines.push(`responsibility_warning: ${code}`);
122
126
  }
123
127
  function appendTemplateHints(lines, hints) {
124
128
  lines.push(`template_hint_primary: ${hints.primary}`);
@@ -263,10 +267,9 @@ function appendAuditResponseSummary(lines, summary) {
263
267
  }
264
268
  }
265
269
  function appendChangeTriggerSummary(lines, summary) {
266
- lines.push(`change_trigger: ${summary.code}`);
267
- if (summary.code === "none") {
270
+ if (summary.code === "none")
268
271
  return;
269
- }
272
+ lines.push(`change_trigger: ${summary.code}`);
270
273
  lines.push(`trigger_confidence: ${summary.confidence}`);
271
274
  lines.push(`cascade_targets: ${summary.cascadeTargets?.join(", ") ?? "(none)"}`);
272
275
  lines.push(`noise_risk: ${summary.noiseRisk}`);
@@ -277,9 +280,7 @@ function appendOperationImpact(lines, impact) {
277
280
  lines.push(`impact_reasons: ${impact.reasons.join(", ")}`);
278
281
  }
279
282
  function appendConflictSummary(lines, summary) {
280
- lines.push(`conflict_type: ${summary.conflictType}`);
281
283
  lines.push(`server_updated: ${summary.serverUpdated}`);
282
- lines.push(`retry_hint: ${summary.retryHint}`);
283
284
  }
284
285
  const responseModeSchema = z.enum(RESPONSE_MODE_VALUES).optional().describe("default: standard");
285
286
  async function main() {
@@ -291,7 +292,13 @@ async function main() {
291
292
  const store = new LocalNoteStore(config, storage);
292
293
  const signalLog = new SignalLog(storage);
293
294
  const engagementIndex = new EngagementIndex();
295
+ let storageContextEmitted = false;
296
+ const projectName = path.basename(config.root);
294
297
  const appendStorageContext = (lines) => {
298
+ if (storageContextEmitted)
299
+ return;
300
+ storageContextEmitted = true;
301
+ lines.push(`project: ${projectName}`);
295
302
  lines.push(`storage_backend: ${config.github ? "github" : "filesystem"}`);
296
303
  lines.push(`storage_root: ${config.root}`);
297
304
  if (config.github) {
@@ -299,16 +306,35 @@ async function main() {
299
306
  lines.push(`storage_branch: ${config.github.branch}`);
300
307
  }
301
308
  };
309
+ /** Returns storage context lines only on first call, empty array after. */
310
+ const storageContextLines = () => {
311
+ if (storageContextEmitted)
312
+ return [];
313
+ storageContextEmitted = true;
314
+ return [
315
+ `project: ${projectName}`,
316
+ `storage_backend: ${config.github ? "github" : "filesystem"}`,
317
+ `storage_root: ${config.root}`,
318
+ ...(config.github
319
+ ? [`storage_repo: ${config.github.owner}/${config.github.repo}`, `storage_branch: ${config.github.branch}`]
320
+ : []),
321
+ ];
322
+ };
302
323
  const appendAutoProjectHealth = async (lines) => {
303
324
  try {
304
325
  const health = await store.lintStructure({
305
326
  limit: 3,
306
327
  });
328
+ const hasAttention = health.unresolvedWikiLinkCount > 0
329
+ || health.duplicateWarningCount > 0
330
+ || health.technicalDebtSignals.dependencyDirectionViolationCount > 0
331
+ || health.orphanNoteCount > 0;
332
+ if (!hasAttention)
333
+ return;
307
334
  appendProjectHealthSummary(lines, health);
308
335
  }
309
- catch (error) {
310
- lines.push("");
311
- lines.push(`project_health: unavailable (${normalizeError(error)})`);
336
+ catch {
337
+ // silently skip if lint fails
312
338
  }
313
339
  };
314
340
  const server = new McpServer({
@@ -335,9 +361,7 @@ async function main() {
335
361
  });
336
362
  await signalLog.flush();
337
363
  const lines = [];
338
- lines.push(`project: ${result.project}`);
339
364
  appendStorageContext(lines);
340
- lines.push(`scope_label: orient`);
341
365
  lines.push(`thought: ${thought.slice(0, 200)}`);
342
366
  lines.push("");
343
367
  if (result.relevant.length > 0) {
@@ -404,13 +428,10 @@ async function main() {
404
428
  });
405
429
  const lines = [];
406
430
  lines.push(`検索クエリ: ${query}`);
407
- lines.push(`対象プロジェクト: ${result.project}`);
408
431
  appendStorageContext(lines);
409
- appendScopeLabel(lines, TOOL_SCOPE_LABELS.search_notes);
410
- lines.push(`response_mode: ${responseMode}`);
411
- appendReadResponseSummary(lines, summary);
412
432
  lines.push(`ヒット件数: ${result.results.length}`);
413
- lines.push(`exact_identifier_matches: ${result.exactIdentifierMatchCount}`);
433
+ if (result.exactIdentifierMatchCount > 0)
434
+ lines.push(`exact_identifier_matches: ${result.exactIdentifierMatchCount}`);
414
435
  lines.push("");
415
436
  if (result.results.length === 0) {
416
437
  lines.push("候補が見つかりませんでした。");
@@ -423,11 +444,13 @@ async function main() {
423
444
  if (responseModeAtLeast(responseMode, "standard")) {
424
445
  lines.push(` permalink: ${item.permalink}`);
425
446
  lines.push(` file: ${item.filePath}`);
426
- lines.push(` exact_identifier_match: ${item.exactIdentifierMatch ? "yes" : "no"}`);
427
- lines.push(` index_like: ${item.indexLike ? "yes" : "no"}`);
447
+ if (item.exactIdentifierMatch)
448
+ lines.push(` exact_identifier_match: yes`);
449
+ if (item.indexLike)
450
+ lines.push(` index_like: yes`);
428
451
  }
429
- if (responseModeAtLeast(responseMode, "verbose")) {
430
- lines.push(` index_like_reasons: ${item.indexLike && item.indexReasons.length > 0 ? item.indexReasons.join(", ") : "(none)"}`);
452
+ if (responseModeAtLeast(responseMode, "verbose") && item.indexLike && item.indexReasons.length > 0) {
453
+ lines.push(` index_like_reasons: ${item.indexReasons.join(", ")}`);
431
454
  }
432
455
  });
433
456
  }
@@ -465,30 +488,18 @@ async function main() {
465
488
  });
466
489
  const lines = [
467
490
  `identifier: ${identifier}`,
468
- `project: ${result.project}`,
469
- `storage_backend: ${config.github ? "github" : "filesystem"}`,
470
- `storage_root: ${config.root}`,
471
- `scope_label: ${TOOL_SCOPE_LABELS.read_note}`,
472
- `response_mode: ${responseMode}`,
473
- `primary_navigation_signal: ${summary.primaryNavigationSignal}`,
474
- `primary_quality_signal: ${summary.primaryQualitySignal}`,
475
- `next_recommended_action: ${summary.nextRecommendedAction}`,
491
+ ...storageContextLines(),
476
492
  `file: ${result.note.relativePath}`,
477
493
  `permalink: ${result.note.permalink}`,
478
494
  ];
479
- if (config.github) {
480
- lines.splice(4, 0, `storage_repo: ${config.github.owner}/${config.github.repo}`, `storage_branch: ${config.github.branch}`);
481
- }
482
- if (summary.nextRecommendedTarget) {
483
- insertBeforeLine(lines, "next_recommended_action:", `next_recommended_target: ${summary.nextRecommendedTarget}`);
484
- }
485
495
  appendChangeTriggerSummary(lines, changeTrigger);
486
496
  appendResponsibilityWarning(lines, result.boundaryWarnings);
487
497
  appendBoundaryWarnings(lines, result.boundaryWarnings);
488
498
  if (responseModeAtLeast(responseMode, "standard")) {
489
499
  lines.push(`link_health: ${result.linkHealth.resolved}/${result.linkHealth.total} resolved`);
490
500
  lines.push(`backlinks: ${result.backlinkCount}`);
491
- lines.push(`orphan_warning: ${result.orphanWarning ? "yes" : "no"}`);
501
+ if (result.orphanWarning)
502
+ lines.push(`orphan_warning: yes`);
492
503
  appendDocumentClarity(lines, result.documentClarity, responseModeAtLeast(responseMode, "verbose"));
493
504
  appendUnresolvedWikiLinks(lines, result.unresolvedWikiLinks);
494
505
  }
@@ -528,7 +539,8 @@ async function main() {
528
539
  lines.push(` score: ${item.score}`);
529
540
  lines.push(` permalink: ${item.permalink}`);
530
541
  lines.push(` file: ${item.filePath}`);
531
- lines.push(` exact_identifier_match: ${item.exactIdentifierMatch ? "yes" : "no"}`);
542
+ if (item.exactIdentifierMatch)
543
+ lines.push(` exact_identifier_match: yes`);
532
544
  });
533
545
  }
534
546
  return textResult(lines.join("\n"));
@@ -582,10 +594,7 @@ async function main() {
582
594
  titleBodyMismatchCandidateCount: summaryBase.titleBodyMismatchCandidateCount,
583
595
  });
584
596
  const lines = [];
585
- lines.push(`project: ${result.project}`);
586
597
  appendStorageContext(lines);
587
- appendScopeLabel(lines, TOOL_SCOPE_LABELS.lint_structure);
588
- lines.push(`response_mode: ${responseMode}`);
589
598
  appendAuditResponseSummary(lines, summary);
590
599
  appendChangeTriggerSummary(lines, changeTrigger);
591
600
  lines.push(`notes: ${result.noteCount}`);
@@ -701,11 +710,6 @@ async function main() {
701
710
  });
702
711
  const flowLines = [
703
712
  "flow ノートを作成/更新しました。",
704
- `project: ${flowResult.project}`,
705
- `scope_label: ${TOOL_SCOPE_LABELS.write_flow_note}`,
706
- `primary_navigation_signal: ${flowSummary.primaryNavigationSignal}`,
707
- `primary_quality_signal: ${flowSummary.primaryQualitySignal}`,
708
- `next_recommended_action: ${flowSummary.nextRecommendedAction}`,
709
713
  `operation: ${flowResult.operation}`,
710
714
  `file: ${flowResult.relativePath}`,
711
715
  `permalink: ${flowResult.permalink}`,
@@ -715,12 +719,9 @@ async function main() {
715
719
  `parent_stock_resolved: ${flowResult.parentStockResolved ? "yes" : "no"}`,
716
720
  `link_health: ${flowResult.linkHealth.resolved}/${flowResult.linkHealth.total} resolved`,
717
721
  `backlinks: ${flowResult.backlinkCount}`,
718
- `orphan_warning: ${flowResult.orphanWarning ? "yes" : "no"}`,
719
722
  ];
720
- flowLines.splice(2, 0, ...[`storage_backend: ${config.github ? "github" : "filesystem"}`, `storage_root: ${config.root}`, ...(config.github ? [`storage_repo: ${config.github.owner}/${config.github.repo}`, `storage_branch: ${config.github.branch}`] : [])]);
721
- if (flowSummary.nextRecommendedTarget) {
722
- insertBeforeLine(flowLines, "next_recommended_action:", `next_recommended_target: ${flowSummary.nextRecommendedTarget}`);
723
- }
723
+ if (flowResult.orphanWarning)
724
+ flowLines.push(`orphan_warning: yes`);
724
725
  appendConflictSummary(flowLines, summarizeNoConflict({ serverUpdated: flowResult.serverUpdated }));
725
726
  appendResponsibilityWarning(flowLines, flowResult.boundaryWarnings);
726
727
  appendStructureScore(flowLines, flowResult.structureScore);
@@ -752,40 +753,26 @@ async function main() {
752
753
  });
753
754
  const lines = [
754
755
  "ノートを作成/更新しました。",
755
- `project: ${result.project}`,
756
- `scope_label: ${TOOL_SCOPE_LABELS.write_note}`,
757
- `primary_navigation_signal: ${summary.primaryNavigationSignal}`,
758
- `primary_quality_signal: ${summary.primaryQualitySignal}`,
759
- `next_recommended_action: ${summary.nextRecommendedAction}`,
760
756
  `operation: ${result.operation}`,
761
757
  `file: ${result.relativePath}`,
762
758
  `permalink: ${result.permalink}`,
763
759
  `title: ${result.title}`,
764
760
  `link_health: ${result.linkHealth.resolved}/${result.linkHealth.total} resolved`,
765
761
  `backlinks: ${result.backlinkCount}`,
766
- `orphan_warning: ${result.orphanWarning ? "yes" : "no"}`,
767
762
  ];
768
- lines.splice(2, 0, ...[
769
- `storage_backend: ${config.github ? "github" : "filesystem"}`,
770
- `storage_root: ${config.root}`,
771
- ...(config.github
772
- ? [`storage_repo: ${config.github.owner}/${config.github.repo}`, `storage_branch: ${config.github.branch}`]
773
- : []),
774
- ]);
775
- if (summary.nextRecommendedTarget) {
776
- insertBeforeLine(lines, "next_recommended_action:", `next_recommended_target: ${summary.nextRecommendedTarget}`);
777
- }
778
763
  appendConflictSummary(lines, summarizeNoConflict({ serverUpdated: result.serverUpdated }));
779
764
  appendResponsibilityWarning(lines, result.boundaryWarnings);
780
765
  appendStructureScore(lines, result.structureScore);
781
766
  appendMemoryContract(lines, result.memoryContract);
782
767
  appendBoundaryWarnings(lines, result.boundaryWarnings);
783
- appendTemplateHints(lines, {
784
- primary: "stock",
785
- alternatives: ["index"],
786
- reason: "通常ノートとして知識を残すときは stock template を基準にする",
787
- whenToSwitch: "再訪導線を固定したい入口ノートなら index template に切り替える",
788
- });
768
+ if (result.memoryContract.status === "fail") {
769
+ appendTemplateHints(lines, {
770
+ primary: "stock",
771
+ alternatives: ["index"],
772
+ reason: "通常ノートとして知識を残すときは stock template を基準にする",
773
+ whenToSwitch: "再訪導線を固定したい入口ノートなら index template に切り替える",
774
+ });
775
+ }
789
776
  appendUnresolvedWikiLinks(lines, result.unresolvedWikiLinks);
790
777
  appendUnresolvedLinkHints(lines, result.unresolvedLinkHints);
791
778
  appendDuplicateWarnings(lines, result.duplicateWarnings);
@@ -812,11 +799,6 @@ async function main() {
812
799
  });
813
800
  const lines = [
814
801
  "flow を stock に昇格しました。",
815
- `project: ${result.project}`,
816
- `scope_label: ${TOOL_SCOPE_LABELS.promote_to_stock}`,
817
- `primary_navigation_signal: ${summary.primaryNavigationSignal}`,
818
- `primary_quality_signal: ${summary.primaryQualitySignal}`,
819
- `next_recommended_action: ${summary.nextRecommendedAction}`,
820
802
  `source_flow: ${result.sourceFlow.title}`,
821
803
  `source_file: ${result.sourceFlow.relativePath}`,
822
804
  `source_permalink: ${result.sourceFlow.permalink}`,
@@ -825,16 +807,6 @@ async function main() {
825
807
  `stock_permalink: ${result.stock.permalink}`,
826
808
  `flow_state: ${result.flowState}`,
827
809
  ];
828
- lines.splice(2, 0, ...[
829
- `storage_backend: ${config.github ? "github" : "filesystem"}`,
830
- `storage_root: ${config.root}`,
831
- ...(config.github
832
- ? [`storage_repo: ${config.github.owner}/${config.github.repo}`, `storage_branch: ${config.github.branch}`]
833
- : []),
834
- ]);
835
- if (summary.nextRecommendedTarget) {
836
- insertBeforeLine(lines, "next_recommended_action:", `next_recommended_target: ${summary.nextRecommendedTarget}`);
837
- }
838
810
  appendTemplateHints(lines, {
839
811
  primary: "stock",
840
812
  alternatives: ["index"],
@@ -871,35 +843,19 @@ async function main() {
871
843
  });
872
844
  const lines = [
873
845
  "ノートを処理しました。",
874
- `project: ${result.project}`,
875
- `scope_label: ${TOOL_SCOPE_LABELS.append_note}`,
876
- `primary_navigation_signal: ${summary.primaryNavigationSignal}`,
877
- `primary_quality_signal: ${summary.primaryQualitySignal}`,
878
- `next_recommended_action: ${summary.nextRecommendedAction}`,
879
846
  `operation: ${result.operation}`,
880
847
  `file: ${result.relativePath}`,
881
848
  `permalink: ${result.permalink}`,
882
849
  `title: ${result.title}`,
883
850
  `link_health: ${result.linkHealth.resolved}/${result.linkHealth.total} resolved`,
884
851
  `backlinks: ${result.backlinkCount}`,
885
- `orphan_warning: ${result.orphanWarning ? "yes" : "no"}`,
886
852
  ];
887
- lines.splice(2, 0, ...[
888
- `storage_backend: ${config.github ? "github" : "filesystem"}`,
889
- `storage_root: ${config.root}`,
890
- ...(config.github
891
- ? [`storage_repo: ${config.github.owner}/${config.github.repo}`, `storage_branch: ${config.github.branch}`]
892
- : []),
893
- ]);
894
- if (summary.nextRecommendedTarget) {
895
- insertBeforeLine(lines, "next_recommended_action:", `next_recommended_target: ${summary.nextRecommendedTarget}`);
896
- }
897
853
  appendConflictSummary(lines, summarizeNoConflict({ serverUpdated: result.serverUpdated }));
898
854
  appendResponsibilityWarning(lines, result.boundaryWarnings);
899
855
  appendStructureScore(lines, result.structureScore);
900
856
  appendMemoryContract(lines, result.memoryContract);
901
857
  appendBoundaryWarnings(lines, result.boundaryWarnings);
902
- if (result.operation === "created") {
858
+ if (result.operation === "created" && result.memoryContract.status === "fail") {
903
859
  appendTemplateHints(lines, {
904
860
  primary: "stock",
905
861
  alternatives: ["index"],
@@ -932,11 +888,6 @@ async function main() {
932
888
  });
933
889
  const lines = [
934
890
  "ノートを削除しました。",
935
- `project: ${result.project}`,
936
- `scope_label: ${TOOL_SCOPE_LABELS.delete_note}`,
937
- `primary_navigation_signal: ${summary.primaryNavigationSignal}`,
938
- `primary_quality_signal: ${summary.primaryQualitySignal}`,
939
- `next_recommended_action: ${summary.nextRecommendedAction}`,
940
891
  `deleted: ${result.title} (${result.relativePath})`,
941
892
  `permalink: ${result.permalink}`,
942
893
  `backlinks_to_deleted: ${result.backlinksToDeleted}`,
@@ -945,16 +896,6 @@ async function main() {
945
896
  `project_link_health_after: ${result.projectLinkHealthAfter.resolved}/${result.projectLinkHealthAfter.total}`,
946
897
  `project_unresolved_delta: ${projectUnresolvedDelta}`,
947
898
  ];
948
- lines.splice(2, 0, ...[
949
- `storage_backend: ${config.github ? "github" : "filesystem"}`,
950
- `storage_root: ${config.root}`,
951
- ...(config.github
952
- ? [`storage_repo: ${config.github.owner}/${config.github.repo}`, `storage_branch: ${config.github.branch}`]
953
- : []),
954
- ]);
955
- if (summary.nextRecommendedTarget) {
956
- insertBeforeLine(lines, "next_recommended_action:", `next_recommended_target: ${summary.nextRecommendedTarget}`);
957
- }
958
899
  appendConflictSummary(lines, summarizeNoConflict({ serverUpdated: result.serverUpdated }));
959
900
  appendOperationImpact(lines, impact);
960
901
  appendStructureScore(lines, result.structureScoreBeforeDelete);
@@ -996,32 +937,16 @@ async function main() {
996
937
  });
997
938
  const lines = [
998
939
  "ノートをリネームしました。",
999
- `project: ${result.project}`,
1000
- `scope_label: ${TOOL_SCOPE_LABELS.rename_note}`,
1001
- `primary_navigation_signal: ${summary.primaryNavigationSignal}`,
1002
- `primary_quality_signal: ${summary.primaryQualitySignal}`,
1003
- `next_recommended_action: ${summary.nextRecommendedAction}`,
1004
940
  `old: ${result.oldTitle} (${result.oldRelativePath})`,
1005
941
  `new: ${result.newTitle} (${result.newRelativePath})`,
1006
942
  `links_updated: ${result.updatedLinks}`,
1007
943
  `files_updated: ${result.updatedFiles}`,
1008
944
  `renamed_note_link_health: ${result.renamedNoteLinkHealth.resolved}/${result.renamedNoteLinkHealth.total}`,
1009
945
  `backlinks: ${result.backlinkCount}`,
1010
- `orphan_warning: ${result.orphanWarning ? "yes" : "no"}`,
1011
946
  `project_link_health_before: ${result.projectLinkHealthBefore.resolved}/${result.projectLinkHealthBefore.total}`,
1012
947
  `project_link_health_after: ${result.projectLinkHealthAfter.resolved}/${result.projectLinkHealthAfter.total}`,
1013
948
  `project_unresolved_delta: ${projectUnresolvedDelta}`,
1014
949
  ];
1015
- lines.splice(2, 0, ...[
1016
- `storage_backend: ${config.github ? "github" : "filesystem"}`,
1017
- `storage_root: ${config.root}`,
1018
- ...(config.github
1019
- ? [`storage_repo: ${config.github.owner}/${config.github.repo}`, `storage_branch: ${config.github.branch}`]
1020
- : []),
1021
- ]);
1022
- if (summary.nextRecommendedTarget) {
1023
- insertBeforeLine(lines, "next_recommended_action:", `next_recommended_target: ${summary.nextRecommendedTarget}`);
1024
- }
1025
950
  appendConflictSummary(lines, summarizeNoConflict({ serverUpdated: result.serverUpdated }));
1026
951
  appendOperationImpact(lines, impact);
1027
952
  appendStructureScore(lines, result.structureScore);
@@ -354,7 +354,7 @@ export class GitHubStorage {
354
354
  }
355
355
  async pullLocal(context) {
356
356
  try {
357
- await this.execFileAsyncFn("git", ["pull", "--ff-only"], {
357
+ await this.execFileAsyncFn("git", ["pull", "--ff-only", "origin", this.branch], {
358
358
  cwd: this.rootPath,
359
359
  timeout: 30_000,
360
360
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tomingtoming/kioq",
3
- "version": "0.9.0",
3
+ "version": "0.9.2",
4
4
  "description": "Japanese-first local markdown MCP server",
5
5
  "type": "module",
6
6
  "bin": {