@chronova/wiki-agent 1.6.5 → 1.7.1

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 CHANGED
@@ -16,8 +16,8 @@ A standalone Ollama-only documentation agent. It inspects your source code and g
16
16
  - **GitHub Actions** — `--init` automatically creates a scheduled update workflow in your repo
17
17
  - **Repo instructions** — reads `AGENTS.md` or `CLAUDE.md` from the project root and follows all conventions documented there
18
18
  - **Change reports** — each run writes `.wiki/.last-update-report.md` with created/edited pages, used as the staging PR body in CI
19
- - **Restricted toolset** — the agent can only read files, write under `.wiki/`, run read-only git subcommands, and inspect pull requests via a read-only `gh` CLI tool; there is no shell tool
20
- - **Staging PR staleness check** — before writing in update mode, the agent checks for open wiki staging PRs and abandons the update if a newer one already exists, preventing duplicate PRs
19
+ - **Restricted toolset** — the agent can only read files, write under `.wiki/`, run read-only git subcommands, and use a `gh` CLI tool for inspecting pull requests and closing stale wiki staging PRs; there is no shell tool
20
+ - **Staging PR staleness check** — before writing in update mode, the agent checks for open wiki staging PRs, abandons the update if a newer one already exists, and closes stale ones with a comment ("This branch is from an earlier staging run and is stale. Closing")
21
21
  - **Frontmatter stripping** — YAML frontmatter is stripped before publishing to the GitHub Wiki tab, since GitHub Wiki renders frontmatter as literal text
22
22
 
23
23
  ## Quickstart
@@ -120,7 +120,7 @@ For cloud:
120
120
  | `WIKI_OLLAMA_BASE_URL` | Override Ollama server URL | `http://localhost:11434` / `https://ollama.com` |
121
121
  | `WIKI_MODEL` | Override model ID | from config |
122
122
  | `WIKI_RECURSION_LIMIT` | Max agent iterations | `200` |
123
- | `GH_TOKEN` | GitHub token for the read-only `gh` CLI tool (used in CI for the staging PR staleness check) | from environment |
123
+ | `GH_TOKEN` | GitHub token for the `gh` CLI tool (read-only inspection plus staging PR close/comment; used in CI for the staging PR staleness check) | from environment |
124
124
 
125
125
  Environment variables take priority over config files.
126
126
 
@@ -191,8 +191,8 @@ bun pm pack
191
191
  ## How it works
192
192
 
193
193
  1. The agent reads `AGENTS.md` or `CLAUDE.md` from the project root and follows all conventions documented there
194
- 2. It inspects your source code using a restricted, read-only toolset: `read_file`, `ls`, `glob`, `grep`, `ast_grep`, `ast_search`, a read-only `git` tool (whitelisted subcommands only — no mutating git, no shell), and a read-only `gh` CLI tool for inspecting pull requests and repository metadata
195
- 3. In update mode, it checks for open wiki staging PRs via `gh pr list` and compares branch timestamps against the latest commit — if a newer staging PR already exists, it abandons the update to prevent duplicates
194
+ 2. It inspects your source code using a restricted toolset: `read_file`, `ls`, `glob`, `grep`, `ast_grep`, `ast_search`, a read-only `git` tool (whitelisted subcommands only — no mutating git, no shell), and a `gh` CLI tool for inspecting pull requests and managing stale wiki staging PRs
195
+ 3. In update mode, it checks for open wiki staging PRs via `gh pr list` and compares branch timestamps against the latest commit — if a newer staging PR already exists, it abandons the update; stale PRs (older branch timestamp) are closed with a comment ("This branch is from an earlier staging run and is stale. Closing")
196
196
  4. It generates wiki pages under `.wiki/` with YAML frontmatter using `write_file` and `edit_file` (the only mutating tools, constrained to `.wiki/`)
197
197
  5. After the run, `index.md` files are synchronized for each directory
198
198
  6. `.last-updated.json` and `.last-update-report.md` are written
@@ -200,4 +200,4 @@ bun pm pack
200
200
  8. In update mode, only pages affected by recent changes are refreshed
201
201
  9. With `--wiki`, the workflow flattens the `.wiki/` tree (stripping frontmatter, converting nested paths to flat dash-joined filenames, rewriting links) and publishes to the GitHub Wiki tab by pushing directly to `<repo>.wiki.git` `master`
202
202
 
