Skip to content

Commit ffbd2ce

Browse files
docs: update capture automation and flow documentation; refine automation installation process and transcript handling for improved accuracy and user experience
1 parent f631822 commit ffbd2ce

7 files changed

Lines changed: 119 additions & 10 deletions

File tree

.almanac/pages/almanac-doctor.md

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
---
2+
title: Almanac Doctor
3+
summary: "`almanac doctor` reports install, agent, update, and wiki status, but it currently stops at diagnosis and prints `run:` hints instead of applying repairs."
4+
topics: [cli, systems]
5+
files:
6+
- src/commands/doctor.ts
7+
- src/commands/doctor-checks/install.ts
8+
- src/commands/doctor-checks/wiki.ts
9+
- src/commands/doctor-checks/updates.ts
10+
- src/commands/doctor-checks/probes.ts
11+
- src/commands/setup.ts
12+
- src/abi-guard.ts
13+
- test/doctor.test.ts
14+
sources:
15+
- docs/plans/2026-04-30-doctor-refactor.md
16+
- docs/bugs/codealmanac-known-bugs.md
17+
- /Users/kushagrachitkara/.codex/sessions/2026/05/12/rollout-2026-05-12T00-52-10-019e1b2c-0679-7bb0-a926-b8643aa710c1.jsonl
18+
verified: 2026-05-13
19+
status: active
20+
---
21+
22+
# Almanac Doctor
23+
24+
`almanac doctor` is the install-and-environment diagnostic command. It is separate from `almanac health`: doctor answers "is this install usable on this machine and in this repo," while health answers "is this wiki graph internally consistent."
25+
26+
## Current command shape
27+
28+
[[src/commands/doctor.ts]] is the composition root. It gathers four check groups and returns either formatted text or a stable JSON object:
29+
30+
- install checks from [[src/commands/doctor-checks/install.ts]]
31+
- agent readiness checks
32+
- update-notifier checks from [[src/commands/doctor-checks/updates.ts]]
33+
- repo wiki checks from [[src/commands/doctor-checks/wiki.ts]]
34+
35+
The 2026-04-30 refactor plan deliberately kept the entrypoint thin and moved durable facts into `doctor-checks/` modules so each section has one owner.
36+
37+
## What install checks cover
38+
39+
The install section currently reports:
40+
41+
- install-path detection, including whether the current binary is running from an ephemeral `npx`-style location
42+
- `better-sqlite3` native-binding readiness
43+
- Claude authentication state
44+
- whether scheduled capture automation is installed
45+
- whether Claude guide files exist under `~/.claude/`
46+
- whether `~/.claude/CLAUDE.md` contains the Almanac import line
47+
48+
[[src/commands/doctor-checks/install.ts]] expresses repairs as `fix: "run: ..."` strings. The command prints those hints, but it does not execute them.
49+
50+
## Relationship to the SQLite ABI guard
51+
52+
[[src/abi-guard.ts]] fails early when `better-sqlite3` cannot load under the current Node ABI and prints an exact rebuild command. Doctor surfaces the same failure class as structured install state: `install.sqlite` reports whether the binding loads and points users at `npm rebuild better-sqlite3` when it does not.
53+
54+
This matters because the SQLite binding is the main query-stack fragility called out in [[sqlite-indexer]] and `docs/bugs/codealmanac-known-bugs.md`. The tool can explain the failure clearly today, but the repair is still manual.
55+
56+
## Wiki-scope checks
57+
58+
The wiki section first resolves the nearest repo with `.almanac/`. When one exists, it reports:
59+
60+
- repo root
61+
- whether the repo is already present in the global [[global-registry]]
62+
- indexed page and topic counts when `.almanac/index.db` is readable
63+
- index age
64+
- most recent capture artifact age
65+
- an `almanac health` summary
66+
67+
If wiki checks throw, [[src/commands/doctor.ts]] degrades to a single `wiki.checks` problem entry instead of crashing the whole command.
68+
69+
## Verification boundaries
70+
71+
Doctor does not currently verify every setup artifact it installs. [[global-agent-instructions]] documents one current gap: install checks verify Claude-side guides and import lines, but there is no Codex-specific doctor check for `~/.codex/AGENTS.md` or `AGENTS.override.md`.
72+
73+
The command also remains diagnostic-only. Even when a fix is straightforward, such as reinstalling automation or rerunning setup to restore guide files, doctor only prints the suggested command.
74+
75+
## Product direction recorded on 2026-05-12
76+
77+
The captured Codex session on 2026-05-12 proposed `almanac doctor --fix` as a follow-on feature after the repo itself hit a real `better-sqlite3` ABI mismatch during exploration. The proposal was to auto-repair only safe local problems that doctor already knows how to diagnose:
78+
79+
- rebuild `better-sqlite3` for the active Node runtime
80+
- recreate a missing `.almanac/index.db`
81+
- rerun setup-owned guide installation
82+
- repair or refresh the global registry
83+
- reinstall scheduled automation when configuration says it should exist
84+
85+
The same discussion kept one boundary explicit: destructive or ambiguous cases should stay manual and continue to surface as warnings rather than silent mutations.

