# V1 Decision Log

This log records design choices and tradeoffs during the V1 harness/process
refactor.

## 2026-05-10 Branch And Plan Setup

Decision: Use branch `v1` for the rewrite.

Context: User requested a new branch named `v1` if available, otherwise an
alternate such as `v2`. Local/remote `v2` already existed; `v1` was free.

Alternatives:
- Use existing `v2`.
- Use a prefixed branch such as `codex/v1`.

Why: The user explicitly asked for the `v1`/`v2` naming scheme. `v1` was
available and clearer for this rewrite.

Consequences: Branch `v1` now tracks `origin/v1`.

## 2026-05-10 Planning Scope

Decision: Treat this as a breaking architecture rewrite, not an incremental
compatibility refactor.

Context: User stated no one is using the codebase and asked not to preserve old
architecture just to fit existing code.

Alternatives:
- Incrementally adapt current `bootstrap` and `capture`.
- Keep hardcoded writer/reviewer and wrap it with new names.

Why: The new architecture requires clean boundaries: operations, process
manager, harness SDK, provider adapters, and simple prompt assembly.

Consequences: Implementation should delete stale architecture where it conflicts
with the new model.

## 2026-05-09 19:47 PDT

Decision: Add harness provider registry with placeholder adapters before porting
Claude and Codex.

Context: The new operation/process layers need a stable provider-neutral
registry and capability model before real provider ports are implemented.

Alternatives:
- Port Claude immediately while defining the registry.
- Reuse `src/agent/providers/*` directly.

Why: Placeholder adapters let the project compile and test the new boundary
without mixing old `RunAgentOptions` semantics into `AgentRunSpec`.

Consequences: Any command using the new harness before provider ports land will
fail clearly with "not implemented yet." Real Claude/Codex behavior lands in the
provider adapter phase.

## 2026-05-09 19:58 PDT

Decision: Background launches write a `queued` run record before spawning the
detached child. The child then rehydrates the spec and owns the transition to
`running`, `done`, or `failed`.

Context: If the parent spawned the child first and then wrote a `running`
record, a fast child could complete and write `done` before the parent wrote its
late `running` record, regressing the final status.

Alternatives:
- Parent writes `running` after spawn with the child PID.
- Parent writes `running` before spawn with PID `0`.
- Add a larger process supervisor before the CLI job path exists.

Why: `queued` keeps jobs visible immediately, avoids a parent/child record write
race, and lets the foreground process manager remain the single owner of actual
harness execution.

Consequences: A just-started background job may briefly show as `queued` until
the child begins. PID visibility comes from the child-owned `running` record
rather than the parent start response.

## 2026-05-09 20:03 PDT

Decision: The Claude harness adapter maps CodeAlmanac `tools` to both Claude
SDK `tools` and `allowedTools`.

Context: Claude SDK docs distinguish availability (`tools`) from auto-approval
(`allowedTools`). The old adapter only set `allowedTools`, which could be
mistaken for a strict capability boundary.

Alternatives:
- Continue setting only `allowedTools`.
- Use the full Claude Code preset and rely on prompts for tool discipline.
- Build a separate CodeAlmanac permission hook before the provider port.

Why: Passing the same mapped tool list to `tools` and `allowedTools` gives the
main agent a concrete available tool surface while keeping background runs
non-interactive with `permissionMode: "dontAsk"`.

Consequences: Tool registry entries remain provider-neutral, but the Claude
adapter is now responsible for name expansion such as `search` to `Glob`/`Grep`
and `web` to `WebSearch`/`WebFetch`. MCP server configs are passed through, but
specific MCP tool names are not invented by the registry.

## 2026-05-09 20:06 PDT

Decision: The Codex V1 adapter uses `codex exec --json` and rejects per-run
programmatic `agents`.

Context: The Codex CLI has official subagents and custom-agent concepts, but
the simple non-interactive `exec` path does not expose a Claude-equivalent
in-memory `agents` map with enforced per-agent tool scopes.

Alternatives:
- Inline requested agents into the prompt as a fallback.
- Generate `.codex/agents/*.toml` files per run.
- Wait for a fuller Codex app-server/thread lifecycle integration before
  supporting Codex agents.

Why: The V1 provider layer should report and enforce the actual primitive it can
control. `codex exec --json` is enough for Build/Absorb/Garden filesystem work,
but pretending it supports Claude-style per-run agents would make the abstraction
misleading.

Consequences: Operation builders should only include `agents` when the selected
provider capability supports `programmaticPerRun`. Codex still gets the same
assembled prompt/system text and can use its own configured harness features.