203
- The agent uses a manual tool-calling loop with the Ollama chat API — no LangChain or LangGraph dependency. The recursion limit prevents infinite loops. There is no general-purpose shell tool; the agent cannot execute arbitrary commands on the host system. The `gh` tool is restricted to read-only subcommands (pr list, pr view, repo view, etc.) — mutating operations like create, merge, and close are blocked.
203
+ The agent uses a manual tool-calling loop with the Ollama chat API — no LangChain or LangGraph dependency. The recursion limit prevents infinite loops. There is no general-purpose shell tool; the agent cannot execute arbitrary commands on the host system. The `gh` tool allows read-only inspection (pr list, pr view, repo view, etc.) plus `pr close` and `pr comment` but only on wiki staging PRs (branches matching `wiki/staging-*`); all other mutating operations are blocked.
package/dist/prompt.js CHANGED
@@ -34,9 +34,9 @@ You have a FIXED, LIMITED set of tools. You CANNOT execute arbitrary commands on
34
34
  - ast_search: search code using an inline ast-grep YAML rule. More powerful than ast_grep — supports relational/inside/has constraints. Use for complex structural queries a single pattern cannot express.
35
35
  - write_file, edit_file: write or edit documentation files. These are the ONLY mutating tools and are constrained to paths under .wiki/.
36
36
  - git: run a READ-ONLY git subcommand (log, diff, show, ls-files, blame, status, remote, describe, rev-parse, shortlog, name-rev, ls-tree, cat-file, reflog). This is the ONLY way to access repository history. Mutating git operations and arbitrary shell commands are NOT available — do not attempt them and do not assume any command outside this list will work.
37
- - gh: run a READ-ONLY GitHub CLI (gh) subcommand in the project root. Use to inspect open pull requests, check wiki staging PR branches, and compare timestamps. Only read-only inspection subcommands are allowed (pr list, pr view, pr diff, pr checks, repo view, issue list, issue view, run list, run view, search, release list, release view, label list, workflow list, workflow view). Mutating operations (create, edit, close, merge, delete, etc.) are blocked.
37
+ - gh: run a GitHub CLI (gh) subcommand in the project root. Read-only inspection is always allowed (pr list, pr view, pr diff, repo view, issue list, etc.). Two mutating operations are permitted ONLY on wiki staging PRs (branches matching wiki/staging-*): 'pr close' and 'pr comment'. All other mutating operations (create, merge, edit, delete, etc.) are blocked.
38
38
 
39
- You cannot run build tools, package managers, test runners, scripts, or any program other than git (read-only) and gh (read-only). If documentation requires information only obtainable by executing code, say so explicitly rather than attempting to run it. Ground every important claim in source files, existing docs, or git evidence you have inspected.
39
+ You cannot run build tools, package managers, test runners, scripts, or any program other than git (read-only) and gh. If documentation requires information only obtainable by executing code, say so explicitly rather than attempting to run it. Ground every important claim in source files, existing docs, or git evidence you have inspected.
40
40
 
41
41
  # Output location
42
42
  - Write documentation under .wiki/ in the project root. Use paths such as .wiki/quickstart.md, .wiki/architecture/overview.md, .wiki/cli/usage.md.
@@ -78,8 +78,12 @@ Use only the tools listed above. Do not invent files, modules, APIs, business ru
78
78
  - Step 3: Get the repository's latest commit timestamp (also Unix seconds):
79
79
  git log -1 --format=%ct
80
80
  - Step 4: Compare the integers. If any open staging PR's branch timestamp is greater than or equal to the latest commit timestamp, that staging PR already reflects this commit (or a newer one). Abandon the update: do not write or edit any files. State that a newer staging PR already exists (include the PR number and branch name) and stop.
81
+ - Step 5: Close stale staging PRs. For every open wiki/staging-* PR whose branch timestamp is LESS than the latest commit timestamp (i.e. it is older than the current commit), close it with a comment:
82
+ gh pr comment <number> --body "This branch is from an earlier staging run and is stale. Closing"
83
+ gh pr close <number>
84
+ Do this BEFORE proceeding with your own update. This keeps the PR queue clean and avoids confusing reviewers with outdated snapshots.
81
85
  - If the gh command fails (e.g. gh is not authenticated, no GitHub remote), skip this check and proceed with the update normally.
82
- - This check prevents duplicate staging PRs and avoids overwriting a newer pending review with older content.
86
+ - This check prevents duplicate staging PRs, closes stale ones, and avoids overwriting a newer pending review with older content.
83
87
 
84
88
  # Loop prevention
85
89
  - Work in phases: discover → plan → write → verify. Do not restart discovery once you have moved to planning or writing.
