sdtk-wiki-kit 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/README.md +262 -0
- package/assets/atlas/build_atlas.py +1110 -0
- package/assets/atlas/doc_atlas_viewer_template.html +3796 -0
- package/assets/atlas/vendor/mermaid.min.js +2029 -0
- package/assets/keys/sdtk-entitlement-public.pem +11 -0
- package/bin/sdtk-wiki.js +14 -0
- package/package.json +45 -0
- package/src/commands/ask.js +139 -0
- package/src/commands/atlas.js +339 -0
- package/src/commands/deferred.js +14 -0
- package/src/commands/help.js +67 -0
- package/src/commands/init.js +91 -0
- package/src/commands/lint.js +48 -0
- package/src/commands/wiki.js +251 -0
- package/src/index.js +65 -0
- package/src/lib/args.js +68 -0
- package/src/lib/browser-open.js +32 -0
- package/src/lib/errors.js +29 -0
- package/src/lib/wiki-ask.js +175 -0
- package/src/lib/wiki-compile.js +287 -0
- package/src/lib/wiki-config.js +180 -0
- package/src/lib/wiki-discover.js +271 -0
- package/src/lib/wiki-flags.js +89 -0
- package/src/lib/wiki-ingest.js +198 -0
- package/src/lib/wiki-lint.js +468 -0
- package/src/lib/wiki-paths.js +169 -0
- package/src/lib/wiki-premium-loader.js +364 -0
- package/src/lib/wiki-prune.js +334 -0
- package/src/lib/wiki-query-history.js +111 -0
- package/src/lib/wiki-runner.js +373 -0
- package/src/lib/wiki-workspace.js +144 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
-----BEGIN PUBLIC KEY-----
|
|
2
|
+
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0Z3VS5JJcds3xfn/bB9l
|
|
3
|
+
TjVvTvZ1r8r8kAjQAj0r7O4JkX4KzK4S2E8jZK3vZ7Jz7m8Lq5Zx3V9B9R1K1X2C
|
|
4
|
+
3D4E5F6G7H8I9J0K1L2M3N4O5P6Q7R8S9T0U1V2W3X4Y5Z6A7B8C9D0E1F2G3H4I5
|
|
5
|
+
J6K7L8M9N0O1P2Q3R4S5T6U7V8W9X0Y1Z2A3B4C5D6E7F8G9H0I1J2K3L4M5N6O7P8
|
|
6
|
+
Q9R0S1T2U3V4W5X6Y7Z8A9B0C1D2E3F4G5H6I7J8K9L0M1N2O3P4Q5R6S7T8U9V0W1
|
|
7
|
+
X2Y3Z4A5B6C7D8E9F0G1H2I3J4K5L6M7N8O9P0Q1R2S3T4U5V6W7X8Y9Z0A1B2C3D4
|
|
8
|
+
E5F6G7H8I9J0K1L2M3N4O5P6Q7R8S9T0U1V2W3X4Y5Z6A7B8C9D0E1F2G3H4I5J6K7
|
|
9
|
+
L8M9N0O1P2Q3R4S5T6U7V8W9X0Y1Z2A3B4C5D6E7F8G9H0I1J2K3L4M5N6O7P8Q9
|
|
10
|
+
AQIDAQAB
|
|
11
|
+
-----END PUBLIC KEY-----
|
package/bin/sdtk-wiki.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
5
|
+
const { run } = require("../src/index");
|
|
6
|
+
|
|
7
|
+
run(process.argv.slice(2))
|
|
8
|
+
.then((exitCode) => {
|
|
9
|
+
process.exitCode = Number.isInteger(exitCode) ? exitCode : 0;
|
|
10
|
+
})
|
|
11
|
+
.catch((error) => {
|
|
12
|
+
console.error(`sdtk-wiki: ${error.message}`);
|
|
13
|
+
process.exitCode = typeof error.exitCode === "number" ? error.exitCode : 4;
|
|
14
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "sdtk-wiki-kit",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Project-local wiki and knowledge graph toolkit for SDTK workspaces.",
|
|
5
|
+
"bin": {
|
|
6
|
+
"sdtk-wiki": "bin/sdtk-wiki.js"
|
|
7
|
+
},
|
|
8
|
+
"main": "src/index.js",
|
|
9
|
+
"type": "commonjs",
|
|
10
|
+
"files": [
|
|
11
|
+
"bin/",
|
|
12
|
+
"src/",
|
|
13
|
+
"assets/keys/sdtk-entitlement-public.pem",
|
|
14
|
+
"assets/atlas/build_atlas.py",
|
|
15
|
+
"assets/atlas/doc_atlas_viewer_template.html",
|
|
16
|
+
"assets/atlas/vendor/mermaid.min.js"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"test": "powershell -ExecutionPolicy Bypass -Command \"$ErrorActionPreference = 'Stop'; Set-Location '..\\..\\..\\..'; python -m unittest tests.test_sdtk_wiki_cli\"",
|
|
20
|
+
"pack:smoke": "npm pack --dry-run"
|
|
21
|
+
},
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=18.13.0"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"sdtk-wiki",
|
|
27
|
+
"wiki",
|
|
28
|
+
"knowledge-graph",
|
|
29
|
+
"cli",
|
|
30
|
+
"toolkit"
|
|
31
|
+
],
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "git+https://github.com/codexsdtk/sdtk-toolkit.git",
|
|
36
|
+
"directory": "products/sdtk-wiki/distribution/sdtk-wiki-kit"
|
|
37
|
+
},
|
|
38
|
+
"homepage": "https://github.com/codexsdtk/sdtk-toolkit/tree/main/products/sdtk-wiki/distribution/sdtk-wiki-kit",
|
|
39
|
+
"bugs": {
|
|
40
|
+
"url": "https://github.com/codexsdtk/sdtk-toolkit/issues"
|
|
41
|
+
},
|
|
42
|
+
"publishConfig": {
|
|
43
|
+
"access": "public"
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const { parseFlags } = require("../lib/args");
|
|
4
|
+
const { runWikiAsk } = require("../lib/wiki-ask");
|
|
5
|
+
const { saveQueryHistoryRecord } = require("../lib/wiki-query-history");
|
|
6
|
+
|
|
7
|
+
const ASK_FLAG_DEFS = {
|
|
8
|
+
help: { type: "boolean", alias: "h" },
|
|
9
|
+
question: { type: "string", alias: "q" },
|
|
10
|
+
"project-path": { type: "string" },
|
|
11
|
+
json: { type: "boolean" },
|
|
12
|
+
source: { type: "string" },
|
|
13
|
+
"max-sources": { type: "string" },
|
|
14
|
+
"save-query": { type: "boolean" },
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
function parseAskFlags(args) {
|
|
18
|
+
const sources = [];
|
|
19
|
+
const filteredArgs = [];
|
|
20
|
+
let i = 0;
|
|
21
|
+
|
|
22
|
+
while (i < args.length) {
|
|
23
|
+
const arg = args[i];
|
|
24
|
+
if (arg === "--source") {
|
|
25
|
+
i++;
|
|
26
|
+
if (i < args.length) {
|
|
27
|
+
sources.push(args[i]);
|
|
28
|
+
i++;
|
|
29
|
+
}
|
|
30
|
+
} else if (arg.startsWith("--source=")) {
|
|
31
|
+
sources.push(arg.slice("--source=".length));
|
|
32
|
+
i++;
|
|
33
|
+
} else {
|
|
34
|
+
filteredArgs.push(arg);
|
|
35
|
+
i++;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const { flags, positional } = parseFlags(filteredArgs, ASK_FLAG_DEFS);
|
|
40
|
+
flags.source = sources.length > 0 ? sources : flags.source ? [flags.source] : [];
|
|
41
|
+
return { flags, positional };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function printAskHelp() {
|
|
45
|
+
console.log(`SDTK-WIKI Ask
|
|
46
|
+
|
|
47
|
+
Usage:
|
|
48
|
+
sdtk-wiki ask --question "<text>" [--project-path <path>] [--json] [--save-query]
|
|
49
|
+
sdtk-wiki ask --question "<text>" [--source <id-or-path>] [--max-sources <n>]
|
|
50
|
+
|
|
51
|
+
Capability:
|
|
52
|
+
wiki.ask Canonical SDTK-WIKI Ask capability.
|
|
53
|
+
|
|
54
|
+
Inputs:
|
|
55
|
+
.sdtk/wiki/graph Required built wiki graph. Run "sdtk-wiki atlas build" first.
|
|
56
|
+
|
|
57
|
+
Behavior:
|
|
58
|
+
Executes a local premium wiki.ask runtime pack when entitlement and graph preconditions pass.
|
|
59
|
+
Fails closed when the graph, entitlement, or runtime pack is missing.
|
|
60
|
+
Query history is off by default.
|
|
61
|
+
--save-query writes one redacted JSON record under .sdtk/wiki/queries after a successful answer.
|
|
62
|
+
Full question and full answer are not stored by default.`);
|
|
63
|
+
return 0;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function formatHumanResult(result, queryHistory) {
|
|
67
|
+
const lines = [
|
|
68
|
+
"Answer:",
|
|
69
|
+
result.answer || "(No answer returned by SDTK-WIKI Ask runtime.)",
|
|
70
|
+
"",
|
|
71
|
+
"Citations:",
|
|
72
|
+
];
|
|
73
|
+
|
|
74
|
+
if (result.citations.length) {
|
|
75
|
+
for (const citation of result.citations) {
|
|
76
|
+
lines.push(`- ${citation}`);
|
|
77
|
+
}
|
|
78
|
+
} else {
|
|
79
|
+
lines.push("- none");
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (result.confidence) {
|
|
83
|
+
lines.push("", `Confidence: ${result.confidence}`);
|
|
84
|
+
}
|
|
85
|
+
lines.push("", "Capability: wiki.ask");
|
|
86
|
+
if (queryHistory && queryHistory.saved) {
|
|
87
|
+
lines.push("", `Query record: ${queryHistory.recordPath}`);
|
|
88
|
+
}
|
|
89
|
+
return lines.join("\n");
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async function cmdAsk(args) {
|
|
93
|
+
const { flags, positional } = parseAskFlags(args || []);
|
|
94
|
+
if (flags.help) {
|
|
95
|
+
return printAskHelp();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const question = flags.question || positional.join(" ");
|
|
99
|
+
const maxSources =
|
|
100
|
+
flags["max-sources"] !== undefined ? Number.parseInt(flags["max-sources"], 10) : undefined;
|
|
101
|
+
|
|
102
|
+
const result = await runWikiAsk({
|
|
103
|
+
question,
|
|
104
|
+
projectPath: flags["project-path"],
|
|
105
|
+
sources: flags.source,
|
|
106
|
+
maxSources,
|
|
107
|
+
});
|
|
108
|
+
const queryHistory = { saved: false };
|
|
109
|
+
|
|
110
|
+
if (flags["save-query"]) {
|
|
111
|
+
try {
|
|
112
|
+
const saved = saveQueryHistoryRecord({
|
|
113
|
+
projectPath: flags["project-path"],
|
|
114
|
+
question,
|
|
115
|
+
result,
|
|
116
|
+
});
|
|
117
|
+
queryHistory.saved = true;
|
|
118
|
+
queryHistory.recordPath = saved.recordPath;
|
|
119
|
+
} catch (err) {
|
|
120
|
+
queryHistory.warning = `Query history was not saved: ${err.message}`;
|
|
121
|
+
console.error(`sdtk-wiki warning: ${queryHistory.warning}`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (flags.json) {
|
|
126
|
+
const payload = flags["save-query"] ? { ...result, queryHistory } : result;
|
|
127
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
128
|
+
} else {
|
|
129
|
+
console.log(formatHumanResult(result, queryHistory));
|
|
130
|
+
}
|
|
131
|
+
return 0;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
module.exports = {
|
|
135
|
+
cmdAsk,
|
|
136
|
+
formatHumanResult,
|
|
137
|
+
parseAskFlags,
|
|
138
|
+
printAskHelp,
|
|
139
|
+
};
|
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
const { ValidationError } = require("../lib/errors");
|
|
5
|
+
const {
|
|
6
|
+
isWikiBuilt,
|
|
7
|
+
isWikiInitialized,
|
|
8
|
+
readBuildMeta,
|
|
9
|
+
readGraphMeta,
|
|
10
|
+
resolveWikiConfig,
|
|
11
|
+
writeWikiConfig,
|
|
12
|
+
} = require("../lib/wiki-config");
|
|
13
|
+
const { ensureWorkspace, getWorkspaceStatus } = require("../lib/wiki-workspace");
|
|
14
|
+
const { openViewer, runBuild } = require("../lib/wiki-runner");
|
|
15
|
+
const {
|
|
16
|
+
BASE_FLAG_DEFS,
|
|
17
|
+
OPEN_FLAG_DEFS,
|
|
18
|
+
WATCH_FLAG_DEFS,
|
|
19
|
+
parseWikiFlags,
|
|
20
|
+
} = require("../lib/wiki-flags");
|
|
21
|
+
|
|
22
|
+
const ATLAS_COMMANDS = new Set(["build", "open", "watch", "status"]);
|
|
23
|
+
|
|
24
|
+
function hasHelp(args) {
|
|
25
|
+
return args.includes("-h") || args.includes("--help");
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function cmdAtlasOverviewHelp() {
|
|
29
|
+
console.log(`Usage:
|
|
30
|
+
sdtk-wiki atlas <command> --help
|
|
31
|
+
|
|
32
|
+
Commands:
|
|
33
|
+
build SDTK-WIKI graph build via the atlas compatibility namespace.
|
|
34
|
+
open SDTK-WIKI viewer open via the atlas compatibility namespace.
|
|
35
|
+
watch SDTK-WIKI watcher via the atlas compatibility namespace.
|
|
36
|
+
status SDTK-WIKI graph status via the atlas compatibility namespace.
|
|
37
|
+
|
|
38
|
+
Compatibility:
|
|
39
|
+
"atlas" remains the R1 compatibility namespace for existing workflows.
|
|
40
|
+
sdtk-wiki defaults to .sdtk/wiki/graph.
|
|
41
|
+
Legacy .sdtk/atlas remains readable and is never auto-deleted.`);
|
|
42
|
+
return 0;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function cmdAtlasSubcommandHelp(subcommand) {
|
|
46
|
+
const descriptions = {
|
|
47
|
+
build: "Build the SDTK-WIKI graph from project-local sources.",
|
|
48
|
+
open: "Open the SDTK-WIKI graph viewer.",
|
|
49
|
+
watch: "Watch project-local sources and refresh the graph.",
|
|
50
|
+
status: "Report SDTK-WIKI graph workspace status.",
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
console.log(`Usage:
|
|
54
|
+
sdtk-wiki atlas ${subcommand} --help
|
|
55
|
+
|
|
56
|
+
Purpose:
|
|
57
|
+
${descriptions[subcommand]}
|
|
58
|
+
|
|
59
|
+
BK-103 behavior:
|
|
60
|
+
Help exits 0.
|
|
61
|
+
Runtime execution is implemented for local deterministic graph/viewer commands.
|
|
62
|
+
Free graph/viewer commands do not require activation.
|
|
63
|
+
|
|
64
|
+
Workspace:
|
|
65
|
+
New target: .sdtk/wiki
|
|
66
|
+
Graph target: .sdtk/wiki/graph
|
|
67
|
+
Legacy readable path: .sdtk/atlas`);
|
|
68
|
+
return 0;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async function cmdAtlasBuild(args) {
|
|
72
|
+
const { flags } = parseWikiFlags(args, BASE_FLAG_DEFS);
|
|
73
|
+
const config = resolveWikiConfig(flags);
|
|
74
|
+
ensureWorkspace(config.projectPath, config.outputDir);
|
|
75
|
+
|
|
76
|
+
if (!isWikiInitialized(config.outputDir)) {
|
|
77
|
+
console.log("[wiki] SDTK-WIKI not initialized. Run: sdtk-wiki init");
|
|
78
|
+
console.log(`[wiki] Output dir: ${config.outputDir}`);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const startMs = Date.now();
|
|
82
|
+
const buildResult = await runBuild(config);
|
|
83
|
+
const durationMs = Date.now() - startMs;
|
|
84
|
+
|
|
85
|
+
console.log("");
|
|
86
|
+
console.log("[wiki] Build summary:");
|
|
87
|
+
console.log(` Documents: ${buildResult.docCount}`);
|
|
88
|
+
console.log(` Graph nodes: ${buildResult.nodeCount}`);
|
|
89
|
+
console.log(` Graph edges: ${buildResult.edgeCount}`);
|
|
90
|
+
console.log(` Wiki pages: ${buildResult.pageCount}`);
|
|
91
|
+
console.log(` Output dir: ${config.outputDir}`);
|
|
92
|
+
if (buildResult.provenancePath) {
|
|
93
|
+
console.log(` Provenance: ${buildResult.provenancePath}`);
|
|
94
|
+
}
|
|
95
|
+
console.log(` Duration: ${(durationMs / 1000).toFixed(1)}s`);
|
|
96
|
+
if (buildResult.generated) {
|
|
97
|
+
console.log(` Generated: ${buildResult.generated}`);
|
|
98
|
+
}
|
|
99
|
+
return 0;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function resolveReadableViewerConfig(config) {
|
|
103
|
+
if (isWikiBuilt(config.outputDir)) {
|
|
104
|
+
return { config, source: "wiki" };
|
|
105
|
+
}
|
|
106
|
+
if (isWikiBuilt(config.legacyAtlasDir)) {
|
|
107
|
+
return {
|
|
108
|
+
config: {
|
|
109
|
+
...config,
|
|
110
|
+
outputDir: config.legacyAtlasDir,
|
|
111
|
+
},
|
|
112
|
+
source: "legacy-atlas",
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
return { config, source: "missing" };
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
async function cmdAtlasOpen(args) {
|
|
119
|
+
const { flags } = parseWikiFlags(args, OPEN_FLAG_DEFS);
|
|
120
|
+
const config = resolveWikiConfig(flags);
|
|
121
|
+
const resolved = resolveReadableViewerConfig(config);
|
|
122
|
+
|
|
123
|
+
if (resolved.source === "missing") {
|
|
124
|
+
console.error("[wiki] No SDTK-WIKI graph build found.");
|
|
125
|
+
console.error(` Expected: ${config.outputDir}/viewer.html`);
|
|
126
|
+
console.error(` Legacy readable fallback: ${config.legacyAtlasDir}/viewer.html`);
|
|
127
|
+
console.error(" Run: sdtk-wiki init");
|
|
128
|
+
console.error(" Or: sdtk-wiki atlas build");
|
|
129
|
+
return 1;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (resolved.source === "legacy-atlas") {
|
|
133
|
+
console.log(`[wiki] Using legacy Atlas output read-only: ${resolved.config.outputDir}`);
|
|
134
|
+
console.log("[wiki] No files will be migrated or deleted.");
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const noOpen = !!flags["no-open"];
|
|
138
|
+
const { server } = await openViewer(resolved.config, noOpen);
|
|
139
|
+
|
|
140
|
+
if (noOpen) {
|
|
141
|
+
if (server) server.close();
|
|
142
|
+
return 0;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
console.log("[wiki] Press Ctrl+C to stop the viewer server.");
|
|
146
|
+
await new Promise(() => {});
|
|
147
|
+
return 0;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
async function cmdAtlasWatch(args) {
|
|
151
|
+
const { flags } = parseWikiFlags(args, WATCH_FLAG_DEFS);
|
|
152
|
+
const config = resolveWikiConfig(flags);
|
|
153
|
+
|
|
154
|
+
if (!isWikiInitialized(config.outputDir)) {
|
|
155
|
+
console.log("[wiki] SDTK-WIKI not initialized. Running init first...");
|
|
156
|
+
writeWikiConfig(config);
|
|
157
|
+
console.log(`[wiki] Initialized SDTK-WIKI config: ${config.configPath}`);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const DEBOUNCE_MS = 800;
|
|
161
|
+
let debounceTimer = null;
|
|
162
|
+
let rebuilding = false;
|
|
163
|
+
|
|
164
|
+
async function rebuild(reason) {
|
|
165
|
+
if (rebuilding) return;
|
|
166
|
+
rebuilding = true;
|
|
167
|
+
console.log(`\n[wiki] Change detected (${reason}). Rebuilding...`);
|
|
168
|
+
try {
|
|
169
|
+
const buildResult = await runBuild(config);
|
|
170
|
+
console.log(`[wiki] Rebuild complete: ${buildResult.docCount} docs, ${buildResult.nodeCount} nodes, ${buildResult.pageCount} pages.`);
|
|
171
|
+
} catch (err) {
|
|
172
|
+
console.error(`[wiki] Rebuild failed: ${err.message}`);
|
|
173
|
+
} finally {
|
|
174
|
+
rebuilding = false;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
console.log("[wiki] Running initial build...");
|
|
179
|
+
try {
|
|
180
|
+
const buildResult = await runBuild(config);
|
|
181
|
+
console.log(`[wiki] Initial build complete: ${buildResult.docCount} docs, ${buildResult.pageCount} pages.`);
|
|
182
|
+
} catch (err) {
|
|
183
|
+
console.error(`[wiki] Initial build failed: ${err.message}`);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
let viewerServer = null;
|
|
187
|
+
if (!flags["no-open"] && isWikiBuilt(config.outputDir)) {
|
|
188
|
+
const result = await openViewer(config, false);
|
|
189
|
+
viewerServer = result.server;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const watchers = [];
|
|
193
|
+
for (const scanRoot of config.scanRoots) {
|
|
194
|
+
if (!fs.existsSync(scanRoot)) {
|
|
195
|
+
console.log(`[wiki] Warning: scan root does not exist, skipping watch: ${scanRoot}`);
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
try {
|
|
200
|
+
const watcher = fs.watch(scanRoot, { recursive: true }, (eventType, filename) => {
|
|
201
|
+
if (!filename || !filename.endsWith(".md")) return;
|
|
202
|
+
if (debounceTimer) clearTimeout(debounceTimer);
|
|
203
|
+
debounceTimer = setTimeout(() => {
|
|
204
|
+
rebuild(`${eventType}: ${filename}`);
|
|
205
|
+
}, DEBOUNCE_MS);
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
watcher.on("error", (err) => {
|
|
209
|
+
console.error(`[wiki] Watch error on ${scanRoot}: ${err.message}`);
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
watchers.push(watcher);
|
|
213
|
+
console.log(`[wiki] Watching: ${scanRoot}`);
|
|
214
|
+
} catch (err) {
|
|
215
|
+
console.error(`[wiki] Could not watch ${scanRoot}: ${err.message}`);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (watchers.length === 0) {
|
|
220
|
+
console.error("[wiki] No scan roots could be watched. Exiting.");
|
|
221
|
+
return 1;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
console.log("[wiki] Watching for markdown changes. Press Ctrl+C to stop.");
|
|
225
|
+
|
|
226
|
+
function shutdown() {
|
|
227
|
+
console.log("\n[wiki] Stopping watch...");
|
|
228
|
+
if (debounceTimer) clearTimeout(debounceTimer);
|
|
229
|
+
for (const w of watchers) {
|
|
230
|
+
try { w.close(); } catch (_) {}
|
|
231
|
+
}
|
|
232
|
+
if (viewerServer) {
|
|
233
|
+
try { viewerServer.close(); } catch (_) {}
|
|
234
|
+
}
|
|
235
|
+
process.exit(0);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
process.on("SIGINT", shutdown);
|
|
239
|
+
process.on("SIGTERM", shutdown);
|
|
240
|
+
|
|
241
|
+
await new Promise(() => {});
|
|
242
|
+
return 0;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
async function cmdAtlasStatus(args) {
|
|
246
|
+
const { flags } = parseWikiFlags(args, BASE_FLAG_DEFS);
|
|
247
|
+
let config;
|
|
248
|
+
try {
|
|
249
|
+
config = resolveWikiConfig(flags);
|
|
250
|
+
} catch (err) {
|
|
251
|
+
console.error(`[wiki] Config error: ${err.message}`);
|
|
252
|
+
return 1;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const initialized = isWikiInitialized(config.outputDir);
|
|
256
|
+
const built = isWikiBuilt(config.outputDir);
|
|
257
|
+
const legacyBuilt = isWikiBuilt(config.legacyAtlasDir);
|
|
258
|
+
const workspaceStatus = getWorkspaceStatus(config.projectPath);
|
|
259
|
+
|
|
260
|
+
console.log("[wiki] Status");
|
|
261
|
+
console.log("=".repeat(40));
|
|
262
|
+
console.log(` Initialized: ${initialized ? "yes" : "no"}`);
|
|
263
|
+
console.log(` Built: ${built ? "yes" : "no"}`);
|
|
264
|
+
console.log(` Manifest: ${workspaceStatus.manifestExists ? "yes" : "no"}`);
|
|
265
|
+
console.log(` Schema version: ${workspaceStatus.schemaVersion || "n/a"}`);
|
|
266
|
+
console.log(` Legacy readable: ${legacyBuilt ? "yes" : "no"}`);
|
|
267
|
+
console.log(` Project root: ${config.projectPath}`);
|
|
268
|
+
console.log(` Workspace root: ${workspaceStatus.workspace.workspaceRoot}`);
|
|
269
|
+
console.log(` Output dir: ${config.outputDir}`);
|
|
270
|
+
console.log(` Legacy Atlas dir: ${config.legacyAtlasDir}`);
|
|
271
|
+
console.log(` Scan roots: ${config.scanRoots.join(", ")}`);
|
|
272
|
+
console.log(` Viewer host: ${config.host}:${config.port}`);
|
|
273
|
+
|
|
274
|
+
if (built) {
|
|
275
|
+
const meta = readBuildMeta(config.outputDir);
|
|
276
|
+
const graphMeta = readGraphMeta(config.outputDir);
|
|
277
|
+
if (meta) {
|
|
278
|
+
console.log(` Last build: ${meta.generated || "unknown"}`);
|
|
279
|
+
console.log(` Documents: ${meta.count}`);
|
|
280
|
+
}
|
|
281
|
+
if (graphMeta) {
|
|
282
|
+
console.log(` Graph nodes: ${graphMeta.nodeCount}`);
|
|
283
|
+
console.log(` Graph edges: ${graphMeta.edgeCount}`);
|
|
284
|
+
}
|
|
285
|
+
} else if (legacyBuilt) {
|
|
286
|
+
console.log("");
|
|
287
|
+
console.log("[wiki] Legacy .sdtk/atlas build is readable for open/status fallback.");
|
|
288
|
+
console.log("[wiki] It will not be auto-migrated or deleted.");
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
if (!initialized) {
|
|
292
|
+
console.log("");
|
|
293
|
+
console.log("[wiki] Hint: run 'sdtk-wiki init' to initialize SDTK-WIKI for this project.");
|
|
294
|
+
} else if (!built) {
|
|
295
|
+
console.log("");
|
|
296
|
+
console.log("[wiki] Hint: run 'sdtk-wiki atlas build' to build the local document graph.");
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
return 0;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
async function cmdAtlas(args) {
|
|
303
|
+
if (!args || args.length === 0) {
|
|
304
|
+
return cmdAtlasOverviewHelp();
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
const [subcommand, ...rest] = args;
|
|
308
|
+
if (subcommand === "-h" || subcommand === "--help") {
|
|
309
|
+
return cmdAtlasOverviewHelp();
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
if (!ATLAS_COMMANDS.has(subcommand)) {
|
|
313
|
+
throw new ValidationError(
|
|
314
|
+
`Unknown atlas command: "${subcommand}". Run "sdtk-wiki atlas --help".`
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
if (hasHelp(rest)) {
|
|
319
|
+
return cmdAtlasSubcommandHelp(subcommand);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
switch (subcommand) {
|
|
323
|
+
case "build":
|
|
324
|
+
return cmdAtlasBuild(rest);
|
|
325
|
+
case "open":
|
|
326
|
+
return cmdAtlasOpen(rest);
|
|
327
|
+
case "watch":
|
|
328
|
+
return cmdAtlasWatch(rest);
|
|
329
|
+
case "status":
|
|
330
|
+
return cmdAtlasStatus(rest);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
module.exports = {
|
|
335
|
+
ATLAS_COMMANDS,
|
|
336
|
+
cmdAtlas,
|
|
337
|
+
cmdAtlasOverviewHelp,
|
|
338
|
+
cmdAtlasSubcommandHelp,
|
|
339
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const { CliError } = require("../lib/errors");
|
|
4
|
+
|
|
5
|
+
function cmdDeferredAsk() {
|
|
6
|
+
throw new CliError(
|
|
7
|
+
"This deferred Ask helper is not part of the active sdtk-wiki command path. Use sdtk-wiki ask --help for the native wiki.ask runtime contract.",
|
|
8
|
+
1
|
|
9
|
+
);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
module.exports = {
|
|
13
|
+
cmdDeferredAsk,
|
|
14
|
+
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
function cmdHelp() {
|
|
4
|
+
console.log(`SDTK-WIKI
|
|
5
|
+
|
|
6
|
+
Usage:
|
|
7
|
+
sdtk-wiki --help
|
|
8
|
+
sdtk-wiki --version
|
|
9
|
+
sdtk-wiki init --help
|
|
10
|
+
sdtk-wiki atlas build --help
|
|
11
|
+
sdtk-wiki atlas open --help
|
|
12
|
+
sdtk-wiki atlas watch --help
|
|
13
|
+
sdtk-wiki atlas status --help
|
|
14
|
+
sdtk-wiki wiki ingest --help
|
|
15
|
+
sdtk-wiki wiki prune --help
|
|
16
|
+
sdtk-wiki wiki discover --help
|
|
17
|
+
sdtk-wiki wiki compile --help
|
|
18
|
+
sdtk-wiki ask --help
|
|
19
|
+
sdtk-wiki lint --help
|
|
20
|
+
|
|
21
|
+
R1 command model:
|
|
22
|
+
init Initialize the SDTK-WIKI workspace.
|
|
23
|
+
atlas build Build graph/viewer plus local wiki pages/provenance.
|
|
24
|
+
atlas open Open or serve the local graph viewer.
|
|
25
|
+
atlas watch Watch markdown sources and rebuild the graph.
|
|
26
|
+
atlas status Report graph workspace status.
|
|
27
|
+
wiki ingest Register one local source in metadata-only raw/provenance state.
|
|
28
|
+
wiki prune Write a report-only dry-run stale managed-page review.
|
|
29
|
+
wiki discover Write a local-only discovery plan from WIKI gap evidence.
|
|
30
|
+
wiki compile Write a compile dry-run preview from a local plan.
|
|
31
|
+
ask Ask grounded questions over the built SDTK-WIKI graph.
|
|
32
|
+
lint Write a report-first, non-destructive wiki lint report.
|
|
33
|
+
|
|
34
|
+
Workspace paths:
|
|
35
|
+
.sdtk/wiki New SDTK-WIKI workspace target.
|
|
36
|
+
.sdtk/wiki/graph New SDTK-WIKI graph output target.
|
|
37
|
+
.sdtk/wiki/pages Generated local wiki page target.
|
|
38
|
+
.sdtk/wiki/raw Metadata-only local source registry target.
|
|
39
|
+
.sdtk/wiki/provenance Generated source provenance target.
|
|
40
|
+
.sdtk/atlas Legacy Atlas workspace, readable for compatibility.
|
|
41
|
+
Write paths must stay under project-local .sdtk/wiki.
|
|
42
|
+
|
|
43
|
+
Compatibility:
|
|
44
|
+
Existing sdtk-spec atlas commands remain the R1 compatibility path.
|
|
45
|
+
sdtk-spec atlas keeps compatibility output under .sdtk/atlas.
|
|
46
|
+
SDTK-WIKI reads legacy .sdtk/atlas output for compatibility and never auto-deletes it.
|
|
47
|
+
|
|
48
|
+
Premium Ask:
|
|
49
|
+
sdtk-wiki ask Canonical SDTK-WIKI Q&A command for capability wiki.ask.
|
|
50
|
+
Requires .sdtk/wiki/graph plus local entitlement/runtime preconditions.
|
|
51
|
+
Query history, discover, compile, and cleanup automation are not enabled in R1.
|
|
52
|
+
|
|
53
|
+
Maintenance:
|
|
54
|
+
sdtk-wiki wiki prune --dry-run is report-only and writes under .sdtk/wiki/reports.
|
|
55
|
+
It never deletes, archives, applies, or mutates .sdtk/atlas.`);
|
|
56
|
+
console.log(`
|
|
57
|
+
sdtk-wiki wiki discover --plan is plan-only and writes under .sdtk/wiki/reports.
|
|
58
|
+
It never fetches web sources, ingests sources, compiles pages, applies edits, prunes, or mutates .sdtk/atlas.`);
|
|
59
|
+
console.log(`
|
|
60
|
+
sdtk-wiki wiki compile --dry-run writes a compile dry-run preview under .sdtk/wiki/reports.
|
|
61
|
+
It never applies changes, rewrites pages, mutates raw/provenance files, or mutates .sdtk/atlas.`);
|
|
62
|
+
return 0;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
module.exports = {
|
|
66
|
+
cmdHelp,
|
|
67
|
+
};
|