Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,36 @@ __pycache__/
*.pyc
.pytest_cache/
*.egg-info/
.coverage
htmlcov/
dist/
build/

# Virtual environments
.venv/
venv/
env/

# Editor/IDE
.vscode/
.idea/

# OS
.DS_Store

# Local secrets/config — never commit real credentials
.env
.env.*.local

# Adapter install-time symlinks. Every adapter README tells the user to
# create these inside this working tree; committing a real symlink breaks
# Windows checkouts without core.symlinks, which the CI matrix includes.
adapters/codex/skills/adr-toolkit
adapters/gemini-cli/skills/adr-toolkit
adapters/antigravity/skills/adr-toolkit

# Task-by-task implementation plans (superpowers subagent-driven-development
# artifacts) — kept locally for reference, not part of the public tree.
# docs/superpowers/specs/ (the design docs) stay tracked; only plans/ is
# excluded. History from before this commit still has them if ever needed.
docs/superpowers/plans/
75 changes: 74 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,74 @@
# ADR-toolkit
# ADR Toolkit

An agent-native Architecture Decision Record toolkit: it inspects your
repository and existing decisions before asking questions, records new
decisions with a human-approved MADR, and checks a diff against Accepted
decisions for structural conflicts — all before anything gets written.

Kafka got introduced into a production system once, and the person who
made that call left the company. Nobody could say why Kafka was chosen
over the alternatives, what problem it solved, or what was consciously
traded away. ADR Toolkit exists so that, going forward, the *reason*
behind a structural decision survives as long as the code does — written
by inspecting the repository first, not invented, and findable by a
successor (human or agent) in under a minute.

## What it does

| Operation | What it does |
|---|---|
| **INIT** | Scaffolds `docs/decisions/` in a repo that has none yet — directory, template, and ADR-0001. |
| **DISCOVER** | Mines existing conventions (dependency manifests, code, git history) for past decisions that were never written down, and drafts retrospective ADRs for ones you approve. |
| **RECORD** | Captures a new decision — before or after implementing it — investigating the code first and asking only what it can't answer (max 3 questions). |
| **CHECK** | Matches a diff against Accepted ADRs' structured `constraints:` rules and reports Related / Review required / Verified violation / No applicable constraint — never picks a fix for you. |

Every file write goes through a deterministic script and is shown to a
human before it happens. Judgment (what's significant, what to ask, how to
draft) is the agent's job; file writes, ID assignment, and validation
never are. See [`examples/quickstart.md`](examples/quickstart.md) for a
full INIT → RECORD → CHECK walkthrough with real command output, or
[`docs/decisions/`](docs/decisions/) for this toolkit's own dogfooded ADRs.

## Install

`skills/adr-toolkit/` is one self-contained, harness-agnostic package —
copy or symlink it wherever your harness looks for skills, then point one
of these adapters at it:

| Harness | Depth | Install |
|---|---|---|
| [Claude Code](.claude-plugin/) | Full plugin, auto-discovered | Add this repo via `.claude-plugin/marketplace.json` |
| [Codex CLI](adapters/codex/) | Agent Plugins 1.0.0 manifest | [`adapters/codex/README.md`](adapters/codex/README.md) |
| [Gemini CLI](adapters/gemini-cli/) | Extension manifest | [`adapters/gemini-cli/README.md`](adapters/gemini-cli/README.md) |
| [Antigravity CLI](adapters/antigravity/) | Plugin manifest | [`adapters/antigravity/README.md`](adapters/antigravity/README.md) |
| Anything else | Generic fallback | [`adapters/generic/README.md`](adapters/generic/README.md) — needs only markdown-reading and shell |

**No AI harness at all?** `create --interactive` runs the same interview
directly in a terminal — no agent required:

```bash
python skills/adr-toolkit/scripts/adr.py create --interactive --dir docs/decisions
```

## Scope

- MADR 4.x format, no new standard.
- CHECK's MVP conflict detection is structural evidence only
(`constraints:` blocks) — no semantic/AST analysis. See
[ADR-0002](docs/decisions/0002-limit-check-s-conflict-detection-to-structural-evidence-only.md).
- Runtime text ships in English, French, Japanese, Korean, and Chinese —
scoped to `index`'s generated output only, since agent-composed prose
needs no lookup table. See
[ADR-0003](docs/decisions/0003-localize-only-index-py-s-generated-strings-not-agent-composed-text.md).
- Everything explicitly deferred out of MVP is tracked in
[`project-roadmap.md`](project-roadmap.md), not silently dropped.

## Contributing

Read [`AGENTS.md`](AGENTS.md) first — it's the shared operating document
every harness (and every human) working in this repo follows, including
the branch policy.

## License

[MIT](LICENSE)
11 changes: 11 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,14 @@ Lightweight human-readable summary of meaningful repository changes.
documentation, not guessed), a repo-root version-sync script, and a
tag-triggered release workflow. This closes out Plan 4 of 4 — the full
ADR Toolkit MVP is now complete on this branch.
- Released v0.1.0 and adopted a Git Flow branch policy
(`develop`/`master`/`feature`/`release`/`hotfix`, direct-tag release
automation), recorded in `AGENTS.md`.
- Dogfooded the toolkit on its own repo: initialized `docs/decisions/`
and recorded the four most significant architectural decisions made
while building it (CHECK's structural-only scope, i18n's index-only
scope, adapter packaging policy, the Git Flow adoption itself).
- Wrote the root `README.md` (previously a one-line stub) and
`examples/quickstart.md`, a full INIT → RECORD → CHECK walkthrough with
real command output, including CHECK catching a live rule violation and
clearing it after a fix.
44 changes: 44 additions & 0 deletions docs/decisions/0001-record-architecture-decisions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
id: ADR-0001
title: Record architecture decisions
status: accepted
date: 2026-08-30
decision_makers: []
related: []
affected_paths:
- docs/decisions/
tags:
- process
retrospective: false
---

# Record architecture decisions

## Context and Problem Statement

We need a consistent way to capture and communicate significant
architectural decisions so future contributors (human or agent) can find
the reasoning behind them.

## Considered Options

* No formal record, rely on commit messages and memory
* Wiki or external documentation tool
* Architecture Decision Records stored alongside the code

## Decision Outcome

Chosen option: **Architecture Decision Records stored alongside the code**, because they version with the code, stay close to what they describe, and are readable by both humans and coding agents.

## Consequences

* Good: decisions and their rationale are discoverable in the repository itself.
* Bad: requires discipline to keep records up to date as decisions evolve.

## Confirmation

* [ ] `docs/decisions/` exists with this file, a template, and an index.

## Revisit Triggers

* The team adopts a different documentation system project-wide.
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
id: ADR-0002
title: Limit CHECK's conflict detection to structural evidence only
status: accepted
date: 2026-08-30
decision_makers: []
related: []
affected_paths:
- skills/adr-toolkit/scripts/commands/check.py
- skills/adr-toolkit/scripts/rules/conflict.py
tags:
- check
- mvp-scope
- architecture
retrospective: false
---

# Limit CHECK's conflict detection to structural evidence only

## Context and Problem Statement

CHECK needs to flag conflicts between a diff and existing Accepted ADRs. The original PRD's 8-type conflict taxonomy includes types (Direct violation via SDK-call detection, Pattern divergence) that require semantic understanding of code intent, which cannot be reliably detected without deep static analysis (AST or import-graph tooling). Shipping unverified semantic detection in a brand-new tool's MVP risks false positives on day one, which is the fastest way to lose adopter trust.

## Considered Options

* Full semantic/AST-based conflict detection matching the original 8-type taxonomy
* Structural-evidence-only detection via a fixed `constraints:` YAML rule vocabulary (`forbidden_import`, `required_path`, `forbidden_path`, `dependency_forbidden`, `file_must_exist`, `test_must_exist`)

## Decision Outcome

Chosen option: **structural-evidence-only detection**, because false positives are the fastest way to lose trust in a brand-new open-source tool, and a fixed rule vocabulary keeps CHECK's core deterministic, matching the project's own Deterministic Core / Agentic Edge principle.

## Consequences

* Good: CHECK never has to make an ambiguous semantic judgment call; every finding is traceable to an explicit, author-written rule.
* Bad: CHECK cannot catch a conflict that requires understanding code intent unless an explicit structural rule was already written for it — semantic drift can slip through undetected.

## Confirmation

`skills/adr-toolkit/scripts/rules/conflict.py` implements exactly four structural matching mechanisms and nothing else; no test in `tests/unit/test_conflict.py` attempts semantic or AST-based matching.

## Revisit Triggers

* Real usage produces enough false-negative reports that users want semantic detection — tracked as "Full semantic conflict taxonomy" in `project-roadmap.md`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
id: ADR-0003
title: Localize only index.py's generated strings, not agent-composed text
status: accepted
date: 2026-08-30
decision_makers: []
related: []
affected_paths:
- skills/adr-toolkit/scripts/core/locale.py
- skills/adr-toolkit/scripts/i18n/
- skills/adr-toolkit/scripts/commands/index.py
tags:
- i18n
- architecture
retrospective: false
---

# Localize only index.py's generated strings, not agent-composed text

## Context and Problem Statement

The product goal is five-language support (en/fr/ja/ko/zh). The original design's repo-structure diagram proposed a flat `scripts/i18n/{locale}.json` key-value file, but most of the toolkit's user-facing text — RECORD/DISCOVER/CHECK's interview questions and reports — is agent-composed natural language, not a fixed Python string. It is not obvious what a translation-key file would even contain for text that is never the same twice.

## Considered Options

* A comprehensive translation-key system covering every user-facing string, including agent-composed prose, requiring the agent to look up keys instead of composing text freely
* Localize only the deterministic, code-owned strings — `index.py`'s generated `README.md` headers and status labels — via a small JSON file, and instruct the agent (via `SKILL.md`) to detect the user's language and compose its own text in it

## Decision Outcome

Chosen option: **localize only index.py's generated strings**, because an LLM agent is already multilingual and needs no phrase-book to ask a question in French — building and maintaining a lookup table for text that was never a fixed string in the first place adds real translation-maintenance burden for no benefit.

## Consequences

* Good: only ten keys need translating and keeping in sync across five locales, not hundreds of agent-prose variants.
* Bad: the agent's exact wording is not guaranteed reproducible or testable per locale the way a translation table's output would be.

## Confirmation

`skills/adr-toolkit/scripts/i18n/*.json` has exactly ten keys per locale; `SKILL.md`'s Language section is the only agent-facing localization instruction, and it is prose, not a lookup table.

## Revisit Triggers

* The tool needs deterministic, exact-wording compliance per locale (for example, an accessibility or compliance audit) — revisit toward a full translation-key system at that point.
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
id: ADR-0004
title: Adapter packaging: manifest-only directories, install-time symlinks, verified formats
status: accepted
date: 2026-08-30
decision_makers: []
related: []
affected_paths:
- adapters/
tags:
- adapters
- harness-support
retrospective: false
---

# Adapter packaging: manifest-only directories, install-time symlinks, verified formats

## Context and Problem Statement

The toolkit ships as one self-contained `skills/adr-toolkit/` package usable by multiple harnesses (Claude Code, Codex CLI, Gemini CLI, Antigravity CLI). Every harness format actually investigated expects a sibling `skills/` directory next to its own manifest file, but duplicating the package once per harness would violate the single-source-of-truth goal that motivated the self-contained package in the first place. Separately, the exact manifest fields for three of the four harnesses were never verified against real documentation before Plan 4 — and guessing already produced a real bug once (Plan 1's Claude Code adapter guessed a `"skills"` key and a nested manifest path that turned out wrong, caught only by that plan's final review).

## Considered Options

* Copy the full `skills/adr-toolkit/` package into each `adapters/<harness>/` directory
* Symlink `skills/adr-toolkit/` into each adapter directory and commit the symlink to git
* Document the symlink as a manual install-time step (never committed), and verify each harness's real manifest format against its actual documentation before writing it

## Decision Outcome

Chosen option: **document the symlink as an install-time step, with formats verified not guessed**, because copying reintroduces drift between copies, committing a symlink breaks on a Windows checkout without `core.symlinks` enabled (this repo's own CI matrix includes `windows-latest`), and guessing manifest formats already produced two real bugs (Claude Code in Plan 1, Codex CLI in Plan 4) that only an actual install-and-run caught.

## Consequences

* Good: one canonical copy of the skill package exists; no manifest format ships without being checked against real documentation or a real install attempt where a harness CLI was available.
* Bad: a user must run one extra manual `ln -s` step before an adapter works — installation cannot be a true zero-step "clone and go."

## Confirmation

`git ls-tree` on any `adapters/<harness>/` directory shows no `120000` (symlink) mode entries; every adapter's `README.md` documents the symlink as an install step; `.gitignore` ignores each adapter's `skills/` path.

## Revisit Triggers

* A harness's real plugin format later supports referencing an external path directly, removing the need for that harness's symlink step — revisit that harness's adapter specifically, not this policy as a whole.
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
---
id: ADR-0005
title: Adopt Git Flow with direct-tag release automation
status: accepted
date: 2026-08-30
decision_makers: []
related: []
affected_paths:
- AGENTS.md
- .github/workflows/
tags:
- process
- release
- git-flow
retrospective: false
---

# Adopt Git Flow with direct-tag release automation

## Context and Problem Statement

The 4-plan MVP was built entirely on one long-lived feature branch with no branch policy; `master` held only the initial commit throughout. Now that the MVP is complete and released as v0.1.0, the project needs an explicit branch and release policy for future work, including how a version gets tagged and published.

## Decision Drivers

* A predictable integration point for future feature/fix/docs work
* Low operational overhead appropriate for a solo/small-team repository
* Reuse the release automation already built and verified in Plan 4, rather than replacing it speculatively

## Considered Options

* Git Flow (`develop`/`master`/`feature`/`release`/`hotfix` branches) with direct-tag release automation
* Git Flow with release-pr automation (Release Please, auto-generating release PRs from Conventional Commits)
* Trunk-based development (small changes merged frequently, feature flags for incomplete work)
* GitHub Flow (one production branch, short-lived feature branches, continuous deployment)

## Decision Outcome

Chosen option: **Git Flow with direct-tag release automation**, because the project already has more than one long-lived integration point in practice (this MVP's own multi-plan history, and future feature batches), and an explicit `develop`/`master` split matches that; direct-tag was chosen over release-pr because Plan 4 already built, task-reviewed, and whole-branch-reviewed a working tag-triggered `release.yml` — replacing tested automation with an unverified new mechanism for a solo/small-team repo trades working automation for unverified automation with no clear benefit yet.

### Consequences

* Good: reuses release automation that is already tested and was independently re-verified during its own final review; explicit branch roles reduce ambiguity for future contributors.
* Bad: Git Flow's extra branch layer (`develop` plus `release/*`) is more ceremony than Trunk-based or GitHub Flow would need for a project this size; direct-tag requires a human to remember to bump `VERSION` and tag correctly, rather than deriving a version automatically from commit history.

### Confirmation

`AGENTS.md`'s "Git Flow Branch and Release Policy" section states the policy in full; `.github/workflows/release.yml` triggers only on `v*` tag pushes and never auto-bumps a version.

## Pros and Cons of the Options

### Git Flow with direct-tag release automation

* Good, because it reuses release automation already built, tested, and verified in this repository
* Bad, because a human must remember every version bump and tag correctly; nothing derives the version from commit history

### Git Flow with release-pr automation

* Good, because changelog and version bumps are generated automatically from Conventional Commit history, reducing human error
* Bad, because it requires disciplined Conventional Commit usage across all contributors and replaces working, verified automation with an unverified new mechanism

### Trunk-based development

* Good, because it minimizes branch ceremony and integration lag for a small, fast-moving codebase
* Bad, because it assumes continuous feature-flag discipline this project has not adopted, and offers no natural checkpoint for a deliberate, reviewed release like v0.1.0

### GitHub Flow

* Good, because it is simpler than Git Flow with only one long-lived branch to reason about
* Bad, because it has no dedicated integration branch separate from production, which matters once multiple features are in flight at once — a scenario this project has already lived through with its 4-plan MVP

## Revisit Triggers

* The team grows beyond solo/small-team and reliable Conventional Commit discipline becomes realistic — revisit toward release-pr automation.
* `develop` and `release/*` prove to be pure overhead with no multi-stream benefit in practice — revisit toward GitHub Flow.
Loading
Loading