Update 2026-05-10 09:55 PDT: Codex lifecycle runs now use `codex app-server
--listen stdio://` instead of the simple `codex exec --json` path. This keeps
the same provider-neutral boundary, but maps app-server thread/turn/item
notifications into richer `HarnessEvent` records. The app-server path supports
model override, reasoning effort, structured output schema, and token usage, but
still rejects programmatic per-run agents, MCP, skills, and max-cost fields until
those can be mapped cleanly.

Security note: app-server turns run with workspace-write filesystem access and
`networkAccess: false` by default. Server-initiated approval and user-input
requests are answered noninteractively with denial or empty answers so lifecycle
commands remain pipeable and do not grant extra authority mid-run. The spawned
app-server also gets `--config mcp_servers={}` so user-level Codex MCP servers
do not leak into CodeAlmanac runs while the provider metadata says MCP is
unsupported. Handshake JSON-RPC calls have a timeout so a stalled or incompatible
app-server becomes a recorded provider failure instead of a permanently running
job. An accepted turn also has a terminal timeout, because a provider can accept
`turn/start` and then fail to emit `turn/completed`.

## 2026-05-09 20:09 PDT

Decision: Keep Cursor as future work in V1 and leave the harness adapter as an
explicit placeholder.

Context: The architecture doc says Cursor is future work and not to implement it
for this rewrite. Claude and Codex are enough to validate the provider boundary
and process manager.

Alternatives:
- Port the old `cursor-agent --print --output-format stream-json` adapter now.
- Remove Cursor from the provider registry entirely.

Why: Keeping the placeholder preserves the intended extension point without
spending implementation time on a provider that the current V1 scope explicitly
defers.

Consequences: Any Cursor run fails clearly until a later Cursor adapter lands.

## 2026-05-09 20:09 PDT

Decision: New init/build scaffolding gitignores `.almanac/runs/` instead of
`.almanac/logs/` or old root-level capture/bootstrap globs.

Context: V1 stores process records and JSONL event logs together under
`.almanac/runs/`. Separate `.almanac/logs/` state belongs to the old capture and
bootstrap architecture.

Alternatives:
- Keep ignoring both `.almanac/logs/` and `.almanac/runs/`.
- Keep the old legacy globs for backwards compatibility.

Why: The user explicitly called out that logs and runs overlap, and V1 should
make `.almanac/runs/` the single local process-state directory.

Consequences: Existing repos may still have older ignored paths, but newly
generated V1 ignore blocks only include the derived SQLite files and
`.almanac/runs/`.

## 2026-05-09 20:30 PDT

Decision: Retire public `almanac bootstrap` wiring in the V1 CLI surface.

Context: `bootstrap` is the old write-capable AI path. It bypasses the V1
operation/process/harness layers and writes old `.almanac/logs/` artifacts.

Alternatives:
- Keep `bootstrap` as a deprecated alias to `init`.
- Leave it public until a later cleanup phase.

Why: The agreed public V1 write commands are `init`, `capture`, `ingest`, and
`garden`. Keeping a second public build path would preserve architecture drift.

Consequences: The public command was removed first, then the old
`runBootstrap`, old hardcoded `runCapture`, capture-status state reader, and
the old `bootstrap`/`writer`/`reviewer` prompt files were deleted in the Phase 8
cleanup. Historical slice plans still describe that path, but V1 runtime code no
longer carries it.

## 2026-05-09 20:30 PDT

Decision: `capture` refuses to start a job when no transcript file is provided
until V1 session discovery is implemented.

Context: The first CLI wiring accepted no-arg capture and launched Absorb with
only text saying no session was provided. That created a job without the source
context the operation needs.

Alternatives:
- Keep launching and let the prompt infer what to do.
- Reuse the old Claude-only transcript resolver immediately.
- Implement full Claude/Codex/Cursor discovery in this review-fix pass.

Why: Failing clearly is safer than running an empty Absorb job. The old resolver
is Claude-specific and would reintroduce the wrong abstraction before the
provider/session discovery layer is designed.

Consequences: Explicit transcript-file capture works. No-arg/latest-session and
flag-based session discovery are a documented follow-up before V1 is complete.

Update 2026-05-09 20:33 PDT: Claude latest-session and `--session <id>`
discovery now work in the V1 command path. Codex/Cursor session discovery and
bulk filters remain explicit follow-up work.

Update 2026-05-09 20:54 PDT: Claude `--since`, `--limit`, and `--all` filters
now work in the V1 command path. Codex/Cursor discovery and cross-app
`--all-apps` remain explicit future work and fail clearly.