.almanac/pages/capture-automation.md

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ files:
1818
sources:
1919
- /Users/kushagrachitkara/.codex/sessions/2026/05/11/rollout-2026-05-11T14-32-08-019e18f4-5e73-7790-ba49-73cc02544a58.jsonl
2020
status: implemented
21-
verified: 2026-05-12
21+
verified: 2026-05-13
2222
---
2323

2424
# Capture Automation
@@ -36,9 +36,11 @@ The same 2026-05-11 session ended with a code review of the shipped scheduler pa
3636
- Setup and uninstall treat scheduler automation as the only public auto-capture path and also clean up legacy Claude/Codex/Cursor hook installs privately.
3737
- Legacy hook cleanup has to recognize multiple provider-era names for the same idea, including `SessionEnd`, `Stop`, and `sessionEnd`, so scheduler migration does not assume one canonical hook label.
3838
- That cleanup is content-based and recursive, not just key-based: it removes old `almanac-capture.sh` command objects from wrapped and unwrapped hook shapes, then prunes now-empty event arrays or wrapper containers so setup/uninstall can heal provider hook files in place.
39-
- `runAutomationInstall()` writes a launchd plist with absolute `node` and `dist/codealmanac.js` program arguments instead of relying on `almanac` being on launchd's reduced `PATH`.
39+
- `runAutomationInstall()` still defaults to absolute `node` and `dist/codealmanac.js` program arguments, but setup overrides that when it was launched from an ephemeral `npx` install. After setup successfully installs a durable global package, the plist switches to `/usr/bin/env almanac capture sweep --quiet ...`; if that durable install fails or is skipped, setup skips scheduler installation rather than pinning launchd to the ephemeral cache path.
4040
- `runAutomationInstall()` records `automation.capture_since` in `~/.almanac/config.toml` the first time scheduled capture is enabled, and later reinstall runs preserve the original activation baseline.
41-
- `almanac capture sweep` skips transcript files whose mtime predates `automation.capture_since` with the `before-automation-activation` reason, so first-run automation does not backfill a user's entire historical chat corpus.
41+
- `runAutomationInstall()` migrates legacy JSON config into TOML before writing `automation.capture_since`, so enabling automation does not discard older agent settings during the same write.
42+
- `almanac capture sweep` skips transcript files whose mtime predates `automation.capture_since` with the `before-automation-activation` reason, and for transcripts that span that boundary it starts at the first line whose own timestamp is at or after the activation time.
43+
- A continued transcript whose file mtime is new enough but whose lines do not carry timestamps is treated as `unchanged` on a fresh ledger rather than being backfilled speculatively.
4244
- The sqlite-free fast path in [[lifecycle-cli]] handles `automation install|status|uninstall` before Commander loads, and validates `automation install --every` explicitly.
4345
- Transcript metadata discovery reads only an initial header chunk for the first lines rather than loading whole transcript files during metadata scanning.
4446

@@ -234,7 +236,7 @@ That keeps the system debuggable:
234236

