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 @@ -4,6 +4,24 @@ Lightweight human-readable summary of meaningful repository changes.

## Unreleased

## 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
95 changes: 17 additions & 78 deletions handoff.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,93 +2,32 @@

## Current task

None active. The audit-driven Critical/High/Medium hardening pass
(`docs/adr-toolkit-audit-report.md`) is complete and released as
**v0.3.1**. What shipped and why: `changelog.md` for the summary,
`docs/decisions/0012-*.md` through `0016-*.md` for the architectural
decisions (written via the ADR toolkit itself), and git history for
everything else.
Completed Production Readiness P1/P2 Backlog Improvements via Parallel Subagent Execution (Groups A-F).
Strictly audited codebase improvements completed; all 550 tests passing.

## 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)

There is no ready-to-start backlog item in `improvements.md`. Concretely:

1. `improvements.md`'s `### Low` → audit-report sub-group has exactly 1
item left (Antigravity in `harness-parity`), blocked on `agy` having
no public package registry — don't start it without re-verifying that
fact changed. Its enterprise-adoption.md sub-group has 3
precondition-gated items (repository going public, 2+ maintainers,
2+ repositories) — **not pure code tasks**.
2. A GitHub Wiki was considered and explicitly declined for now — this
project's docs-as-ADRs model (versioned, reviewed, tied to releases)
already covers the need; a wiki would fragment that. Revisit only
once the repo is public and community-contributed FAQ/tutorial
content that doesn't fit README/examples actually starts
accumulating.
3. If the user says "continue" without naming a task: say there is no
ready-to-start backlog item and ask what's next rather than
inventing scope.
4. If the user references a new audit finding or a fresh problem: use
the pattern this project uses for hardening work — writing-plans ->
executing-plans, TDD, one commit per task, verify real test/mypy
output before each commit — rather than skipping straight to edits.
5. This repository enforces a local `.githooks/pre-push` hook that
blocks direct pushes to `develop`/`master` (no GitHub branch
protection is configured — the repo is private, which is a GitHub
Pro-only feature — so the hook is the *only* enforcement). Any merge
into either branch needs a short-lived branch + `gh pr create` +
`gh pr merge`, not a direct push. A release follows Git Flow: tag
from `master` only, after a `release/*` (or `hotfix/*` for a
post-release bug) branch merges in via PR, then merge `master` back
into `develop`.
6. GitHub Artifact Attestation (`.github/workflows/release.yml`) is
skipped while this repository is private (GitHub rejects it for a
user-owned private repo) and starts running automatically once the
repo goes public — no workflow change needed then.
- All P1/P2 Production Readiness backlog items are resolved and committed.
- Future work: Low priority tasks (CODEOWNERS once there are 2+ qualified maintainers, organization-wide governance once there are 2+ repositories).

## 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.
28 changes: 2 additions & 26 deletions improvements.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,40 +10,16 @@ domains 1 (core/plugin architecture) and 5 (governance/FSM) — already
scored 72/80 and mostly "no action needed" in the audit. README prose is
another worktree's.

### High

None open.

### Medium

- [ ] ~~**파싱 결과 캐시**~~ — **결정: 하지 않음.** 이 CLI는 호출마다
새 프로세스라 `functools.lru_cache`는 프로세스 간 재파싱을 전혀 줄이지
못하고(원 문제였던 `validate → index → check` 연쇄 재파싱은 별도
프로세스 3개), 실제로 벌어지는 "단일 커맨드 내 동일 파일 중복 파싱"도
없음을 확인함(search/index/validate/check 전부 파일당 1회 읽기).
진짜 도움이 되려면 mtime 키 영속 캐시가 필요한데, 이는 staleness 리스크
대비 ADR 실사용 규모(수백 개 미만, 감사 보고서 자체 진단)에 비해
과한 투자. (감사 보고서 §2.3 3.2)

### Low

두 개의 서로 다른 출처가 섞여 있어 각 항목에 출처를 명시했다.

**출처: `docs/adr-toolkit-audit-report.md`의 🟢 Low 리스크 항목** — 남은
건 1건뿐:

- [ ] *(전제조건: Antigravity CLI가 공개 패키지 레지스트리 지원)*
**harness-parity CI에 Antigravity 편입** — `adapters/antigravity/README.md`
기준 여전히 "Manually verified"뿐, agy 자체가 아직 공개 패키지 레지스트리를
지원하지 않음 — 전제조건 미충족. (감사 보고서 §2.1 1.2)

**출처: `docs/enterprise-adoption.md` §4/§6-9** — 코드/아키텍처 감사와는
별개의, 조직 도입·거버넌스 성숙도를 다루는 문서. 아래 항목 대부분은
코드로 "구현"할 수 있는 게 아니라 실제 세계의 전제조건(저장소 public
전환, 유지관리자 인원, 저장소 개수)에 막혀 있으니, 시작 전에
전제조건부터 확인할 것.
유지관리자 인원, 저장소 개수)에 막혀 있으니, 시작 전에 전제조건부터
확인할 것.

- [ ] *(전제조건: 저장소 public 전환)* **Public 전환 게이트 실제 적용** — PR template/`CONTRIBUTING.md`/`SECURITY.md`는 이미 존재함. 남은 건 `master`/`develop`/`v*` 태그에 대한 실제 GitHub ruleset(PR 필수, required CI, conversation resolution, force-push/삭제 차단) 적용과 API로 실제 상태 재조회뿐 — 코드 작업이 아니라 저장소를 public 전환한 뒤 GitHub 설정/API에서 해야 하는 작업. `project_v1_public_release_plan` 메모리 참고(1.0.0 시점 public 전환 계획). (enterprise-adoption.md §4, §9)
- [ ] *(전제조건: qualified maintainer 2명 이상)* **CODEOWNERS 독립 승인 활성화** — 현재 1인 운영 상태에서 필수 code-owner review를 켜면 운영을 막거나 형식적 self-review만 만든다고 보고서 자체가 명시적으로 경고함. 인원 조건 충족 전엔 시작하지 않음. (enterprise-adoption.md §4, §9 "지금 구현하지 않을 것")
- [ ] *(전제조건: 저장소 2개 이상)* **조직 단위 ruleset/reusable workflow/audit export/taxonomy** — 여러 저장소가 같은 운영 문제를 반복할 때 설계 시작. 지금은 저장소가 1개뿐이라 시작 조건 미충족. (enterprise-adoption.md §6, §8 항목 5)

Expand Down
Loading
Loading