codealmanac 0.2.6 → 0.2.7
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/LICENSE +21 -133
- package/README.md +20 -15
- package/dist/{agents-HYRWRHRX.js → agents-V2ZOIACP.js} +6 -5
- package/dist/{chunk-PDFS5VFE.js → chunk-447U3GQJ.js} +5 -17
- package/dist/chunk-447U3GQJ.js.map +1 -0
- package/dist/{chunk-3E7JNMTZ.js → chunk-5BWUMAOX.js} +4 -29
- package/dist/chunk-5BWUMAOX.js.map +1 -0
- package/dist/{chunk-KQUVMF27.js → chunk-BFIG2CXM.js} +2 -516
- package/dist/chunk-BFIG2CXM.js.map +1 -0
- package/dist/{chunk-K2JBCB7R.js → chunk-BQY5L3DL.js} +7 -43
- package/dist/chunk-BQY5L3DL.js.map +1 -0
- package/dist/{chunk-F53U6JQG.js → chunk-CQJVM34R.js} +2 -2
- package/dist/chunk-FUBE6KCO.js +124 -0
- package/dist/chunk-FUBE6KCO.js.map +1 -0
- package/dist/chunk-IZBXXAVL.js +524 -0
- package/dist/chunk-IZBXXAVL.js.map +1 -0
- package/dist/{chunk-7JUX4ADQ.js → chunk-IZT6RBHS.js} +1 -1
- package/dist/{chunk-DW32TL5W.js → chunk-JLQZELHQ.js} +18 -58
- package/dist/chunk-JLQZELHQ.js.map +1 -0
- package/dist/{chunk-2BNDNGUR.js → chunk-KZXWPG4P.js} +4 -8
- package/dist/{chunk-2BNDNGUR.js.map → chunk-KZXWPG4P.js.map} +1 -1
- package/dist/{chunk-GPFVEF6V.js → chunk-QIA22IAM.js} +6 -24
- package/dist/chunk-QIA22IAM.js.map +1 -0
- package/dist/{chunk-J7DNV2DH.js → chunk-RALBM6HZ.js} +43 -355
- package/dist/chunk-RALBM6HZ.js.map +1 -0
- package/dist/{chunk-HJ3WREGP.js → chunk-U5DLLWIC.js} +3 -3
- package/dist/chunk-WL4UE7Q6.js +1386 -0
- package/dist/chunk-WL4UE7Q6.js.map +1 -0
- package/dist/{chunk-VXDPUOQ5.js → chunk-ZUQN5Y3K.js} +129 -382
- package/dist/chunk-ZUQN5Y3K.js.map +1 -0
- package/dist/{chunk-ODJAAJGZ.js → chunk-ZZLLOAI6.js} +3 -3
- package/dist/{cli-MKXCNEMW.js → cli-XWPNARA6.js} +37 -20
- package/dist/cli-XWPNARA6.js.map +1 -0
- package/dist/codealmanac.js +1 -1
- package/dist/{config-F7FKEQ7F.js → config-KH3JUMG6.js} +4 -4
- package/dist/doctor-ENJT665Z.js +18 -0
- package/dist/{hook-4SVX446M.js → hook-2NP3UE7U.js} +2 -4
- package/dist/paths-O5CZADP2.js +14 -0
- package/dist/process-KFSLENL3.js +61 -0
- package/dist/{register-commands-2F6SXLDI.js → register-commands-LULZUSPO.js} +999 -1030
- package/dist/register-commands-LULZUSPO.js.map +1 -0
- package/dist/uninstall-BD4MMQ7M.js +16 -0
- package/dist/uninstall-BD4MMQ7M.js.map +1 -0
- package/dist/update-XSKPDFMJ.js +11 -0
- package/dist/update-XSKPDFMJ.js.map +1 -0
- package/dist/{wiki-IGNRNLUZ.js → wiki-O4RWMAE6.js} +8 -6
- package/dist/wiki-O4RWMAE6.js.map +1 -0
- package/guides/mini.md +8 -6
- package/guides/reference.md +89 -32
- package/hooks/almanac-capture.sh +7 -8
- package/package.json +3 -4
- package/prompts/agents/.gitkeep +1 -0
- package/prompts/base/notability.md +139 -0
- package/prompts/base/purpose.md +85 -0
- package/prompts/base/syntax.md +114 -0
- package/prompts/operations/absorb.md +43 -0
- package/prompts/operations/build.md +49 -0
- package/prompts/operations/garden.md +51 -0
- package/COMMERCIAL.md +0 -9
- package/dist/chunk-3E7JNMTZ.js.map +0 -1
- package/dist/chunk-DW32TL5W.js.map +0 -1
- package/dist/chunk-GPFVEF6V.js.map +0 -1
- package/dist/chunk-J7DNV2DH.js.map +0 -1
- package/dist/chunk-K2JBCB7R.js.map +0 -1
- package/dist/chunk-KQUVMF27.js.map +0 -1
- package/dist/chunk-PDFS5VFE.js.map +0 -1
- package/dist/chunk-VXDPUOQ5.js.map +0 -1
- package/dist/cli-MKXCNEMW.js.map +0 -1
- package/dist/doctor-37UH3HT5.js +0 -17
- package/dist/register-commands-2F6SXLDI.js.map +0 -1
- package/dist/uninstall-C62ZOK32.js +0 -17
- package/dist/update-2UGOFN5C.js +0 -11
- package/dist/wiki-IGNRNLUZ.js.map +0 -1
- package/prompts/bootstrap.md +0 -176
- package/prompts/reviewer.md +0 -129
- package/prompts/writer.md +0 -134
- /package/dist/{agents-HYRWRHRX.js.map → agents-V2ZOIACP.js.map} +0 -0
- /package/dist/{chunk-F53U6JQG.js.map → chunk-CQJVM34R.js.map} +0 -0
- /package/dist/{chunk-7JUX4ADQ.js.map → chunk-IZT6RBHS.js.map} +0 -0
- /package/dist/{chunk-HJ3WREGP.js.map → chunk-U5DLLWIC.js.map} +0 -0
- /package/dist/{chunk-ODJAAJGZ.js.map → chunk-ZZLLOAI6.js.map} +0 -0
- /package/dist/{config-F7FKEQ7F.js.map → config-KH3JUMG6.js.map} +0 -0
- /package/dist/{doctor-37UH3HT5.js.map → doctor-ENJT665Z.js.map} +0 -0
- /package/dist/{hook-4SVX446M.js.map → hook-2NP3UE7U.js.map} +0 -0
- /package/dist/{uninstall-C62ZOK32.js.map → paths-O5CZADP2.js.map} +0 -0
- /package/dist/{update-2UGOFN5C.js.map → process-KFSLENL3.js.map} +0 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
removeImportLine,
|
|
4
|
+
runUninstall
|
|
5
|
+
} from "./chunk-BQY5L3DL.js";
|
|
6
|
+
import "./chunk-ZUQN5Y3K.js";
|
|
7
|
+
import "./chunk-447U3GQJ.js";
|
|
8
|
+
import "./chunk-RALBM6HZ.js";
|
|
9
|
+
import "./chunk-FUBE6KCO.js";
|
|
10
|
+
import "./chunk-5BWUMAOX.js";
|
|
11
|
+
import "./chunk-IZT6RBHS.js";
|
|
12
|
+
export {
|
|
13
|
+
removeImportLine,
|
|
14
|
+
runUninstall
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=uninstall-BD4MMQ7M.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
-
ensureFreshIndex,
|
|
4
3
|
findEntry,
|
|
5
|
-
openIndex,
|
|
6
4
|
runHealth
|
|
7
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-IZBXXAVL.js";
|
|
6
|
+
import {
|
|
7
|
+
ensureFreshIndex,
|
|
8
|
+
openIndex
|
|
9
|
+
} from "./chunk-BFIG2CXM.js";
|
|
8
10
|
import {
|
|
9
11
|
formatDuration
|
|
10
12
|
} from "./chunk-4CODZRHH.js";
|
|
11
13
|
import "./chunk-FM3VRDK7.js";
|
|
12
14
|
import {
|
|
13
15
|
findNearestAlmanacDir
|
|
14
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-IZT6RBHS.js";
|
|
15
17
|
|
|
16
18
|
// src/commands/doctor-checks/wiki.ts
|
|
17
19
|
import { existsSync, readdirSync, statSync } from "fs";
|
|
@@ -24,7 +26,7 @@ async function gatherWikiChecks(options) {
|
|
|
24
26
|
status: "info",
|
|
25
27
|
key: "wiki.none",
|
|
26
28
|
message: "No wiki in current directory",
|
|
27
|
-
fix: "run: almanac
|
|
29
|
+
fix: "run: almanac init (to create one in this repo)"
|
|
28
30
|
});
|
|
29
31
|
return checks;
|
|
30
32
|
}
|
|
@@ -234,4 +236,4 @@ function countHealthProblems(jsonStdout) {
|
|
|
234
236
|
export {
|
|
235
237
|
gatherWikiChecks
|
|
236
238
|
};
|
|
237
|
-
//# sourceMappingURL=wiki-
|
|
239
|
+
//# sourceMappingURL=wiki-O4RWMAE6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/doctor-checks/wiki.ts"],"sourcesContent":["import { existsSync, readdirSync, statSync } from \"node:fs\";\nimport path from \"node:path\";\n\nimport type Database from \"better-sqlite3\";\n\nimport { ensureFreshIndex } from \"../../indexer/index.js\";\nimport { openIndex } from \"../../indexer/schema.js\";\nimport { findNearestAlmanacDir } from \"../../paths.js\";\nimport { findEntry } from \"../../registry/index.js\";\nimport { runHealth, type HealthReport } from \"../health.js\";\nimport { formatDuration } from \"./duration.js\";\nimport type { Check, DoctorOptions } from \"./types.js\";\n\nexport async function gatherWikiChecks(options: DoctorOptions): Promise<Check[]> {\n const checks: Check[] = [];\n const repoRoot = findNearestAlmanacDir(options.cwd);\n\n if (repoRoot === null) {\n checks.push({\n status: \"info\",\n key: \"wiki.none\",\n message: \"No wiki in current directory\",\n fix: \"run: almanac init (to create one in this repo)\",\n });\n return checks;\n }\n\n checks.push({\n status: \"info\",\n key: \"wiki.repo\",\n message: `repo: ${repoRoot}`,\n });\n\n try {\n await ensureFreshIndex({ repoRoot });\n } catch {\n // non-fatal: counts below and the health probe report any real issue.\n }\n\n checks.push(await describeRegistry(repoRoot));\n\n const almanacDir = path.join(repoRoot, \".almanac\");\n const dbPath = path.join(almanacDir, \"index.db\");\n checks.push(...describeCounts(dbPath));\n checks.push(describeIndexFreshness(dbPath));\n checks.push(describeLastCapture(almanacDir, options.now));\n checks.push(await describeHealth(repoRoot, options));\n\n return checks;\n}\n\nasync function describeRegistry(repoRoot: string): Promise<Check> {\n try {\n const entry = await findEntry({ path: repoRoot });\n if (entry !== null) {\n return {\n status: \"ok\",\n key: \"wiki.registered\",\n message: `registered as '${entry.name}'`,\n };\n }\n return {\n status: \"info\",\n key: \"wiki.registered\",\n message: \"not yet registered (will register on first command)\",\n };\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n status: \"problem\",\n key: \"wiki.registered\",\n message: `could not read registry: ${msg}`,\n fix: \"inspect ~/.almanac/registry.json; remove or fix the malformed entry\",\n };\n }\n}\n\nfunction describeCounts(dbPath: string): Check[] {\n const checks: Check[] = [];\n let pageCount: number | null = null;\n let topicCount: number | null = null;\n\n if (existsSync(dbPath)) {\n try {\n const db = openIndex(dbPath);\n try {\n pageCount = countRows(db, \"pages\");\n topicCount = countRows(db, \"topics\");\n } finally {\n db.close();\n }\n } catch {\n pageCount = null;\n }\n }\n\n if (pageCount !== null) {\n checks.push({\n status: \"info\",\n key: \"wiki.pages\",\n message: `pages: ${pageCount}`,\n });\n }\n if (topicCount !== null) {\n checks.push({\n status: \"info\",\n key: \"wiki.topics\",\n message: `topics: ${topicCount}`,\n });\n }\n\n return checks;\n}\n\nfunction countRows(db: Database.Database, table: string): number {\n const row = db\n .prepare<[], { n: number }>(`SELECT COUNT(*) AS n FROM ${table}`)\n .get();\n return row?.n ?? 0;\n}\n\nfunction describeIndexFreshness(dbPath: string): Check {\n if (!existsSync(dbPath)) {\n return {\n status: \"info\",\n key: \"wiki.index\",\n message: \"index: not built yet (run any query command)\",\n };\n }\n try {\n const dbMtime = statSync(dbPath).mtimeMs;\n const age = Date.now() - dbMtime;\n return {\n status: \"info\",\n key: \"wiki.index\",\n message: `index: rebuilt ${formatDuration(age)} ago`,\n };\n } catch {\n return {\n status: \"info\",\n key: \"wiki.index\",\n message: \"index: present\",\n };\n }\n}\n\nfunction describeLastCapture(\n almanacDir: string,\n nowFn?: () => Date,\n): Check {\n if (!existsSync(almanacDir)) {\n return {\n status: \"info\",\n key: \"wiki.capture\",\n message: \"last capture: never\",\n };\n }\n const logDirs = [path.join(almanacDir, \"logs\"), almanacDir];\n const captures = logDirs\n .flatMap((dir) => {\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return [];\n }\n return entries\n .filter(\n (e) =>\n e.startsWith(\".capture-\") &&\n (e.endsWith(\".log\") || e.endsWith(\".jsonl\")),\n )\n .map((e) => ({ dir, name: e }));\n })\n .map((e) => {\n try {\n return {\n name: e.name,\n mtime: statSync(path.join(e.dir, e.name)).mtimeMs,\n };\n } catch {\n return null;\n }\n })\n .filter((e): e is { name: string; mtime: number } => e !== null);\n if (captures.length === 0) {\n return {\n status: \"info\",\n key: \"wiki.capture\",\n message: \"last capture: never\",\n };\n }\n captures.sort((a, b) => b.mtime - a.mtime);\n const latest = captures[0]!;\n const now = (nowFn?.() ?? new Date()).getTime();\n const age = now - latest.mtime;\n return {\n status: \"info\",\n key: \"wiki.capture\",\n message: `last capture: ${formatDuration(age)} ago (${latest.name})`,\n };\n}\n\nasync function describeHealth(\n repoRoot: string,\n options: DoctorOptions,\n): Promise<Check> {\n const healthFn = options.runHealthFn ?? runHealth;\n try {\n const healthRes = await healthFn({\n cwd: repoRoot,\n json: true,\n });\n const problems = countHealthProblems(healthRes.stdout);\n if (problems === 0) {\n return {\n status: \"ok\",\n key: \"wiki.health\",\n message: \"almanac health reports 0 problems\",\n };\n }\n return {\n status: \"problem\",\n key: \"wiki.health\",\n message: `almanac health reports ${problems} problem${problems === 1 ? \"\" : \"s\"}`,\n fix: \"run: almanac health\",\n };\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n status: \"info\",\n key: \"wiki.health\",\n message: `could not run almanac health: ${msg}`,\n };\n }\n}\n\nconst HEALTH_PROBLEM_KEYS: (keyof HealthReport)[] = [\n \"orphans\",\n \"stale\",\n \"dead_refs\",\n \"broken_links\",\n \"broken_xwiki\",\n \"empty_topics\",\n \"empty_pages\",\n \"slug_collisions\",\n];\n\nfunction countHealthProblems(jsonStdout: string): number {\n try {\n const report = JSON.parse(jsonStdout) as Partial<HealthReport>;\n let total = 0;\n for (const key of HEALTH_PROBLEM_KEYS) {\n const arr = report[key];\n if (Array.isArray(arr)) total += arr.length;\n }\n return total;\n } catch {\n return 0;\n }\n}\n"],"mappings":"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","names":[]}
|
package/guides/mini.md
CHANGED
|
@@ -4,7 +4,7 @@ This repo has a `.almanac/` directory. It's a **living wiki** written for AI age
|
|
|
4
4
|
|
|
5
5
|
You are the primary reader. When the user asks you to do something, **check the wiki before you touch related code** — it will often answer the question the user didn't think to ask ("we tried that in March, here's why it broke").
|
|
6
6
|
|
|
7
|
-
You don't write the wiki during normal work.
|
|
7
|
+
You usually don't write the wiki during normal work. `almanac capture` runs automatically at session end through the installed hook, reads the session transcript, and starts an Absorb job that writes or updates pages. Your job during the session is: **read, use, occasionally fix obvious errors.**
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
|
@@ -165,9 +165,10 @@ You don't write anything. At session end the capture agent reads the transcript,
|
|
|
165
165
|
|
|
166
166
|
## What runs automatically (don't invoke these)
|
|
167
167
|
|
|
168
|
-
- **`almanac capture`** —
|
|
168
|
+
- **`almanac capture`** — starts a background Absorb job after supported agent sessions through the installed hook.
|
|
169
169
|
- **`almanac reindex`** — runs implicitly before every query when pages changed.
|
|
170
|
-
|
|
170
|
+
|
|
171
|
+
Run `almanac init` yourself when you are creating the first wiki for a repo.
|
|
171
172
|
|
|
172
173
|
---
|
|
173
174
|
|
|
@@ -186,7 +187,7 @@ If the user has multiple repos with `.almanac/`, they're globally registered. Pa
|
|
|
186
187
|
- **Reference code with `[[...]]`.** Inline mentions are fine but only `[[...]]` gets indexed.
|
|
187
188
|
- **List files in frontmatter.** Pages about specific code need `files: [...]` to surface in `--mentions` queries.
|
|
188
189
|
|
|
189
|
-
The
|
|
190
|
+
The Absorb/Garden prompts enforce these during wiki-writing runs. Stricter with yourself = less rework.
|
|
190
191
|
|
|
191
192
|
---
|
|
192
193
|
|
|
@@ -210,9 +211,10 @@ Empty stdout plus `# 0 results` on stderr means the query ran and genuinely matc
|
|
|
210
211
|
```bash
|
|
211
212
|
almanac doctor # install.hook: ok/problem, wiki.capture: last capture age
|
|
212
213
|
almanac hook status # just the hook entry
|
|
213
|
-
|
|
214
|
+
almanac jobs
|
|
215
|
+
ls -lah .almanac/runs/
|
|
214
216
|
```
|
|
215
|
-
No
|
|
217
|
+
No jobs at all → the hook isn't installed, bailed before starting capture, or `cwd` was outside any wiki (silent correct no-op). Capture ran but wrote nothing → the Absorb run decided there was no durable wiki change, or the session was pure-read. Use `almanac jobs show <run-id>` and `almanac jobs logs <run-id>` for details.
|
|
216
218
|
|
|
217
219
|
---
|
|
218
220
|
|
package/guides/reference.md
CHANGED
|
@@ -6,12 +6,12 @@ Groupings match `almanac --help`:
|
|
|
6
6
|
|
|
7
7
|
1. **Query** — `search`, `show`, `health`, `list`
|
|
8
8
|
2. **Edit** — `tag`, `untag`, `topics ...`
|
|
9
|
-
3. **Wiki lifecycle** — `
|
|
9
|
+
3. **Wiki lifecycle** — `init`, `capture`, `ingest`, `garden`, `jobs`, `hook ...`, `reindex`
|
|
10
10
|
4. **Setup** — `setup`, `uninstall`, `doctor`, `update`
|
|
11
11
|
|
|
12
12
|
Every query/edit command auto-registers the current repo in `~/.almanac/registry.json` on first run. Exceptions: `list --drop` (skips auto-register so the removal intent isn't undone) and the setup group (installers, not wiki commands — they never touch the registry).
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
A wiki gets scaffolded two ways: run `almanac init` yourself, or clone a repo that already has `.almanac/` committed (auto-registered on first query/edit command).
|
|
15
15
|
|
|
16
16
|
---
|
|
17
17
|
|
|
@@ -116,26 +116,81 @@ All topic subcommands accept `--wiki <name>`. `list` / `show` accept `--json`.
|
|
|
116
116
|
|
|
117
117
|
### 1.3 Wiki lifecycle
|
|
118
118
|
|
|
119
|
-
#### `almanac
|
|
119
|
+
#### `almanac init`
|
|
120
120
|
|
|
121
|
-
|
|
121
|
+
Build the first wiki for this repo. Requires the selected provider to be installed and ready.
|
|
122
122
|
|
|
123
|
-
|
|
123
|
+
| Flag | Semantics |
|
|
124
|
+
|---|---|
|
|
125
|
+
| `--using <provider[/model]>` | Override the configured provider/model for this run. |
|
|
126
|
+
| `--background` | Start as a detached CodeAlmanac job. |
|
|
127
|
+
| `--json` | Emit structured JSON for background job start. Cannot be combined with foreground mode. |
|
|
128
|
+
| `--force` | Allow rebuilding an existing populated wiki. |
|
|
129
|
+
| `-y, --yes` | Confirm non-interactively. |
|
|
130
|
+
|
|
131
|
+
`init` runs foreground by default because first setup is an onboarding action. The Build operation receives the shared prompt base (`purpose`, `notability`, `syntax`) plus the Build algorithm prompt and runtime context.
|
|
124
132
|
|
|
125
|
-
#### `almanac capture [
|
|
133
|
+
#### `almanac capture [sessionFiles...]`
|
|
126
134
|
|
|
127
|
-
|
|
135
|
+
Absorb coding-session knowledge into the wiki. Usually automatic: the installed hook invokes this at session end. Refuses if no `.almanac/` exists in cwd or any parent.
|
|
128
136
|
|
|
129
137
|
| Flag | Semantics |
|
|
130
138
|
|---|---|
|
|
131
|
-
| `[
|
|
132
|
-
| `--
|
|
133
|
-
| `--
|
|
134
|
-
| `--
|
|
135
|
-
| `--
|
|
136
|
-
| `--
|
|
139
|
+
| `[sessionFiles...]` | Explicit session transcript files. |
|
|
140
|
+
| `--app <app>` | Source app: `claude`, `codex`, `cursor`, or `generic`. |
|
|
141
|
+
| `--session <id>` | Target a specific session by ID. |
|
|
142
|
+
| `--since <duration-or-date>` | Capture sessions since a time. |
|
|
143
|
+
| `--limit <n>` | Maximum sessions to capture. |
|
|
144
|
+
| `--all` | Capture all matching sessions. |
|
|
145
|
+
| `--all-apps` | Capture from all supported apps. |
|
|
146
|
+
| `--using <provider[/model]>` | Override the configured provider/model for this run. |
|
|
147
|
+
| `--foreground` | Run attached instead of starting a background job. |
|
|
148
|
+
| `--json` | Emit structured JSON for background job start. Cannot be combined with `--foreground`. |
|
|
149
|
+
| `-y, --yes` | Confirm non-interactively. |
|
|
150
|
+
|
|
151
|
+
`capture` maps to the internal Absorb operation with `targetKind: "session"`. It starts background by default. Run records and JSONL event logs live under `.almanac/runs/`.
|
|
152
|
+
|
|
153
|
+
#### `almanac ingest <paths...>`
|
|
154
|
+
|
|
155
|
+
Absorb knowledge from one or more files or folders.
|
|
156
|
+
|
|
157
|
+
| Flag | Semantics |
|
|
158
|
+
|---|---|
|
|
159
|
+
| `<paths...>` | One or more files/folders to use as starting context. |
|
|
160
|
+
| `--using <provider[/model]>` | Override the configured provider/model for this run. |
|
|
161
|
+
| `--foreground` | Run attached instead of starting a background job. |
|
|
162
|
+
| `--json` | Emit structured JSON for background job start. Cannot be combined with `--foreground`. |
|
|
163
|
+
| `-y, --yes` | Confirm non-interactively. |
|
|
164
|
+
|
|
165
|
+
`ingest` maps to the internal Absorb operation with `targetKind: "path"`. The input is raw material, not the output; Absorb updates the wiki only when it finds durable project understanding.
|
|
166
|
+
|
|
167
|
+
#### `almanac garden`
|
|
168
|
+
|
|
169
|
+
Improve the wiki as a graph: page boundaries, links, topics, hubs, stale claims, archive/supersession chains, and synthesis quality.
|
|
170
|
+
|
|
171
|
+
| Flag | Semantics |
|
|
172
|
+
|---|---|
|
|
173
|
+
| `--using <provider[/model]>` | Override the configured provider/model for this run. |
|
|
174
|
+
| `--foreground` | Run attached instead of starting a background job. |
|
|
175
|
+
| `--json` | Emit structured JSON for background job start. Cannot be combined with `--foreground`. |
|
|
176
|
+
| `-y, --yes` | Confirm non-interactively. |
|
|
177
|
+
|
|
178
|
+
`garden` starts background by default.
|
|
179
|
+
|
|
180
|
+
#### `almanac jobs`
|
|
181
|
+
|
|
182
|
+
Inspect and manage CodeAlmanac runs stored under `.almanac/runs/`.
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
almanac jobs
|
|
186
|
+
almanac jobs list
|
|
187
|
+
almanac jobs show <run-id>
|
|
188
|
+
almanac jobs logs <run-id>
|
|
189
|
+
almanac jobs attach <run-id>
|
|
190
|
+
almanac jobs cancel <run-id>
|
|
191
|
+
```
|
|
137
192
|
|
|
138
|
-
|
|
193
|
+
Each jobs subcommand accepts `--json`. `attach` streams the JSONL event log until the run reaches `done`, `failed`, `cancelled`, or `stale`.
|
|
139
194
|
|
|
140
195
|
#### `almanac hook install | uninstall | status`
|
|
141
196
|
|
|
@@ -242,11 +297,10 @@ almanac agents model claude --default
|
|
|
242
297
|
|
|
243
298
|
`agents use` writes the default provider. `agents model` writes the provider-local model override; `--default`, `default`, or `null` resets the provider to its own default. The older `almanac set default-agent ...` and `almanac set model ...` commands remain compatibility aliases and print deprecation warnings.
|
|
244
299
|
|
|
245
|
-
`
|
|
300
|
+
`init`, `capture`, `ingest`, and `garden` resolve provider settings in this order:
|
|
246
301
|
|
|
247
302
|
```text
|
|
248
|
-
--
|
|
249
|
-
--model flag > ALMANAC_MODEL env > config.agent.models[provider] > provider default
|
|
303
|
+
--using flag > project config > user config > provider default
|
|
250
304
|
```
|
|
251
305
|
|
|
252
306
|
#### `almanac config`
|
|
@@ -514,8 +568,8 @@ Claude Code invokes `SessionEnd` hooks after each session. Payload on stdin:
|
|
|
514
568
|
|
|
515
569
|
1. Parse payload with `jq`. Missing `jq` → exit 0 silently.
|
|
516
570
|
2. Walk upward from `cwd` for a `.almanac/`. Bounded at filesystem root.
|
|
517
|
-
3. Background `almanac capture "$TRANSCRIPT" --session "$SESSION_ID"
|
|
518
|
-
4. Exit always `0`. Capture failures must never break
|
|
571
|
+
3. Background `almanac capture "$TRANSCRIPT" --session "$SESSION_ID"`, redirect the hook sidecar to `.almanac/runs/.capture-$SESSION_ID.hook.log`, `disown`.
|
|
572
|
+
4. Exit always `0`. Capture failures must never break the host agent's session-end path.
|
|
519
573
|
|
|
520
574
|
Falls back to `npx --no-install codealmanac` if `almanac` isn't on `PATH`.
|
|
521
575
|
|
|
@@ -541,21 +595,23 @@ Falls back to `npx --no-install codealmanac` if `almanac` isn't on `PATH`.
|
|
|
541
595
|
```bash
|
|
542
596
|
almanac doctor # catch-all — reports hook state + last capture age
|
|
543
597
|
almanac hook status # just the hook entry
|
|
544
|
-
|
|
598
|
+
almanac jobs
|
|
599
|
+
ls -lah .almanac/runs/
|
|
545
600
|
```
|
|
546
601
|
|
|
547
|
-
Installed but no
|
|
602
|
+
Installed but no job: the session-end event didn't fire, the script bailed before starting capture (add `set -x` to trace), or no `.almanac/` existed upward from `cwd` (silent correct no-op).
|
|
548
603
|
|
|
549
604
|
### Diagnosing "capture ran but wrote nothing"
|
|
550
605
|
|
|
551
606
|
```bash
|
|
552
|
-
|
|
607
|
+
almanac jobs show <run-id>
|
|
608
|
+
almanac jobs logs <run-id>
|
|
553
609
|
```
|
|
554
610
|
|
|
555
611
|
Common causes:
|
|
556
|
-
-
|
|
612
|
+
- Provider auth is missing in the hook environment. Claude Code's hook env is minimal; `~/.zshrc` is NOT sourced. Export needed env vars via host-agent settings, or rely on provider OAuth credentials where available.
|
|
557
613
|
- Transcript path didn't resolve. Capture prints resolution status early.
|
|
558
|
-
-
|
|
614
|
+
- Absorb found no durable wiki change.
|
|
559
615
|
- Session was pure-read with no decisions or discoveries. Correct no-op.
|
|
560
616
|
|
|
561
617
|
---
|
|
@@ -576,12 +632,12 @@ Common causes:
|
|
|
576
632
|
### Registration paths
|
|
577
633
|
|
|
578
634
|
- **Silent auto-register** — every query/edit command (except `list --drop`) calls `autoRegisterIfNeeded` on cwd. A repo with `.almanac/` but no registry entry → added with `name = basename(cwd)`, no description. Makes "cloned a repo with `.almanac/` committed" just work.
|
|
579
|
-
- **`almanac
|
|
635
|
+
- **`almanac init`** — creates and registers the wiki. `name` defaults to the repo basename; edit `~/.almanac/registry.json` if you need to rename it.
|
|
580
636
|
- **`almanac list --drop <name>`** — the only removal path. Skips auto-register so the removal isn't immediately undone.
|
|
581
637
|
|
|
582
638
|
### `--wiki <name>`
|
|
583
639
|
|
|
584
|
-
Route the command at a specific registered wiki. Used when you're in one repo but querying another. Without `--wiki`, commands resolve to the wiki whose `path` is an ancestor of cwd. If none, commands error
|
|
640
|
+
Route the command at a specific registered wiki. Used when you're in one repo but querying another. Without `--wiki`, commands resolve to the wiki whose `path` is an ancestor of cwd. If none, commands error with a fix such as `run: almanac init`.
|
|
585
641
|
|
|
586
642
|
### Cross-wiki link resolution
|
|
587
643
|
|
|
@@ -597,7 +653,7 @@ Route the command at a specific registered wiki. Used when you're in one repo bu
|
|
|
597
653
|
|
|
598
654
|
## 9. Notability and writing conventions
|
|
599
655
|
|
|
600
|
-
The
|
|
656
|
+
The Build, Absorb, and Garden prompts enforce these during wiki-writing runs. Applying them yourself reduces rework.
|
|
601
657
|
|
|
602
658
|
### Patterns to avoid (bad → good)
|
|
603
659
|
|
|
@@ -737,10 +793,11 @@ Missing `files:` frontmatter, OR path referenced only in inline prose (not via `
|
|
|
737
793
|
almanac doctor # reports hook state + last capture age + auth
|
|
738
794
|
claude auth status # OAuth token present?
|
|
739
795
|
echo "${ANTHROPIC_API_KEY:0:10}" # API key fallback?
|
|
740
|
-
|
|
796
|
+
almanac jobs
|
|
797
|
+
ls -lah .almanac/runs/
|
|
741
798
|
```
|
|
742
799
|
|
|
743
|
-
No
|
|
800
|
+
No jobs at all → script bailed before starting capture. Add `set -x` to `hooks/almanac-capture.sh` to trace. If the hook itself isn't installed, `almanac doctor` reports `install.hook: problem` with `run: almanac setup --yes`.
|
|
744
801
|
|
|
745
802
|
### "slug collision warnings"
|
|
746
803
|
|
|
@@ -752,9 +809,9 @@ Case sensitivity on Linux. Schema v2 stores `original_path` for case-preserving
|
|
|
752
809
|
|
|
753
810
|
### Forensics files
|
|
754
811
|
|
|
755
|
-
- `.almanac/
|
|
756
|
-
- `.almanac/
|
|
757
|
-
- `.almanac/
|
|
812
|
+
- `.almanac/runs/<run-id>.json` — CodeAlmanac run record with status, provider, model, timings, log path, and failure metadata.
|
|
813
|
+
- `.almanac/runs/<run-id>.jsonl` — provider event log for the run. Read with `almanac jobs logs <run-id>`.
|
|
814
|
+
- `.almanac/runs/.capture-<session-id>.hook.log` — hook sidecar containing stdout/stderr from the capture start command. Present only for hook-invoked captures.
|
|
758
815
|
|
|
759
816
|
---
|
|
760
817
|
|
package/hooks/almanac-capture.sh
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
set -u
|
|
17
17
|
|
|
18
|
-
# CodeAlmanac's own
|
|
18
|
+
# CodeAlmanac's own build/capture agents may run provider CLIs internally.
|
|
19
19
|
# Their SessionEnd events must not trigger another capture, or one capture
|
|
20
20
|
# can become an unbounded capture chain.
|
|
21
21
|
if [ "${CODEALMANAC_INTERNAL_SESSION:-}" = "1" ]; then
|
|
@@ -50,7 +50,7 @@ fi
|
|
|
50
50
|
DIR="$CWD"
|
|
51
51
|
while [ "$DIR" != "/" ] && [ -n "$DIR" ]; do
|
|
52
52
|
if [ -d "$DIR/.almanac" ]; then
|
|
53
|
-
LOG_DIR="$DIR/.almanac/
|
|
53
|
+
LOG_DIR="$DIR/.almanac/runs"
|
|
54
54
|
mkdir -p "$LOG_DIR" || exit 0
|
|
55
55
|
# Prefer `almanac` on PATH; fall back to `npx codealmanac` if the
|
|
56
56
|
# binary isn't linked (happens with non-global installs).
|
|
@@ -65,8 +65,8 @@ while [ "$DIR" != "/" ] && [ -n "$DIR" ]; do
|
|
|
65
65
|
|
|
66
66
|
run_capture() {
|
|
67
67
|
cd "$DIR" && \
|
|
68
|
-
$CMD capture "$TRANSCRIPT" --session "$SESSION_ID"
|
|
69
|
-
> "$LOG_DIR/.capture-$SESSION_ID.log" 2>&1
|
|
68
|
+
$CMD capture "$TRANSCRIPT" --session "$SESSION_ID" \
|
|
69
|
+
> "$LOG_DIR/.capture-$SESSION_ID.hook.log" 2>&1
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
# Codex Stop is turn-scoped, not session-scoped. Debounce it so an
|
|
@@ -90,10 +90,9 @@ while [ "$DIR" != "/" ] && [ -n "$DIR" ]; do
|
|
|
90
90
|
exit 0
|
|
91
91
|
fi
|
|
92
92
|
|
|
93
|
-
# Background the capture, redirect all output to a session-scoped
|
|
94
|
-
#
|
|
95
|
-
#
|
|
96
|
-
# own log file consistently if desired.
|
|
93
|
+
# Background the capture start, redirect all output to a session-scoped
|
|
94
|
+
# hook sidecar. The process manager writes canonical run records and JSONL
|
|
95
|
+
# event logs under the same `.almanac/runs/` directory.
|
|
97
96
|
( run_capture ) &
|
|
98
97
|
# Detach so the shell doesn't wait on the subprocess.
|
|
99
98
|
disown $! 2>/dev/null || true
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codealmanac",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.7",
|
|
4
4
|
"description": "A living wiki for codebases, maintained by AI agents. Documents what the code can't say: decisions, flows, invariants, incidents, gotchas.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"wiki",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"codebase",
|
|
11
11
|
"knowledge-base"
|
|
12
12
|
],
|
|
13
|
-
"license": "
|
|
13
|
+
"license": "MIT",
|
|
14
14
|
"author": "Rohan Sheth",
|
|
15
15
|
"repository": {
|
|
16
16
|
"type": "git",
|
|
@@ -32,8 +32,7 @@
|
|
|
32
32
|
"hooks",
|
|
33
33
|
"guides",
|
|
34
34
|
"README.md",
|
|
35
|
-
"LICENSE"
|
|
36
|
-
"COMMERCIAL.md"
|
|
35
|
+
"LICENSE"
|
|
37
36
|
],
|
|
38
37
|
"engines": {
|
|
39
38
|
"node": "20.x || 22.x || 23.x || 24.x || 25.x"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Page Notability And Graph Structure
|
|
2
|
+
|
|
3
|
+
Use these rules to decide what deserves a page, what deserves a topic, and how
|
|
4
|
+
clusters should form. These are judgment tools, not a closed schema.
|
|
5
|
+
|
|
6
|
+
## Page Existence
|
|
7
|
+
|
|
8
|
+
A page deserves to exist when it captures durable, reusable project
|
|
9
|
+
understanding that would be costly, useful, or risky to reconstruct later.
|
|
10
|
+
|
|
11
|
+
Good page candidates include:
|
|
12
|
+
|
|
13
|
+
- **Entity**: a named thing the project reasons about, such as `run`,
|
|
14
|
+
`provider`, `topic`, `stripe`, `postgres`, or `claude-agent-sdk`.
|
|
15
|
+
- **Subsystem**: an area with responsibility and boundaries.
|
|
16
|
+
- **Flow**: behavior that crosses files, commands, systems, or agents.
|
|
17
|
+
- **Contract**: obligations between callers, providers, schemas, APIs,
|
|
18
|
+
commands, file formats, or external services.
|
|
19
|
+
- **Data model**: records, schemas, storage formats, indexes, serialized files,
|
|
20
|
+
or external payloads whose shape affects behavior.
|
|
21
|
+
- **Operation**: a recurring project or product action with inputs, outputs,
|
|
22
|
+
side effects, and verification.
|
|
23
|
+
- **Decision or rationale**: why the project chose one path over plausible
|
|
24
|
+
alternatives.
|
|
25
|
+
- **Risk or invariant**: a rule, coupling, assumption, or fragile behavior that
|
|
26
|
+
future work must preserve.
|
|
27
|
+
- **Dependency**: an external runtime, service, SDK, API, framework, law,
|
|
28
|
+
platform, or tool as used by this project.
|
|
29
|
+
- **Influence**: an external idea, paper, tradition, book, framework, or prior
|
|
30
|
+
art that shaped this project.
|
|
31
|
+
- **Research synthesis**: conclusions from docs, papers, experiments, external
|
|
32
|
+
references, or design exploration.
|
|
33
|
+
- **Market or product synthesis**: durable understanding about users,
|
|
34
|
+
positioning, pricing, competitors, sentiment, or product strategy.
|
|
35
|
+
- **Incident or postmortem**: what happened, what was learned, and what changed.
|
|
36
|
+
- **Hub**: a navigational page that explains a dense cluster.
|
|
37
|
+
|
|
38
|
+
Genres are vocabulary, not enforcement. Create a different shape when the
|
|
39
|
+
material genuinely needs it.
|
|
40
|
+
|
|
41
|
+
## What Usually Does Not Deserve A Page
|
|
42
|
+
|
|
43
|
+
Avoid pages that are only:
|
|
44
|
+
|
|
45
|
+
- file-by-file summaries
|
|
46
|
+
- folder trees in prose
|
|
47
|
+
- raw transcripts
|
|
48
|
+
- generic API documentation copied from an external source
|
|
49
|
+
- task progress logs
|
|
50
|
+
- roadmaps that belong in an issue tracker
|
|
51
|
+
- guesses about intent that the repo or sources do not support
|
|
52
|
+
- one-off facts obvious from one nearby file
|
|
53
|
+
- date-stamped notes with no synthesis value
|
|
54
|
+
- pages whose only claim is that something exists
|
|
55
|
+
|
|
56
|
+
If the useful part of an input can be folded into an existing synthesis page,
|
|
57
|
+
do that instead of creating a new page.
|
|
58
|
+
|
|
59
|
+
## Entities
|
|
60
|
+
|
|
61
|
+
Entity pages are first-class. Use the natural name as the slug when possible:
|
|
62
|
+
`stripe.md`, `postgres.md`, `run.md`, `topic.md`, `claude-agent-sdk.md`.
|
|
63
|
+
|
|
64
|
+
An entity page should explain:
|
|
65
|
+
|
|
66
|
+
- what the entity means in this project
|
|
67
|
+
- where it is represented in code, docs, config, or external systems
|
|
68
|
+
- who creates, reads, mutates, or depends on it
|
|
69
|
+
- what states, versions, or variants matter
|
|
70
|
+
- what assumptions and constraints surround it
|
|
71
|
+
- what related pages a future agent should read next
|
|
72
|
+
|
|
73
|
+
External entity pages are not encyclopedia entries. They describe the entity's
|
|
74
|
+
role in this project.
|
|
75
|
+
|
|
76
|
+
## Topics And Clusters
|
|
77
|
+
|
|
78
|
+
Topics are reading neighborhoods. A topic should help answer: what should an
|
|
79
|
+
agent read together?
|
|
80
|
+
|
|
81
|
+
Good topics name stable areas of meaning:
|
|
82
|
+
|
|
83
|
+
- `provider-harness`
|
|
84
|
+
- `prompt-system`
|
|
85
|
+
- `wiki-indexing`
|
|
86
|
+
- `agent-tools-market`
|
|
87
|
+
- `product-positioning`
|
|
88
|
+
- `claude-agent-sdk`
|
|
89
|
+
- `pricing`
|
|
90
|
+
|
|
91
|
+
Bad topics are bookkeeping labels:
|
|
92
|
+
|
|
93
|
+
- `misc`
|
|
94
|
+
- `notes`
|
|
95
|
+
- `research`
|
|
96
|
+
- `external`
|
|
97
|
+
- exact filenames
|
|
98
|
+
- dates by default
|
|
99
|
+
|
|
100
|
+
Prefer existing topics. Create a topic when several pages now form a real
|
|
101
|
+
cluster or a new cluster is clearly expected to grow.
|
|
102
|
+
|
|
103
|
+
## Hubs
|
|
104
|
+
|
|
105
|
+
A hub exists when search results are no longer enough to understand a cluster.
|
|
106
|
+
|
|
107
|
+
A hub should explain:
|
|
108
|
+
|
|
109
|
+
- what the cluster is
|
|
110
|
+
- which pages are core
|
|
111
|
+
- what a new agent should read first
|
|
112
|
+
- how the pages relate
|
|
113
|
+
- which pages are current synthesis and which are historical context
|
|
114
|
+
- what tensions, open questions, or major changes shape the area
|
|
115
|
+
|
|
116
|
+
Small clusters do not need separate hub pages. The main entity or subsystem
|
|
117
|
+
page can act as the local hub until navigation becomes unclear.
|
|
118
|
+
|
|
119
|
+
## Splitting And Merging
|
|
120
|
+
|
|
121
|
+
Use summary style. A page may start broad. When a section grows into an
|
|
122
|
+
independently useful concept, split it into its own page and leave a short
|
|
123
|
+
summary plus link on the original page.
|
|
124
|
+
|
|
125
|
+
Split when:
|
|
126
|
+
|
|
127
|
+
- a section has its own internal structure
|
|
128
|
+
- other pages want to link to that section specifically
|
|
129
|
+
- incidents, decisions, or docs cluster around a subtopic
|
|
130
|
+
- a page is doing multiple unrelated jobs
|
|
131
|
+
|
|
132
|
+
Merge when:
|
|
133
|
+
|
|
134
|
+
- two pages answer the same future-agent question
|
|
135
|
+
- one page is only a stub pointing to another
|
|
136
|
+
- a set of date-stamped fragments should become an evolving synthesis page
|
|
137
|
+
|
|
138
|
+
Archive or supersede when knowledge is no longer current but remains useful as
|
|
139
|
+
history. Delete only when the page has no durable value.
|