@itradingai/aiwiki 0.2.16 → 0.2.18
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 +34 -0
- package/dist/src/app.js +218 -7
- package/dist/src/context.js +173 -16
- package/docs/AGENT_HANDOFF.md +54 -0
- package/docs/POSITIONING_CONTEXT_COMPILER_PLAN.md +347 -0
- package/docs/USAGE.md +56 -0
- package/package.json +1 -1
- package/skill/LINT_PROTOCOL.md +12 -5
- package/skill/QUERY_PROTOCOL.md +21 -4
- package/skill/SKILL.md +54 -1
- package/skill/UPGRADE_NOTES.md +22 -0
package/README.md
CHANGED
|
@@ -247,3 +247,37 @@ aiwiki lint --path "F:\knowledge_data\aiwiki-test"
|
|
|
247
247
|
## License
|
|
248
248
|
|
|
249
249
|
MIT. See [LICENSE](LICENSE).
|
|
250
|
+
|
|
251
|
+
## Query Filters
|
|
252
|
+
|
|
253
|
+
AIWiki retrieval is local Markdown/frontmatter search. It is intentionally lightweight: no vector search, no database, no external search, and no RAG-over-wiki.
|
|
254
|
+
|
|
255
|
+
```bash
|
|
256
|
+
aiwiki context "AI Agent" --type wiki_entries --source-role input --wiki-type source_knowledge --status active --limit 5
|
|
257
|
+
aiwiki query "AI Agent" --type source_cards --status to-review --limit 3
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
`context` returns Agent-readable JSON with `query_scope`, `result_quality`, `recommended_next_action`, `match_reasons`, `quality_signals`, and `related_refs`. `query` uses the same retrieval path and shows the match reasons and quality hints for humans.
|
|
261
|
+
|
|
262
|
+
## Agent Skill Sync and Upgrade
|
|
263
|
+
|
|
264
|
+
AIWiki is Agent-first: after installing or upgrading the npm package, sync the packaged AIWiki skill into the local Agent environment.
|
|
265
|
+
|
|
266
|
+
First install and later upgrades use the same safe command:
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
npm install -g @itradingai/aiwiki@latest
|
|
270
|
+
aiwiki agent sync --yes
|
|
271
|
+
aiwiki agent check
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
For one Agent:
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
aiwiki agent sync --agent codex --yes
|
|
278
|
+
aiwiki agent sync --agent claude --yes
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
`agent sync` is idempotent. Missing targets are installed, current targets are left unchanged, and changed old skill files are backed up before overwrite. Use `--dry-run` to preview and `--json` when an AI Agent needs stable machine-readable status.
|
|
282
|
+
|
|
283
|
+
After sync, restart or reload the target Agent so it reads the new AIWiki skill. To roll back, copy the generated `.bak-<timestamp>` file back over the target skill file.
|
package/dist/src/app.js
CHANGED
|
@@ -17,6 +17,14 @@ export async function runCli(argv, streams = { stdout: process.stdout, stderr: p
|
|
|
17
17
|
writeLine(streams.stdout, `aiwiki ${await packageVersion()}`);
|
|
18
18
|
return 0;
|
|
19
19
|
}
|
|
20
|
+
if (command === "agent" && (subcommand === "help" || args.flags.has("help"))) {
|
|
21
|
+
printAgentHelp(streams.stdout);
|
|
22
|
+
return 0;
|
|
23
|
+
}
|
|
24
|
+
if ((command === "context" || command === "query") && args.flags.has("help")) {
|
|
25
|
+
printContextHelp(streams.stdout);
|
|
26
|
+
return 0;
|
|
27
|
+
}
|
|
20
28
|
if (args.flags.has("help") || !command || command === "help" || command === "-h") {
|
|
21
29
|
printHelp(streams.stdout);
|
|
22
30
|
return 0;
|
|
@@ -54,8 +62,24 @@ export async function runCli(argv, streams = { stdout: process.stdout, stderr: p
|
|
|
54
62
|
}
|
|
55
63
|
return 0;
|
|
56
64
|
}
|
|
65
|
+
if (command === "agent" && subcommand === "sync") {
|
|
66
|
+
const result = await syncAgentSkills({
|
|
67
|
+
agentId: flagString(args, "agent"),
|
|
68
|
+
yes: flagBool(args, "yes"),
|
|
69
|
+
dryRun: flagBool(args, "dry-run"),
|
|
70
|
+
json: flagBool(args, "json"),
|
|
71
|
+
streams
|
|
72
|
+
});
|
|
73
|
+
if (flagBool(args, "json")) {
|
|
74
|
+
writeLine(streams.stdout, JSON.stringify(result, null, 2));
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
printAgentSyncResult(streams.stdout, result);
|
|
78
|
+
}
|
|
79
|
+
return 0;
|
|
80
|
+
}
|
|
57
81
|
if (command === "agent" && subcommand === "check") {
|
|
58
|
-
await
|
|
82
|
+
await printAgentCheckDetailed(streams.stdout, await discoverAgentTargets(), flagBool(args, "json"));
|
|
59
83
|
return 0;
|
|
60
84
|
}
|
|
61
85
|
if (command === "agent" && (subcommand === "list" || !subcommand)) {
|
|
@@ -137,7 +161,7 @@ export async function runCli(argv, streams = { stdout: process.stdout, stderr: p
|
|
|
137
161
|
if (!query) {
|
|
138
162
|
throw new CliError("请提供查询主题。");
|
|
139
163
|
}
|
|
140
|
-
writeLine(streams.stdout, JSON.stringify(await buildContext(root, query), null, 2));
|
|
164
|
+
writeLine(streams.stdout, JSON.stringify(await buildContext(root, query, contextOptions(args)), null, 2));
|
|
141
165
|
return 0;
|
|
142
166
|
}
|
|
143
167
|
if (command === "query") {
|
|
@@ -146,7 +170,7 @@ export async function runCli(argv, streams = { stdout: process.stdout, stderr: p
|
|
|
146
170
|
if (!query) {
|
|
147
171
|
throw new CliError("请提供查询主题。");
|
|
148
172
|
}
|
|
149
|
-
writeLine(streams.stdout, renderQuery(await buildContext(root, query)));
|
|
173
|
+
writeLine(streams.stdout, renderQuery(await buildContext(root, query, contextOptions(args))));
|
|
150
174
|
return 0;
|
|
151
175
|
}
|
|
152
176
|
if (command === "next") {
|
|
@@ -247,6 +271,8 @@ function printHelp(stream) {
|
|
|
247
271
|
writeLine(stream, " aiwiki agent list");
|
|
248
272
|
writeLine(stream, " aiwiki agent install");
|
|
249
273
|
writeLine(stream, " aiwiki agent install --agent codex --yes");
|
|
274
|
+
writeLine(stream, " aiwiki agent sync --yes");
|
|
275
|
+
writeLine(stream, " aiwiki agent check --json");
|
|
250
276
|
writeLine(stream, " aiwiki prompt agent");
|
|
251
277
|
writeLine(stream, " aiwiki doctor");
|
|
252
278
|
writeLine(stream, " aiwiki status");
|
|
@@ -262,6 +288,41 @@ function printHelp(stream) {
|
|
|
262
288
|
writeLine(stream, " aiwiki ingest-url <url> --content-file <file>");
|
|
263
289
|
writeLine(stream, " aiwiki agent check");
|
|
264
290
|
}
|
|
291
|
+
function printAgentHelp(stream) {
|
|
292
|
+
writeLine(stream, "AIWiki Agent commands");
|
|
293
|
+
writeLine(stream, "");
|
|
294
|
+
writeLine(stream, "Agent-first setup and upgrade:");
|
|
295
|
+
writeLine(stream, " aiwiki agent sync --yes");
|
|
296
|
+
writeLine(stream, " aiwiki agent sync --agent codex --yes");
|
|
297
|
+
writeLine(stream, " aiwiki agent sync --agent codex --dry-run");
|
|
298
|
+
writeLine(stream, " aiwiki agent sync --json --yes");
|
|
299
|
+
writeLine(stream, "");
|
|
300
|
+
writeLine(stream, "Status:");
|
|
301
|
+
writeLine(stream, " aiwiki agent check");
|
|
302
|
+
writeLine(stream, " aiwiki agent check --json");
|
|
303
|
+
writeLine(stream, "");
|
|
304
|
+
writeLine(stream, "Compatibility:");
|
|
305
|
+
writeLine(stream, " aiwiki agent install --agent codex --yes");
|
|
306
|
+
writeLine(stream, " aiwiki agent install --agent codex --yes --force");
|
|
307
|
+
writeLine(stream, "");
|
|
308
|
+
writeLine(stream, "sync is idempotent: missing targets are installed, current targets are left unchanged, and different targets are backed up before overwrite.");
|
|
309
|
+
}
|
|
310
|
+
function printContextHelp(stream) {
|
|
311
|
+
writeLine(stream, "AIWiki context/query");
|
|
312
|
+
writeLine(stream, "");
|
|
313
|
+
writeLine(stream, "Local Markdown/frontmatter retrieval for host Agents and humans:");
|
|
314
|
+
writeLine(stream, " aiwiki context <topic> --limit 10");
|
|
315
|
+
writeLine(stream, " aiwiki query <topic> --type wiki_entries --status active");
|
|
316
|
+
writeLine(stream, "");
|
|
317
|
+
writeLine(stream, "Filters:");
|
|
318
|
+
writeLine(stream, " --type wiki_entries|source_cards|claims|topics|outlines|raw_refs");
|
|
319
|
+
writeLine(stream, " --source-role input|processing|output");
|
|
320
|
+
writeLine(stream, " --wiki-type source_knowledge|personal_knowledge");
|
|
321
|
+
writeLine(stream, " --status active|to-review|ready|draft");
|
|
322
|
+
writeLine(stream, " --limit <1-50>");
|
|
323
|
+
writeLine(stream, "");
|
|
324
|
+
writeLine(stream, "context JSON includes query_scope, result_quality, recommended_next_action, match_reasons, quality_signals, and related_refs.");
|
|
325
|
+
}
|
|
265
326
|
function parseLintSeverity(value) {
|
|
266
327
|
if (value === undefined) {
|
|
267
328
|
return undefined;
|
|
@@ -362,6 +423,40 @@ async function printAgentCheck(stream, targets) {
|
|
|
362
423
|
}
|
|
363
424
|
}
|
|
364
425
|
}
|
|
426
|
+
async function printAgentCheckDetailed(stream, targets, json = false) {
|
|
427
|
+
const checked = await Promise.all(targets.map(async (target) => ({
|
|
428
|
+
...target,
|
|
429
|
+
state: await inspectAgentTarget(target),
|
|
430
|
+
installed: target.target ? await exists(target.target) : false
|
|
431
|
+
})));
|
|
432
|
+
if (json) {
|
|
433
|
+
writeLine(stream, JSON.stringify({
|
|
434
|
+
schema_version: "aiwiki.agent_check.v1",
|
|
435
|
+
generated_at: new Date().toISOString(),
|
|
436
|
+
targets: checked.map((target) => ({
|
|
437
|
+
id: target.id,
|
|
438
|
+
name: target.name,
|
|
439
|
+
detected: target.detected,
|
|
440
|
+
installable: target.installable,
|
|
441
|
+
installed: target.installed,
|
|
442
|
+
state: target.state,
|
|
443
|
+
source: target.source,
|
|
444
|
+
target: target.target
|
|
445
|
+
}))
|
|
446
|
+
}, null, 2));
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
writeLine(stream, "AIWiki Agent check");
|
|
450
|
+
for (const target of checked) {
|
|
451
|
+
writeLine(stream, `${target.id}: ${target.name} | detected=${target.detected ? "yes" : "no"} | installed=${target.installed ? "yes" : "no"} | installable=${target.installable ? "yes" : "no"} | state=${target.state}`);
|
|
452
|
+
if (target.detected && target.installable && (target.state === "missing" || target.state === "different")) {
|
|
453
|
+
writeLine(stream, ` suggested: aiwiki agent sync --agent ${target.id} --yes`);
|
|
454
|
+
}
|
|
455
|
+
else if (target.detected && !target.installable) {
|
|
456
|
+
writeLine(stream, " suggested: aiwiki prompt agent");
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
}
|
|
365
460
|
async function installAgentSkill(options) {
|
|
366
461
|
const targets = await discoverAgentTargets();
|
|
367
462
|
const installable = targets.filter((target) => target.detected && target.installable);
|
|
@@ -400,8 +495,8 @@ async function installAgentSkill(options) {
|
|
|
400
495
|
return undefined;
|
|
401
496
|
}
|
|
402
497
|
}
|
|
403
|
-
await
|
|
404
|
-
return selected;
|
|
498
|
+
const result = await copyInstallFileSafe(selected.source, selected.target, options.force);
|
|
499
|
+
return { ...selected, ...result };
|
|
405
500
|
}
|
|
406
501
|
async function askQuestion(streams, question) {
|
|
407
502
|
if (!process.stdin.isTTY) {
|
|
@@ -415,7 +510,28 @@ async function askQuestion(streams, question) {
|
|
|
415
510
|
rl.close();
|
|
416
511
|
}
|
|
417
512
|
}
|
|
513
|
+
async function syncAgentSkills(options) {
|
|
514
|
+
const targets = await discoverAgentTargets();
|
|
515
|
+
const selected = options.agentId ? targets.find((target) => target.id === options.agentId) : undefined;
|
|
516
|
+
if (!selected && options.agentId) {
|
|
517
|
+
throw new CliError(`未知宿主 Agent: ${options.agentId}`);
|
|
518
|
+
}
|
|
519
|
+
const syncTargets = selected ? [selected] : targets.filter((target) => target.detected && target.installable);
|
|
520
|
+
if (!syncTargets.length) {
|
|
521
|
+
throw new CliError("No detected installable Agent targets. Run aiwiki agent list or aiwiki prompt agent.");
|
|
522
|
+
}
|
|
523
|
+
if (!options.yes && !options.dryRun) {
|
|
524
|
+
throw new CliError("agent sync modifies Agent skill files. Re-run with --yes, or use --dry-run to preview.");
|
|
525
|
+
}
|
|
526
|
+
return {
|
|
527
|
+
schema_version: "aiwiki.agent_sync.v1",
|
|
528
|
+
generated_at: new Date().toISOString(),
|
|
529
|
+
dry_run: options.dryRun,
|
|
530
|
+
results: await Promise.all(syncTargets.map((target) => syncAgentTarget(target, options.dryRun)))
|
|
531
|
+
};
|
|
532
|
+
}
|
|
418
533
|
async function copyInstallFile(source, target, force) {
|
|
534
|
+
return copyInstallFileSafe(source, target, force);
|
|
419
535
|
await fs.access(source);
|
|
420
536
|
if (!force && (await exists(target))) {
|
|
421
537
|
throw new CliError(`目标文件已存在: ${target}。如需覆盖,请加 --force。`);
|
|
@@ -423,6 +539,84 @@ async function copyInstallFile(source, target, force) {
|
|
|
423
539
|
await fs.mkdir(path.dirname(target), { recursive: true });
|
|
424
540
|
await fs.copyFile(source, target);
|
|
425
541
|
}
|
|
542
|
+
async function copyInstallFileSafe(source, target, force) {
|
|
543
|
+
await fs.access(source);
|
|
544
|
+
const targetExists = await exists(target);
|
|
545
|
+
if (!force && targetExists) {
|
|
546
|
+
throw new CliError(`目标文件已存在: ${target}。如需覆盖,请运行 aiwiki agent sync --agent <id> --yes,或为 install 加 --force。`);
|
|
547
|
+
}
|
|
548
|
+
if (targetExists && await sameFileContent(source, target)) {
|
|
549
|
+
return { action: "current" };
|
|
550
|
+
}
|
|
551
|
+
await fs.mkdir(path.dirname(target), { recursive: true });
|
|
552
|
+
const backupPath = targetExists ? await backupFile(target) : undefined;
|
|
553
|
+
await fs.copyFile(source, target);
|
|
554
|
+
return { action: targetExists ? "updated" : "installed", backupPath };
|
|
555
|
+
}
|
|
556
|
+
async function inspectAgentTarget(target) {
|
|
557
|
+
if (!target.installable || !target.source || !target.target) {
|
|
558
|
+
return "unsupported";
|
|
559
|
+
}
|
|
560
|
+
if (!(await exists(target.target))) {
|
|
561
|
+
return "missing";
|
|
562
|
+
}
|
|
563
|
+
return await sameFileContent(target.source, target.target) ? "current" : "different";
|
|
564
|
+
}
|
|
565
|
+
async function syncAgentTarget(target, dryRun) {
|
|
566
|
+
const state = await inspectAgentTarget(target);
|
|
567
|
+
const base = {
|
|
568
|
+
id: target.id,
|
|
569
|
+
name: target.name,
|
|
570
|
+
detected: target.detected,
|
|
571
|
+
installable: target.installable,
|
|
572
|
+
state,
|
|
573
|
+
target: target.target,
|
|
574
|
+
source: target.source,
|
|
575
|
+
changed: false,
|
|
576
|
+
dryRun
|
|
577
|
+
};
|
|
578
|
+
if (state === "unsupported" || !target.source || !target.target) {
|
|
579
|
+
return { ...base, action: "unsupported", note: target.note };
|
|
580
|
+
}
|
|
581
|
+
if (state === "current") {
|
|
582
|
+
return { ...base, action: "current" };
|
|
583
|
+
}
|
|
584
|
+
if (dryRun) {
|
|
585
|
+
return { ...base, action: state === "missing" ? "would_install" : "would_update", changed: true };
|
|
586
|
+
}
|
|
587
|
+
const result = await copyInstallFileSafe(target.source, target.target, true);
|
|
588
|
+
return { ...base, action: result.action, backupPath: result.backupPath, changed: result.action !== "current" };
|
|
589
|
+
}
|
|
590
|
+
async function sameFileContent(source, target) {
|
|
591
|
+
try {
|
|
592
|
+
const [sourceText, targetText] = await Promise.all([fs.readFile(source, "utf8"), fs.readFile(target, "utf8")]);
|
|
593
|
+
return sourceText === targetText;
|
|
594
|
+
}
|
|
595
|
+
catch {
|
|
596
|
+
return false;
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
async function backupFile(target) {
|
|
600
|
+
const parsed = path.parse(target);
|
|
601
|
+
const stamp = new Date().toISOString().replace(/[-:]/g, "").replace(/\.\d{3}Z$/, "Z");
|
|
602
|
+
const backupPath = path.join(parsed.dir, `${parsed.base}.bak-${stamp}`);
|
|
603
|
+
await fs.copyFile(target, backupPath);
|
|
604
|
+
return backupPath;
|
|
605
|
+
}
|
|
606
|
+
function printAgentSyncResult(stream, report) {
|
|
607
|
+
writeLine(stream, "AIWiki Agent sync");
|
|
608
|
+
writeLine(stream, `dry_run: ${report.dry_run ? "yes" : "no"}`);
|
|
609
|
+
for (const item of report.results) {
|
|
610
|
+
writeLine(stream, `${item.id}: ${item.name} | state=${item.state} | action=${item.action} | changed=${item.changed ? "yes" : "no"}`);
|
|
611
|
+
if (item.target) {
|
|
612
|
+
writeLine(stream, ` target: ${item.target}`);
|
|
613
|
+
}
|
|
614
|
+
if (item.backupPath) {
|
|
615
|
+
writeLine(stream, ` backup: ${item.backupPath}`);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
writeLine(stream, "next: restart or reload the target Agent so it reads the synced AIWiki skill.");
|
|
619
|
+
}
|
|
426
620
|
function printAgentPrompt(stream) {
|
|
427
621
|
writeLine(stream, "AIWiki Agent 中文提示");
|
|
428
622
|
writeLine(stream, "");
|
|
@@ -508,7 +702,7 @@ async function printNext(stream, root, runCount, checks, targets, report) {
|
|
|
508
702
|
if (runCount === 0) {
|
|
509
703
|
writeLine(stream, "");
|
|
510
704
|
writeLine(stream, "No ingest records yet.");
|
|
511
|
-
writeLine(stream, "- aiwiki agent
|
|
705
|
+
writeLine(stream, "- aiwiki agent sync --yes");
|
|
512
706
|
writeLine(stream, "- Then ask the host Agent to ingest a URL.");
|
|
513
707
|
writeLine(stream, "- AIWiki CLI does not fetch webpages; the host Agent supplies content.");
|
|
514
708
|
writeLine(stream, "- repair_order: empty_workspace");
|
|
@@ -535,12 +729,25 @@ function recommendedNextAction(runCount, lintStatus, hasMissingSystemFiles) {
|
|
|
535
729
|
return "next_action: aiwiki lint";
|
|
536
730
|
}
|
|
537
731
|
if (runCount === 0) {
|
|
538
|
-
return "next_action: aiwiki agent
|
|
732
|
+
return "next_action: aiwiki agent sync --yes";
|
|
539
733
|
}
|
|
540
734
|
return "next_action: aiwiki query <topic>";
|
|
541
735
|
}
|
|
736
|
+
function contextOptions(args) {
|
|
737
|
+
const limit = flagString(args, "limit");
|
|
738
|
+
return {
|
|
739
|
+
filters: {
|
|
740
|
+
type: flagString(args, "type"),
|
|
741
|
+
source_role: flagString(args, "source-role"),
|
|
742
|
+
wiki_type: flagString(args, "wiki-type"),
|
|
743
|
+
status: flagString(args, "status")
|
|
744
|
+
},
|
|
745
|
+
limit: limit === undefined ? undefined : Number(limit)
|
|
746
|
+
};
|
|
747
|
+
}
|
|
542
748
|
function renderQuery(context) {
|
|
543
749
|
const lines = [`AIWiki 查询: ${context.query}`, ""];
|
|
750
|
+
lines.push(`结果质量: matches=${context.result_quality.total_matches}, best_score=${context.result_quality.best_score}, has_wiki_entry=${context.result_quality.has_wiki_entry ? "yes" : "no"}`, `下一步建议: ${context.recommended_next_action}`, `查询范围: groups=${context.query_scope.searched_groups.join(",") || "none"}, limit=${context.query_scope.limit}, filters=${JSON.stringify(context.query_scope.filters)}`, "");
|
|
544
751
|
appendQueryGroup(lines, "Wiki 条目", context.matches.wiki_entries);
|
|
545
752
|
appendQueryGroup(lines, "资料卡", context.matches.source_cards);
|
|
546
753
|
appendQueryGroup(lines, "选题", context.matches.topics);
|
|
@@ -561,9 +768,13 @@ function appendQueryGroup(lines, label, items) {
|
|
|
561
768
|
}
|
|
562
769
|
for (const item of items.slice(0, 5)) {
|
|
563
770
|
lines.push(`- ${item.title} (${item.path})`);
|
|
771
|
+
lines.push(` score=${item.score}; reasons=${item.match_reasons.join(",") || "unknown"}; quality=${item.quality_signals.join(",") || "none"}`);
|
|
564
772
|
if (item.summary) {
|
|
565
773
|
lines.push(` ${item.summary}`);
|
|
566
774
|
}
|
|
775
|
+
if (item.related_refs.length) {
|
|
776
|
+
lines.push(` related: ${item.related_refs.slice(0, 5).join("; ")}`);
|
|
777
|
+
}
|
|
567
778
|
if (item.warnings.length) {
|
|
568
779
|
lines.push(` 提示: ${item.warnings.join(";")}`);
|
|
569
780
|
}
|
package/dist/src/context.js
CHANGED
|
@@ -11,13 +11,28 @@ const GROUPS = [
|
|
|
11
11
|
{ key: "outlines", dir: "08-outputs/outlines", weight: 2 },
|
|
12
12
|
{ key: "raw_refs", dir: "02-raw/articles", weight: 1 }
|
|
13
13
|
];
|
|
14
|
-
|
|
14
|
+
const DEFAULT_LIMIT = 10;
|
|
15
|
+
export async function buildContext(rootPath, query, options = {}, now = new Date().toISOString()) {
|
|
15
16
|
const root = path.resolve(rootPath);
|
|
16
17
|
const tokens = tokenize(query);
|
|
18
|
+
const limit = normalizeLimit(options.limit);
|
|
19
|
+
const filters = normalizeFilters(options.filters);
|
|
17
20
|
const result = {
|
|
18
21
|
schema_version: "aiwiki.context.v1",
|
|
19
22
|
query,
|
|
20
23
|
generated_at: now,
|
|
24
|
+
query_scope: {
|
|
25
|
+
filters,
|
|
26
|
+
limit,
|
|
27
|
+
searched_groups: []
|
|
28
|
+
},
|
|
29
|
+
result_quality: {
|
|
30
|
+
total_matches: 0,
|
|
31
|
+
best_score: 0,
|
|
32
|
+
has_wiki_entry: false,
|
|
33
|
+
warnings: []
|
|
34
|
+
},
|
|
35
|
+
recommended_next_action: "broaden_query",
|
|
21
36
|
matches: {
|
|
22
37
|
wiki_entries: [],
|
|
23
38
|
source_cards: [],
|
|
@@ -26,34 +41,41 @@ export async function buildContext(rootPath, query, now = new Date().toISOString
|
|
|
26
41
|
outlines: [],
|
|
27
42
|
raw_refs: []
|
|
28
43
|
},
|
|
29
|
-
suggested_answer_structure: ["
|
|
44
|
+
suggested_answer_structure: ["topic overview", "core claims", "available evidence", "reuse judgment", "next action"],
|
|
30
45
|
warnings: []
|
|
31
46
|
};
|
|
32
47
|
if (!tokens.length) {
|
|
33
48
|
result.warnings.push("query is empty after tokenization");
|
|
49
|
+
finalizeQuality(result);
|
|
34
50
|
return result;
|
|
35
51
|
}
|
|
36
52
|
for (const group of GROUPS.filter((item) => item.key !== "raw_refs")) {
|
|
53
|
+
if (!groupAllowed(group.key, filters.type)) {
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
37
56
|
const dir = path.join(root, group.dir);
|
|
38
57
|
if (!(await exists(dir))) {
|
|
39
58
|
continue;
|
|
40
59
|
}
|
|
41
|
-
|
|
42
|
-
|
|
60
|
+
result.query_scope.searched_groups.push(group.key);
|
|
61
|
+
const matches = await searchDir(root, dir, tokens, group.weight, group.key, filters);
|
|
62
|
+
result.matches[group.key].push(...matches.slice(0, limit));
|
|
43
63
|
}
|
|
44
|
-
if (!result.matches.wiki_entries.length) {
|
|
45
|
-
result.warnings.push("
|
|
64
|
+
if (!result.matches.wiki_entries.length && groupAllowed("raw_refs", filters.type)) {
|
|
65
|
+
result.warnings.push("No Wiki Entry matched; results may come from source cards, topics, outlines, or raw references.");
|
|
46
66
|
const rawGroup = GROUPS.find((item) => item.key === "raw_refs");
|
|
47
67
|
if (rawGroup) {
|
|
48
68
|
const rawDir = path.join(root, rawGroup.dir);
|
|
49
69
|
if (await exists(rawDir)) {
|
|
50
|
-
result.
|
|
70
|
+
result.query_scope.searched_groups.push(rawGroup.key);
|
|
71
|
+
result.matches.raw_refs.push(...(await searchDir(root, rawDir, tokens, rawGroup.weight, rawGroup.key, filters)).slice(0, limit));
|
|
51
72
|
}
|
|
52
73
|
}
|
|
53
74
|
}
|
|
75
|
+
finalizeQuality(result);
|
|
54
76
|
return result;
|
|
55
77
|
}
|
|
56
|
-
async function searchDir(root, dir, tokens, weight) {
|
|
78
|
+
async function searchDir(root, dir, tokens, weight, groupKey, filters) {
|
|
57
79
|
const files = await listMarkdownFiles(dir);
|
|
58
80
|
const matches = [];
|
|
59
81
|
for (const file of files) {
|
|
@@ -61,12 +83,24 @@ async function searchDir(root, dir, tokens, weight) {
|
|
|
61
83
|
const parsed = parseMarkdown(text);
|
|
62
84
|
const rel = relativePath(root, file);
|
|
63
85
|
const title = frontmatterString(parsed.frontmatter, "title") ?? path.basename(file, ".md");
|
|
86
|
+
const type = frontmatterString(parsed.frontmatter, "type") ?? groupKey;
|
|
87
|
+
const status = frontmatterString(parsed.frontmatter, "status");
|
|
88
|
+
const sourceRole = frontmatterString(parsed.frontmatter, "source_role");
|
|
89
|
+
const wikiType = frontmatterString(parsed.frontmatter, "wiki_type");
|
|
90
|
+
if (!passesFilters({ type, groupKey, status, source_role: sourceRole, wiki_type: wikiType }, filters)) {
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
const topics = frontmatterArray(parsed.frontmatter, "topics");
|
|
94
|
+
const tags = frontmatterArray(parsed.frontmatter, "tags");
|
|
95
|
+
const relatedRefs = relatedReferences(parsed.frontmatter, parsed.body);
|
|
96
|
+
const sourceUrl = frontmatterString(parsed.frontmatter, "source_url") ?? "";
|
|
64
97
|
const haystack = [
|
|
65
98
|
rel,
|
|
66
99
|
title,
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
100
|
+
sourceUrl,
|
|
101
|
+
topics.join(" "),
|
|
102
|
+
tags.join(" "),
|
|
103
|
+
relatedRefs.join(" "),
|
|
70
104
|
parsed.body
|
|
71
105
|
].join("\n").toLowerCase();
|
|
72
106
|
const hits = tokens.filter((token) => haystack.includes(token.toLowerCase())).length;
|
|
@@ -77,8 +111,9 @@ async function searchDir(root, dir, tokens, weight) {
|
|
|
77
111
|
const quality = frontmatterString(parsed.frontmatter, "quality");
|
|
78
112
|
const groundingMarkers = frontmatterArray(parsed.frontmatter, "grounding_markers");
|
|
79
113
|
const groundingNeedsReview = frontmatterBoolean(parsed.frontmatter, "grounding_needs_review");
|
|
114
|
+
const groundingEvidenceAvailable = frontmatterBoolean(parsed.frontmatter, "grounding_evidence_available");
|
|
80
115
|
const warnings = generationMode === "deterministic_fallback"
|
|
81
|
-
? ["
|
|
116
|
+
? ["This Wiki Entry is a deterministic fallback; it may need host-agent enrichment."]
|
|
82
117
|
: [];
|
|
83
118
|
if (groundingNeedsReview) {
|
|
84
119
|
warnings.push(`Grounding needs review${groundingMarkers.length ? `: ${groundingMarkers.join(", ")}` : ""}.`);
|
|
@@ -88,11 +123,19 @@ async function searchDir(root, dir, tokens, weight) {
|
|
|
88
123
|
path: rel,
|
|
89
124
|
summary: frontmatterString(parsed.frontmatter, "summary") ?? summarize(parsed.body, quality),
|
|
90
125
|
score: Number(((hits / tokens.length) * weight).toFixed(2)),
|
|
91
|
-
|
|
92
|
-
|
|
126
|
+
type,
|
|
127
|
+
topics,
|
|
128
|
+
tags,
|
|
129
|
+
source_url: sourceUrl,
|
|
130
|
+
status,
|
|
131
|
+
source_role: sourceRole,
|
|
132
|
+
wiki_type: wikiType,
|
|
133
|
+
match_reasons: matchReasons(tokens, { rel, title, body: parsed.body, topics, tags, relatedRefs, sourceUrl }),
|
|
134
|
+
quality_signals: qualitySignals({ quality, generationMode, groundingEvidenceAvailable, groundingNeedsReview, status, relatedRefs }),
|
|
135
|
+
related_refs: relatedRefs,
|
|
93
136
|
generation_mode: generationMode,
|
|
94
137
|
quality,
|
|
95
|
-
grounding_evidence_available:
|
|
138
|
+
grounding_evidence_available: groundingEvidenceAvailable,
|
|
96
139
|
grounding_needs_review: groundingNeedsReview,
|
|
97
140
|
grounding_markers: groundingMarkers,
|
|
98
141
|
warnings
|
|
@@ -125,7 +168,121 @@ function tokenize(value) {
|
|
|
125
168
|
function summarize(body, quality) {
|
|
126
169
|
const compact = body.replace(/\s+/g, " ").trim();
|
|
127
170
|
if (quality === "scaffold") {
|
|
128
|
-
return "
|
|
171
|
+
return "Only a scaffold preview is available; enrich before relying on it as a final answer.";
|
|
129
172
|
}
|
|
130
173
|
return compact.length > 180 ? `${compact.slice(0, 180)}...` : compact;
|
|
131
174
|
}
|
|
175
|
+
function normalizeLimit(value) {
|
|
176
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
177
|
+
return DEFAULT_LIMIT;
|
|
178
|
+
}
|
|
179
|
+
return Math.max(1, Math.min(50, Math.floor(value)));
|
|
180
|
+
}
|
|
181
|
+
function normalizeFilters(filters) {
|
|
182
|
+
return Object.fromEntries(Object.entries(filters ?? {})
|
|
183
|
+
.filter(([, value]) => typeof value === "string" && value.trim())
|
|
184
|
+
.map(([key, value]) => [key, String(value).trim()]));
|
|
185
|
+
}
|
|
186
|
+
function groupAllowed(groupKey, typeFilter) {
|
|
187
|
+
if (!typeFilter) {
|
|
188
|
+
return true;
|
|
189
|
+
}
|
|
190
|
+
return normalizeType(typeFilter) === normalizeType(groupKey);
|
|
191
|
+
}
|
|
192
|
+
function passesFilters(item, filters) {
|
|
193
|
+
if (filters.type && normalizeType(filters.type) !== normalizeType(item.type) && normalizeType(filters.type) !== normalizeType(item.groupKey)) {
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
if (filters.status && filters.status !== item.status) {
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
199
|
+
if (filters.source_role && filters.source_role !== item.source_role) {
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
202
|
+
if (filters.wiki_type && filters.wiki_type !== item.wiki_type) {
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
return true;
|
|
206
|
+
}
|
|
207
|
+
function normalizeType(value) {
|
|
208
|
+
return value.replace(/-/g, "_").toLowerCase();
|
|
209
|
+
}
|
|
210
|
+
function relatedReferences(frontmatter, body) {
|
|
211
|
+
const refs = [
|
|
212
|
+
frontmatterString(frontmatter, "source_card"),
|
|
213
|
+
frontmatterString(frontmatter, "raw_file"),
|
|
214
|
+
frontmatterString(frontmatter, "claims_note"),
|
|
215
|
+
frontmatterString(frontmatter, "assets_note"),
|
|
216
|
+
frontmatterString(frontmatter, "topics_note"),
|
|
217
|
+
frontmatterString(frontmatter, "outline_note"),
|
|
218
|
+
...extractWikilinks(body)
|
|
219
|
+
].filter((value) => Boolean(value));
|
|
220
|
+
return Array.from(new Set(refs));
|
|
221
|
+
}
|
|
222
|
+
function extractWikilinks(body) {
|
|
223
|
+
const refs = [];
|
|
224
|
+
const pattern = /\[\[([^\]|]+)(?:\|[^\]]+)?\]\]/g;
|
|
225
|
+
for (const match of body.matchAll(pattern)) {
|
|
226
|
+
refs.push(match[1].trim());
|
|
227
|
+
}
|
|
228
|
+
return refs;
|
|
229
|
+
}
|
|
230
|
+
function matchReasons(tokens, fields) {
|
|
231
|
+
const reasons = new Set();
|
|
232
|
+
for (const token of tokens.map((item) => item.toLowerCase())) {
|
|
233
|
+
if (fields.title.toLowerCase().includes(token))
|
|
234
|
+
reasons.add("title");
|
|
235
|
+
if (fields.rel.toLowerCase().includes(token))
|
|
236
|
+
reasons.add("path");
|
|
237
|
+
if (fields.sourceUrl.toLowerCase().includes(token))
|
|
238
|
+
reasons.add("source_url");
|
|
239
|
+
if (fields.topics.join(" ").toLowerCase().includes(token))
|
|
240
|
+
reasons.add("topics");
|
|
241
|
+
if (fields.tags.join(" ").toLowerCase().includes(token))
|
|
242
|
+
reasons.add("tags");
|
|
243
|
+
if (fields.relatedRefs.join(" ").toLowerCase().includes(token))
|
|
244
|
+
reasons.add("relationships");
|
|
245
|
+
if (fields.body.toLowerCase().includes(token))
|
|
246
|
+
reasons.add("body");
|
|
247
|
+
}
|
|
248
|
+
return Array.from(reasons);
|
|
249
|
+
}
|
|
250
|
+
function qualitySignals(item) {
|
|
251
|
+
const signals = [];
|
|
252
|
+
if (item.quality)
|
|
253
|
+
signals.push(`quality:${item.quality}`);
|
|
254
|
+
if (item.status)
|
|
255
|
+
signals.push(`status:${item.status}`);
|
|
256
|
+
if (item.generationMode)
|
|
257
|
+
signals.push(`generation_mode:${item.generationMode}`);
|
|
258
|
+
if (item.groundingEvidenceAvailable === true)
|
|
259
|
+
signals.push("grounding:evidence_available");
|
|
260
|
+
if (item.groundingEvidenceAvailable === false)
|
|
261
|
+
signals.push("grounding:no_evidence_flag");
|
|
262
|
+
if (item.groundingNeedsReview)
|
|
263
|
+
signals.push("grounding:needs_review");
|
|
264
|
+
if (item.relatedRefs.length)
|
|
265
|
+
signals.push("relationships:present");
|
|
266
|
+
return signals;
|
|
267
|
+
}
|
|
268
|
+
function finalizeQuality(result) {
|
|
269
|
+
const all = Object.values(result.matches).flat();
|
|
270
|
+
result.result_quality = {
|
|
271
|
+
total_matches: all.length,
|
|
272
|
+
best_score: all.reduce((best, item) => Math.max(best, item.score), 0),
|
|
273
|
+
has_wiki_entry: result.matches.wiki_entries.length > 0,
|
|
274
|
+
warnings: result.warnings
|
|
275
|
+
};
|
|
276
|
+
if (!all.length) {
|
|
277
|
+
result.recommended_next_action = "broaden_query_or_ingest_source";
|
|
278
|
+
}
|
|
279
|
+
else if (!result.matches.wiki_entries.length) {
|
|
280
|
+
result.recommended_next_action = "review_source_cards_then_create_wiki_entry";
|
|
281
|
+
}
|
|
282
|
+
else if (all.some((item) => item.grounding_needs_review || item.quality === "scaffold")) {
|
|
283
|
+
result.recommended_next_action = "review_grounding_or_enrich_entry";
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
result.recommended_next_action = "use_matches_for_answer";
|
|
287
|
+
}
|
|
288
|
+
}
|
package/docs/AGENT_HANDOFF.md
CHANGED
|
@@ -247,3 +247,57 @@ Lint 输出会包含摘要、最高优先级问题、分级报告,以及建议
|
|
|
247
247
|
Before ingesting, querying, or reorganizing material, read `_system/purpose.md` in the target AIWiki workspace. Treat it as the local contract for what belongs in this knowledge base, what should stay out, and how future multi-knowledge-base routing should be handled.
|
|
248
248
|
|
|
249
249
|
If the material does not fit the purpose file, do not force it into the knowledge base as confirmed knowledge. Record the mismatch, ask for review when needed, or keep it as a traceable source rather than a claim.
|
|
250
|
+
|
|
251
|
+
## Context JSON for Retrieval
|
|
252
|
+
|
|
253
|
+
When answering from AIWiki, prefer:
|
|
254
|
+
|
|
255
|
+
```bash
|
|
256
|
+
aiwiki context "<topic>" --limit 10
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
Use filters when the user intent is narrow:
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
aiwiki context "<topic>" --type wiki_entries --source-role input --wiki-type source_knowledge --status active
|
|
263
|
+
aiwiki context "<topic>" --type source_cards --status to-review
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
`context` is local Markdown/frontmatter retrieval only. Do not describe it as vector search, RAG, a database query, or external web search.
|
|
267
|
+
|
|
268
|
+
Read these fields before responding:
|
|
269
|
+
|
|
270
|
+
- `query_scope`: what was searched and which filters were applied.
|
|
271
|
+
- `result_quality.total_matches` and `result_quality.has_wiki_entry`: whether the answer is grounded in a Wiki Entry or only in supporting artifacts.
|
|
272
|
+
- `recommended_next_action`: whether to answer, enrich, review grounding, or broaden the query.
|
|
273
|
+
- `match_reasons`: why each result matched, such as title, body, tags, topics, relationships, or source URL.
|
|
274
|
+
- `quality_signals`: scaffold, enriched, status, grounding, and relationship hints.
|
|
275
|
+
- `related_refs`: local wikilinks and frontmatter relationships such as `source_card`, `raw_file`, and run artifacts.
|
|
276
|
+
|
|
277
|
+
If `quality_signals` contains `quality:scaffold` or `grounding:needs_review`, tell the user the result is a traceable lead that needs enrichment or review. Do not present it as confirmed final knowledge.
|
|
278
|
+
|
|
279
|
+
## Agent Skill Upgrade Flow
|
|
280
|
+
|
|
281
|
+
When the user asks you to install, update, upgrade, or repair AIWiki integration, run:
|
|
282
|
+
|
|
283
|
+
```bash
|
|
284
|
+
aiwiki agent sync --yes
|
|
285
|
+
aiwiki agent check
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
Use JSON when you need exact state:
|
|
289
|
+
|
|
290
|
+
```bash
|
|
291
|
+
aiwiki agent sync --json --yes
|
|
292
|
+
aiwiki agent check --json
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
Interpret sync results:
|
|
296
|
+
|
|
297
|
+
- `installed`: target did not exist and now has the packaged skill.
|
|
298
|
+
- `current`: installed skill already matches the packaged skill.
|
|
299
|
+
- `updated`: installed skill differed; the old file was backed up and replaced.
|
|
300
|
+
- `would_install` / `would_update`: dry-run preview only.
|
|
301
|
+
- `unsupported`: no safe automatic target is known; use `aiwiki prompt agent`.
|
|
302
|
+
|
|
303
|
+
After sync, report the target path, backup path when present, and that the user may need to restart or reload the Agent. Do not claim the new skill is active until the Agent has reloaded it.
|
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
# AIWiki 定位调整与产品方案
|
|
2
|
+
|
|
3
|
+
本文基于 `20260607-aiwiki定位.md` 的判断,并结合当前 AIWiki 仓库现状整理。结论是:文档大方向可取,但不能把 AIWiki 改成重学习、重记忆、重人工复习的 Knowledge MEMO。AIWiki 更适合继续做 Agent-first 本地上下文编译器。
|
|
4
|
+
|
|
5
|
+
## 一句话定位
|
|
6
|
+
|
|
7
|
+
AIWiki 不是替代搜索,也不是替你读书,而是把你真正需要反复调用的资料、判断和输出,编译成 AI 能查询、能引用、能检查、能继续使用的本地知识资产。
|
|
8
|
+
|
|
9
|
+
更锋利的对外表达:
|
|
10
|
+
|
|
11
|
+
> 公开知识交给搜索。
|
|
12
|
+
> 私有判断、项目经验、输出风格、证据链,交给 AIWiki。
|
|
13
|
+
|
|
14
|
+
## 建议取舍判断
|
|
15
|
+
|
|
16
|
+
| 文档建议 | 判断 | 原因 | 落地优先级 |
|
|
17
|
+
| --- | --- | --- | --- |
|
|
18
|
+
| 不把 AIWiki 宣传成普通个人知识库或资料索引 | 可取 | 当前 README 已强调 Agent-first 和本地 LLM-wiki 后端,但还可以更明确地区分搜索、收藏夹和上下文编译器 | P0 |
|
|
19
|
+
| 保留 Markdown Wiki 形态 | 可取 | AIWiki 面向人和 Agent 协作,Markdown 的可读、可 diff、可回滚、可被 Agent 编辑是核心优势 | P0 |
|
|
20
|
+
| 强化个人判断层 | 强烈可取 | 当前 payload 已有 `source_role=processing`,但产品心智和目录/命令输出还没有把 personal insight 变成一等资产 | P0 |
|
|
21
|
+
| 强化输出资产层 | 强烈可取 | 当前已有 `source_role=output` 和 `represents_user_view=true` 边界,这是 AIWiki 最有差异化的一层 | P0 |
|
|
22
|
+
| `context` 从资料检索升级为任务上下文包 | 强烈可取 | 当前 `context` 已是 JSON 结构,适合加 `mode` 和按任务分组的结果,不需要推倒重做 | P0 |
|
|
23
|
+
| `query` 输出按资料类型分组 | 可取 | 这是低成本心智升级:从“搜索结果”变成“知识资产调度” | P1 |
|
|
24
|
+
| `lint` 从结构检查升级为知识质量检查 | 可取 | 当前 lint 已有元数据边界、fallback、grounding 检查,可继续加入 insight/output/evidence 使用关系检查 | P1 |
|
|
25
|
+
| `next` 从命令导航升级为加工建议 | 可取 | 适合帮助用户把资料推进到 insight、output、topic 或 review,而不是只提示下一条 CLI 命令 | P1 |
|
|
26
|
+
| 新增 Retain / Review | 部分可取 | 可以做轻量回看,但不应成为主流程,也不要第一阶段引入 FSRS 或 Anki 式学习系统 | P2 |
|
|
27
|
+
| 把 AIWiki 改成纯人脑内化工具 | 不建议 | 会偏离当前 Agent-first CLI 边界,也会让产品过重 | 不做 |
|
|
28
|
+
| 引入多知识库、自动采集、内置网页抓取 | 不建议 | 与当前仓库 AGENTS.md 和 README 边界冲突;这些属于 AIWiki Pro 或宿主 Agent/服务层,不属于基础 CLI | 不做 |
|
|
29
|
+
|
|
30
|
+
## 产品原则
|
|
31
|
+
|
|
32
|
+
1. AIWiki 只沉淀值得复用的上下文,不收藏所有公开知识。
|
|
33
|
+
2. 外部资料默认不代表用户观点。
|
|
34
|
+
3. 用户自己的输出和判断比外部输入更值钱。
|
|
35
|
+
4. AIWiki CLI 不调用 LLM;高质量分析由宿主 Agent 提供,AIWiki 负责规范、落盘、追踪、检查。
|
|
36
|
+
5. 保持单知识库、单命令 `aiwiki`、本地 Markdown 的基本边界。
|
|
37
|
+
6. Review / Retain 是增强闭环,不是默认主流程。
|
|
38
|
+
|
|
39
|
+
## 三类知识资产模型
|
|
40
|
+
|
|
41
|
+
### 1. Source Knowledge:来源证据
|
|
42
|
+
|
|
43
|
+
用于保存外部文章、网页、报告、视频转写、书籍摘录等。
|
|
44
|
+
|
|
45
|
+
建议字段:
|
|
46
|
+
|
|
47
|
+
```yaml
|
|
48
|
+
source_role: input
|
|
49
|
+
wiki_type: source_knowledge
|
|
50
|
+
represents_user_view: false
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
价值标准:
|
|
54
|
+
|
|
55
|
+
- 是否能作为证据引用。
|
|
56
|
+
- 是否能支撑观点或反驳观点。
|
|
57
|
+
- 是否能生成选题、方案、脚本或研究方向。
|
|
58
|
+
- 是否能和已有资料、判断、输出建立连接。
|
|
59
|
+
|
|
60
|
+
### 2. Personal Insight:个人判断
|
|
61
|
+
|
|
62
|
+
用于保存用户或宿主 Agent 帮用户整理出的判断、取舍、冲突、决策理由。
|
|
63
|
+
|
|
64
|
+
建议先复用现有 `source_role=processing`,并把 `wiki_type` 从宽泛的 `thought_note` 收窄为更明确的 `personal_insight` 或 `decision_note`。第一阶段可以兼容旧值。
|
|
65
|
+
|
|
66
|
+
建议字段:
|
|
67
|
+
|
|
68
|
+
```yaml
|
|
69
|
+
type: insight_note
|
|
70
|
+
source_role: processing
|
|
71
|
+
wiki_type: personal_insight
|
|
72
|
+
represents_user_view: true
|
|
73
|
+
confidence: low | medium | high
|
|
74
|
+
based_on:
|
|
75
|
+
- 03-sources/article-cards/example.md
|
|
76
|
+
- 05-wiki/source-knowledge/example.md
|
|
77
|
+
used_for:
|
|
78
|
+
- article
|
|
79
|
+
- product_decision
|
|
80
|
+
- client_solution
|
|
81
|
+
- research
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
条目应回答:
|
|
85
|
+
|
|
86
|
+
- 我认同什么,为什么。
|
|
87
|
+
- 我反对什么,为什么。
|
|
88
|
+
- 对项目、文章、产品或客户方案有什么启发。
|
|
89
|
+
- 能否转成文章观点、产品决策或执行动作。
|
|
90
|
+
- 和我已有判断是否冲突。
|
|
91
|
+
|
|
92
|
+
### 3. Output Knowledge:可复用输出
|
|
93
|
+
|
|
94
|
+
用于保存用户已经发布或交付过的文章、方案、PRD、README、报价、视频脚本、群内回答等。
|
|
95
|
+
|
|
96
|
+
建议字段:
|
|
97
|
+
|
|
98
|
+
```yaml
|
|
99
|
+
source_role: output
|
|
100
|
+
wiki_type: personal_knowledge
|
|
101
|
+
represents_user_view: true
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
价值标准:
|
|
105
|
+
|
|
106
|
+
- 能反映用户真实观点。
|
|
107
|
+
- 能反映用户表达风格。
|
|
108
|
+
- 能被新文章、新方案、新脚本复用。
|
|
109
|
+
- 能回溯到支撑它的 source 和 insight。
|
|
110
|
+
|
|
111
|
+
## 命令方案
|
|
112
|
+
|
|
113
|
+
### `aiwiki context`
|
|
114
|
+
|
|
115
|
+
定位:从“相关资料包”升级为“任务上下文包”。
|
|
116
|
+
|
|
117
|
+
新增 `--mode`:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
aiwiki context "AI知识库是否还有必要" --mode write
|
|
121
|
+
aiwiki context "AIWiki产品定位" --mode decide
|
|
122
|
+
aiwiki context "Karpathy LLM Wiki" --mode research
|
|
123
|
+
aiwiki context "我的公众号文章风格" --mode style
|
|
124
|
+
aiwiki context "某个知识点" --mode learn
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
建议返回结构:
|
|
128
|
+
|
|
129
|
+
```json
|
|
130
|
+
{
|
|
131
|
+
"schema_version": "aiwiki.context.v2",
|
|
132
|
+
"query": "AIWiki产品定位",
|
|
133
|
+
"mode": "decide",
|
|
134
|
+
"external_sources": [],
|
|
135
|
+
"personal_insights": [],
|
|
136
|
+
"past_outputs": [],
|
|
137
|
+
"conflicts": [],
|
|
138
|
+
"usable_arguments": [],
|
|
139
|
+
"missing_context": [],
|
|
140
|
+
"recommended_next_action": ""
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
兼容策略:
|
|
145
|
+
|
|
146
|
+
- 保留 v1 `matches` 结构一段时间。
|
|
147
|
+
- v2 可以先在结果中新增字段,不立刻移除旧字段。
|
|
148
|
+
- `--mode` 缺省为 `general`。
|
|
149
|
+
|
|
150
|
+
### `aiwiki query`
|
|
151
|
+
|
|
152
|
+
定位:给人看的知识资产摘要,不是普通搜索结果。
|
|
153
|
+
|
|
154
|
+
建议输出分组:
|
|
155
|
+
|
|
156
|
+
```text
|
|
157
|
+
外部资料
|
|
158
|
+
- ...
|
|
159
|
+
|
|
160
|
+
个人判断
|
|
161
|
+
- ...
|
|
162
|
+
|
|
163
|
+
已发布输出
|
|
164
|
+
- ...
|
|
165
|
+
|
|
166
|
+
证据与冲突
|
|
167
|
+
- ...
|
|
168
|
+
|
|
169
|
+
建议下一步
|
|
170
|
+
- ...
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
优先级:
|
|
174
|
+
|
|
175
|
+
- 命中 output 和 insight 时,展示在 source 前面。
|
|
176
|
+
- source 只作为证据,不默认当成结论。
|
|
177
|
+
|
|
178
|
+
### `aiwiki lint`
|
|
179
|
+
|
|
180
|
+
定位:从文件结构健康检查升级为知识资产健康检查。
|
|
181
|
+
|
|
182
|
+
保留现有检查:
|
|
183
|
+
|
|
184
|
+
- 缺少系统文件。
|
|
185
|
+
- Source Card 没有 Wiki Entry。
|
|
186
|
+
- Wiki Entry 缺少 source_card / raw_file。
|
|
187
|
+
- fallback scaffold 过期。
|
|
188
|
+
- grounding needs review。
|
|
189
|
+
- `represents_user_view=true` 但不是 output。
|
|
190
|
+
- 重复 URL、重复标题、断链。
|
|
191
|
+
|
|
192
|
+
新增质量检查:
|
|
193
|
+
|
|
194
|
+
- 某主题只有 source,没有 insight。
|
|
195
|
+
- 某 insight 没有 `based_on`。
|
|
196
|
+
- 某 output 没有关联 source 或 insight。
|
|
197
|
+
- source 被错误标记为代表用户观点。
|
|
198
|
+
- claim 没有 source quote 或证据边界。
|
|
199
|
+
- 某主题存在冲突观点但没有决策结论。
|
|
200
|
+
- enriched entry 只有摘要,没有 reusable judgment / reusable knowledge。
|
|
201
|
+
|
|
202
|
+
### `aiwiki next`
|
|
203
|
+
|
|
204
|
+
定位:从命令导航升级为加工建议。
|
|
205
|
+
|
|
206
|
+
建议输出:
|
|
207
|
+
|
|
208
|
+
```text
|
|
209
|
+
当前最值得做:
|
|
210
|
+
- 这 3 篇 source 只有摘要,没有个人判断。
|
|
211
|
+
- 这个主题已有 5 条 source,可以生成主题页。
|
|
212
|
+
- 这条 output 没有证据链,建议补 linked sources。
|
|
213
|
+
- 这个观点和历史输出存在冲突,建议进入 review。
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### `aiwiki review` 或 `aiwiki retain`
|
|
217
|
+
|
|
218
|
+
定位:轻量回看,不做重学习系统。
|
|
219
|
+
|
|
220
|
+
第一版只做候选生成:
|
|
221
|
+
|
|
222
|
+
```text
|
|
223
|
+
今日建议回看:
|
|
224
|
+
- 3 条个人 insight
|
|
225
|
+
- 2 条高价值 source knowledge
|
|
226
|
+
- 1 条已输出文章中的核心观点
|
|
227
|
+
|
|
228
|
+
可生成卡片:
|
|
229
|
+
- 观点卡
|
|
230
|
+
- 证据卡
|
|
231
|
+
- 反驳卡
|
|
232
|
+
- 案例卡
|
|
233
|
+
- 输出卡
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
暂不做:
|
|
237
|
+
|
|
238
|
+
- FSRS。
|
|
239
|
+
- 每日强制复习。
|
|
240
|
+
- Anki 兼容。
|
|
241
|
+
- 学习进度系统。
|
|
242
|
+
|
|
243
|
+
## README 与对外话术
|
|
244
|
+
|
|
245
|
+
建议把开头改得更锋利:
|
|
246
|
+
|
|
247
|
+
```text
|
|
248
|
+
AIWiki 是一个 Agent-first 本地上下文编译器。
|
|
249
|
+
|
|
250
|
+
它不替代搜索,也不替你读书,而是把你真正需要反复调用的资料、判断和输出,编译成 AI 能查询、能引用、能检查、能继续使用的本地知识资产。
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
“它解决什么”建议改成:
|
|
254
|
+
|
|
255
|
+
- 公开资料搜索得到,但你的使用场景、判断和输出痕迹搜不到。
|
|
256
|
+
- 链接和资料散在聊天记录里,后续很难被 Agent 复用。
|
|
257
|
+
- AI 总结过一次内容,但没有沉淀成可追踪、可查询、可检查的上下文资产。
|
|
258
|
+
- 想把来源证据、个人判断、选题、大纲和已输出内容放进同一个本地知识系统。
|
|
259
|
+
- 想让宿主 Agent 负责理解内容,让 AIWiki 负责稳定落盘、连接和检查。
|
|
260
|
+
|
|
261
|
+
不建议继续主打:
|
|
262
|
+
|
|
263
|
+
```text
|
|
264
|
+
打造你的 AI 个人知识库
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
这个说法太泛,容易被理解成“AI 时代还要不要收藏夹”。
|
|
268
|
+
|
|
269
|
+
## 分阶段落地
|
|
270
|
+
|
|
271
|
+
### P0:定位与 schema 心智对齐
|
|
272
|
+
|
|
273
|
+
目标:不大改代码,先把产品定位和现有字段解释清楚。
|
|
274
|
+
|
|
275
|
+
任务:
|
|
276
|
+
|
|
277
|
+
1. 更新 README、FAQ、USAGE 的定位话术。
|
|
278
|
+
2. 在 docs 中新增“三类资产模型”说明。
|
|
279
|
+
3. 在 Agent handoff / skill 中要求宿主 Agent 区分 source、insight、output。
|
|
280
|
+
4. 明确 `source_role=input` 永远不默认代表用户观点。
|
|
281
|
+
5. 为 `processing` 角色补充 personal insight 示例 payload。
|
|
282
|
+
|
|
283
|
+
验收:
|
|
284
|
+
|
|
285
|
+
- 新用户能在 README 前 30 秒理解 AIWiki 不是搜索替代品。
|
|
286
|
+
- 文档能解释 source、insight、output 三层差异。
|
|
287
|
+
- 不引入新命令、不破坏旧 payload。
|
|
288
|
+
|
|
289
|
+
### P1:任务上下文与质量检查
|
|
290
|
+
|
|
291
|
+
目标:让 AIWiki 从“能查到资料”升级为“能为任务组织上下文”。
|
|
292
|
+
|
|
293
|
+
任务:
|
|
294
|
+
|
|
295
|
+
1. `context` 增加 `--mode`。
|
|
296
|
+
2. `context` 输出新增 `external_sources`、`personal_insights`、`past_outputs`、`conflicts`、`usable_arguments`、`missing_context`。
|
|
297
|
+
3. `query` 输出按资产类型分组。
|
|
298
|
+
4. `lint` 增加 insight/output/evidence 质量检查。
|
|
299
|
+
5. `next` 增加加工建议。
|
|
300
|
+
|
|
301
|
+
验收:
|
|
302
|
+
|
|
303
|
+
- 同一个 query 在 `write`、`decide`、`research`、`style` 下返回不同的建议结构。
|
|
304
|
+
- 有 insight/output 时优先暴露,不被 source 淹没。
|
|
305
|
+
- `lint` 能指出“只有资料、没有个人判断”和“输出没有证据链”。
|
|
306
|
+
|
|
307
|
+
### P2:轻量回看闭环
|
|
308
|
+
|
|
309
|
+
目标:吸收 Retain 思想,但不把 AIWiki 变成学习软件。
|
|
310
|
+
|
|
311
|
+
任务:
|
|
312
|
+
|
|
313
|
+
1. 新增 `review` 或 `retain` 的候选生成命令。
|
|
314
|
+
2. 支持观点卡、证据卡、反驳卡、案例卡、输出卡。
|
|
315
|
+
3. Review Queue 只作为入口,不成为默认强制流程。
|
|
316
|
+
|
|
317
|
+
验收:
|
|
318
|
+
|
|
319
|
+
- 命令能生成今日回看候选。
|
|
320
|
+
- 不需要用户维护复杂学习计划。
|
|
321
|
+
- 不引入 FSRS 或重型记忆系统。
|
|
322
|
+
|
|
323
|
+
## 不做清单
|
|
324
|
+
|
|
325
|
+
- 不做通用网页抓取。
|
|
326
|
+
- 不做多知识库。
|
|
327
|
+
- 不做 CLI 内置 LLM。
|
|
328
|
+
- 不做默认人工审核流程。
|
|
329
|
+
- 不把 Review Queue 变成强制主流程。
|
|
330
|
+
- 不把 AIWiki 改成 Anki 或 Knowledge MEMO。
|
|
331
|
+
- 不用 `aiwiki-pro` 作为用户命令。
|
|
332
|
+
|
|
333
|
+
## 推荐任务拆分
|
|
334
|
+
|
|
335
|
+
1. `AIWIKI-POS-001`:更新 README / FAQ / USAGE 定位话术。
|
|
336
|
+
2. `AIWIKI-POS-002`:补充三类资产模型文档和示例 payload。
|
|
337
|
+
3. `AIWIKI-CTX-001`:为 `context` 增加 `--mode` 和 v2 结果字段。
|
|
338
|
+
4. `AIWIKI-QRY-001`:让 `query` 按 source / insight / output 分组展示。
|
|
339
|
+
5. `AIWIKI-LINT-001`:增加知识质量 lint。
|
|
340
|
+
6. `AIWIKI-NEXT-001`:让 `next` 输出加工建议。
|
|
341
|
+
7. `AIWIKI-REV-001`:设计轻量 review / retain 候选生成。
|
|
342
|
+
|
|
343
|
+
## 最终判断
|
|
344
|
+
|
|
345
|
+
这份定位文档对 AIWiki 是利好。它指出了“普通个人知识库/资料索引”在 AI 时代价值下降,这个判断应该接受;但它没有否定 AIWiki 的 Agent-first 本地上下文后端方向。真正可取的调整,是把 AIWiki 从“存知识”进一步收窄成“存上下文、判断和使用痕迹”。
|
|
346
|
+
|
|
347
|
+
AIWiki 下一步最该做的不是扩功能,而是把已有地基讲清楚、排出优先级,然后补齐 personal insight、output knowledge、task context 和 quality lint 这四块。
|
package/docs/USAGE.md
CHANGED
|
@@ -434,3 +434,59 @@ aiwiki status
|
|
|
434
434
|
- `next_action`: the recommended next command.
|
|
435
435
|
|
|
436
436
|
`aiwiki next` uses the same repair order: fix workspace structure first, then lint errors, lint warnings, empty-workspace onboarding, and finally healthy-state query guidance.
|
|
437
|
+
|
|
438
|
+
## Query and Context Filters
|
|
439
|
+
|
|
440
|
+
`aiwiki context` and `aiwiki query` use local Markdown/frontmatter search. They do not use vector search, a database, external search, or RAG-over-wiki.
|
|
441
|
+
|
|
442
|
+
Useful filters:
|
|
443
|
+
|
|
444
|
+
```bash
|
|
445
|
+
aiwiki context "AI Agent" --type wiki_entries --source-role input --wiki-type source_knowledge --status active --limit 5
|
|
446
|
+
aiwiki query "AI Agent" --type source_cards --status to-review --limit 3
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
Supported filters:
|
|
450
|
+
|
|
451
|
+
- `--type`: one result group, such as `wiki_entries`, `source_cards`, `claims`, `topics`, `outlines`, or `raw_refs`.
|
|
452
|
+
- `--source-role`: frontmatter `source_role`, usually `input`, `processing`, or `output`.
|
|
453
|
+
- `--wiki-type`: frontmatter `wiki_type`, such as `source_knowledge` or `personal_knowledge`.
|
|
454
|
+
- `--status`: frontmatter status, such as `active`, `to-review`, `ready`, or `draft`.
|
|
455
|
+
- `--limit`: per-group result limit, clamped from 1 to 50.
|
|
456
|
+
|
|
457
|
+
The JSON result keeps the stable `schema_version: "aiwiki.context.v1"` and now also includes:
|
|
458
|
+
|
|
459
|
+
- `query_scope`: filters, limit, and searched groups.
|
|
460
|
+
- `result_quality`: total matches, best score, whether a Wiki Entry was found, and warnings.
|
|
461
|
+
- `recommended_next_action`: for example `use_matches_for_answer`, `review_grounding_or_enrich_entry`, or `broaden_query_or_ingest_source`.
|
|
462
|
+
- Per match: `match_reasons`, `quality_signals`, and `related_refs`.
|
|
463
|
+
|
|
464
|
+
Use `match_reasons` to explain why a result matched. Use `quality_signals` before answering confidently: scaffold or grounding-review entries should be treated as traceable leads, not final knowledge.
|
|
465
|
+
|
|
466
|
+
## Agent Skill Sync
|
|
467
|
+
|
|
468
|
+
AIWiki does not modify Agent configuration during `npm install`. After first install or upgrade, sync the packaged skill explicitly:
|
|
469
|
+
|
|
470
|
+
```bash
|
|
471
|
+
aiwiki agent sync --yes
|
|
472
|
+
aiwiki agent check
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
For one host Agent:
|
|
476
|
+
|
|
477
|
+
```bash
|
|
478
|
+
aiwiki agent sync --agent codex --yes
|
|
479
|
+
aiwiki agent sync --agent claude --yes
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
Useful Agent-facing options:
|
|
483
|
+
|
|
484
|
+
```bash
|
|
485
|
+
aiwiki agent sync --dry-run
|
|
486
|
+
aiwiki agent sync --json --yes
|
|
487
|
+
aiwiki agent check --json
|
|
488
|
+
aiwiki agent help
|
|
489
|
+
aiwiki context --help
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
`agent sync` is safe for first install and cross-version upgrades. It installs missing targets, leaves current targets unchanged, and backs up changed installed skill files before overwrite. If a backup is created, tell the user the backup path and that rollback means copying the backup file back to the target path.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@itradingai/aiwiki",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.18",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Agent-first AI knowledge base CLI for turning articles, links and notes into Obsidian-ready source cards, topics, outlines and reusable knowledge assets.",
|
|
6
6
|
"license": "MIT",
|
package/skill/LINT_PROTOCOL.md
CHANGED
|
@@ -15,15 +15,23 @@ Use this protocol when the user asks:
|
|
|
15
15
|
aiwiki lint
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
2.
|
|
19
|
-
|
|
18
|
+
2. When you need machine-readable triage, call:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
aiwiki lint --json
|
|
22
|
+
aiwiki next
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
3. Read the terminal report.
|
|
26
|
+
4. Mention the report path, usually:
|
|
20
27
|
|
|
21
28
|
```text
|
|
22
29
|
dashboards/Lint Report.md
|
|
23
30
|
```
|
|
24
31
|
|
|
25
|
-
|
|
26
|
-
|
|
32
|
+
5. Explain warnings and errors as structure-health feedback.
|
|
33
|
+
6. Do not frame lint as "the user must manually audit every note".
|
|
34
|
+
7. If `aiwiki next` recommends `aiwiki agent sync --yes`, treat Agent skill setup as the next operational step before asking the user to ingest or query more material.
|
|
27
35
|
|
|
28
36
|
## Issue Meaning
|
|
29
37
|
|
|
@@ -39,4 +47,3 @@ Prefer small, traceable fixes:
|
|
|
39
47
|
- Fix broken wikilinks.
|
|
40
48
|
- Add missing `source_card` or `raw_file` paths.
|
|
41
49
|
- Ask the host Agent to provide `analysis` for scaffold entries.
|
|
42
|
-
|
package/skill/QUERY_PROTOCOL.md
CHANGED
|
@@ -16,11 +16,29 @@ Use this protocol when the user asks:
|
|
|
16
16
|
aiwiki context "<topic>"
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
+
Add filters when the user intent is specific:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
aiwiki context "<topic>" --type wiki_entries --status active --limit 5
|
|
23
|
+
aiwiki context "<topic>" --source-role input --wiki-type source_knowledge --limit 5
|
|
24
|
+
aiwiki context "<topic>" --source-role output --limit 5
|
|
25
|
+
aiwiki context "<topic>" --type source_cards --status to-review --limit 5
|
|
26
|
+
```
|
|
27
|
+
|
|
19
28
|
3. Read the JSON result.
|
|
20
29
|
4. Prefer `matches.wiki_entries` before source cards, claims, topics, outlines, or raw refs.
|
|
21
|
-
5.
|
|
22
|
-
6.
|
|
23
|
-
7.
|
|
30
|
+
5. Read `query_scope` to understand what was searched.
|
|
31
|
+
6. Read `result_quality` before deciding how confident the answer can be.
|
|
32
|
+
7. Follow `recommended_next_action`:
|
|
33
|
+
- `use_matches_for_answer`: answer from the matches.
|
|
34
|
+
- `review_grounding_or_enrich_entry`: answer cautiously and suggest enrichment/review.
|
|
35
|
+
- `review_source_cards_then_create_wiki_entry`: explain that only source-level material exists.
|
|
36
|
+
- `broaden_query_or_ingest_source`: ask for a broader query or ingest more material.
|
|
37
|
+
8. Use `match_reasons` to explain why an item was selected.
|
|
38
|
+
9. Use `quality_signals` to decide whether the result is enriched, scaffold, needs grounding review, or only has weak source support.
|
|
39
|
+
10. Use `related_refs` to mention useful local follow-up files.
|
|
40
|
+
11. If the best Wiki Entry has `quality: "scaffold"` or `quality_signals` includes `grounding:needs_review`, tell the user that the entry is a traceable lead and may need Agent enrichment or evidence review.
|
|
41
|
+
12. Do not scan `02-raw` by default unless:
|
|
24
42
|
- Wiki Entries are insufficient.
|
|
25
43
|
- The user asks to verify the original source.
|
|
26
44
|
- There is a source conflict.
|
|
@@ -35,4 +53,3 @@ Include:
|
|
|
35
53
|
- Source basis.
|
|
36
54
|
- Known gaps or scaffold warnings.
|
|
37
55
|
- Suggested next step.
|
|
38
|
-
|
package/skill/SKILL.md
CHANGED
|
@@ -3,12 +3,46 @@ name: aiwiki
|
|
|
3
3
|
description: Agent-first AIWiki workflow for turning one URL/body into local Wiki knowledge files.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
+
<!-- aiwiki-skill-version: 0.2.18 -->
|
|
7
|
+
|
|
6
8
|
# AIWiki Skill
|
|
7
9
|
|
|
8
10
|
Use this skill when the user asks an Agent to process one URL, article body, or local text file with the `aiwiki` keyword, or says phrases like `入库 <url>` / `收录 <url>` / `从 AIWiki 里了解 <topic>`.
|
|
9
11
|
|
|
10
12
|
AIWiki CLI does not fetch webpages and does not call an LLM. The host Agent reads and understands the source; AIWiki validates, writes, links, tracks, queries, and lints local Markdown knowledge files.
|
|
11
13
|
|
|
14
|
+
## Agent-First Setup and Upgrade
|
|
15
|
+
|
|
16
|
+
When the user asks you to install, update, or repair AIWiki Agent integration, prefer the idempotent sync command:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
aiwiki agent sync --yes
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
For a specific host:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
aiwiki agent sync --agent codex --yes
|
|
26
|
+
aiwiki agent sync --agent claude --yes
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Use `--dry-run` to preview without writing, and `--json` when you need machine-readable status:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
aiwiki agent sync --agent codex --dry-run
|
|
33
|
+
aiwiki agent sync --json --yes
|
|
34
|
+
aiwiki agent check --json
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Sync behavior:
|
|
38
|
+
|
|
39
|
+
- missing installed skill: install the packaged AIWiki skill
|
|
40
|
+
- current installed skill: leave unchanged
|
|
41
|
+
- different installed skill: backup the old file, then overwrite with the packaged skill
|
|
42
|
+
- unsupported host: do not write; use `aiwiki prompt agent` as a manual fallback
|
|
43
|
+
|
|
44
|
+
After sync, tell the user the target path, any backup path, and that the target Agent may need to restart or reload before the new skill is active. Never edit Agent config during `npm install`; sync is the explicit safe step.
|
|
45
|
+
|
|
12
46
|
## Knowledge Base Purpose
|
|
13
47
|
|
|
14
48
|
Before ingesting, querying, linting, or reorganizing material, read `_system/purpose.md` in the target AIWiki workspace when it exists. Treat it as the local contract for:
|
|
@@ -143,7 +177,26 @@ When the user asks to understand a topic from AIWiki, call:
|
|
|
143
177
|
aiwiki context "<topic>"
|
|
144
178
|
```
|
|
145
179
|
|
|
146
|
-
Use
|
|
180
|
+
Use filters when the user's intent is clear:
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
aiwiki context "<topic>" --type wiki_entries --status active --limit 5
|
|
184
|
+
aiwiki context "<topic>" --source-role output --limit 5
|
|
185
|
+
aiwiki context "<topic>" --type source_cards --status to-review --limit 5
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Use the returned JSON to answer. Prefer Wiki Entries first, but read these fields before responding:
|
|
189
|
+
|
|
190
|
+
- `query_scope`: filters, limit, and searched groups
|
|
191
|
+
- `result_quality`: total matches, best score, and whether a Wiki Entry was found
|
|
192
|
+
- `recommended_next_action`: whether to answer, broaden the query, enrich, or review grounding
|
|
193
|
+
- `match_reasons`: why each result matched
|
|
194
|
+
- `quality_signals`: scaffold, enriched, grounding, status, and relationship hints
|
|
195
|
+
- `related_refs`: local wikilinks and frontmatter relationships
|
|
196
|
+
|
|
197
|
+
Do not scan `02-raw` by default unless the Wiki result is insufficient, the user asks to verify the original text, or sources conflict.
|
|
198
|
+
|
|
199
|
+
If `quality_signals` contains `quality:scaffold` or `grounding:needs_review`, tell the user the result is a traceable lead that needs enrichment or review. Do not present it as final confirmed knowledge.
|
|
147
200
|
|
|
148
201
|
For direct human terminal output, use:
|
|
149
202
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# AIWiki Skill Upgrade Notes
|
|
2
|
+
|
|
3
|
+
Use this note when an Agent finishes `aiwiki agent sync`.
|
|
4
|
+
|
|
5
|
+
## Current Major Changes
|
|
6
|
+
|
|
7
|
+
- Agent integration should use `aiwiki agent sync --yes` for both first install and upgrades.
|
|
8
|
+
- Sync backs up changed installed skill files before overwriting them.
|
|
9
|
+
- `aiwiki agent check --json` and `aiwiki agent sync --json --yes` provide machine-readable status for Agents.
|
|
10
|
+
- `aiwiki context` supports `--type`, `--source-role`, `--wiki-type`, `--status`, and `--limit`.
|
|
11
|
+
- Context JSON includes `query_scope`, `result_quality`, `recommended_next_action`, `match_reasons`, `quality_signals`, and `related_refs`.
|
|
12
|
+
- Scaffold or grounding-review matches are traceable leads, not final confirmed knowledge.
|
|
13
|
+
|
|
14
|
+
## Agent Reply After Sync
|
|
15
|
+
|
|
16
|
+
Tell the user:
|
|
17
|
+
|
|
18
|
+
- which Agent targets were installed, current, updated, or unsupported
|
|
19
|
+
- where the new skill was written
|
|
20
|
+
- where the old skill was backed up, if any
|
|
21
|
+
- that the Agent may need a restart or reload
|
|
22
|
+
- that rollback is possible by copying the backup file back to the target path
|