echoctl 0.1.0

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 (71) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +171 -0
  3. package/bin/echoctl.js +2 -0
  4. package/package.json +56 -0
  5. package/scripts/annotate.js +73 -0
  6. package/scripts/build-docs.js +805 -0
  7. package/scripts/cli/commands/capture.js +20 -0
  8. package/scripts/cli/commands/constants.js +70 -0
  9. package/scripts/cli/commands/doctor.js +10 -0
  10. package/scripts/cli/commands/helpers.js +27 -0
  11. package/scripts/cli/commands/hook.js +48 -0
  12. package/scripts/cli/commands/import_cmd.js +184 -0
  13. package/scripts/cli/commands/init.js +45 -0
  14. package/scripts/cli/commands/mcp.js +16 -0
  15. package/scripts/cli/commands/migrate.js +65 -0
  16. package/scripts/cli/commands/pipeline.js +26 -0
  17. package/scripts/cli/commands/project.js +35 -0
  18. package/scripts/cli/commands/refresh.js +14 -0
  19. package/scripts/cli/commands/search.js +28 -0
  20. package/scripts/cli/commands/serve.js +73 -0
  21. package/scripts/cli/commands/status.js +11 -0
  22. package/scripts/cli/commands/stop.js +136 -0
  23. package/scripts/cli/commands/tag.js +89 -0
  24. package/scripts/cli/echoctl.js +44 -0
  25. package/scripts/convert.js +55 -0
  26. package/scripts/import-sessions.js +213 -0
  27. package/scripts/index.js +92 -0
  28. package/scripts/lib/cli/names.js +33 -0
  29. package/scripts/lib/domain/anchor.js +78 -0
  30. package/scripts/lib/domain/echo-format.js +265 -0
  31. package/scripts/lib/domain/errors.js +8 -0
  32. package/scripts/lib/domain/validation.js +126 -0
  33. package/scripts/lib/hooks/capture.js +401 -0
  34. package/scripts/lib/hooks/status.js +78 -0
  35. package/scripts/lib/i18n/format.js +183 -0
  36. package/scripts/lib/i18n/messages/en.js +41 -0
  37. package/scripts/lib/i18n/messages/zh-CN.js +40 -0
  38. package/scripts/lib/import/manifest.js +87 -0
  39. package/scripts/lib/import/providers/claude-code.js +272 -0
  40. package/scripts/lib/import/scanner.js +128 -0
  41. package/scripts/lib/infra/config.js +36 -0
  42. package/scripts/lib/infra/echo-paths.js +44 -0
  43. package/scripts/lib/infra/markdown-store.js +161 -0
  44. package/scripts/lib/infra/query-log.js +27 -0
  45. package/scripts/lib/infra/read-stdin.js +11 -0
  46. package/scripts/lib/infra/workspace.js +93 -0
  47. package/scripts/lib/interfaces/mcp/server.js +151 -0
  48. package/scripts/lib/interfaces/mcp/tools.js +152 -0
  49. package/scripts/lib/mcp-server.js +3 -0
  50. package/scripts/lib/usecases/aggregate-all-projects.js +45 -0
  51. package/scripts/lib/usecases/convert-buffer.js +43 -0
  52. package/scripts/lib/usecases/discover-claude-imports.js +80 -0
  53. package/scripts/lib/usecases/import-claude-project.js +89 -0
  54. package/scripts/lib/usecases/init-workspace.js +52 -0
  55. package/scripts/lib/usecases/install-claude-hook.js +139 -0
  56. package/scripts/lib/usecases/legacy-candidates.js +134 -0
  57. package/scripts/lib/usecases/live-session-state.js +109 -0
  58. package/scripts/lib/usecases/migrate-legacy-buffer.js +209 -0
  59. package/scripts/lib/usecases/project-registry.js +170 -0
  60. package/scripts/lib/usecases/query-articles.js +380 -0
  61. package/scripts/lib/usecases/refresh-serve.js +77 -0
  62. package/scripts/lib/usecases/run-doctor.js +213 -0
  63. package/scripts/lib/usecases/run-pipeline.js +104 -0
  64. package/scripts/lib/usecases/snapshot-manifest.js +48 -0
  65. package/scripts/lib/usecases/status-collector.js +142 -0
  66. package/scripts/lib/usecases/strip-comments.js +7 -0
  67. package/scripts/lib/usecases/write-comment.js +122 -0
  68. package/scripts/resolve.js +65 -0
  69. package/scripts/search.js +98 -0
  70. package/scripts/serve.js +778 -0
  71. package/scripts/validate.js +79 -0