## 2026-05-09 20:30 PDT

Decision: Codex `exec` adapter rejects unsupported per-run fields instead of
advertising and silently dropping them.

Context: Codex metadata previously said reasoning effort, MCP, skills, and
context usage were supported, but the `codex exec --json` adapter did not map
those fields.

Alternatives:
- Keep the broader capability flags for future Codex SDK/app-server support.
- Convert unsupported fields into prompt text.

Why: Provider capabilities must describe the actual adapter primitive, not the
provider ecosystem in general.

Consequences: Current Codex V1 runs support the simple exec path: prompt, cwd,
model, workspace-write sandbox, output schema, JSONL events, and usage parsing.
Future richer Codex transports can re-enable capabilities when implemented.

## 2026-05-09 20:54 PDT

Decision: Lifecycle command provider selection uses config only when `--using`
is omitted.

Context: V1 initially parsed a missing `--using` value as Claude. That matched
the historical default but ignored user and project config, contradicting the
public command contract.

Alternatives:
- Keep hardcoded Claude as the lifecycle default.
- Require `--using` on every write-capable lifecycle command.

Why: `almanac agents use`, `almanac agents model`, and project config are the
existing provider preference surfaces. The V1 lifecycle commands should share
that configuration instead of creating a second default system.

Consequences: `init`, `capture`, `ingest`, and `garden` resolve configured
provider/model defaults through `readConfig({ cwd })`. Explicit `--using`
continues to win for that run only.

## 2026-05-09 21:05 PDT

Decision: Run records are terminal-state guarded by the process manager.

Context: A running job can be cancelled from the `jobs` command while its child
process is still executing. The foreground manager also performs post-harness
work such as page snapshots, indexing, summaries, and final record writes.

Alternatives:
- Let the child always overwrite the record with its final status.
- Treat cancellation as advisory and rely on stale detection.

Why: `.almanac/runs/<run-id>.json` is the lifecycle source of truth. Once a
record is cancelled, later in-memory process state should not resurrect it as
done or failed. Separately, finalization errors should be visible as failed run
records rather than becoming stale running records.

Consequences: Foreground finalization re-reads the current record before writing
terminal status. If the current record is already cancelled, it returns that
record. Finalization errors are caught and recorded as failed runs where
possible.

## 2026-05-09 21:05 PDT

Decision: Harness provider metadata describes implemented adapter behavior, not
the broader provider product.

Context: Codex and Cursor have broader product capabilities than the current V1
adapters. Codex V1 is a one-shot `codex exec --json` adapter, and Cursor is an
explicit not-implemented placeholder.

Alternatives:
- Advertise broader provider capabilities so future work is visible.
- Remove Cursor from the registry until implemented.

Why: Operation code will eventually branch on capability metadata. Aspirational
metadata makes that boundary unsafe because callers can trust features that the
adapter rejects or cannot run.

Consequences: Codex metadata no longer advertises session persistence, resume,
interrupt, or subagents in V1. Cursor remains listed but advertises no executable
runtime capabilities until its adapter is implemented.

Update 2026-05-09 21:09 PDT: Claude structured output is also marked false
until the adapter maps `AgentRunSpec.output` into Claude SDK options. Codex
keeps structured output true because its adapter maps `schemaPath` to
`--output-schema`.

## 2026-05-10 Prompt Base Split

Decision: Split shared prompt guidance into `purpose.md`, `notability.md`, and
`syntax.md`, then concatenate those before every operation prompt.

Context: The operation prompts need shared guidance for the broader wiki
philosophy: project memory, deep-research cache, codebase as anchor but not
boundary, entities, external dependencies, influences, research/product/market
synthesis, topics, hubs, frontmatter, source grounding, and wikilink syntax.
Keeping all of that inside each operation prompt would duplicate prose and make
Build/Absorb/Garden harder to keep aligned.

Alternatives:
- Keep one large `wiki-doctrine.md`.
- Keep only the three operation prompts and duplicate shared rules.
- Split into many tiny modules such as `topics.md`, `links.md`, `style.md`,
  and `notability.md`.

Why: Three base modules keep the distinction clear without creating prompt
plumbing sprawl:

- `purpose.md`: why the wiki exists.
- `notability.md`: what deserves pages/topics/hubs and how clusters evolve.
- `syntax.md`: how pages are written and grounded.

Consequences: `src/operations/run.ts` now loads base prompts before the
operation prompt. Future improvements to wiki philosophy can usually land in a
base prompt without touching operation algorithms. Helper/subagent guidance
stays in operation prompts because it is execution behavior, not wiki doctrine.
