docs(decisions): add ADR-lite decision log
Add docs/decisions/ with a convention README and back-fill two decisions that previously had no in-repo home: merging PRs with rebase (ADR 0001) and the agent-identity claimed-not-vouched trust posture from PRD 0027 (ADR 0002). Point docs/INDEX.md at it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+1
-1
@@ -1 +1 @@
|
|||||||
Research notes live in `research/`. Product requirement docs live in `prds/`.
|
Research notes live in `research/`. Product requirement docs live in `prds/`. Decision records (ADR-lite) live in `decisions/`.
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
# ADR 0001: Merge PRs with rebase, not merge commits
|
||||||
|
|
||||||
|
- **Status:** Accepted
|
||||||
|
- **Date:** 2026-05-28
|
||||||
|
- **Deciders:** didericis
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
PRs need a merge strategy. Gitea offers merge-commit, squash, rebase,
|
||||||
|
and rebase-merge. The project uses [Conventional
|
||||||
|
Commits](https://www.conventionalcommits.org/) enforced by a
|
||||||
|
`commit-msg` hook, and PRDs typically land as a multi-commit PR where
|
||||||
|
each commit is meaningful on its own (e.g. PR #95: a `docs(prd)` commit,
|
||||||
|
a `feat(manifest)` implementation commit, and a `docs(manifest)`
|
||||||
|
commit). The history should stay readable and the individual
|
||||||
|
conventional commits should survive onto `main`.
|
||||||
|
|
||||||
|
## Decision
|
||||||
|
|
||||||
|
Merge PRs with **rebase** (Gitea's `rebase` style; `Do: "rebase"` via
|
||||||
|
the API). The branch's commits are replayed onto `main` with no merge
|
||||||
|
commit, producing a linear history that preserves each commit verbatim.
|
||||||
|
|
||||||
|
## Consequences
|
||||||
|
|
||||||
|
- **Linear history**, no merge bubbles; `git log --oneline` reads as a
|
||||||
|
straight sequence of conventional commits.
|
||||||
|
- **Each commit is preserved** (unlike squash, which would collapse the
|
||||||
|
PRD/impl/docs commits into one and lose the staged structure).
|
||||||
|
- **Commit SHAs are rewritten at merge.** The replayed commits on `main`
|
||||||
|
get new SHAs, and the source branch is deleted, so a link to a file
|
||||||
|
by *branch name* (`/src/branch/<feature>/…`) dies at merge. This is
|
||||||
|
why links to not-yet-merged files are pinned to a **commit SHA**
|
||||||
|
(`/src/commit/<sha>/…`), which stays reachable via the retained
|
||||||
|
`refs/pull/<n>/head` ref. See
|
||||||
|
`docs/research/issue-tracking-vs-in-repo-decision-history.md`.
|
||||||
|
- **Trade-off accepted:** without a merge commit, the "these commits
|
||||||
|
landed together as PR #N" grouping is not recorded in git itself — it
|
||||||
|
lives in forge state (the PR). That is a mild concession against the
|
||||||
|
keep-history-in-the-repo posture; the conventional-commit scopes and
|
||||||
|
PRD references in the messages keep changes traceable without it.
|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
- `docs/research/issue-tracking-vs-in-repo-decision-history.md` — the
|
||||||
|
commit-pinning consequence above.
|
||||||
|
- Observed practice: PRs #92, #93 merged with rebase; #95 to follow.
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
# ADR 0002: Agent-set git identity is claimed, not vouched
|
||||||
|
|
||||||
|
- **Status:** Accepted
|
||||||
|
- **Date:** 2026-05-28
|
||||||
|
- **Deciders:** didericis
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
PRD 0027 lifts `git.user` (name/email) to the agent layer, so an agent
|
||||||
|
file may declare its own commit identity. Agent files can live in
|
||||||
|
`$CWD/.bot-bottle/agents/` — i.e. they can be supplied by a cloned,
|
||||||
|
less-trusted repository. That raises the question of whether a
|
||||||
|
repo-supplied agent setting its own git identity is a security concern,
|
||||||
|
and whether agent identity should be gated differently for `$CWD`
|
||||||
|
agents than for `$HOME` agents.
|
||||||
|
|
||||||
|
This record exists because the decision is a **trust posture** worth
|
||||||
|
finding on its own, separate from the feature PRD that introduced it.
|
||||||
|
The full analysis lives in PRD 0027; the decision is summarized here.
|
||||||
|
|
||||||
|
## Decision
|
||||||
|
|
||||||
|
Allow agents to set `git.user`, and treat an agent-declared identity as
|
||||||
|
**claimed, not vouched**. No `$CWD`-vs-`$HOME` gating on the identity
|
||||||
|
field. `git.remotes` stays bottle-only (home-only).
|
||||||
|
|
||||||
|
## Consequences
|
||||||
|
|
||||||
|
- A cloned repo's agent file can present any commit author name/email,
|
||||||
|
including one that reads like a real person's. This is accepted: git
|
||||||
|
authorship is **not a credential** (push auth is the bottle's remote
|
||||||
|
key/token), is **already forgeable** from inside the bottle at runtime
|
||||||
|
(`git config user.email …`), and was never a trust anchor.
|
||||||
|
- If attribution integrity ever matters, the answer is commit
|
||||||
|
**signing** (SSH/GPG), not the author field — so this decision closes
|
||||||
|
no door that was open.
|
||||||
|
- `git.remotes` is deliberately *not* lifted to the agent layer: it
|
||||||
|
carries credentials and host trust (IdentityFile, KnownHostKey) and
|
||||||
|
remains a bottle-only, home-only concern.
|
||||||
|
- Revisit if a future change ever makes commit identity load-bearing
|
||||||
|
(e.g. enforced signing keyed on author), at which point gating
|
||||||
|
`$CWD`-supplied identities would matter.
|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
- PRD 0027 (`docs/prds/0027-agent-git-user-identity.md`) — full trust
|
||||||
|
analysis and schema.
|
||||||
|
- Issue #94, PR #95 — the feature this decision was made for.
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
# Decision records
|
||||||
|
|
||||||
|
Short, durable records of decisions — one file per decision. This is a
|
||||||
|
lightweight [Architecture Decision Record](https://adr.github.io/)
|
||||||
|
practice: capture *what was decided and why* in a versioned file so the
|
||||||
|
reasoning lives in the clone, not in a forge issue thread or a chat log
|
||||||
|
that disappears when the provider does.
|
||||||
|
|
||||||
|
See `docs/research/issue-tracking-vs-in-repo-decision-history.md` for
|
||||||
|
the rationale behind keeping decision history in-repo.
|
||||||
|
|
||||||
|
## When to write one
|
||||||
|
|
||||||
|
| Artifact | For |
|
||||||
|
|---|---|
|
||||||
|
| **PRD** (`docs/prds/`) | A feature: what to build, scope, success criteria. |
|
||||||
|
| **Research note** (`docs/research/`) | A landscape/tradeoff investigation. |
|
||||||
|
| **Decision record** (`docs/decisions/`) | A decision that isn't itself a feature — a policy, a convention, a "we will / won't do this," or a load-bearing choice made inside a larger PRD that deserves to be discoverable on its own. |
|
||||||
|
|
||||||
|
A decision that's fully specified by a PRD doesn't need duplicating
|
||||||
|
here. Write a record when the *decision* would otherwise be buried in
|
||||||
|
prose, lost in an issue thread, or have no in-repo home at all (small
|
||||||
|
requests that don't merit a PRD; non-feature choices like merge
|
||||||
|
strategy or a trust posture).
|
||||||
|
|
||||||
|
## Format
|
||||||
|
|
||||||
|
One Markdown file per decision, numbered sequentially and zero-padded
|
||||||
|
(`0001-…`, `0002-…`), matching the PRD numbering style. Keep it short —
|
||||||
|
the discipline is writing it down, not the ceremony.
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# ADR 0000: <short imperative title>
|
||||||
|
|
||||||
|
- **Status:** Proposed | Accepted | Superseded by ADR NNNN
|
||||||
|
- **Date:** YYYY-MM-DD
|
||||||
|
- **Deciders:** <who>
|
||||||
|
|
||||||
|
## Context
|
||||||
|
What forced the decision; the constraints in play.
|
||||||
|
|
||||||
|
## Decision
|
||||||
|
What we decided, stated plainly.
|
||||||
|
|
||||||
|
## Consequences
|
||||||
|
What follows — the good, and the costs/trade-offs accepted.
|
||||||
|
|
||||||
|
## Links
|
||||||
|
PRDs, research notes, issues/PRs. Forge links are convenience
|
||||||
|
pointers; the reasoning above must stand without them.
|
||||||
|
```
|
||||||
|
|
||||||
|
## Index
|
||||||
|
|
||||||
|
- [ADR 0001](0001-merge-prs-with-rebase.md) — merge PRs with rebase, not merge commits.
|
||||||
|
- [ADR 0002](0002-agent-identity-claimed-not-vouched.md) — agent-set git identity is claimed, not vouched.
|
||||||
Reference in New Issue
Block a user