@@ -0,0 +1,79 @@
1
+ #!/usr/bin/env node
2
+ const { ensureDir } = require("./lib/infra/workspace");
3
+ const { resolveDataDirs } = require("./lib/infra/echo-paths");
4
+ const store = require("./lib/infra/markdown-store");
5
+ const v = require("./lib/domain/validation");
6
+
7
+ function runValidate(opts = {}) {
8
+ const dirs = opts.dirs || resolveDataDirs();
9
+ const { articlesDir, commentsDir } = dirs;
10
+
11
+ ensureDir(articlesDir);
12
+ ensureDir(commentsDir);
13
+ const errors = [];
14
+
15
+ const loadedArticles = store.loadArticles(articlesDir, { strict: true });
16
+ const loadedComments = store.loadComments(commentsDir);
17
+
18
+ const articles = {};
19
+ const comments = {};
20
+ const records = [];
21
+ const fileMap = {};
22
+
23
+ for (const a of loadedArticles) {
24
+ const rel = `articles/${a.relPath}`;
25
+ if (fileMap[a.id]) {
26
+ errors.push(`${rel}: duplicate id "${a.id}" (also at ${fileMap[a.id]})`);
27
+ } else {
28
+ fileMap[a.id] = rel;
29
+ articles[a.id] = { file: rel, data: a.data };
30
+ }
31
+ records.push({ id: a.id, data: a.data, file: rel });
32
+ errors.push(...v.validateArticle({ id: a.id, data: a.data, file: rel }));
33
+ }
34
+
35
+ for (const c of loadedComments) {
36
+ const rel = c._file;
37
+ fileMap[c.id] = rel;
38
+ records.push({ id: c.id, data: c, file: rel });
39
+ comments[c.id] = { file: rel, data: c };
40
+ errors.push(...v.validateAnnotation({ id: c.id, data: c, file: rel }));
41
+ }
42
+
43
+ errors.push(...v.checkDuplicateIds(records));
44
+
45
+ const ofMap = {};
46
+ for (const [id, c] of Object.entries(comments)) {
47
+ ofMap[id] = c.data.evolution?.of || [];
48
+ }
49
+
50
+ const commentData = {};
51
+ for (const [id, c] of Object.entries(comments)) {
52
+ commentData[id] = c.data;
53
+ }
54
+
55
+ errors.push(...v.checkEvolutionReferences(commentData, commentData, fileMap));
56
+ errors.push(...v.checkArticleReferences(commentData, new Set(Object.keys(articles)), fileMap));
57
+ errors.push(...v.checkAllCycles(Object.keys(comments), ofMap, fileMap));
58
+
59
+ return {
60
+ success: errors.length === 0,
61
+ errors,
62
+ articleCount: Object.keys(articles).length,
63
+ commentCount: Object.keys(comments).length,
64
+ };
65
+ }
66
+
67
+ if (require.main === module) {
68
+ const result = runValidate();
69
+ if (result.success) {
70
+ console.log(`OK — ${result.articleCount} articles, ${result.commentCount} comments`);
71
+ process.exit(0);
72
+ } else {
73
+ console.log(`FAIL — ${result.errors.length} error(s):\n`);
74
+ for (const e of result.errors) console.log(` ${e}`);
75
+ process.exit(1);
76
+ }
77
+ }
78
+
79
+ module.exports = { runValidate };