235237
The same session tightened that separation one step further: the scheduler entry should only need wakeup-level state such as interval, command path, and log paths. Sweep behavior such as enabled apps, quiet window, and other capture defaults should live in CodeAlmanac-owned config that `almanac capture sweep` reads when it starts. For the first version, even that split can stay minimal: the wakeup cadence may still be the only scheduler-owned knob, and changing it would rewrite or reload the platform scheduler entry.
236238

237-
The current macOS implementation now follows that stronger shape. `runAutomationInstall()` writes launchd `ProgramArguments` as the absolute Node executable plus the resolved `dist/codealmanac.js` entrypoint, then appends `capture sweep`. The scheduler still stays intentionally thin, but it no longer depends on `almanac` being present on launchd's reduced `PATH`.
239+
The current macOS implementation now follows that stronger shape, but with one setup-time distinction. Direct installs still write launchd `ProgramArguments` as the absolute Node executable plus the resolved `dist/codealmanac.js` entrypoint, then append `capture sweep`. Setup switches to `/usr/bin/env almanac ...` only after it has first converted an ephemeral `npx` launch into a durable global install. If that durable install does not happen, setup leaves automation uninstalled instead of writing a launchd entry that points into the temporary `npx` cache.
238240

239241
## Verification status
240242

@@ -247,6 +249,7 @@ One specific observation from that smoke pass is worth keeping as a sanity ancho
247249
That machine-level macOS smoke test was completed on 2026-05-12. The important proof points were:
248250

249251
- `node dist/codealmanac.js automation install` wrote a launchd plist whose `ProgramArguments` used the absolute Node executable plus the resolved `dist/codealmanac.js` entrypoint.
252+
- `almanac setup` invoked from an ephemeral `npx` location no longer writes that cache path into launchd. After a successful global install it writes `/usr/bin/env almanac ...`; otherwise it skips automation and tells the user a durable install is required.
250253
- The same plist also wrote `EnvironmentVariables.PATH`, preserving the install-time shell PATH so launchd could find user-managed CLIs such as a Codex binary installed under `nvm`.
251254
- A temporary stress configuration of `--every 1m --quiet 1s` produced real scheduled sweeps, started Codex absorb jobs successfully after the PATH fix, and those jobs completed with wiki page updates rather than failing at process startup.
252255

@@ -283,6 +286,8 @@ Future work in this area should preserve the distinction between:
283286

284287
The implementation stores that baseline as `automation.capture_since` in the global config schema. `runAutomationInstall()` writes it only when no valid value already exists, which keeps setup and reinstall idempotent: re-running setup refreshes the launchd plist but does not accidentally move the capture boundary forward and skip active post-install sessions.
285288

289+
The review follow-up on 2026-05-13 made that boundary more precise for fresh ledgers. If a transcript started before automation was enabled but later gained new lines, sweep does not have to drop the entire file. When transcript lines carry their own timestamps, the fresh ledger starts at the first line at or after `automation.capture_since` and captures only the post-activation continuation. When the transcript lacks line timestamps, sweep refuses to infer the boundary and treats the file as already covered until newer appended content makes the continuation explicit.
290+
286291
## Manual smoke ladder
287292

288293
The same session also converged on a practical verification ladder that future debugging should reuse instead of jumping straight to `launchd`:

.almanac/pages/capture-flow.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@ files:
1313
sources:
1414
- /Users/kushagrachitkara/.codex/sessions/2026/05/11/rollout-2026-05-11T14-32-08-019e18f4-5e73-7790-ba49-73cc02544a58.jsonl
1515
- /Users/kushagrachitkara/.codex/sessions/2026/05/11/rollout-2026-05-11T21-33-50-019e1a76-701d-7583-a76c-b3739632ee9b.jsonl
16+
- /Users/kushagrachitkara/.codex/sessions/2026/05/12/rollout-2026-05-12T20-25-14-019e1f5d-ff59-7ee1-a73b-836277d8092b.jsonl
1617
- https://openai.com/api/pricing/
1718
- https://developers.openai.com/api/docs/models/gpt-5.5
18-
verified: 2026-05-12
19+
verified: 2026-05-13
1920
---
2021

