Product boundary notes
Date: 2026-06-27 Status: discussion record, not implementation plan
This note records the follow-up discussion after README.md. The README is the
primary synthesis. This file preserves the product boundary decisions, rejected
frames, and the conversation-capture implications so the next design pass does
not repeat the same confusion.
The core confusion#
The confusing question was:
Is codealmanac local, hosted, an engine, a CLI, or a Modal runtime?That question mixes five layers:
artifact .almanac/ committed in the repo
engine the code wiki updater/searcher
CLI the user-facing command surface
hosted product teams, auth, GitHub App, billing, runs, source capture
worker runtime Modal sandbox that runs the engineThe answer is not to split every layer into a separate product. The answer is to keep the user story simple and keep internal seams honest.
Product stance#
codealmanac should be one open-core product.
Free:
your machine
your keys
your local checkout
local reading
optional local building
Paid:
our hosted control plane
our compute
GitHub App automation
team access
run history
source capture
delivery back into the repoPaid is not a smarter engine. Paid is less work, shared team state, hosted compute, and access-controlled automation.
Source of truth#
For code wikis, hosted is not the source of truth.
source of truth:
.almanac/ files on the canonical branch
query/read layer:
local index.db in a checkout
hosted DB index for dashboard/search without a checkout
hosted control plane:
decides and runs updates, then writes them back through gitThis differs from the general /almanac product, where the hosted wiki can be
the canonical thing users pull from. CodeAlmanac is repo-native because the code
repo itself is branched, reviewed, and versioned.
Rule:
default branch = published wiki
PR branch = proposed wiki stateCLI stance#
Use one codealmanac CLI. Do not split into almanac, codealmanac, and
usealmanac for the same product.
The CLI should have postures:
reader:
read local .almanac/ files
search/show/serve
no login required
hosted:
login
connect repo/account
inspect runs/repos
install coding-agent capture hooks
view captured sources
local lab:
opt-in local execution
init --local / build --local / sync / garden
user machine, user keys, user commitsThis keeps one product surface while making the trust boundary visible.
Hosted features#
Hosted should mean team orchestration around a repo-native wiki.
Hosted features:
GitHub App installation
team and repo access control
billing and quotas
hosted update runs
Modal worker execution
PR/check/dashboard surfaces
run history and status
delivery policy
conversation/source capture
source attachment to runs
retention and deletion controls
hosted read index for dashboard users without a local checkoutHosted should not mean:
the .almanac/ files move out of git
local search/show proxy through hosted APIs
the OSS engine is crippled
the user must understand Modal or worker requestsLocal OSS features#
The free/local path should remain real because trust matters.
Local features:
read .almanac/
search/show/serve
create a local .almanac/ in lab mode
run local updates in lab mode
sync local coding-agent sessions in lab mode
write changes into the working tree by default
optionally auto-commit debounced/quarantined wiki commitsLocal users pay with their own setup, model auth, compute, review, and maintenance effort.
Modal worker stance#
Modal is not a user-facing CLI surface.
The worker should receive a resolved hosted run request:
run id
repo checkout/workspace
operation
attached source references
delivery-independent settingsThen it runs the engine and returns a neutral result bundle.
The worker should not be designed around a human command such as:
codealmanac ingest github:pr:123 --sources ...That shape leaks too much product meaning into a command string. It makes the engine rediscover things the hosted backend already resolved, and it makes conversation sources feel bolted on.
Better shape:
hosted backend resolves policy and sources
worker checks out repo
worker prepares run input
engine receives one resolved request
engine writes .almanac/ changes
worker returns UpdateBundle
backend deliversThe exact engine entrypoint can still be a CLI for packaging reasons, but it should be a machine entrypoint over a typed request, not the human workflow CLI.
Conversation capture stance#
Conversation capture belongs to the hosted posture unless the user explicitly enables local lab capture.
Hosted capture:
codealmanac login
codealmanac agents install
Codex/Claude Stop hook fires
hook command uploads transcript delta
server stores raw evidence and normalized events
later run attaches relevant source ids
worker receives attached source referencesCapture does not start an update run by itself. It records source evidence.
Do not define "conversation" as the trigger. Provider sessions are resumable and turn boundaries are clearer. The v1 capture boundary is provider turn stop.
Rejected frames#
Rejected: two product names for one code product.
almanac = local
usealmanac = hostedThis makes the OSS and hosted tiers feel independent even though the hosted product is paid CodeAlmanac.
Rejected: almanac cloud.
almanac cloud loginThis sounds like cloud is an add-on to a local product. The README's stronger
frame is one codealmanac CLI with capabilities unlocked by posture.
Rejected: hosted as canonical wiki store.
hosted wiki replaces .almanac/That is closer to the general /almanac product, not the code-repo product.
Rejected: per-turn hosted update runs.
every captured coding-agent turn triggers a wiki updateThis creates noisy runs, unclear delivery, privacy pressure, and repo-state races. Capture and update should remain separate.
Rejected: source handoff as a magic committed-looking folder.
.usealmanac/run/source-index.jsonIf the worker needs scratch files, keep them outside the repo checkout or make
their runtime-only nature impossible to confuse with .almanac/.
Command sketch#
Reader:
codealmanac search "checkout"
codealmanac show checkout-flow
codealmanac serveHosted:
codealmanac login
codealmanac whoami
codealmanac use <account-or-repo>
codealmanac repos
codealmanac runs
codealmanac agents install
codealmanac agents status
codealmanac sources listLocal lab:
codealmanac setup
codealmanac init --local
codealmanac sync --local
codealmanac garden --local
codealmanac build --localThe exact names can change. The important thing is that commands teach posture: read, hosted, or local lab.
Open decisions#
Engine of record:
TS engine today vs Python port laterWorker request shape:
library call vs machine CLI command
typed request file vs stdin JSONLocal lab naming:
--local flags vs lab namespaceDelivery defaults:
PR branch
dedicated almanac/update branch
working tree
scheduled PR
direct commit when opted inCapture visibility:
owner-only raw transcript
team-visible existence/attachment
raw access grants
retention and delete semanticsShort version#
CodeAlmanac is not framework-vs-platform. It is open-core.
same brand
same CLI
same engine
same .almanac/ artifact
different postureThe repo is the medium. Hosted writes. Local reads. Git is the handoff.