@itradingai/aiwiki 0.2.15 → 0.2.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/src/app.js CHANGED
@@ -6,7 +6,7 @@ import { fileURLToPath } from "node:url";
6
6
  import { flagBool, flagString, parseArgs } from "./args.js";
7
7
  import { buildContext } from "./context.js";
8
8
  import { deriveFileTitle, ingestFile, ingestPayload } from "./ingest.js";
9
- import { lintWorkspace, renderLintReport, writeLintReport } from "./lint.js";
9
+ import { filterLintReport, lintWorkspace, renderLintReport, renderLintSummary, writeLintReport } from "./lint.js";
10
10
  import { CliError, writeLine } from "./output.js";
11
11
  import { confirmInit, directorySummary, doctor, exists, initWorkspace, promptForSetup, promptForInitPath, readConfig, resolveWorkspace, setDefaultWorkspace, statusSummary } from "./workspace.js";
12
12
  export async function runCli(argv, streams = { stdout: process.stdout, stderr: process.stderr }) {
@@ -159,10 +159,16 @@ export async function runCli(argv, streams = { stdout: process.stdout, stderr: p
159
159
  }
160
160
  if (command === "lint") {
161
161
  const root = await resolveWorkspace(flagString(args, "path"));
162
- const report = await lintWorkspace(root);
163
- const reportPath = await writeLintReport(root, report);
162
+ const severity = parseLintSeverity(flagString(args, "severity"));
163
+ const report = filterLintReport(await lintWorkspace(root), severity);
164
+ if (flagBool(args, "json")) {
165
+ writeLine(streams.stdout, JSON.stringify(report, null, 2));
166
+ return 0;
167
+ }
168
+ const reportPath = flagBool(args, "no-write") ? undefined : await writeLintReport(root, report);
169
+ writeLine(streams.stdout, renderLintSummary(report, reportPath));
170
+ writeLine(streams.stdout, "");
164
171
  writeLine(streams.stdout, renderLintReport(report));
165
- writeLine(streams.stdout, `report: ${reportPath}`);
166
172
  return 0;
167
173
  }
168
174
  if (command === "ingest-agent") {
@@ -256,6 +262,15 @@ function printHelp(stream) {
256
262
  writeLine(stream, " aiwiki ingest-url <url> --content-file <file>");
257
263
  writeLine(stream, " aiwiki agent check");
258
264
  }
265
+ function parseLintSeverity(value) {
266
+ if (value === undefined) {
267
+ return undefined;
268
+ }
269
+ if (value === "error" || value === "warning" || value === "info") {
270
+ return value;
271
+ }
272
+ throw new CliError("lint --severity must be error, warning, or info");
273
+ }
259
274
  async function discoverAgentTargets() {
260
275
  const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "..");
261
276
  const skillSource = path.join(packageRoot, "skill", "SKILL.md");
package/dist/src/lint.js CHANGED
@@ -19,14 +19,17 @@ export async function lintWorkspace(rootPath, now = new Date().toISOString()) {
19
19
  ...await readNotes(root, "08-outputs/outlines")
20
20
  ];
21
21
  const issues = [];
22
+ issues.push(...await systemFileIssues(root));
22
23
  const wikiSourceCards = new Set(wikiEntries.map((note) => frontmatterString(note.frontmatter, "source_card")).filter(Boolean));
23
24
  for (const card of sourceCards) {
24
25
  if (!wikiSourceCards.has(card.path)) {
25
26
  issues.push({
26
27
  severity: "warning",
27
28
  path: card.path,
28
- message: "Source Card 没有对应 Wiki Entry。",
29
- suggestion: `重新入库或生成 05-wiki/source-knowledge/${path.basename(card.path)}`
29
+ category: "isolated_source_card",
30
+ action: "reingest",
31
+ message: "Source Card has no matching Wiki Entry.",
32
+ suggestion: `Reingest or create a matching 05-wiki/source-knowledge/${path.basename(card.path)} entry.`
30
33
  });
31
34
  }
32
35
  }
@@ -35,26 +38,68 @@ export async function lintWorkspace(rootPath, now = new Date().toISOString()) {
35
38
  const rawFile = frontmatterString(entry.frontmatter, "raw_file");
36
39
  const mode = frontmatterString(entry.frontmatter, "generation_mode");
37
40
  if (!sourceCard) {
38
- issues.push({ severity: "warning", path: entry.path, message: "Wiki Entry 缺少 source_card。", suggestion: "补写 source_card vault 路径。" });
41
+ issues.push({
42
+ severity: "warning",
43
+ path: entry.path,
44
+ category: "missing_source",
45
+ action: "reingest",
46
+ message: "Wiki Entry is missing source_card.",
47
+ suggestion: "Add the vault path of the source card."
48
+ });
39
49
  }
40
50
  if (!rawFile) {
41
- issues.push({ severity: "warning", path: entry.path, message: "Wiki Entry 缺少 raw_file。", suggestion: "补写 raw_file vault 路径。" });
51
+ issues.push({
52
+ severity: "warning",
53
+ path: entry.path,
54
+ category: "missing_source",
55
+ action: "reingest",
56
+ message: "Wiki Entry is missing raw_file.",
57
+ suggestion: "Add the vault path of the raw source file."
58
+ });
42
59
  }
43
60
  if (mode === "deterministic_fallback") {
44
- issues.push({ severity: "info", path: entry.path, message: "Wiki Entry 是 deterministic fallback,仅包含来源和正文预览。", suggestion: "让宿主 Agent 基于原文补充 analysis 或 wiki_entry。" });
61
+ issues.push({
62
+ severity: "info",
63
+ path: entry.path,
64
+ category: "stale_scaffold",
65
+ action: "enrich",
66
+ message: "Wiki Entry is a deterministic fallback and only contains source trace plus a content preview.",
67
+ suggestion: "Ask the host Agent to enrich it with analysis or a full wiki_entry."
68
+ });
45
69
  const createdAt = Date.parse(frontmatterString(entry.frontmatter, "created_at") ?? "");
46
70
  if (Number.isFinite(createdAt) && Date.parse(now) - createdAt > 7 * 24 * 60 * 60 * 1000) {
47
- issues.push({ severity: "warning", path: entry.path, message: "fallback Wiki Entry 超过 7 天未补全。", suggestion: "重新运行宿主 Agent 生成 enriched Wiki Entry。" });
71
+ issues.push({
72
+ severity: "warning",
73
+ path: entry.path,
74
+ category: "stale_scaffold",
75
+ action: "enrich",
76
+ message: "Fallback Wiki Entry is older than 7 days.",
77
+ suggestion: "Reingest with a host Agent to generate an enriched Wiki Entry."
78
+ });
48
79
  }
49
80
  }
50
81
  if (mode === "agent_enriched") {
51
- const hasSummary = /## 一句话总结/.test(entry.body) || Boolean(frontmatterString(entry.frontmatter, "summary"));
52
- const hasKeyPoints = /## 核心观点[\s\S]*-\s+/.test(entry.body);
82
+ const hasSummary = /##\s+.+/.test(entry.body) || Boolean(frontmatterString(entry.frontmatter, "summary"));
83
+ const hasKeyPoints = /-\s+/.test(entry.body);
53
84
  if (!hasSummary) {
54
- issues.push({ severity: "warning", path: entry.path, message: "agent_enriched Wiki Entry 缺少 summary。", suggestion: "让宿主 Agent 提供 analysis.summary。" });
85
+ issues.push({
86
+ severity: "warning",
87
+ path: entry.path,
88
+ category: "weak_entry",
89
+ action: "enrich",
90
+ message: "agent_enriched Wiki Entry is missing a summary.",
91
+ suggestion: "Ask the host Agent to provide analysis.summary."
92
+ });
55
93
  }
56
94
  if (!hasKeyPoints) {
57
- issues.push({ severity: "warning", path: entry.path, message: "agent_enriched Wiki Entry 缺少 key_points。", suggestion: "让宿主 Agent 提供 analysis.key_points。" });
95
+ issues.push({
96
+ severity: "warning",
97
+ path: entry.path,
98
+ category: "weak_entry",
99
+ action: "enrich",
100
+ message: "agent_enriched Wiki Entry is missing key points.",
101
+ suggestion: "Ask the host Agent to provide analysis.key_points."
102
+ });
58
103
  }
59
104
  }
60
105
  if (frontmatterBoolean(entry.frontmatter, "grounding_needs_review") === true) {
@@ -62,15 +107,24 @@ export async function lintWorkspace(rootPath, now = new Date().toISOString()) {
62
107
  issues.push({
63
108
  severity: "warning",
64
109
  path: entry.path,
65
- message: `Wiki Entry 需要 grounding 复核${markers.length ? `: ${markers.join(", ")}` : "。"}`,
66
- suggestion: "检查 source_quote 是否能在 Raw 中找到;coverage_suspected_incomplete 仅代表启发式疑似风险。"
110
+ category: "grounding_review",
111
+ action: "mark_reviewed",
112
+ message: `Wiki Entry needs grounding review${markers.length ? `: ${markers.join(", ")}` : "."}`,
113
+ suggestion: "Check whether source quotes are present in Raw. Heuristic coverage risks are not confirmed facts."
67
114
  });
68
115
  }
69
116
  if (frontmatterBoolean(entry.frontmatter, "represents_user_view") === true && frontmatterString(entry.frontmatter, "source_role") !== "output") {
70
- issues.push({ severity: "warning", path: entry.path, message: "只有 output 角色应标记为代表用户观点。", suggestion: "将 represents_user_view 改为 false,或将 source_role 改为 output。" });
117
+ issues.push({
118
+ severity: "warning",
119
+ path: entry.path,
120
+ category: "metadata_boundary",
121
+ action: "mark_reviewed",
122
+ message: "Only output source_role entries should represent the user's view.",
123
+ suggestion: "Set represents_user_view to false, or change source_role to output when it is user-authored output."
124
+ });
71
125
  }
72
126
  }
73
- issues.push(...duplicateIssues(sourceCards, "source_url", "重复 URL"));
127
+ issues.push(...duplicateIssues(sourceCards, "source_url", "Duplicate URL"));
74
128
  issues.push(...duplicateTitles(allNotes));
75
129
  issues.push(...brokenLinkIssues(root, allNotes));
76
130
  return {
@@ -84,6 +138,15 @@ export async function lintWorkspace(rootPath, now = new Date().toISOString()) {
84
138
  issues
85
139
  };
86
140
  }
141
+ export function filterLintReport(report, severity) {
142
+ if (!severity) {
143
+ return report;
144
+ }
145
+ return {
146
+ ...report,
147
+ issues: report.issues.filter((issue) => issue.severity === severity)
148
+ };
149
+ }
87
150
  export async function writeLintReport(rootPath, report) {
88
151
  const root = path.resolve(rootPath);
89
152
  const target = safeJoin(root, "dashboards", "Lint Report.md");
@@ -92,6 +155,8 @@ export async function writeLintReport(rootPath, report) {
92
155
  return relativePath(root, target);
93
156
  }
94
157
  export function renderLintReport(report) {
158
+ const counts = severityCounts(report.issues);
159
+ const topIssue = report.issues[0];
95
160
  return [
96
161
  "# AIWiki Lint Report",
97
162
  "",
@@ -103,17 +168,49 @@ export function renderLintReport(report) {
103
168
  `- Source Cards: ${report.summary.source_cards}`,
104
169
  `- Raw Files: ${report.summary.raw_files}`,
105
170
  `- Runs: ${report.summary.runs}`,
171
+ `- Errors: ${counts.error}`,
172
+ `- Warnings: ${counts.warning}`,
173
+ `- Info: ${counts.info}`,
174
+ `- Top Issue: ${topIssue ? formatIssueLine(topIssue) : "none"}`,
106
175
  "",
107
- "## Issues",
176
+ "## Suggested Handling Order",
108
177
  "",
109
- ...(report.issues.length ? report.issues.map((issue) => {
110
- const suffix = issue.path ? ` (${issue.path})` : "";
111
- const suggestion = issue.suggestion ? `\n - Suggested Fix: ${issue.suggestion}` : "";
112
- return `- [${issue.severity}] ${issue.message}${suffix}${suggestion}`;
113
- }) : ["- none"]),
178
+ "- Fix error issues first.",
179
+ "- Review warning issues next.",
180
+ "- Use info issues for enrichment and cleanup backlog.",
181
+ "",
182
+ ...renderIssueGroup("Errors", report.issues.filter((issue) => issue.severity === "error")),
183
+ ...renderIssueGroup("Warnings", report.issues.filter((issue) => issue.severity === "warning")),
184
+ ...renderIssueGroup("Info", report.issues.filter((issue) => issue.severity === "info")),
114
185
  ""
115
186
  ].join("\n");
116
187
  }
188
+ export function renderLintSummary(report, reportPath) {
189
+ const counts = severityCounts(report.issues);
190
+ const topIssue = report.issues[0];
191
+ return [
192
+ `lint_summary: errors=${counts.error} warnings=${counts.warning} info=${counts.info}`,
193
+ `top_issue: ${topIssue ? formatIssueLine(topIssue) : "none"}`,
194
+ ...(reportPath ? [`report: ${reportPath}`] : [])
195
+ ].join("\n");
196
+ }
197
+ async function systemFileIssues(root) {
198
+ const issues = [];
199
+ for (const systemFile of ["_system/purpose.md", "_system/index.md", "_system/log.md"]) {
200
+ if (await exists(path.join(root, systemFile))) {
201
+ continue;
202
+ }
203
+ issues.push({
204
+ severity: "error",
205
+ path: systemFile,
206
+ category: "workspace_structure",
207
+ action: "repair_structure",
208
+ message: `Required system file is missing: ${systemFile}`,
209
+ suggestion: `Run aiwiki setup --path "${root}" --yes`
210
+ });
211
+ }
212
+ return issues;
213
+ }
117
214
  async function readNotes(root, dir) {
118
215
  const absolute = path.join(root, dir);
119
216
  if (!(await exists(absolute))) {
@@ -163,7 +260,13 @@ function duplicateIssues(notes, field, label) {
163
260
  seen.set(value, [...(seen.get(value) ?? []), note.path]);
164
261
  }
165
262
  return Array.from(seen.entries()).flatMap(([value, paths]) => paths.length > 1
166
- ? [{ severity: "warning", message: `${label}: ${value}`, suggestion: paths.join(", ") }]
263
+ ? [{
264
+ severity: "warning",
265
+ category: "duplicate",
266
+ action: "mark_reviewed",
267
+ message: `${label}: ${value}`,
268
+ suggestion: paths.join(", ")
269
+ }]
167
270
  : []);
168
271
  }
169
272
  function duplicateTitles(notes) {
@@ -175,7 +278,13 @@ function duplicateTitles(notes) {
175
278
  seen.set(note.title, [...(seen.get(note.title) ?? []), note.path]);
176
279
  }
177
280
  return Array.from(seen.entries()).flatMap(([title, paths]) => paths.length > 1
178
- ? [{ severity: "info", message: `重复标题: ${title}`, suggestion: paths.join(", ") }]
281
+ ? [{
282
+ severity: "info",
283
+ category: "duplicate_title",
284
+ action: "archive",
285
+ message: `Duplicate title: ${title}`,
286
+ suggestion: paths.join(", ")
287
+ }]
179
288
  : []);
180
289
  }
181
290
  function brokenLinkIssues(root, notes) {
@@ -185,12 +294,43 @@ function brokenLinkIssues(root, notes) {
185
294
  for (const link of note.body.matchAll(/\[\[([^\]|]+)(?:\|[^\]]+)?\]\]/g)) {
186
295
  const target = link[1].replace(/\\/g, "/").replace(/\.md$/i, "");
187
296
  if (!existing.has(target) && !isRunLocalLink(target)) {
188
- issues.push({ severity: "error", path: note.path, message: `内部链接断裂: ${target}`, suggestion: "检查目标文件是否存在或更新 wikilink。" });
297
+ issues.push({
298
+ severity: "error",
299
+ path: note.path,
300
+ category: "broken_link",
301
+ action: "fix_link",
302
+ message: `Broken wikilink: ${target}`,
303
+ suggestion: "Check whether the target file exists or update the wikilink."
304
+ });
189
305
  }
190
306
  }
191
307
  }
192
308
  return issues;
193
309
  }
310
+ function renderIssueGroup(title, issues) {
311
+ return [
312
+ `## ${title}`,
313
+ "",
314
+ ...(issues.length ? issues.map((issue) => {
315
+ const suggestion = issue.suggestion ? `\n - Suggested Fix: ${issue.suggestion}` : "";
316
+ const action = issue.action ? `\n - Action: ${issue.action}` : "";
317
+ return `- ${formatIssueLine(issue)}${action}${suggestion}`;
318
+ }) : ["- none"]),
319
+ ""
320
+ ];
321
+ }
322
+ function formatIssueLine(issue) {
323
+ const suffix = issue.path ? ` (${issue.path})` : "";
324
+ const category = issue.category ? ` {${issue.category}}` : "";
325
+ return `[${issue.severity}]${category} ${issue.message}${suffix}`;
326
+ }
327
+ function severityCounts(issues) {
328
+ return {
329
+ error: issues.filter((issue) => issue.severity === "error").length,
330
+ warning: issues.filter((issue) => issue.severity === "warning").length,
331
+ info: issues.filter((issue) => issue.severity === "info").length
332
+ };
333
+ }
194
334
  function isRunLocalLink(target) {
195
335
  // Run-local notes are valid trace links but are not part of the long-term note set.
196
336
  return target.startsWith("09-runs/");
@@ -199,6 +199,28 @@ aiwiki query "<主题>"
199
199
  aiwiki lint
200
200
  ```
201
201
 
202
+ 需要机器读取时用:
203
+
204
+ ```bash
205
+ aiwiki lint --json
206
+ ```
207
+
208
+ 只想看某一级别时用:
209
+
210
+ ```bash
211
+ aiwiki lint --severity error
212
+ aiwiki lint --severity warning
213
+ aiwiki lint --severity info
214
+ ```
215
+
216
+ 只做临时检查、不改 dashboard 时用:
217
+
218
+ ```bash
219
+ aiwiki lint --no-write
220
+ ```
221
+
222
+ Lint 输出会包含摘要、最高优先级问题、分级报告,以及建议动作。把 `error` 当作必须先修的结构问题,把 `warning` 当作需要处理或复核的维护问题,把 `info` 当作富集、归档或后续整理 backlog。
223
+
202
224
  `context` 返回 JSON,注意其中的 `generation_mode`、`quality` 和 `warnings`。如果结果是 `deterministic_fallback` / `scaffold`,回复时要说明它只是可追溯脚手架,不是高质量知识提炼。
203
225
 
204
226
  `context` 也可能返回 grounding 字段。回复用户时可以把 `grounding_needs_review: true` 解释为“这条资料需要复核证据或覆盖度”,不要说成“AIWiki 已确认漏掉重点”。
package/docs/README.md CHANGED
@@ -9,6 +9,7 @@ AIWiki 是一个 Agent-first 的本地知识库工具,用来把宿主 Agent
9
9
  - 示例展示:[SHOWCASE.md](SHOWCASE.md)
10
10
  - 常见问题:[FAQ.md](FAQ.md)
11
11
  - 路线图:[ROADMAP.md](ROADMAP.md)
12
+ - 开发记录:[development-log.md](development-log.md)
12
13
 
13
14
  ## Quick Start
14
15
 
package/docs/USAGE.md CHANGED
@@ -318,13 +318,23 @@ aiwiki query "AI Agent"
318
318
  aiwiki lint
319
319
  ```
320
320
 
321
+ 常用工作台模式:
322
+
323
+ ```bash
324
+ aiwiki lint --severity warning
325
+ aiwiki lint --json
326
+ aiwiki lint --no-write
327
+ ```
328
+
329
+ `lint` 会先输出 `lint_summary`、`top_issue` 和报告路径,再按 Errors / Warnings / Info 分组展示问题。每个问题会尽量给出建议动作,例如 `enrich`、`fix_link`、`reingest`、`archive` 或 `mark_reviewed`。`--severity` 只查看指定级别,`--json` 给宿主 Agent 使用,`--no-write` 只在终端检查而不更新 `dashboards/Lint Report.md`。
330
+
321
331
  查看下一步建议:
322
332
 
323
333
  ```bash
324
334
  aiwiki next
325
335
  ```
326
336
 
327
- `lint` 输出报告并写入 `dashboards/Lint Report.md`。
337
+ 默认情况下,`lint` 输出报告并写入 `dashboards/Lint Report.md`。
328
338
 
329
339
  ## 8. 高级调试
330
340
 
@@ -0,0 +1,97 @@
1
+ # AIWiki Development Log
2
+
3
+ This log records queue-driven AIWiki development milestones that should remain visible to future maintainers, not only in automation chat history.
4
+
5
+ ## 2026-06-05 - AIWIKI-004 lint workbench
6
+
7
+ Status: implemented, locally verified, pushed to GitHub, blocked on npm OTP before publication.
8
+
9
+ Version target: `@itradingai/aiwiki@0.2.16`
10
+
11
+ Commit: `932386c` (`Turn lint into an actionable maintenance workbench`)
12
+
13
+ ### Goal
14
+
15
+ Turn `aiwiki lint` from a plain report writer into a practical structure-maintenance workbench for humans and host Agents.
16
+
17
+ The scoped acceptance criteria were:
18
+
19
+ - summarize lint output in the terminal with errors, warnings, info, top issue, and report path;
20
+ - group the markdown report by severity and provide a handling order;
21
+ - support `--severity error|warning|info`;
22
+ - support `--json` for machine-readable Agent use;
23
+ - support `--no-write` for temporary checks that do not update `dashboards/Lint Report.md`;
24
+ - add lightweight knowledge-gap signals where feasible;
25
+ - attach advisory review actions such as `enrich`, `fix_link`, `archive`, `reingest`, and `mark_reviewed`.
26
+
27
+ ### Implemented
28
+
29
+ - `src/lint.ts`
30
+ - Added `LintSeverity` and advisory `LintAction`.
31
+ - Added issue `category` and `action` fields.
32
+ - Added system-file checks for `_system/purpose.md`, `_system/index.md`, and `_system/log.md`.
33
+ - Added signals for isolated Source Cards, stale deterministic fallback entries, grounding-review entries, metadata-boundary issues, duplicate URLs/titles, and broken wikilinks.
34
+ - Added severity filtering, terminal summary rendering, and severity-grouped report rendering.
35
+
36
+ - `src/app.ts`
37
+ - Added `aiwiki lint --severity error|warning|info`.
38
+ - Added `aiwiki lint --json`.
39
+ - Added `aiwiki lint --no-write`.
40
+ - Kept the default behavior of writing `dashboards/Lint Report.md`.
41
+
42
+ - `tests/cli.test.ts` and `tests/ingest.test.ts`
43
+ - Covered lint summary output, severity filtering, JSON output, no-write behavior, and updated lint issue text assertions.
44
+
45
+ - `docs/USAGE.md` and `docs/AGENT_HANDOFF.md`
46
+ - Documented human and Agent-facing lint modes.
47
+
48
+ ### Verification
49
+
50
+ - `npm test`: passed, 53 tests.
51
+ - `npm run release:check`: passed, including 53 tests and release-check.
52
+ - `npm pack --dry-run`: passed for `@itradingai/aiwiki@0.2.16`.
53
+ - Clean export pack from `C:/tmp/aiwiki-004-publish`: passed, 31 files, shasum `945c70d3d4cf20c9550deaaf92036786b75e62cf`.
54
+
55
+ ### Release State
56
+
57
+ GitHub push succeeded:
58
+
59
+ ```text
60
+ 2e4b253..932386c main -> main
61
+ ```
62
+
63
+ npm publication is blocked by a one-time password challenge:
64
+
65
+ ```text
66
+ npm error code EOTP
67
+ npm error This operation requires a one-time password from your authenticator.
68
+ ```
69
+
70
+ Current registry version remains `0.2.15`, so remote smoke tests for `0.2.16` have not run yet.
71
+
72
+ ### Resume Steps
73
+
74
+ From the clean publish directory:
75
+
76
+ ```powershell
77
+ cd C:\tmp\aiwiki-004-publish
78
+ npm publish --access public --otp=<code>
79
+ npm view @itradingai/aiwiki version
80
+ ```
81
+
82
+ After `npm view` returns `0.2.16`, run remote smoke tests for:
83
+
84
+ ```bash
85
+ aiwiki lint --path <tmp-vault>
86
+ aiwiki lint --severity warning --path <tmp-vault>
87
+ aiwiki lint --json --path <tmp-vault>
88
+ aiwiki lint --no-write --path <tmp-vault>
89
+ ```
90
+
91
+ Then update the queue through `published`, `remote_verified`, and `done`.
92
+
93
+ ### Notes For Future Changes
94
+
95
+ - Lint actions are advisory only. Do not make `archive`, `reingest`, `mark_reviewed`, or related actions mutate files without a separate explicit task.
96
+ - Keep lint local-file-only. Do not add crawling, vector search, RAG-over-wiki, RBAC, RSS, scheduled collection, or browser plugins under this queue item.
97
+ - The original working tree had unrelated `skill/SKILL.md` changes. Publication must use a clean commit export until that WIP is resolved.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itradingai/aiwiki",
3
- "version": "0.2.15",
3
+ "version": "0.2.16",
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",