2122
# Capture Flow
@@ -44,6 +45,8 @@ Repeated JSON envelopes, long tool schemas, verbose stdout, and other raw payloa
4445

4546
The same transcript also exposed a concrete Codex-specific version of that noise pattern: naive text search can get swamped by the opening `session_meta` payload, repeated `turn_context` blocks, and serialized tool catalogs before it reaches the user/problem signal. Future transcript tooling should therefore prefer event-type-aware extraction over generic line-oriented grep whenever it is trying to recover capture-relevant meaning rather than debug the transcript format itself.
4647

48+
A short 2026-05-12 Codex transcript made that asymmetry concrete. The user asked one short question and the assistant answered `hello`, but the saved JSONL still reached `192` lines and `650,091` bytes because the opening `session_meta` record embedded the full global and project instruction text, and later records repeated desktop app context and tool metadata. That means transcript volume can be dominated by harness scaffolding even when the human-visible conversation is trivial.
49+
4750
A later Codex subagent experiment sharpened that cost-model warning with real usage data. A helper agent was asked to read and summarize a `716,942`-byte / `414`-line session transcript whose naive `chars / 4` estimate was about `179k` tokens. The helper's own Codex transcript finished at `315,173` cumulative `total_tokens`, with `260,992` of those counted as cached input. The durable lesson is that transcript size is not a reliable proxy for actual capture cost once the agent takes multiple turns, carries tool output forward, and benefits from cache reuse. Future optimization work should benchmark candidate capture strategies against real transcript `token_count` logs rather than assuming file-size heuristics are good enough.
4851

4952
The same experiment also showed why any future "estimate capture cost" feature needs a model-aware pricing rule, not just token totals. Using OpenAI's published 2026-05-12 GPT-5.5 standard rates, the run's `311,995` input tokens and `3,178` output tokens translate to a simple base-rate estimate of about `$0.48` when cached-input discounts are applied, or about `$1.66` if none of the input had been cached. But GPT-5.5's own model page also states that prompts above `272K` input tokens are billed at higher full-session rates. The durable conclusion is not the exact dollar figure from this one transcript; it is that transcript benchmarks must preserve raw token counts, cached-vs-uncached breakdown, and the pricing rule version used for the estimate.

.almanac/pages/capture-ledger.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ files:
1212
sources:
1313
- /Users/kushagrachitkara/.codex/sessions/2026/05/11/rollout-2026-05-11T14-32-08-019e18f4-5e73-7790-ba49-73cc02544a58.jsonl
1414
status: implemented
15-
verified: 2026-05-12
15+
verified: 2026-05-13
1616
---
1717

