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.
- package/LICENSE +21 -0
- package/README.md +171 -0
- package/bin/echoctl.js +2 -0
- package/package.json +56 -0
- package/scripts/annotate.js +73 -0
- package/scripts/build-docs.js +805 -0
- package/scripts/cli/commands/capture.js +20 -0
- package/scripts/cli/commands/constants.js +70 -0
- package/scripts/cli/commands/doctor.js +10 -0
- package/scripts/cli/commands/helpers.js +27 -0
- package/scripts/cli/commands/hook.js +48 -0
- package/scripts/cli/commands/import_cmd.js +184 -0
- package/scripts/cli/commands/init.js +45 -0
- package/scripts/cli/commands/mcp.js +16 -0
- package/scripts/cli/commands/migrate.js +65 -0
- package/scripts/cli/commands/pipeline.js +26 -0
- package/scripts/cli/commands/project.js +35 -0
- package/scripts/cli/commands/refresh.js +14 -0
- package/scripts/cli/commands/search.js +28 -0
- package/scripts/cli/commands/serve.js +73 -0
- package/scripts/cli/commands/status.js +11 -0
- package/scripts/cli/commands/stop.js +136 -0
- package/scripts/cli/commands/tag.js +89 -0
- package/scripts/cli/echoctl.js +44 -0
- package/scripts/convert.js +55 -0
- package/scripts/import-sessions.js +213 -0
- package/scripts/index.js +92 -0
- package/scripts/lib/cli/names.js +33 -0
- package/scripts/lib/domain/anchor.js +78 -0
- package/scripts/lib/domain/echo-format.js +265 -0
- package/scripts/lib/domain/errors.js +8 -0
- package/scripts/lib/domain/validation.js +126 -0
- package/scripts/lib/hooks/capture.js +401 -0
- package/scripts/lib/hooks/status.js +78 -0
- package/scripts/lib/i18n/format.js +183 -0
- package/scripts/lib/i18n/messages/en.js +41 -0
- package/scripts/lib/i18n/messages/zh-CN.js +40 -0
- package/scripts/lib/import/manifest.js +87 -0
- package/scripts/lib/import/providers/claude-code.js +272 -0
- package/scripts/lib/import/scanner.js +128 -0
- package/scripts/lib/infra/config.js +36 -0
- package/scripts/lib/infra/echo-paths.js +44 -0
- package/scripts/lib/infra/markdown-store.js +161 -0
- package/scripts/lib/infra/query-log.js +27 -0
- package/scripts/lib/infra/read-stdin.js +11 -0
- package/scripts/lib/infra/workspace.js +93 -0
- package/scripts/lib/interfaces/mcp/server.js +151 -0
- package/scripts/lib/interfaces/mcp/tools.js +152 -0
- package/scripts/lib/mcp-server.js +3 -0
- package/scripts/lib/usecases/aggregate-all-projects.js +45 -0
- package/scripts/lib/usecases/convert-buffer.js +43 -0
- package/scripts/lib/usecases/discover-claude-imports.js +80 -0
- package/scripts/lib/usecases/import-claude-project.js +89 -0
- package/scripts/lib/usecases/init-workspace.js +52 -0
- package/scripts/lib/usecases/install-claude-hook.js +139 -0
- package/scripts/lib/usecases/legacy-candidates.js +134 -0
- package/scripts/lib/usecases/live-session-state.js +109 -0
- package/scripts/lib/usecases/migrate-legacy-buffer.js +209 -0
- package/scripts/lib/usecases/project-registry.js +170 -0
- package/scripts/lib/usecases/query-articles.js +380 -0
- package/scripts/lib/usecases/refresh-serve.js +77 -0
- package/scripts/lib/usecases/run-doctor.js +213 -0
- package/scripts/lib/usecases/run-pipeline.js +104 -0
- package/scripts/lib/usecases/snapshot-manifest.js +48 -0
- package/scripts/lib/usecases/status-collector.js +142 -0
- package/scripts/lib/usecases/strip-comments.js +7 -0
- package/scripts/lib/usecases/write-comment.js +122 -0
- package/scripts/resolve.js +65 -0
- package/scripts/search.js +98 -0
- package/scripts/serve.js +778 -0
- 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 };
|