Skip to content

Model one Almanac project across multiple local checkouts #47

Description

@markds75

Bug / design gap

CodeAlmanac treats local checkout paths too much like project identity. When the same project is checked out in multiple local directories, read-command auto-registration can collide on the derived basename and crash with a raw SQLite uniqueness error on repositories.name.

The crash is the immediate symptom, but the deeper issue is that CodeAlmanac should understand one Almanac project across multiple workspaces/checkouts/worktrees.

Why this matters

The point of an Almanac is shared project memory. If each local checkout becomes a separate registered wiki/project, then parallel agent workstreams and team members can end up with separate local identities for what is logically the same codebase. That makes project memory feel path-local instead of project-local.

For teams, the committed almanac/ tree should be the shared source of project knowledge. Different developers and agents may make different design decisions, but those changes should converge through normal Git review and merge flows against the same project wiki, not through unrelated local registrations.

Repro symptom

  1. Check out the same repository in two directories with the same basename, for example:
    • /work/a/lmfellow
    • /work/b/lmfellow
  2. Ensure both contain an initialized almanac/ wiki.
  3. Run a read command from the first checkout so CodeAlmanac auto-registers it as lmfellow.
  4. Run a read command from the second checkout.

Actual behavior

The second auto-registration derives the same name, lmfellow. The local registry has repositories.name as UNIQUE, so SQLite raises an integrity error. Users can see a raw traceback instead of a product-level explanation.

Desired product model

CodeAlmanac should distinguish:

  • Project identity: the shared codebase / Almanac project, likely derived from Git identity such as canonical remote URL and possibly other repository metadata.
  • Workspace identity: a local checkout, worktree, or agent workspace path where commands are run.
  • Wiki source: the committed almanac/ tree that travels with the repository and is reviewed/merged through Git.

In that model, /work/a/lmfellow and /work/b/lmfellow can both be workspaces for the same lmfellow project rather than competing registered projects with colliding names.

Design questions

  • What should be the canonical project identity for local repositories? Git remote URL? Git common-dir? A stored Almanac project id? A combination?
  • How should workspaces be stored? A separate workspace table keyed by local path and linked to one project seems likely.
  • When running from a workspace, should commands read/write the current checkout's almanac/ tree while attributing runs and indexes to the shared project identity?
  • How should ambiguity be handled when two different projects want the same display name?
  • How should existing path-keyed repository registrations migrate?

Non-goal / temporary workaround

Auto-suffixing derived names (lmfellow-2, lmfellow-3) would avoid the crash, but it reinforces the wrong model by treating same-project workspaces as separate Almanac projects. That may be acceptable only as a temporary mitigation, not the desired design.

Acceptance direction

A future fix should make read-command auto-registration robust for multiple local checkouts of the same project without creating separate project identities for the same codebase. At minimum, the current raw SQLite integrity error should be replaced with a clear product-level error if the full workspace/project model is not implemented in the first pass.