1818
# Capture Ledger
@@ -102,6 +102,8 @@ The follow-up implementation made that boundary concrete by adding `automation.c
102102

103103
That review also tightened the config contract one step further: `automation.capture_since` is user-level only, not project-configurable. `almanac config set --project automation.capture_since ...` and the matching unset path should fail, because a repo-local override would let one wiki silently redefine the user's global historical capture boundary.
104104

105+
The 2026-05-13 review tightened the first-entry behavior around that boundary. A fresh ledger entry is not always a zero cursor. If the transcript file itself is newer than `automation.capture_since` but some early lines predate that timestamp, the initial cursor starts at the first line whose own timestamp is at or after the activation boundary. If the transcript lacks line timestamps, sweep refuses to guess and treats the file as already covered until later appended content makes a safe continuation boundary visible.
106+
105107
`capture sweep --dry-run` is intentionally read-only with respect to ledger state. The sweep still computes eligibility against any existing ledger entries, but it should not create `.almanac/runs/capture-ledger.json` or advance cursors when the user is only previewing work. The first sweep tests lock this behavior in.
106108

107109
## Update timing
@@ -176,3 +178,5 @@ The durable recommendation from the later session state is:
176178
- keep automatic capture scheduler-only so no hook path bypasses the ledger
177179

178180
Future edits should preserve one subtle distinction here: "scheduler-only" removed hook bypasses at the product level, but duplicate prevention still depends on both the ledger and repo-local sweep locking. The current implementation uses `.almanac/runs/capture-sweep.lock` plus early pending-entry writes so overlapping sweeps skip busy repos instead of racing to enqueue the same continuation twice.
181+
182+
That lock layer also has its own recovery contract now. The lock is a directory containing `owner.json` with the sweep pid and start time. A later sweep treats the lock as stale when the owner metadata is missing, the timestamp is too old, or the recorded pid is no longer alive; in those cases it removes the abandoned lock and proceeds. A healthy in-process sweep still causes `sweep-already-running` for that repo.

.almanac/pages/global-agent-instructions.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ sources:
1515
- /Users/kushagrachitkara/.codex/sessions/2026/05/12/rollout-2026-05-12T14-29-09-019e1e17-fe55-7362-b42e-bb000f81f93e.jsonl
1616
- /Users/kushagrachitkara/.codex/sessions/2026/05/12/rollout-2026-05-12T20-25-14-019e1f5d-ff59-7ee1-a73b-836277d8092b.jsonl
1717
status: active
18-
verified: 2026-05-12
18+
verified: 2026-05-13
1919
---
2020

2121
# Global Agent Instructions
@@ -53,6 +53,14 @@ Uninstall also cleans up the pre-rename Claude and Codex artifacts from the olde
5353

5454
If cleanup removes the only remaining content from `CLAUDE.md`, `AGENTS.md`, or `AGENTS.override.md`, uninstall deletes that file instead of leaving an empty fingerprint behind.
5555

56+
## Markdown-only reset for reinstall tests
57+
58+
A 2026-05-12 manual reinstall test verified a narrower reset path than full uninstall. For testing only the agent-instruction markdown wiring, it was enough to delete `~/.claude/almanac.md`, `~/.claude/almanac-reference.md`, and the legacy `codealmanac*.md` guide files, then clear `~/.claude/CLAUDE.md` and `~/.codex/AGENTS.md` to zero bytes.
59+
60+
That state is "as good as new" only for the markdown artifacts. It does not remove other Almanac install state such as the launchd automation plist, hook cleanup state, the global npm package, or `~/.almanac` data. The distinction matters because users may ask whether a fresh `npx codealmanac` run will recreate the guides; the answer is yes for the markdown layer, but no session should describe that partial reset as a full machine-level clean slate.
61+
62+
The same test also confirmed one setup edge condition from code against a real install. When `~/.codex/AGENTS.override.md` is absent and `~/.codex/AGENTS.md` is empty, rerunning setup recreates the managed `<!-- almanac:start --> ... <!-- almanac:end -->` block in `AGENTS.md` rather than requiring the file to be deleted first.
63+
5664
## No single clean-slate command
5765

5866
The repo does not currently implement a one-shot "clean slate" command for Almanac artifacts. The 2026-05-11 naming-migration plan records a future slash-command recipe for that job, but the current tree still has no `.claude/commands/clean-slate.md`, no dedicated CLI command under [[src/commands/]], and no CLI registration for such a command.
@@ -68,4 +76,6 @@ The 2026-05-12 install-verification session confirmed the current fresh-install
6876
- `~/.claude/CLAUDE.md` containing `@~/.claude/almanac.md`
6977
- `~/.codex/AGENTS.md` containing the managed `<!-- almanac:start -->` block when no non-empty `AGENTS.override.md` exists
7078

79+
The same session also confirmed the reinstall path from a markdown-only reset: after clearing the markdown artifacts manually, a fresh `npx codealmanac` install recreated the two Claude guide files, restored the `@~/.claude/almanac.md` import, and repopulated `~/.codex/AGENTS.md` with the inline managed block.
80+
7181
[[src/commands/doctor-checks/install.ts]] currently verifies only the Claude-side artifacts through `install.guides` and `install.import`. There is no Codex-specific doctor check yet, so debugging "Codex is not seeing Almanac guidance" still requires reading `~/.codex/AGENTS.override.md` and `~/.codex/AGENTS.md` directly and checking which file is active.

0 commit comments

Comments
 (0)