package/dist/tools.js CHANGED
@@ -444,13 +444,13 @@ export function createTools(projectRoot) {
444
444
  type: "function",
445
445
  function: {
446
446
  name: "gh",
447
- description: "Run a read-only GitHub CLI (gh) subcommand in the project root. Use to inspect open pull requests, check wiki staging PR branches, and compare timestamps. Only read-only inspection subcommands are permitted no mutating operations (create, edit, close, merge, delete, etc.).",
447
+ description: "Run a GitHub CLI (gh) subcommand in the project root. Read-only inspection (pr list, pr view, pr diff, repo view, issue list, etc.) is always allowed. Two mutating operations are permitted but ONLY on wiki staging PRs (branches matching wiki/staging-*): `gh pr close <number>` and `gh pr comment <number> --body <text>`. Use to inspect open PRs, check staging branch timestamps, and close stale wiki staging PRs with a comment.",
448
448
  parameters: {
449
449
  type: "object",
450
450
  properties: {
451
451
  args: {
452
452
  type: "string",
453
- description: "gh subcommand and arguments, without the leading 'gh'. Example: 'pr list --state open --head wiki/staging-* --json headRefName,updatedAt,number,title', 'pr view <number> --json updatedAt,headRefName,body', 'pr view <number> --json files'.",
453
+ description: "gh subcommand and arguments, without the leading 'gh'. Example: 'pr list --state open --json number,headRefName,title', 'pr view <number> --json headRefName', 'pr close <number> --comment \"This branch is from an earlier staging run and is stale. Closing\"', 'pr comment <number> --body \"stale\"'.",
454
454
  },
455
455
  },
456
456
  required: ["args"],
@@ -459,33 +459,57 @@ export function createTools(projectRoot) {
459
459
  },
460
460
  handler: async (args) => {
461
461
  const argString = args.args ?? "";
462
- // Only read-only / inspection subcommands are permitted. The agent
463
- // cannot mutate GitHub state through this tool.
464
462
  const ALLOWED_GH_SUBCOMMANDS = {
465
463
  pr: true, issue: true, repo: true, run: true, api: true,
466
464
  "search": true, release: true, label: true, workflow: true,
467
465
  };
468
- // Mutating subcommand prefixes that must never run, even under an
469
- // allowed top-level command (e.g. `gh pr create`, `gh pr merge`).
466
+ // Actions that are always blocked (never safe for an automated agent).
470
467
  const BLOCKED_ACTIONS = {
471
- create: true, edit: true, close: true, reopen: true, merge: true,
472
- delete: true, ready: true, review: true, comment: true,
468
+ create: true, edit: true, reopen: true, merge: true,
469
+ delete: true, ready: true, review: true,
473
470
  lock: true, unlock: true, assign: true, unassign: true,
474
471
  label: true, unlabel: true, transfer: true, archive: true,
475
472
  unarchive: true, deploy: true, rerun: true, cancel: true,
476
473
  publish: true, set: true, add: true, remove: true,
477
474
  };
475
+ // Actions allowed ONLY on wiki staging PRs (branches matching
476
+ // wiki/staging-*). The handler verifies the PR's headRefName before
477
+ // executing these.
478
+ const STAGING_ONLY_ACTIONS = {
479
+ close: true, comment: true,
480
+ };
478
481
  const tokens = argString.trim().split(/\s+/);
479
482
  const subcommand = tokens[0] ?? "";
480
483
  if (!ALLOWED_GH_SUBCOMMANDS[subcommand]) {
481
- return `Error: gh subcommand '${subcommand}' is not permitted. Only read-only inspection subcommands are allowed (pr, issue, repo, run, api, search, release, label, workflow).`;
484
+ return `Error: gh subcommand '${subcommand}' is not permitted. Only inspection subcommands and pr close/comment on wiki staging PRs are allowed (pr, issue, repo, run, api, search, release, label, workflow).`;
482
485
  }
483
- // For `gh pr` and similar, check the action token (second token)
484
- // against the blocklist. `gh pr list`, `gh pr view`, `gh pr diff`,
485
- // `gh pr checks` are read-only and allowed.
486
486
  const action = tokens[1] ?? "";
487
487
  if (BLOCKED_ACTIONS[action]) {
488
- return `Error: gh ${subcommand} ${action} is a mutating operation. Only read-only inspection is allowed (list, view, diff, checks, status).`;
488
+ return `Error: gh ${subcommand} ${action} is a blocked operation.`;
489
+ }
490
+ // For close/comment on PRs, verify the target is a wiki staging PR.
491
+ // The PR number is the third token: 'gh pr close <number>' or
492
+ // 'gh pr comment <number> --body ...'.
493
+ if (STAGING_ONLY_ACTIONS[action] && subcommand === "pr") {
494
+ const prNumber = tokens[2] ?? "";
495
+ if (!/^\d+$/.test(prNumber)) {
496
+ return `Error: a valid PR number is required for gh pr ${action}.`;
497
+ }
498
+ // Fetch the PR's headRefName to verify it's a wiki staging branch.
499
+ try {
500
+ const { stdout } = await execAsync(`gh pr view ${prNumber} --json headRefName`, { cwd: projectRoot, maxBuffer: 1024 * 1024, timeout: 30_000 });
501
+ const parsed = JSON.parse(stdout);
502
+ if (!parsed.headRefName?.startsWith("wiki/staging-")) {
503
+ return `Error: gh pr ${action} is only permitted on wiki staging PRs (branches matching wiki/staging-*). PR #${prNumber} has headRefName '${parsed.headRefName ?? "unknown"}'.`;
504
+ }
505
+ }
506
+ catch (error) {
507
+ const message = error instanceof Error ? error.message : String(error);
508
+ return `Error: could not verify PR #${prNumber} is a wiki staging PR: ${message}`;
509
+ }
510
+ }
511
+ else if (STAGING_ONLY_ACTIONS[action]) {
512
+ return `Error: gh ${subcommand} ${action} is not supported. Only gh pr ${action} is permitted, and only on wiki staging PRs.`;
489
513
  }
490
514
  // Reject shell metacharacters that could chain commands or inject
491
515
  // flags, same guard as the git tool.
package/dist/tui/App.js CHANGED
@@ -2,6 +2,7 @@ import React, { useState, useCallback } from "react";
2
2
  import { Box, Text, useApp, useInput } from "ink";
3
3
  import { CredentialsSetup } from "./CredentialsSetup.js";
4
4
  import { RunView } from "./RunView.js";
5
+ import { VERSION } from "../version.js";
5
6
  export function App({ command, cwd, config, verbose, wiki }) {
6
7
  const [needsSetup, setNeedsSetup] = useState(config.mode === "cloud" && !config.apiKey);
7
8
  const [resolvedConfig, setResolvedConfig] = useState(config);
@@ -21,7 +22,7 @@ export function App({ command, cwd, config, verbose, wiki }) {
21
22
  onConfigSaved: handleConfigSaved,
22
23
  });
23
24
  }
24
- return React.createElement(Box, { flexDirection: "column" }, React.createElement(Box, { borderStyle: "round", borderColor: "cyan", paddingX: 1 }, React.createElement(Text, null, React.createElement(Text, { bold: true }, "Wiki Agent v0.1.0"), " | ", React.createElement(Text, { color: "cyan" }, `Ollama (${resolvedConfig.mode})`), " | ", React.createElement(Text, { color: "gray" }, `model: ${resolvedConfig.model}`), " | ", React.createElement(Text, { color: "gray" }, cwd))), React.createElement(RunView, {
25
+ return React.createElement(Box, { flexDirection: "column" }, React.createElement(Box, { borderStyle: "round", borderColor: "cyan", paddingX: 1 }, React.createElement(Text, null, React.createElement(Text, { bold: true }, `Wiki Agent v${VERSION}`), " | ", React.createElement(Text, { color: "cyan" }, `Ollama (${resolvedConfig.mode})`), " | ", React.createElement(Text, { color: "gray" }, `model: ${resolvedConfig.model}`), " | ", React.createElement(Text, { color: "gray" }, cwd))), React.createElement(RunView, {
25
26
  command,
26
27
  cwd,
27
28
  config: resolvedConfig,
@@ -0,0 +1 @@
1
+ export declare const VERSION: string;
@@ -0,0 +1,6 @@
1
+ import { createRequire } from "node:module";
2
+ // Read the version from package.json so the TUI and CLI stay in sync
3
+ // with releases without a hardcoded string to update.
4
+ const require = createRequire(import.meta.url);
5
+ const pkg = require("../package.json");
6
+ export const VERSION = pkg.version;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chronova/wiki-agent",
3
- "version": "1.6.5",
3
+ "version": "1.7.1",
4
4
  "description": "Standalone Ollama-only documentation agent",
5
5
  "type": "module",
6
6
  "bin": {