rigjs 3.0.33 → 4.0.2

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.
Files changed (99) hide show
  1. package/.claude/skills/rig-wiki/SKILL.md +104 -0
  2. package/.claude-plugin/plugin.json +14 -0
  3. package/README.md +18 -1
  4. package/README_CN.md +17 -1
  5. package/RIG_CREW_SKILL.md +274 -0
  6. package/RIG_WIKI_SKILL.md +104 -0
  7. package/bin/rig.js +0 -0
  8. package/built/index.js +376 -299
  9. package/doc/architecture/README.md +139 -0
  10. package/doc/architecture/agents.md +180 -0
  11. package/doc/architecture/fc.md +17 -0
  12. package/doc/architecture/wiki.md +278 -0
  13. package/lib/crew/ask.ts +24 -0
  14. package/lib/crew/board.ts +123 -0
  15. package/lib/crew/config.ts +109 -0
  16. package/lib/crew/doctor.ts +40 -0
  17. package/lib/crew/inbox.ts +29 -0
  18. package/lib/crew/index.ts +108 -0
  19. package/lib/crew/init.ts +113 -0
  20. package/lib/crew/paths.ts +13 -0
  21. package/lib/crew/project.ts +84 -0
  22. package/lib/crew/role.ts +121 -0
  23. package/lib/crew/roleCommand.ts +150 -0
  24. package/lib/crew/state.ts +19 -0
  25. package/lib/crew/status.ts +27 -0
  26. package/lib/crew/stub.ts +9 -0
  27. package/lib/crew/sync.ts +15 -0
  28. package/lib/crew/task.ts +92 -0
  29. package/lib/crew/vault.ts +266 -0
  30. package/lib/installLocal.ts +189 -0
  31. package/lib/rig/index.ts +26 -3
  32. package/lib/wiki/README.md +79 -0
  33. package/lib/wiki/agent/claude.ts +65 -0
  34. package/lib/wiki/agent/codex.ts +22 -0
  35. package/lib/wiki/agent/index.ts +11 -0
  36. package/lib/wiki/agent/list.ts +27 -0
  37. package/lib/wiki/agent/pi.ts +21 -0
  38. package/lib/wiki/agent/registry.ts +16 -0
  39. package/lib/wiki/agent/types.ts +37 -0
  40. package/lib/wiki/agent/use.ts +21 -0
  41. package/lib/wiki/config.ts +99 -0
  42. package/lib/wiki/daemon/index.ts +25 -0
  43. package/lib/wiki/daemon/install.ts +69 -0
  44. package/lib/wiki/daemon/logs.ts +16 -0
  45. package/lib/wiki/daemon/runner.ts +42 -0
  46. package/lib/wiki/daemon/start.ts +20 -0
  47. package/lib/wiki/daemon/status.ts +23 -0
  48. package/lib/wiki/daemon/stop.ts +16 -0
  49. package/lib/wiki/daemon/uninstall.ts +17 -0
  50. package/lib/wiki/db.ts +71 -0
  51. package/lib/wiki/fetch.ts +206 -0
  52. package/lib/wiki/index.ts +106 -0
  53. package/lib/wiki/indexCmd.ts +23 -0
  54. package/lib/wiki/ingest.ts +271 -0
  55. package/lib/wiki/init.ts +125 -0
  56. package/lib/wiki/installSkill.ts +92 -0
  57. package/lib/wiki/lint.ts +252 -0
  58. package/lib/wiki/list.ts +69 -0
  59. package/lib/wiki/pathGuard.ts +87 -0
  60. package/lib/wiki/paths.ts +29 -0
  61. package/lib/wiki/platform.ts +8 -0
  62. package/lib/wiki/qmd.ts +205 -0
  63. package/lib/wiki/query.ts +144 -0
  64. package/lib/wiki/rebuild.ts +56 -0
  65. package/lib/wiki/register.ts +94 -0
  66. package/lib/wiki/scan.ts +0 -0
  67. package/lib/wiki/uninstallSkill.ts +37 -0
  68. package/lib/wiki/unregister.ts +16 -0
  69. package/package.json +36 -6
  70. package/scripts/postinstall.mjs +108 -0
  71. package/scripts/publish.mjs +93 -0
  72. package/scripts/sync-skill.mjs +33 -0
  73. package/scripts/version-code.mjs +86 -0
  74. package/skills.md +54 -0
  75. package/.github/workflows/npm-publish.yml +0 -22
  76. package/demo/.env.oem1 +0 -4
  77. package/demo/.env.oem2 +0 -4
  78. package/demo/babel.config.js +0 -5
  79. package/demo/env.rig.json5 +0 -8
  80. package/demo/jsconfig.json +0 -19
  81. package/demo/package.json +0 -59
  82. package/demo/package.rig.json5 +0 -78
  83. package/demo/public/favicon.ico +0 -0
  84. package/demo/public/index.html +0 -17
  85. package/demo/rig_dev/.gitkeep +0 -0
  86. package/demo/rig_helper.d.ts +0 -4
  87. package/demo/rig_helper.js +0 -10
  88. package/demo/rigs/.gitkeep +0 -0
  89. package/demo/src/App.vue +0 -34
  90. package/demo/src/assets/logo.png +0 -0
  91. package/demo/src/components/HelloWorld.vue +0 -58
  92. package/demo/src/main.js +0 -8
  93. package/demo/vue.config.js +0 -8
  94. package/demo/yarn.lock +0 -6312
  95. package/develop.png +0 -0
  96. package/jest/test.rig.json5 +0 -14
  97. package/jest.config.ts +0 -16
  98. package/production.png +0 -0
  99. package/tsconfig.json +0 -53