Activity

  1. markds75 commented on Jul 21, 2026

    @markds75
    Author

    Additional design note: merging transcript-derived decisions

    After more discussion, the hard part is not only the local registry collision or even Markdown merge mechanics. The hardest part is how multiple Claude/Codex workstreams should feed decisions from their transcripts into one shared project wiki.

    A useful framing: transcript ingestion should extract knowledge candidates, not directly mutate project truth.

    Proposed pipeline

    Claude/Codex transcripts from workspaces
            |
            v
    structured decision/fact candidates
            |
            v
    dedupe + conflict detection + branch/merge awareness
            |
            v
    wiki update proposal
            |
            v
    reviewed committed Markdown in almanac/
    

    A transcript may say “the agent chose X while working on branch A,” but the Almanac should only say “the project follows X” once that decision survives review, merge, or explicit acceptance.

    Candidate shape

    Candidates probably need fields such as:

    • project id
    • workspace id
    • branch / commit range, when available
    • transcript session id and evidence range
    • kind: decision, invariant, flow, gotcha, incident, todo, etc.
    • summary
    • affected files
    • proposed page or topic
    • confidence
    • status: proposed, accepted, rejected, superseded, stale
    • relations: duplicates, conflicts, supersedes

    Merge cases

    • Same decision, same meaning: one wiki update with multiple evidence refs.
    • Related decisions, different scope: one consolidated page/section with scoped nuance.
    • Conflicting decisions: one accepted project decision; rejected alternatives can be summarized in a Considered/Rejected section, but should not both become truth.
    • Branch-local decisions: if the code never merges, the candidate should expire, stay branch-local, or remain proposed rather than entering project truth.

    Important rule

    Only merged/reviewed code should create project truth automatically. Transcript-derived decisions from unmerged workstreams should remain proposed candidates. If CodeAlmanac cannot tell whether the branch merged, it should be conservative and require Garden/review to accept the candidate.

    Design implication

    This reinforces the need for a project/workspace model. Workspaces produce transcript evidence and candidates, but the shared project owns the durable wiki truth. Background sync should not blindly turn every local agent transcript into committed project knowledge.

    Direct transcript-to-wiki mutation is likely too eager for parallel workstreams. A safer design is:

    1. discover transcripts per workspace,
    2. extract structured candidates,
    3. group candidates by shared project identity,
    4. dedupe/conflict-check them,
    5. propose wiki updates,
    6. commit accepted knowledge into almanac/ through normal Git review/merge.

    That means the basename collision is one symptom of a larger missing model: CodeAlmanac needs to distinguish shared project memory from local workspace activity and treat transcript-derived knowledge as evidence/proposals until it becomes settled project knowledge.

  2. markds75 commented on Jul 21, 2026

    @markds75
    Author

    Additional design note: --wiki <name> currently selects a path-bound registration

    One more implication: today's --wiki <name> behavior shows that this is not just an auto-registration collision.

    Currently, --wiki lmfellow means roughly:

    name -> one registered repository row -> one stored root_path
    

    It does not mean "the shared lmfellow project, resolved through the workspace I am currently in." If lmfellow is registered to /a/lmfellow, then running a command from /b/lmfellow with --wiki lmfellow still targets the stored /a/lmfellow root.

    That means the current selector conflates two things that probably need to be separate:

    • Project selector: which shared Almanac project/codebase?
    • Workspace selector: which local checkout/worktree should this command read or write?

    Design implication

    If CodeAlmanac supports one project across multiple checkouts, name likely belongs at the project level, not the workspace/root-path level.

    A future shape might be:

    projects
      project_id
      name
      canonical_git_identity
      default_workspace_id
    
    workspaces
      workspace_id
      project_id
      root_path
      git_common_dir
      branch
      last_seen_at
    

    Then --wiki lmfellow would select the project. Command execution would still need an active workspace:

    • If cwd is a known workspace for that project, use cwd.
    • If cwd is outside known workspaces, use a configured default workspace or fail with a clear message.
    • A later explicit --workspace selector may be needed for non-cwd workflows.

    Command behavior implications

    For read/write commands:

    codealmanac show architecture/foo --wiki lmfellow

    If run from /b/lmfellow, the intuitive behavior is:

    select project lmfellow
    use active workspace /b/lmfellow
    read /b/lmfellow/almanac
    

    For sync:

    codealmanac sync --wiki lmfellow

    The project selector should scope to the shared project, but transcript evidence may come from any known workspace for that project. That reinforces the earlier candidate/proposal model: sync can discover transcript-derived knowledge across workspaces, but should not blindly mutate project truth from every local transcript.

    Scope update

    The issue should cover both:

    1. the immediate crash from same-basename auto-registration, and
    2. the deeper selector model problem where --wiki <name> currently identifies a single path-bound registration instead of a shared project plus an active workspace.

    A suffix-based name workaround would not solve this, because it would keep treating /a/lmfellow and /b/lmfellow as unrelated wiki projects rather than workspaces for the same project.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions