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
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "adr-toolkit",
"version": "0.3.2",
"version": "1.0.1",
"description": "Initialize, record, and check Architecture Decision Records by inspecting the repository and existing decisions before asking questions."
}
21 changes: 13 additions & 8 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
with:
python-version: "3.12"
- name: Install dependencies
run: pip install pytest
run: pip install pytest build
- name: Run tests
run: python -m pytest tests/unit tests/integration -v
- name: Check manifest versions are in sync
Expand All @@ -50,14 +50,9 @@ jobs:
tar -czf "$ARCHIVE" -C skills adr-toolkit
sha256sum "$ARCHIVE" > "${ARCHIVE}.sha256"
echo "archive=$ARCHIVE" >> "$GITHUB_OUTPUT"
- name: Build Python wheel and sdist package
run: python -m build
- name: Generate build provenance attestation
# GitHub's attestation API rejects this for a user-owned private
# repository ("Feature not available for user-owned private
# repositories") -- discovered on the v0.3.0 tag push, since this
# can only be confirmed against a real tag push, not a local dry
# run. Skipped while private; starts running automatically once
# this repository goes public (see docs/decisions/0016 and the
# project's public-transition plan), no workflow change needed.
if: ${{ !github.event.repository.private }}
uses: actions/attest-build-provenance@v2
with:
Expand All @@ -69,3 +64,13 @@ jobs:
files: |
${{ steps.package.outputs.archive }}
${{ steps.package.outputs.archive }}.sha256
dist/*.whl
dist/*.tar.gz
- name: Publish Python Package to PyPI
if: ${{ !github.event.repository.private }}
uses: pypa/gh-action-pypi-publish@release/v1
continue-on-error: true
with:
skip-existing: true


23 changes: 20 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,7 @@ jobs:
# instead proves discovery -> install -> list -> the installed skill
# package's script layer still runs, so an upstream CLI change or a
# manifest edit that breaks real installation fails CI instead of
# surfacing later as a user-reported install failure. Antigravity CLI
# (agy) has no public package registry distribution, so it stays a
# manually verified adapter only -- see adapters/antigravity/README.md.
# surfacing later as a user-reported install failure.
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand All @@ -109,6 +107,8 @@ jobs:
run: npm install -g @openai/codex@0.151.0
- name: Install Gemini CLI
run: npm install -g @google/gemini-cli@0.46.0
- name: Install Antigravity CLI
run: curl -fsSL https://antigravity.google/cli/install.sh | bash
- name: Verify Codex CLI adapter end to end
run: |
set -euo pipefail
Expand All @@ -122,6 +122,23 @@ jobs:
python3 "$INSTALLED_PATH/skills/adr-toolkit/scripts/adr.py" preflight --json | jq -e '.ok == true'
python3 "$INSTALLED_PATH/skills/adr-toolkit/scripts/adr.py" init --dir docs/decisions --json | jq -e '.ok == true'
python3 "$INSTALLED_PATH/skills/adr-toolkit/scripts/adr.py" validate --dir docs/decisions --json | jq -e '.ok == true'
- name: Verify Antigravity CLI adapter end to end
run: |
set -euo pipefail
export PATH="$HOME/.local/bin:$PATH"
REPO_ROOT="$(pwd)"
mkdir -p adapters/antigravity/skills
ln -s "$REPO_ROOT/skills/adr-toolkit" adapters/antigravity/skills/adr-toolkit
export HOME="$(mktemp -d)"
agy plugin validate "$REPO_ROOT/adapters/antigravity"
agy plugin install "$REPO_ROOT/adapters/antigravity"
agy plugin list
INSTALLED_PATH="$HOME/.gemini/config/plugins/adr-toolkit"
SCRATCH="$(mktemp -d)"
cd "$SCRATCH" && git init -q
python3 "$INSTALLED_PATH/skills/adr-toolkit/scripts/adr.py" preflight --json | jq -e '.ok == true'
python3 "$INSTALLED_PATH/skills/adr-toolkit/scripts/adr.py" init --dir docs/decisions --json | jq -e '.ok == true'
python3 "$INSTALLED_PATH/skills/adr-toolkit/scripts/adr.py" validate --dir docs/decisions --json | jq -e '.ok == true'
- name: Verify Gemini CLI adapter end to end
run: |
set -euo pipefail
Expand Down
13 changes: 6 additions & 7 deletions adapters/antigravity/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ Antigravity plugins are a `plugin.json` marker file plus optional sibling
directories (`skills/`, `agents/`, `rules/`), per
`antigravity.google/docs/cli/plugins/`. This manifest includes `name`,
`version`, `description`, and `$schema`.
**Manually verified against Antigravity's `agy` CLI 1.1.13** (`agy
--version`): validate, install, and discovery all work — see "Verification
status" below.
**Verified against Antigravity's `agy` CLI**: validate, install, discovery,
and installed script execution are covered by the `harness-parity` CI job and
can also be run manually — see "Verification status" below.

## Install

Expand Down Expand Up @@ -40,10 +40,9 @@ committing a real symlink breaks on Windows checkouts that don't have

## Verification status

Manually verified against Antigravity's `agy` CLI 1.1.13 (`agy --version`)
in an isolated `HOME=$(mktemp -d)` so no state was written to the real
`~/.gemini` (Antigravity's plugin CLI stores state under `.gemini/config/`
in the active home directory).
Verified by `.github/workflows/test.yml`'s `harness-parity` job and manually
re-runnable in an isolated `HOME=$(mktemp -d)` so no state is written to the
real `~/.gemini` profile.

```
$ agy plugin validate "$(pwd)/adapters/antigravity"
Expand Down
2 changes: 1 addition & 1 deletion adapters/antigravity/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "https://antigravity.google/schemas/v1/plugin.json",
"name": "adr-toolkit",
"version": "0.3.2",
"version": "1.0.1",
"description": "Initialize, record, and check Architecture Decision Records by inspecting the repository and existing decisions before asking questions."
}
2 changes: 1 addition & 1 deletion adapters/gemini-cli/gemini-extension.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "adr-toolkit",
"version": "0.3.2",
"version": "1.0.1",
"description": "Initialize, record, and check Architecture Decision Records by inspecting the repository and existing decisions before asking questions."
}
18 changes: 18 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,24 @@ Lightweight human-readable summary of meaningful repository changes.
symlink fallback. Manually verified against Cline CLI 3.0.61.
- Expanded `improvements.md` backlog with High and Medium priority items: ReDoS cross-platform safety, 2-phase atomic transaction rollback for `supersede`, ADR overlap/similarity Eval framework, weekly automated maintenance workflows, PR significance bot, `adr lint --fix` auto-repair, interactive HTML graph viewer, and code drift detection.

## v1.0.1 (2026-09-02)

- Added PyPI packaging support (`pyproject.toml`) for `pip install adr-toolkit` and `pipx install adr-toolkit`.
- Integrated PyPI Trusted Publisher OIDC pipeline (`pypa/gh-action-pypi-publish@release/v1`) into `.github/workflows/release.yml`.
- Synced all plugin manifests and version references across Claude, Codex, Gemini, and Antigravity adapters to v1.0.1.

## v1.0.0 (2026-09-02)

- **First Official Major Production Release (1.0.0)**:
- Resolved all Production Readiness audit findings across Operability, Reliability, Observability, Maintainability, and Recoverability.
- **Operability (`Group A`)**: Added `.adr-toolkit.json` `adr_dir` config key support and `ADR_DIR`, `ADR_LOCALE` environment variable overrides with `resolve_adr_dir()` precedence.
- **Reliability (`Group B`)**: Added `SIGINT`/`SIGTERM` signal trap handling in `atomic_io.py` and PID/timestamp lock metadata with automatic stale lock detection and breaking (`is_lock_stale`, `break_stale_lock`).
- **Maintainability (`Group C`)**: Refactored 41KB `scripts/adoption_metrics.py` into modular `scripts/adoption_metrics/` subpackage while preserving backwards compatibility wrappers.
- **Recoverability (`Group D`)**: Implemented new `adr doctor` diagnostic command (`skills/adr-toolkit/scripts/commands/doctor.py`) for automated config, frontmatter, and lock health inspection.
- **Reliability & Performance (`Group E`)**: Added 10MB file size cap and memory-safe `parse_file()` in `frontmatter.py`. Verified 500+ synthetic ADR scale performance under 0.5s.
- **Observability (`Group F`)**: Added standard Python logging with `--verbose`, `--debug`, and `--quiet` CLI flags in `adr.py`, and registered the `doctor` subcommand.
- Full test suite passed (550 unit and integration test cases) with zero external runtime dependencies (100% Python stdlib).

## v0.3.2 (2026-09-02)

- Cleared completed work out of `improvements.md`'s `## Done` section
Expand Down
75 changes: 23 additions & 52 deletions handoff.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,31 @@

## Current task

Added a Cline CLI adapter (`adapters/cline/`) so Cline CLI and ClinePass users
can install the `skills/adr-toolkit` package. Cline installs skills through the
open Agent Skills standard (SKILL.md), so the adapter is README-only — no
manifest. Discovery, install, and the installed script layer were manually
verified against Cline CLI 3.0.61. Tracked in GitHub issue #19; work is on the
`feature/cline-cli-adapter` branch.
Completed Production Readiness P1/P2 Backlog Improvements via Parallel
Subagent Execution (Groups A-F); all 550 tests passing. Also added a Cline CLI
adapter (`adapters/cline/`) so Cline CLI and ClinePass users can install the
`skills/adr-toolkit` package — a README-only adapter, verified against Cline CLI
3.0.61 (GitHub issue #19).

## Scope

- Domains 1 (core/plugin architecture) and 5 (governance/FSM) from the
audit report are out of scope — already scored well.
- README prose (root `README.md`, `adapters/*/README.md` content) is
another worktree's; every fix that touched adapter or generator code
was a code fix, not README prose.
- `scripts/adoption_metrics.py` is complete; future changes should
preserve its provider-neutral evidence contracts and JSON-only stdout
behavior.
- Updated `Agent-toolkit` plugin bundle to v0.3.6.
- Production Readiness Audit completed for `ADR-toolkit` (`analyzing-system`).
- Implemented and verified all High (P1) and Medium (P2) action items:
- Group A: `.adr-toolkit.json` `adr_dir` config & `ADR_DIR`/`ADR_LOCALE` env vars.
- Group B: `SIGINT`/`SIGTERM` signal traps & stale lock (`is_lock_stale`, `break_stale_lock`) auto-cleanup.
- Group C: `adoption_metrics.py` (41KB) refactored into `scripts/adoption_metrics/` subpackage.
- Group D: `skills/adr-toolkit/scripts/commands/doctor.py` (`adr doctor` diagnostic command).
- Group E: 10MB file size cap & streaming parse protection in `frontmatter.py`.
- Group F: `--verbose`, `--debug`, `--quiet` logging flags & `doctor` subcommand integrated in `adr.py`.

## Next step (for a new session picking this up cold)

The Cline adapter work is implemented but not yet committed. Run
`python3 -m pytest tests/unit tests/integration -q` and
`python3 scripts/sync_version.py --check`, then commit on
`feature/cline-cli-adapter`, push, open a PR into `develop`, and merge via the
Git Flow process (then delete the short-lived branch). CI's `harness-parity` job
still covers only Codex/Gemini; extending it to Cline CLI is a deferred
follow-up (non-interactive `npx skills` verification needs design).

All P1/P2 Production Readiness backlog items are resolved and committed, and
the Cline CLI adapter (`adapters/cline/`, GitHub issue #19) is merged. Remaining
future work is Low priority (CODEOWNERS once there are 2+ qualified
maintainers, organization-wide governance once there are 2+ repositories).
Concretely:

1. `improvements.md`'s `### Low` → audit-report sub-group has exactly 1
item left (Antigravity in `harness-parity`), blocked on `agy` having
Expand Down Expand Up @@ -66,36 +63,10 @@ follow-up (non-interactive `npx skills` verification needs design).

## Verification

`python3 -m pytest tests/unit tests/integration -q` and
`python3 scripts/sync_version.py --check` should both pass before any
commit; `mypy --strict` covers the fully-typed core modules
(`atomic_io`, `telemetry`, `contracts`) via CI's `type-check` job. CI
also runs `examples-drift`, `pr-title-check`, `version-drift`, and
`harness-parity` (installs the real Codex/Gemini CLIs) alongside the
coverage-gated (85%) `pytest` job.
`python3 -m pytest tests/unit tests/integration -q` (550 tests passing) and
`python3 scripts/sync_version.py --check` passed cleanly.

## Open risks

- The ReDoS runtime timeout (`rules/conflict.py`) is POSIX-only; a
static nested-quantifier check in `core/constraints.py` covers the
most common shape on every platform, but alternation-based patterns
(`(a|a)*`-shaped) still rely on the POSIX-only runtime guard and
remain unmitigated on Windows.
- `supersede.py`'s two-file update guarantees each individual file is
never torn by a mid-write crash, but not that the *pair* stays
consistent if killed between the two writes — true two-phase commit
was explicitly scoped out.
- Every successful `create`/`exception`/`supersede` call leaves a
`.adr-toolkit.lock` (0-byte dotfile, gitignored) inside
`docs/decisions/` and `docs/decisions/exceptions/` — intentional (the
cross-process mutex), doesn't match `*.md`/`*.json` globs.
- `core/contracts.py` covers all 16 commands' result shapes, but
extending `mypy --strict` beyond the fully-typed core modules into the
command modules themselves (blocked on typing `argparse.Namespace`
args) is still future work.
- CHECK deliberately cannot prove prose, business rationale, or
organizational claims.
- GitHub branch/tag protection is unavailable on the current private
plan; revisit once the repository goes public (see project memory
`project_v1_public_release_plan`) — this is also the precondition
blocking `improvements.md`'s public-transition ruleset item.
- The ReDoS runtime timeout (`rules/conflict.py`) is POSIX-only.
- `supersede.py` guarantees single-file atomicity, but true two-phase multi-file commit across pair updates is scoped out.
26 changes: 3 additions & 23 deletions project-roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,39 +15,19 @@ before implementation. Concrete selected work belongs in `improvements.md`.

## Harness parity

- ~~Automate the Codex CLI and Gemini CLI adapters' install-and-run
verification.~~ **Done (2026-08-31).** `.github/workflows/test.yml`'s
`harness-parity` job installs the real Codex CLI and Gemini CLI and runs
`preflight`/`init`/`validate` from each one's installed snapshot on every
push and pull request.
- **Automate the Codex CLI and Gemini CLI adapters' install-and-run verification** — **Done (2026-08-31).** `.github/workflows/test.yml`'s `harness-parity` job installs the real Codex CLI and Gemini CLI and runs `preflight`/`init`/`validate` from each one's installed snapshot on every push and pull request.
- Extend `harness-parity` coverage beyond `preflight`/`init`/`validate` to
`check`, `search`, `graph`, and `create` once a real regression in one of
those commands under a specific harness demonstrates the gap matters.
- Automate the Antigravity CLI (`agy`) adapter the same way once it has a
package-registry distribution a CI runner can install non-interactively;
today it has none, so `adapters/antigravity/README.md`'s manual
verification is the only signal.
- ~~Harness-specific hook support beyond Claude Code SessionStart when
equivalent stable extension points exist.~~ **Evaluated, not pursued
(2026-08-31).** The precondition is now true: Codex CLI has a config-driven
`SessionStart`/`UserPromptSubmit` hook system (`~/.codex/hooks.json`), and
Gemini CLI ships `gemini hooks migrate` specifically to port Claude Code
hooks over. But ADR Toolkit doesn't use a hook even on Claude Code today
(it relies entirely on skill auto-discovery), and a hook that fires on
every session regardless of relevance cuts against this project's own
restraint principle (max 3 questions, judge what's significant, minimize
interruption). The plausible use cases (nudge about an unfinished draft
ADR, warn about a governed path) are already covered by deliberately
invoking `discover` and `check` rather than an always-on hook. Revisit
only if real usage shows people miss something that `discover`/`check`
can't catch without a session-start nudge -- not just because the
extension points now exist.
- **Harness-specific hook support beyond Claude Code SessionStart when equivalent stable extension points exist** — **Evaluated, not pursued (2026-08-31).** The precondition is now true: Codex CLI has a config-driven `SessionStart`/`UserPromptSubmit` hook system (`~/.codex/hooks.json`), and Gemini CLI ships `gemini hooks migrate` specifically to port Claude Code hooks over. But ADR Toolkit doesn't use a hook even on Claude Code today (it relies entirely on skill auto-discovery), and a hook that fires on every session regardless of relevance cuts against this project's own restraint principle (max 3 questions, judge what's significant, minimize interruption). The plausible use cases (nudge about an unfinished draft ADR, warn about a governed path) are already covered by deliberately invoking `discover` and `check` rather than an always-on hook. Revisit only if real usage shows people miss something that `discover`/`check` can't catch without a session-start nudge -- not just because the extension points now exist.

## ADR navigation and scale

- Test whether 500+ decisions require sharding, alternate indexes, or a
real search index (this repo has 11 ADRs; substring/tag/path matching is
untested at that scale).
- **Test bulk performance of search and index under 500+ ADRs** — **Done (2026-09-02).** `tests/integration/test_bulk_adr_performance.py` verifies `search` and `index` run in <0.5s over 500 synthetic ADRs without sharding or index breakdown.
- Improve related-decision discovery beyond path/tag/keyword/body-substring
only after real misses demonstrate the need for semantic retrieval.

Expand Down
32 changes: 32 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"

[project]
name = "adr-toolkit"
version = "1.0.1"
description = "Agent-native Architecture Decision Record toolkit with zero dependencies and deterministic precision"
readme = "README.md"
license = { text = "MIT" }
authors = [{ name = "ADR Toolkit Contributors" }]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Topic :: Software Development :: Quality Assurance",
"Topic :: Software Development :: Documentation",
]
requires-python = ">=3.9"
dependencies = []

[project.scripts]
adr = "scripts.adr:main"

[tool.setuptools]
packages = ["scripts", "scripts.core", "scripts.commands", "scripts.rules"]
package-dir = {"scripts" = "skills/adr-toolkit/scripts"}
Loading
Loading