@@ -0,0 +1,139 @@
1
+ # rig — Architecture (planning notes)
2
+
3
+ > Status: Draft v0 — 2026-05-17. Author: Bo Wang.
4
+ > Audience: future contributors + Claude Code when working in this repo.
5
+ > Scope: not exhaustive — captures the *shape* of rig as it grows beyond the original "yarn-workspaces + git" multi-repo tool.
6
+
7
+ ---
8
+
9
+ ## 0. What rig is, and is becoming
10
+
11
+ Originally: a thin CLI on top of `yarn workspaces + git` that lets you share code between projects without publishing to a registry (`rig init / add / dev / install / build / deploy / publish / sync / tag`). See `README.md` for that side of the story.
12
+
13
+ Now: rig is becoming the user's personal "outer brain" CLI — a single entry point for *non-application* automation that lives across all the user's projects. The first two extensions:
14
+
15
+ 1. **`rig wiki *`** — Karpathy-style LLM Wiki ops over registered project directories, with a launchd daemon for periodic ingest/lint. See `wiki.md`.
16
+ 2. **`rig fc *`** — Aliyun Function Compute deploy commands (planned, not yet specced). See `fc.md` (placeholder; written when work starts).
17
+
18
+ Both groups follow the same shape — local config in `~/.rig/`, per-project opt-in via `package.rig.json5`, optional background daemon, **macOS only** for v1.
19
+
20
+ ---
21
+
22
+ ## 1. Top-level command tree
23
+
24
+ ```
25
+ rig
26
+ ├── (existing: pkg/workspace ops)
27
+ │ ├── init / add / dev / install / preinstall / postinstall
28
+ │ ├── build / deploy / publish / sync / tag
29
+ │ ├── check / info / env
30
+ │ └── -v / --version
31
+
32
+ ├── wiki # see wiki.md
33
+ │ ├── init [<path>]
34
+ │ ├── register [<path>] [--name <n>]
35
+ │ ├── unregister <name|path>
36
+ │ ├── list
37
+ │ ├── scan [--wiki <n> | --all | <path>]
38
+ │ ├── fetch <url> [--wiki <n>]
39
+ │ ├── ingest <path> [--wiki <n>] [--dry-run]
40
+ │ ├── query "..." [--wiki <n>]
41
+ │ ├── lint [--wiki <n> | --all]
42
+ │ ├── index [--wiki <n> | --all] # qmd-only; no-op + warn otherwise
43
+ │ ├── install-skill / uninstall-skill # symlink built-in Claude skill
44
+ │ ├── agent list | use <claude|codex|pi>
45
+ │ └── daemon start | stop | status | logs [-f] | install | uninstall
46
+
47
+ └── fc # planned — Aliyun Function Compute (TBD)
48
+ ```
49
+
50
+ Naming convention for new groups: `rig <noun> <verb>`. Single-verb top-level commands are grandfathered for the original pkg ops only.
51
+
52
+ ---
53
+
54
+ ## 2. Directory layout
55
+
56
+ ### 2.1 Code layout (this repo)
57
+ ```
58
+ lib/
59
+ ├── rig/ # entry point (commander wiring)
60
+ ├── <pkg-cmd>/ # existing: init, add, dev, install, build, deploy, ...
61
+ ├── wiki/ # NEW — see wiki.md
62
+ │ ├── index.ts # `rig wiki` commander subtree
63
+ │ ├── paths.ts platform.ts config.ts db.ts qmd.ts
64
+ │ ├── init.ts register.ts unregister.ts list.ts
65
+ │ ├── scan.ts fetch.ts ingest.ts query.ts lint.ts indexCmd.ts
66
+ │ ├── installSkill.ts uninstallSkill.ts
67
+ │ ├── agent/
68
+ │ │ ├── index.ts list.ts use.ts
69
+ │ │ ├── types.ts claude.ts codex.ts pi.ts
70
+ │ └── daemon/
71
+ │ ├── index.ts start.ts stop.ts status.ts logs.ts
72
+ │ ├── install.ts uninstall.ts runner.ts
73
+ ├── fc/ # placeholder
74
+ ├── classes/ utils/ # existing
75
+ ```
76
+
77
+ ### 2.2 User-side layout (`~/.rig/`)
78
+ ```
79
+ ~/.rig/
80
+ ├── config.json5 # default agent, paths, feature flags
81
+ ├── wiki.config.json5 # registered wikis + per-wiki schedule overrides
82
+ ├── state.db # SQLite (better-sqlite3) — sha cache, last_run, ingest_log, FTS5 fallback
83
+ ├── locks/ # flock-based per-wiki advisory locks
84
+ ├── logs/
85
+ │ ├── wiki-daemon.log
86
+ │ └── wikis/<wiki-name>/<op>-YYYY-MM-DD.log
87
+ └── cache/ # scratch + agent sandbox copies
88
+ ```
89
+
90
+ rig never writes outside `~/.rig/`, `~/Library/LaunchAgents/` (only `daemon install`), and the user's CWD.
91
+
92
+ ### 2.3 Per-project layout
93
+ A project opts into `rig wiki` by either:
94
+ - Running `rig wiki register` from its root (auto-detects `harness/llm-wiki/` or asks for a path), or
95
+ - Adding a `wiki` block to its `package.rig.json5`.
96
+
97
+ The per-project wiki dir follows the layout from `wiki.md §2` — `purpose.md / schema.md / index.md / overview.md / log.md / reviews.md / raw/ / wiki/{sources,entities,concepts,synthesis,queries}/`.
98
+
99
+ ---
100
+
101
+ ## 3. Cross-cutting concerns
102
+
103
+ | Topic | Decision |
104
+ |---|---|
105
+ | Config format | JSON5 (matches rig conventions) |
106
+ | Config merge order | built-in < `~/.rig/config.json5` < `~/.rig/wiki.config.json5` < project `package.rig.json5` < CLI flag |
107
+ | Human output | `lib/print` (ora + chalk) |
108
+ | Machine output | `--json` flag on all `wiki` subcommands; daemon writes JSONL |
109
+ | Platform | **macOS only** for v1 (arm64 + x64). Linux/Windows: explicit error and exit |
110
+ | Daemon | macOS `launchd` user agent; Linux deferred to P5 |
111
+ | Agent | Requires one of `claude` / `codex` / `pi` on PATH for `ingest/query/lint`; v1 ships Claude only |
112
+ | qmd | Optional; auto-detected; functional fallback when absent |
113
+ | Safety | All writes diffed first; `raw/ / purpose.md / schema.md` never edited by rig (enforced in code) |
114
+ | Local DB | `better-sqlite3@12.10.0` pinned — see `wiki.md §13` |
115
+ | Node | `engines.node = ">=22 <27"` (driven by better-sqlite3 prebuilds) |
116
+
117
+ ---
118
+
119
+ ## 4. Roadmap
120
+
121
+ | Phase | Scope | State |
122
+ |---|---|---|
123
+ | P1 | `rig wiki init/register/list/scan/fetch/ingest/query/lint`, manual only, Claude adapter, qmd-aware | scaffolding now |
124
+ | P2 | `rig wiki daemon *` (launchd), per-wiki schedule, JSONL logs | after P1 runs ~2 weeks |
125
+ | P3 | Codex + pi-agent adapters; `rig wiki agent use <…>` switch | when a second agent is actually needed |
126
+ | P4 | `rig fc *` (Aliyun Function Compute) | independent track |
127
+ | P5 | Linux daemon, better logs UI | after macOS daemon is stable |
128
+
129
+ Out of scope (intentionally): web/desktop UI for wiki browsing (Obsidian + VSCode are enough); cross-machine wiki sync (git's job); cross-machine daemon coordination (each box runs its own).
130
+
131
+ ---
132
+
133
+ ## 5. Related docs
134
+
135
+ - `wiki.md` — full `rig wiki` design (commands, config, daemon, SQLite schema).
136
+ - `agents.md` — agent-CLI adapter interface + Claude/Codex/pi notes.
137
+ - `fc.md` — placeholder for future Aliyun FC work.
138
+
139
+ User-facing docs stay in `README.md` / `README_CN.md`. Files here capture design intent, not how-to.
@@ -0,0 +1,180 @@
1
+ # rig wiki — Agent adapter
2
+
3
+ > Status: Draft v0 — 2026-05-17.
4
+ > v1 implementation: Claude Code only. Codex / pi-agent are speced as stubs so the interface is forward-compatible.
5
+
6
+ ---
7
+
8
+ ## 1. Single interface
9
+
10
+ `lib/wiki/agent/types.ts`:
11
+
12
+ ```ts
13
+ export type AgentName = 'claude' | 'codex' | 'pi';
14
+
15
+ export interface AgentAdapter {
16
+ name: AgentName;
17
+
18
+ /** Returns whether the CLI is on PATH and which version. */
19
+ detect(): Promise<{ installed: boolean; version?: string; path?: string }>;
20
+
21
+ /**
22
+ * One-shot non-interactive run.
23
+ * The host has already copied the wiki dir into `cwd` (a sandbox).
24
+ * The adapter spawns the CLI, waits for completion, returns stdout/stderr.
25
+ * The host then diffs sandbox vs original to extract writes.
26
+ */
27
+ run(opts: AgentRunOpts): Promise<AgentRunResult>;
28
+ }
29
+
30
+ export interface AgentRunOpts {
31
+ prompt: string; // user-facing instruction
32
+ systemPrompt?: string; // appended to the agent's system prompt
33
+ files?: string[]; // extra files to inject (read-only)
34
+ cwd: string; // sandbox path
35
+ allowWrite: boolean; // ingest=true, query/lint=false
36
+ tools?: ('webfetch' | 'qmd' | 'bash')[]; // tool whitelist hint
37
+ timeoutMs?: number; // hard kill after this
38
+ }
39
+
40
+ export interface AgentRunResult {
41
+ ok: boolean;
42
+ stdout: string;
43
+ stderr: string;
44
+ durationMs: number;
45
+ exitCode: number;
46
+ }
47
+ ```
48
+
49
+ The **host** (not the adapter) handles the diff-vs-original step. That keeps adapters small and means we don't trust any agent's "I wrote these files" report.
50
+
51
+ ---
52
+
53
+ ## 2. Sandbox-copy-and-diff flow
54
+
55
+ For any operation that may write:
56
+
57
+ ```
58
+ 1. host: mkdir ~/.rig/cache/sandbox/<wiki>/<run-id>/
59
+ 2. host: copy <wiki-dir> → sandbox (excluding raw/, purpose.md, schema.md — read-only)
60
+ 3. host: write read-only injection files (purpose.md, schema.md, etc.) into sandbox/.rig-readonly/
61
+ 4. host: adapter.run({ cwd: sandbox, allowWrite: true, ... })
62
+ 5. host: diff sandbox vs <wiki-dir> using `diff -urN`
63
+ 6. host: filter diff (reject any patch touching raw/, purpose.md, schema.md)
64
+ 7. host: present diff to user (or apply directly in daemon `--apply` mode)
65
+ 8. host: rm -rf sandbox
66
+ ```
67
+
68
+ Rationale: all three target agents (Claude, Codex, pi) have different permission models; this flow normalizes them. Even a fully unrestricted agent can't corrupt the real wiki because step 6 throws away forbidden patches.
69
+
70
+ ---
71
+
72
+ ## 3. Claude Code adapter (v1 — only implementation)
73
+
74
+ `lib/wiki/agent/claude.ts`:
75
+
76
+ ```ts
77
+ spawn('claude', [
78
+ '-p', // print mode (non-interactive)
79
+ '--system-prompt', systemPrompt,
80
+ ...allowedToolsFlags(opts.allowWrite, opts.tools),
81
+ opts.prompt
82
+ ], { cwd: opts.cwd, stdio: ['ignore', 'pipe', 'pipe'], timeout: opts.timeoutMs });
83
+ ```
84
+
85
+ Allowed-tools whitelist (passed via `--allowedTools`):
86
+ - `query` / `lint`: `Read, Bash(qmd:*)`
87
+ - `ingest`: `Read, Write, Edit, Bash(qmd:*)`
88
+ - `fetch`: `Read, Write, WebFetch`
89
+
90
+ System prompt prepended (host always wraps adapter's `systemPrompt`):
91
+ ```
92
+ You are the executor for `rig wiki <op>`.
93
+ You MUST follow <wiki>/schema.md exactly.
94
+ You MUST NOT edit raw/, purpose.md, schema.md. Host enforces this and will reject any such patch.
95
+ Output is consumed by a CLI; keep stdout to status updates only. Persist actual content by writing files.
96
+ ```
97
+
98
+ Version check: parse `claude --version`. Require Claude Code >= 2.0 (tools API stable).
99
+
100
+ Why no direct Anthropic API:
101
+ - Requires an API key + billing setup that not every machine has.
102
+ - Different protocol; we'd reinvent the tool plumbing Claude Code already gives us.
103
+ - Claude Code is already the user's daily driver — its config (`~/.claude/settings.json`) is the source of truth for credentials and MCP servers.
104
+
105
+ ---
106
+
107
+ ## 4. Codex adapter (stub)
108
+
109
+ Target: OpenAI's `codex` CLI (the `Codex` agent, not the IDE plugin).
110
+
111
+ Expected invocation (v1 stub, not implemented):
112
+ ```ts
113
+ spawn('codex', [
114
+ 'exec', '--no-tui',
115
+ '--cwd', opts.cwd,
116
+ // codex permission model TBD — likely needs --readonly when !allowWrite
117
+ opts.prompt
118
+ ], { ... });
119
+ ```
120
+
121
+ Open questions before P3 ships this:
122
+ - Does codex have a `--allowed-tools`-equivalent flag, or only coarse `--readonly` / full access?
123
+ - What does codex print as its "I'm done" signal? Does `--no-tui` exist?
124
+ - Does codex respect external `cwd` or insist on its own workspace?
125
+
126
+ Until those are answered, the adapter `detect()` returns installed but `run()` throws `not-implemented`.
127
+
128
+ ---
129
+
130
+ ## 5. pi-agent adapter (stub)
131
+
132
+ Target: Personal-Intelligence-style agent CLI. Exact upstream TBD (Bo to specify).
133
+
134
+ Expected invocation pattern:
135
+ ```ts
136
+ // many pi-agent CLIs take prompt-file to avoid argv-length limits
137
+ const tmpFile = await writeTmp(opts.prompt);
138
+ spawn('pi', ['run', '--prompt-file', tmpFile, '--cwd', opts.cwd], { ... });
139
+ ```
140
+
141
+ Same "open questions" caveat as Codex. Stub `detect()` returns installed when `which pi` succeeds; `run()` throws `not-implemented`.
142
+
143
+ ---
144
+
145
+ ## 6. Choosing the agent
146
+
147
+ | Operation | Recommended | Why |
148
+ |---|---|---|
149
+ | `ingest` | Claude | long context, stable tool calls, v1 default |
150
+ | `query` | any | whichever is on the box |
151
+ | `lint` | Claude or Codex | both do structured scans well |
152
+ | `fetch` | any with WebFetch | falls back to `curl` + Readability if absent |
153
+
154
+ Default agent: `~/.rig/config.json5` → `wiki.defaultAgent` (initially `'claude'`).
155
+ Per-invocation override: `--agent <name>` flag.
156
+
157
+ ---
158
+
159
+ ## 7. Detection registry
160
+
161
+ `lib/wiki/agent/index.ts` exports a single registry:
162
+
163
+ ```ts
164
+ import { ClaudeAdapter } from './claude';
165
+ import { CodexAdapter } from './codex';
166
+ import { PiAdapter } from './pi';
167
+ export const adapters: AgentAdapter[] = [
168
+ new ClaudeAdapter(),
169
+ new CodexAdapter(),
170
+ new PiAdapter(),
171
+ ];
172
+ export function getAdapter(name: AgentName) {
173
+ const a = adapters.find(x => x.name === name);
174
+ if (!a) throw new Error(`unknown agent: ${name}`);
175
+ return a;
176
+ }
177
+ ```
178
+
179
+ `rig wiki agent list` iterates `adapters`, calls `detect()`, prints a table.
180
+ `rig wiki agent use <name>` rejects names whose adapter `run()` is `not-implemented`.
@@ -0,0 +1,17 @@
1
+ # rig fc — Aliyun Function Compute (placeholder)
2
+
3
+ > Status: Not started — 2026-05-17. Bo intends to add `rig fc *` subcommands for deploying / managing Aliyun Function Compute services. This file is a placeholder so the architecture tree is complete.
4
+
5
+ Spec will be written when work begins. Expected shape (subject to revision):
6
+
7
+ ```
8
+ rig fc init # write fc.rig.json5 in current project
9
+ rig fc deploy [--env <name>] # build + upload + invoke deploy
10
+ rig fc invoke <fn> [--params ...]
11
+ rig fc logs <fn> [-f]
12
+ rig fc list
13
+ rig fc rollback <fn> <version>
14
+ ```
15
+
16
+ Auth: `~/.rig/config.json5` `fc:` block (Aliyun AK/SK or RAM credentials).
17
+ Per-project config: `<project>/fc.rig.json5` listing functions, runtime, triggers.
@@ -0,0 +1,278 @@
1
+ # rig wiki — Design
2
+
3
+ > Status: Draft v0 — 2026-05-17.
4
+ > Source spec: see `harness/llm-wiki/llm-wiki solution.md` §1–§13 in the Maestro repo (it remains the requirements doc; this file is the rig-side implementation contract).
5
+
6
+ ---
7
+
8
+ ## 1. Goal
9
+
10
+ Bring Karpathy-style LLM Wiki ops to *any* project on this machine, with a single CLI entry point and an optional launchd daemon for periodic ingest/lint. `rig` is the host; per-project wikis live in each project's own tree (default: `harness/llm-wiki/`).
11
+
12
+ ---
13
+
14
+ ## 2. Per-wiki directory layout (the projects rig acts on)
15
+
16
+ ```
17
+ <project>/<wiki>/ # default: harness/llm-wiki
18
+ ├── purpose.md # scope (human-only, LLM read-only)
19
+ ├── schema.md # structure rules (human-only, LLM read-only)
20
+ ├── index.md # catalog (LLM-maintained)
21
+ ├── overview.md # narrative summary (LLM-maintained)
22
+ ├── log.md # append-only op log (LLM appends)
23
+ ├── reviews.md # uncertain items LLM flagged (LLM appends, human resolves)
24
+ ├── raw/ # external immutable source material (LLM read-only)
25
+ └── wiki/ # LLM-authored
26
+ ├── sources/ # one page per raw/<source>
27
+ ├── entities/ # people, orgs, products, places
28
+ ├── concepts/ # abstract ideas
29
+ ├── synthesis/ # cross-source integration
30
+ └── queries/ # archived Q&A worth keeping
31
+ ```
32
+
33
+ Filenames are kebab-case; `wiki/**` no dates in names; `raw/**` keeps `YYYY-MM-DD-` prefix.
34
+
35
+ Frontmatter for every `wiki/**` page:
36
+ ```yaml
37
+ ---
38
+ type: source | entity | concept | synthesis | query
39
+ sources: [<source-slug>, ...]
40
+ source-sha: <sha> # source pages only
41
+ source-path: raw/... | <relpath-in-project>
42
+ ingested-at: <ISO>
43
+ last-updated: <ISO>
44
+ ---
45
+ ```
46
+
47
+ Hard rules enforced by rig:
48
+ - Never edit `raw/`, `purpose.md`, `schema.md`.
49
+ - `raw/` file sha drift = `RAW DRIFT` error, not a re-ingest trigger.
50
+ - Living-doc paths (`include` glob) sha drift = `MODIFIED`, proposes re-ingest.
51
+
52
+ ---
53
+
54
+ ## 3. Commands
55
+
56
+ > All commands accept `--json` (machine output) and `--wiki <name>` (target a registered wiki). With neither, the command resolves the wiki by walking up from CWD; failing that, errors out.
57
+
58
+ ### `rig wiki init [<path>]`
59
+ Bootstrap a fresh wiki dir under `<path>` (default CWD):
60
+ - creates `purpose.md`, `schema.md` from templates
61
+ - creates empty `index.md`, `overview.md`, `log.md`, `reviews.md`
62
+ - creates `raw/` and the five `wiki/<subdir>/` dirs (each with `.gitkeep`)
63
+ - does **not** register; for that, run `rig wiki register`
64
+
65
+ ### `rig wiki register [<path>] [--name <n>] [--force]`
66
+ Append/replace an entry in `~/.rig/wiki.config.json5`:
67
+ ```json5
68
+ { name, path, project, include, exclude, schedule, ingestRules }
69
+ ```
70
+ - `--name` default: project `package.json` name, fallback to path basename
71
+ - if project has a `package.rig.json5`, also writes a `wiki:` block back to it (bidirectional)
72
+ - duplicates rejected unless `--force`
73
+
74
+ ### `rig wiki unregister <name|path>`
75
+ Remove from `~/.rig/wiki.config.json5`. Disk wiki content untouched.
76
+
77
+ ### `rig wiki list`
78
+ Table of registered wikis with page counts + last scan/ingest/lint times. Banner row: detected agent CLI, qmd status, daemon state.
79
+
80
+ ### `rig wiki scan [--wiki <n> | --all | <path>]`
81
+ Walk `include` globs + `raw/`. Diff file sha vs `state.db.source_sha`. Output four-state report (NEW / MODIFIED / DELETED / RAW DRIFT / UNCHANGED). No agent calls.
82
+
83
+ ### `rig wiki fetch <url> [--wiki <n>]`
84
+ Agent-as-fetcher: verbatim download → `raw/YYYY-MM-DD-<slug>.md` + frontmatter (`source-url`, `fetched-at`, `fetcher`, `content-sha`). Never summarizes — that's `ingest`'s job.
85
+
86
+ ### `rig wiki ingest <path> [--wiki <n>] [--dry-run]`
87
+ Two-step CoT (`analysis` → `generation`) inside an agent sandbox (copy-on-write `~/.rig/cache/sandbox/<wiki>/<run-id>/`):
88
+ 1. inject `purpose.md` + `schema.md` + `overview.md` + `index.md` + source → analysis output (entities/concepts/contradictions/reviews)
89
+ 2. feed analysis back → agent writes `wiki/sources/<slug>.md` + updates related entity/concept pages + `index.md` + `overview.md` + `log.md` + (if any) `reviews.md`
90
+ 3. host diffs sandbox vs original → `--dry-run` prints diff; otherwise prompts to apply
91
+ 4. on apply: trigger incremental `qmd embed` (if qmd installed)
92
+
93
+ ### `rig wiki query "..." [--wiki <n>]`
94
+ With qmd: `qmd query --json` → top-k → agent synthesizes answer with `[[wikilink]]` citations.
95
+ Without qmd: inject `purpose.md` + `index.md` + `overview.md` + heuristically-picked pages.
96
+
97
+ ### `rig wiki lint [--wiki <n> | --all]`
98
+ Health check — contradictions, orphans, stale claims, broken `sources[]` refs, reviews.md backlog. Output: `<wiki>/lint-report-YYYY-MM-DD.md` (gitignored by default). Severe findings → non-zero exit.
99
+
100
+ ### `rig wiki index [--wiki <n> | --all]`
101
+ Equivalent to `qmd collection add ... && qmd embed`. If qmd not installed: warn and no-op (exit 0; qmd is optional).
102
+
103
+ ### `rig wiki install-skill / uninstall-skill`
104
+ Symlink rig's bundled Claude skill (`.claude/skills/rig-wiki/`) into `~/.claude/skills/rig-wiki/`. Lets every machine that has `rig` installed get the slash command without manual copy.
105
+
106
+ ### `rig wiki agent list | use <name>`
107
+ - `list`: prints which agent CLIs are on PATH (claude/codex/pi), their versions, and which is default.
108
+ - `use <name>`: writes `wiki.defaultAgent` in `~/.rig/config.json5`. v1 only accepts `claude`.
109
+
110
+ ### `rig wiki daemon start | stop | status | logs [-f] | install | uninstall`
111
+ See §5.
112
+
113
+ ---
114
+
115
+ ## 4. Config files
116
+
117
+ ### `~/.rig/config.json5`
118
+ ```json5
119
+ {
120
+ wiki: {
121
+ defaultAgent: 'claude',
122
+ qmd: { enabled: 'auto' }, // 'auto' | 'on' | 'off'
123
+ logRotateMB: 50
124
+ }
125
+ }
126
+ ```
127
+
128
+ ### `~/.rig/wiki.config.json5`
129
+ ```json5
130
+ {
131
+ defaults: {
132
+ schedule: { scan: '0 */6 * * *', lint: '0 3 * * *', ingest: null }
133
+ },
134
+ wikis: [
135
+ {
136
+ name: 'maestro',
137
+ path: '/abs/path/.../harness/llm-wiki',
138
+ project: '/abs/path/.../maestro',
139
+ include: ['harness/dev/**', 'harness/projects/**'],
140
+ exclude: ['harness/llm-wiki/**'],
141
+ schedule: { scan: '0 */6 * * *', lint: '0 3 * * *' },
142
+ ingestRules: [
143
+ { match: 'raw/**/*.md', mode: 'auto-on-new' },
144
+ { match: 'harness/dev/**/*.md', mode: 'propose-only' }
145
+ ]
146
+ }
147
+ ]
148
+ }
149
+ ```
150
+
151
+ ### Project `package.rig.json5` (`wiki` block)
152
+ ```json5
153
+ {
154
+ wiki: {
155
+ name: 'maestro',
156
+ path: 'harness/llm-wiki',
157
+ include: ['harness/dev/**'],
158
+ exclude: ['harness/llm-wiki/**']
159
+ }
160
+ }
161
+ ```
162
+
163
+ Merge order: built-in defaults < `~/.rig/config.json5` < `~/.rig/wiki.config.json5` < project `package.rig.json5` < CLI flag.
164
+
165
+ ---
166
+
167
+ ## 5. Daemon (macOS launchd)
168
+
169
+ `rig wiki daemon install` writes `~/Library/LaunchAgents/ai.flashhand.rig.wiki.plist` and bootstraps via `launchctl bootstrap gui/<uid> <plist>`.
170
+
171
+ Plist (template):
172
+ ```xml
173
+ <?xml version="1.0" encoding="UTF-8"?>
174
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
175
+ <plist version="1.0"><dict>
176
+ <key>Label</key><string>ai.flashhand.rig.wiki</string>
177
+ <key>ProgramArguments</key><array>
178
+ <string>/usr/local/bin/node</string>
179
+ <string>{{RIG_BUILT_INDEX}}</string>
180
+ <string>wiki</string><string>daemon</string><string>runner</string>
181
+ </array>
182
+ <key>RunAtLoad</key><true/>
183
+ <key>KeepAlive</key><true/>
184
+ <key>StandardOutPath</key><string>{{HOME}}/.rig/logs/wiki-daemon.log</string>
185
+ <key>StandardErrorPath</key><string>{{HOME}}/.rig/logs/wiki-daemon.log</string>
186
+ </dict></plist>
187
+ ```
188
+
189
+ Runner loop:
190
+ - read `~/.rig/wiki.config.json5`, register `cron` jobs per wiki for `schedule.scan` / `schedule.lint`
191
+ - on tick: run subcommand internally (no fork), write JSONL to `~/.rig/logs/wikis/<wiki>/<op>-YYYY-MM-DD.log`
192
+ - `ingestRules.mode === 'auto-on-new'` matches on the latest scan → `ingest --apply` (only when sandbox-diff is sub-policy)
193
+ - `propose-only` matches → write `<wiki>/proposals/<source>.diff` for human review
194
+ - never retry; never backfill missed runs
195
+
196
+ Control commands:
197
+ - `daemon start/stop`: `launchctl bootstrap` / `bootout`
198
+ - `daemon status`: parse `launchctl print gui/<uid>/ai.flashhand.rig.wiki`
199
+ - `daemon logs [-f]`: tail `~/.rig/logs/wiki-daemon.log`
200
+ - `daemon install/uninstall`: write/remove plist
201
+
202
+ ---
203
+
204
+ ## 6. Exit codes
205
+
206
+ | Code | Meaning |
207
+ |---|---|
208
+ | 0 | success |
209
+ | 10 | scan found RAW DRIFT |
210
+ | 11 | lint found severe items |
211
+ | 20 | agent CLI missing or version too low |
212
+ | 21 | qmd required (only with `--require-qmd`) but absent |
213
+ | 30 | config file corrupt |
214
+ | 31 | wiki lock contention (another rig process holds the lock) |
215
+ | 32 | not on macOS |
216
+ | 1 | other error |
217
+
218
+ `--json` output shape: `{ ok: boolean, code: number, data?: any, error?: { message, hint } }`.
219
+
220
+ ---
221
+
222
+ ## 7. SQLite schema (`~/.rig/state.db`)
223
+
224
+ Single file via `better-sqlite3@12.10.0`. WAL mode. Migrations are idempotent on every open.
225
+
226
+ ```sql
227
+ CREATE TABLE IF NOT EXISTS source_sha (
228
+ wiki TEXT NOT NULL, path TEXT NOT NULL,
229
+ sha TEXT NOT NULL, mtime INTEGER NOT NULL,
230
+ PRIMARY KEY (wiki, path)
231
+ );
232
+ CREATE TABLE IF NOT EXISTS last_run (
233
+ wiki TEXT NOT NULL, op TEXT NOT NULL,
234
+ ts INTEGER NOT NULL, exit_code INTEGER NOT NULL,
235
+ PRIMARY KEY (wiki, op)
236
+ );
237
+ CREATE TABLE IF NOT EXISTS ingest_log (
238
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
239
+ wiki TEXT NOT NULL, source_path TEXT NOT NULL,
240
+ ts INTEGER NOT NULL, diff_hash TEXT NOT NULL,
241
+ applied INTEGER NOT NULL
242
+ );
243
+ CREATE VIRTUAL TABLE IF NOT EXISTS pages_fts5 USING fts5(
244
+ wiki, slug, body, tokenize='unicode61 remove_diacritics 2'
245
+ );
246
+ ```
247
+
248
+ Cross-process locks are **not** SQLite locks — they're `fcntl` flocks on `~/.rig/locks/<wiki>.lock`. Failure to acquire = exit `31`.
249
+
250
+ ---
251
+
252
+ ## 8. qmd integration
253
+
254
+ Auto-detect via `which qmd` at startup.
255
+
256
+ With qmd:
257
+ - `query`: `qmd query --json "..."` (auto-runs `qmd mcp` daemon)
258
+ - `ingest` end-step: `qmd embed --collection <wiki>` (incremental)
259
+ - `lint`: walk via `qmd ls --collection <wiki>`
260
+
261
+ Without qmd:
262
+ - `query` falls back to feeding `index.md + overview.md + heuristic` to the agent
263
+ - `index` is a no-op + warn
264
+ - `pages_fts5` (in `state.db`) is populated on every ingest as a degraded local search backend; used by qmd-less `query`
265
+
266
+ ---
267
+
268
+ ## 9. Agent integration
269
+
270
+ See `agents.md`. Single `AgentAdapter` interface; v1 implements Claude Code only. All adapters run inside a sandbox-copy of the wiki dir, then the host diffs the sandbox against the original to detect/apply writes.
271
+
272
+ ---
273
+
274
+ ## 10. Built-in Claude skill (`.claude/skills/rig-wiki/`)
275
+
276
+ Ships inside the rig npm tarball (`package.json` `files` includes `.claude/skills/**`). User runs `rig wiki install-skill` once per machine — symlinks `<rigjs-install>/.claude/skills/rig-wiki` to `~/.claude/skills/rig-wiki`. Claude Code picks it up next session.
277
+
278
+ The skill itself is a thin wrapper: its instructions tell Claude when to invoke which `rig wiki *` command. It does not duplicate the wiki logic.
@@ -0,0 +1,24 @@
1
+ import fs from 'fs';
2
+ import print from '../print';
3
+ import { requireCrew } from './config';
4
+ import { appendLog, rootPath } from './vault';
5
+ import crewBoard from './board';
6
+
7
+ interface AskOpts { crew?: string; }
8
+
9
+ export default function crewAsk(messageParts: string[] | string | undefined, opts: AskOpts): void {
10
+ const crew = requireCrew(opts.crew);
11
+ const message = Array.isArray(messageParts) ? messageParts.join(' ') : (messageParts || '');
12
+ if (!message.trim()) {
13
+ print.info('no message supplied; running a lightweight Lead tick.');
14
+ print.info('MVP Lead tick only refreshes status. LLM delegation will be added in a later phase.');
15
+ crewBoard({ crew: crew.name });
16
+ return;
17
+ }
18
+ const file = rootPath(crew, 'Current-Goal.md');
19
+ fs.appendFileSync(file, `\n- ${new Date().toISOString()} ${message.trim()}\n`, 'utf8');
20
+ appendLog(crew, `Lead input: ${message.trim()}`);
21
+ print.succeed(`added goal input to ${file}`);
22
+ crewBoard({ crew: crew.name });
23
+ }
24
+