From cdee1c169300df324a38a88139b6764e8cbb8b8f Mon Sep 17 00:00:00 2001 From: shcommit Date: Sat, 5 Sep 2026 22:59:40 +0900 Subject: [PATCH 01/21] docs: expand improvements backlog with high and medium items --- changelog.md | 2 ++ handoff.md | 10 +++------- improvements.md | 16 +++++++++++----- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/changelog.md b/changelog.md index 2ccb47a..32d6da8 100644 --- a/changelog.md +++ b/changelog.md @@ -4,6 +4,8 @@ Lightweight human-readable summary of meaningful repository changes. ## Unreleased +- 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. + ## v0.3.2 (2026-09-02) - Cleared completed work out of `improvements.md`'s `## Done` section diff --git a/handoff.md b/handoff.md index 45f7223..58ab750 100644 --- a/handoff.md +++ b/handoff.md @@ -2,12 +2,7 @@ ## 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. +Expanded `improvements.md` with High and Medium backlog items covering ReDoS cross-platform safety, 2-phase atomic transaction rollback, ADR overlap/similarity Eval infrastructure, weekly maintenance automation, PR significance bot, frontmatter auto-linter, interactive graph visualization, and code drift detection. ## Scope @@ -22,7 +17,8 @@ everything else. ## Next step (for a new session picking this up cold) -There is no ready-to-start backlog item in `improvements.md`. Concretely: +Review the newly expanded `improvements.md` High/Medium items and pick an implementation candidate (e.g. `adr lint --fix` or ReDoS cross-platform guard). + 1. `improvements.md`'s `### Low` → audit-report sub-group has exactly 1 item left (Antigravity in `harness-parity`), blocked on `agy` having diff --git a/improvements.md b/improvements.md index 7d2a10c..ab7960e 100644 --- a/improvements.md +++ b/improvements.md @@ -5,17 +5,23 @@ Concrete implementation backlog. Unscheduled product bets belong in ## Open -Backlog derived from `docs/adr-toolkit-audit-report.md`. Scope excludes -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. +Backlog derived from `docs/adr-toolkit-audit-report.md`, operational experiences, and developer friction analysis. ### High -None open. +- [ ] **ReDoS 크로스 플랫폼 Guard (Windows 비-POSIX 타임아웃)** — `rules/conflict.py`의 정규식 ReDoS 타임아웃 구동 방식이 `signal.SIGALRM` 기반이라 POSIX 전용 환경으로 제한됨. Static constraint checker (`core/constraints.py`) 외 교차 정규식 타임아웃을 Windows에서도 안전하게 처리할 수 있도록 스레드/프로세스 타임아웃 워커 도입. (`handoff.md` Open Risk 대응) +- [ ] **ADR `supersede` 2단계 원자적 트랜잭션 롤백 보장** — `supersede` 커맨드가 기존 ADR 상태 변경(Superseded)과 신규 ADR 생성/수정(Superseding)을 연쇄 실행할 때, 프로세스 중간 강제 종료 시 발생할 수 있는 '반쪽짜리 업데이트' 방지를 위한 트랜잭션 백업/롤백 안전장치 구축. ### Medium +- [ ] **ADR 중첩/유사도 감지 및 파편화 방지 Eval 시스템** — 작성하려 하거나 기존에 존재하는 ADR 간 내용/주제/영향 범위의 중첩(overlap) 및 파편화를 사전 감지하는 로직과, ADR 집합의 중복·충돌·일관성을 지속해서 평가/검증하는 Evaluation 프레임워크 구축. (유사도 기반 `supersede` 권장, 중복 작성 방지) +- [ ] **개발용 플러그인 메인 저장소 Symlink 자동화 스크립트** — local development 시 `~/.gemini/config/plugins/adr-toolkit`이 임시 워크트리가 아닌 메인 저장소를 항상 바라보도록 하고, 버전 갱신 시 symlink 유효성을 체크하는 도구/가이드 정립. +- [ ] **주간 자동 ADR 헬스체크 및 무효화/깨진 링크 점검 오토메이션** — 주 1회(GitHub Actions Scheduled Workflow 등) 실행되어 오래 방치된 `PROPOSED` ADR, 리팩터링으로 깨진 `affected_paths` 경로, 버전 드리프트를 자동 점검하고 이슈/알림을 생성하는 주간 유지보수 시스템. +- [ ] **PR 시 아키텍처 영향도 자동 판별 및 ADR 작성 유도 (Significance Bot)** — 중요 경계 코드 수정 시 ADR 누락을 PR 체크 단계에서 감지하고 관련 ADR 템플릿과 초안 생성을 자동 가이드하는 CI 봇 연동. +- [ ] **Frontmatter 자동 교정 및 린터 (`adr lint --fix`)** — 사용자가 손으로 수정하며 발생하는 프론트매터 오탈자, 필수 태그/날짜 누락, 들여쓰기 오류 등을 안전하게 자동 보정하는 UX 개선 기능. +- [ ] **대화형 의존성 시각화 뷰어 (`adr graph --format=html`)** — 현 mermaid/json 출력 외에도 단일 HTML/SVG 파일로 ADR 간의 이행/대체/참조 그래프를 브라우저에서 인터랙티브하게 탐색할 수 있는 뷰어 기능. +- [ ] **코드 드리프트 자동 탐지 (`adr drift`)** — ADR 작성 날짜 및 `affected_paths`의 실제 `git log` 변경 이력을 교차 분석하여, ADR 합의 시점 이후 지침과 다르게 변경된 코드 영역을 추적·리포팅하는 서브커맨드. + - [ ] ~~**파싱 결과 캐시**~~ — **결정: 하지 않음.** 이 CLI는 호출마다 새 프로세스라 `functools.lru_cache`는 프로세스 간 재파싱을 전혀 줄이지 못하고(원 문제였던 `validate → index → check` 연쇄 재파싱은 별도 From 0e5526acf87ba4de120448e601267ce351327f1e Mon Sep 17 00:00:00 2001 From: shcommit Date: Sat, 5 Sep 2026 23:16:41 +0900 Subject: [PATCH 02/21] chore: pin dev tooling and add a scoped ruff config Pins pytest/pytest-cov/mypy/ruff so Dependabot's pip ecosystem has real versions to track, and adds an E9+F ruff selection scoped to what already passes today (broader rule sets are a follow-up). Co-Authored-By: Claude Sonnet 5 --- pyproject.toml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 58f8e4b..74d282c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,6 +27,21 @@ dependencies = [] [project.scripts] adr = "scripts.adr:main" +[project.optional-dependencies] +dev = [ + "pytest==8.4.2", + "pytest-cov==7.1.0", + "mypy==1.19.1", + "ruff==0.16.6", +] + +[tool.ruff] +target-version = "py39" +extend-exclude = ["docs/decisions"] + +[tool.ruff.lint] +select = ["E9", "F"] + [tool.setuptools] packages = ["scripts", "scripts.core", "scripts.commands", "scripts.rules"] package-dir = {"scripts" = "skills/adr-toolkit/scripts"} From 15bfc96581f1b5510e1678b080ff4e816a8139ac Mon Sep 17 00:00:00 2001 From: shcommit Date: Sat, 5 Sep 2026 23:19:42 +0900 Subject: [PATCH 03/21] fix: resolve pre-existing ruff findings (unused imports/variable) Clears the codebase for the new lint CI job added in a later task. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01TAZPZwzSutmru6kSCEogu6 --- scripts/adoption_metrics/reporting.py | 2 -- scripts/verify_examples.py | 4 +--- skills/adr-toolkit/scripts/core/atomic_io.py | 1 - tests/integration/test_index_markdown_injection.py | 1 - tests/unit/test_config.py | 1 - tests/unit/test_dependency_scanner.py | 1 - tests/unit/test_identifiers.py | 1 - tests/unit/test_repository_paths.py | 1 - 8 files changed, 1 insertion(+), 11 deletions(-) diff --git a/scripts/adoption_metrics/reporting.py b/scripts/adoption_metrics/reporting.py index d58bd23..9bcf4ad 100644 --- a/scripts/adoption_metrics/reporting.py +++ b/scripts/adoption_metrics/reporting.py @@ -2,8 +2,6 @@ import argparse import json -import subprocess -import sys from datetime import datetime, timezone from pathlib import Path from typing import Any, Dict, List, Optional diff --git a/scripts/verify_examples.py b/scripts/verify_examples.py index acc33e1..d2b5b9a 100644 --- a/scripts/verify_examples.py +++ b/scripts/verify_examples.py @@ -13,8 +13,6 @@ import argparse import json -import os -import re import subprocess import sys import tempfile @@ -250,7 +248,7 @@ def main(argv=None) -> int: parser = argparse.ArgumentParser(description="Verify and sync examples/*.md with adr.py") parser.add_argument("--check", action="store_true", help="Check that examples are executable and valid") parser.add_argument("--update", action="store_true", help="Auto-update examples if needed") - args = parser.parse_args(argv) + parser.parse_args(argv) if hasattr(sys.stdout, "reconfigure"): sys.stdout.reconfigure(encoding="utf-8", errors="backslashreplace") diff --git a/skills/adr-toolkit/scripts/core/atomic_io.py b/skills/adr-toolkit/scripts/core/atomic_io.py index 8b38115..0bdc9aa 100644 --- a/skills/adr-toolkit/scripts/core/atomic_io.py +++ b/skills/adr-toolkit/scripts/core/atomic_io.py @@ -17,7 +17,6 @@ from contextlib import contextmanager from pathlib import Path from typing import Any, Iterator -from types import FrameType if sys.platform == "win32": import msvcrt diff --git a/tests/integration/test_index_markdown_injection.py b/tests/integration/test_index_markdown_injection.py index f182bc8..39bc19c 100644 --- a/tests/integration/test_index_markdown_injection.py +++ b/tests/integration/test_index_markdown_injection.py @@ -1,7 +1,6 @@ """Proves INDEX's generated README cannot be split into a second, attacker-controlled link via an ADR title (docs/adr-toolkit-audit-report.md, Top-3 #2).""" -from pathlib import Path from types import SimpleNamespace from scripts.commands import index diff --git a/tests/unit/test_config.py b/tests/unit/test_config.py index d986376..3d7faa1 100644 --- a/tests/unit/test_config.py +++ b/tests/unit/test_config.py @@ -1,5 +1,4 @@ import json -import os import pytest diff --git a/tests/unit/test_dependency_scanner.py b/tests/unit/test_dependency_scanner.py index 1ef8a8f..07f5a94 100644 --- a/tests/unit/test_dependency_scanner.py +++ b/tests/unit/test_dependency_scanner.py @@ -1,4 +1,3 @@ -from pathlib import Path from scripts.evidence import dependency_scanner diff --git a/tests/unit/test_identifiers.py b/tests/unit/test_identifiers.py index f105801..f09a757 100644 --- a/tests/unit/test_identifiers.py +++ b/tests/unit/test_identifiers.py @@ -1,4 +1,3 @@ -from pathlib import Path import pytest diff --git a/tests/unit/test_repository_paths.py b/tests/unit/test_repository_paths.py index c0f2997..512a513 100644 --- a/tests/unit/test_repository_paths.py +++ b/tests/unit/test_repository_paths.py @@ -1,6 +1,5 @@ """Tests for resolve_from_root's boundary enforcement (docs/adr-toolkit-audit-report.md §2.2 2.3).""" -from pathlib import Path import pytest From 819efd1a388b9240d47794cbc6dfce8fd6054bf4 Mon Sep 17 00:00:00 2001 From: shcommit Date: Sat, 5 Sep 2026 23:20:21 +0900 Subject: [PATCH 04/21] docs: add OSS repo governance & hardening spec and implementation plan Records the audit findings (repo public since 2026-08-29 with v1.0.1 released but zero branch protection, develop/master release drift, missing label taxonomy/dependabot/issue forms/lint job) and the NOW-tier implementation plan those findings led to. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01TAZPZwzSutmru6kSCEogu6 --- ...05-oss-repo-governance-hardening-design.md | 266 ++++++++++++++++++ 1 file changed, 266 insertions(+) create mode 100644 docs/superpowers/specs/2026-09-05-oss-repo-governance-hardening-design.md diff --git a/docs/superpowers/specs/2026-09-05-oss-repo-governance-hardening-design.md b/docs/superpowers/specs/2026-09-05-oss-repo-governance-hardening-design.md new file mode 100644 index 0000000..39a119b --- /dev/null +++ b/docs/superpowers/specs/2026-09-05-oss-repo-governance-hardening-design.md @@ -0,0 +1,266 @@ +# OSS Repository Governance & Hardening Design + +## Scope + +Make ADR Toolkit's GitHub operations (issue/PR triage, labels, dependency +updates, CI gates, branch protection, contributor onboarding) hold up if +issues and PRs grow from single digits into the hundreds, without adding +automation the current one-maintainer, one-repository reality doesn't need +yet. Covers `.github/**` configuration, CI workflow structure, and the +GitHub-side settings that can't live in code. Does not change ADR Toolkit's +product code, CLI behavior, or `docs/decisions/` governance model. + +## Context — audit findings as of 2026-09-05 + +Re-verified against the live repository (`gh api`/`gh repo view`), not just +file presence, because `docs/enterprise-adoption.md` §4/§8 and +`improvements.md`'s "Low" backlog describe this repo as still private with a +single precondition ("저장소 public 전환") blocking the public-readiness gate. +That precondition has already been met and those documents are now stale: + +- The repository has been **public since 2026-08-29**, and `master` has + already shipped `v1.0.0` and `v1.0.1` (PyPI publishing pipeline, antigravity + harness-parity CI, a Windows lock-metadata fix, mypy `--strict` fix). +- Despite being public, `master` has **zero branch protection** + (`gh api repos/.../branches/master/protection` → `404 Branch not + protected`). `develop` is unprotected too. `docs/enterprise-adoption.md` + §9's "Public" stage completion condition ("ruleset API 검증") is therefore + **not actually satisfied**, even though the PR template, `CONTRIBUTING.md`, + and `SECURITY.md` pieces of that same stage are done. +- `develop` was frozen at the `v0.3.2` sync point while `master` advanced + through the `v1.0.0`/`v1.0.1` releases — the git-flow-mandated + release-branch back-merge into `develop` never happened. **Fixed as a + prerequisite to this spec** via `chore/sync-develop-with-v1.0.1` (PR #17, + not yet merged at spec time) — this branch is based on that synced state. +- No `dependabot.yml`, no `CODEOWNERS`, no path-based auto-labeler. Labels are + the unmodified GitHub defaults (`bug`, `enhancement`, `documentation`, + `good first issue`, `help wanted`, `question`, `duplicate`, `invalid`, + `wontfix`, `accessibility`) — no `type:`/`area:`/`priority:`/`size:` axis at + all, so nothing about a large backlog would currently self-organize. + Issue templates are legacy Markdown (`bug_report.md`, `feature_request.md`), + not structured Issue Forms. +- CI (`.github/workflows/test.yml`) is already more mature than a typical + small OSS repo: multi-OS/multi-Python pytest matrix, a coverage floor + (`--cov-fail-under=85`), a scoped mypy `--strict` job, generated-file drift + checks (`sync_version.py --check`, `verify_examples.py --check`), a + Conventional-Commit PR title gate, and a `harness-parity` job that installs + the real Codex/Gemini CLIs against this repo. There is **no lint job** at + all (no ruff/flake8/black anywhere in the repo) and no dependency/security + scan step. +- `harness-parity` contains one remote-installer pattern the request asked to + scrutinize: `curl -fsSL https://antigravity.google/cli/install.sh | bash`. + (Antigravity itself is manually verified only, per + `adapters/antigravity/README.md` — this curl step doesn't currently run in + CI for that adapter.) +- GitHub Actions are pinned to major-version tags from verified publishers + (`actions/*@v4/@v5`, `softprops/action-gh-release@v2`, + `pypa/gh-action-pypi-publish@release/v1`) — not full commit-SHA pinning, but + not `@latest`/`@master` either. `release.yml` already scopes permissions + per-job (`contents: write`, `id-token: write`, `attestations: write`) and + `test.yml` sets repo-wide `permissions: contents: read`; least-privilege is + already largely in place, not a gap. +- Dependency ecosystems actually in use: Python (`pyproject.toml`) and GitHub + Actions. No `package.json` anywhere — the `npm install -g` calls in + `harness-parity` install pinned global CLIs for testing, not a project + dependency Dependabot should manage. No Docker. +- `project-roadmap.md`'s "Public and enterprise governance" section and + `docs/enterprise-adoption.md` §8 already correctly defer **mandatory** + CODEOWNERS review and organization-wide ruleset/reusable-workflow work + behind explicit preconditions (2+ qualified maintainers; 2+ repositories) + that still aren't met. This spec does not revisit that call — see + Out of Scope. + +## Problem Statement + +The repository's day-to-day contributor mechanics (label triage, dependency +freshness, PR gating, branch protection) were never built out because the +project was small and private. It is now public with two releases shipped, +but none of the operational scaffolding that keeps a growing issue/PR queue +navigable for a single maintainer exists yet, and the one piece of the +public-readiness plan that mattered most for actually protecting the release +history — branch protection — silently never got applied when the repo went +public. Left as-is, the first sign of trouble will be either an unreviewed +force-push/deletion incident on `master`, or a backlog of unlabeled, +untriaged issues and PRs once external contributors show up. + +## Solution + +Add the minimum GitHub-native automation that lets issues and PRs +self-organize (path-based labels, a label taxonomy, Dependabot, Issue Forms) +and close the branch-protection gap that public status already requires, +while explicitly deferring anything that assumes a maintainer team or an +issue volume this repository doesn't have yet (mandatory CODEOWNERS review, +stale-bot, org-wide rulesets). Every "not now" gets a written trigger +condition instead of a vague "later," matching how `project-roadmap.md` and +`docs/enterprise-adoption.md` already record deferred work in this repo. + +## User Stories + +1. As the sole maintainer, I want new issues/PRs to arrive pre-labeled by the + file paths they touch so I don't manually triage every one. +2. As the sole maintainer, I want dependency and Action version bumps to + arrive as routine, reviewable PRs instead of silent drift or a manual audit. +3. As a first-time contributor, I want a structured bug/feature form instead + of a blank Markdown template, so I give the maintainer what's needed on + the first pass. +4. As the sole maintainer, I want `master`/`develop`/`v*` tags protected from + force-push and deletion now that the repo is public, without being forced + into mandatory independent code-owner review I can't actually staff. +5. As a future contributor, I want a small set of well-labeled "good first + issue" candidates to exist so I know where to start. +6. As the sole maintainer, I want CI to catch missing lint/security-scan + coverage that today has no job at all, without turning every PR into a + slow, heavyweight gate. + +## Decisions + +### NOW — apply in this branch + +- **Path-based auto-labeler**: a labeler config mapping changed-file globs to + `area:*` labels (e.g. `skills/adr-toolkit/**` / `scripts/**` → `area:core`, + `adapters/**` → `area:adapter`, `.github/**` → `area:github`, `docs/**` → + `area:docs`, `tests/**` → `type:test`), run by a workflow triggered on + `pull_request_target` with `contents: read`/`pull-requests: write` only. +- **Label taxonomy**: introduce `type:*`, `area:*`, `priority:*`, `size:*`, + plus `needs-triage` and `blocked`, sized to this repo's actual directories + (`core`/`cli`/`adapter`/`github`/`docs`) rather than the generic list + verbatim. Keep the existing default labels (`bug`, `enhancement`, + `good first issue`, `help wanted`, `documentation`) rather than replacing + them, since GitHub's defaults already cover part of `type:*`/`area:docs` + and dropping them would break any existing issue/PR history referencing + them. +- **Dependabot**: `pip` (root `pyproject.toml`) and `github-actions` + ecosystems only — no `npm`/`docker` entries, since neither has a manifest + Dependabot could act on. Weekly schedule, grouped updates, auto-created + PRs. +- **Issue Forms**: replace the two Markdown templates with structured YAML + forms (bug report: version, OS, environment, affected + component/adapter, expected/actual behavior, repro steps, logs; feature + request: problem, use case, proposed solution, alternatives, affected + area, contribution willingness), plus a `config.yml` pointing to + Discussions/`SECURITY.md` for questions and vulnerabilities instead of a + blank issue. +- **Lint CI job**: add a fast lint job (the repo has no lint tool configured + at all today) to the existing fast-gate jobs in `test.yml`, separate from + the slower `harness-parity` job. +- **Dependency/security scan**: add a lightweight `pip-audit`-style check for + the Python dependency surface as a fast-gate job. +- **Branch protection / ruleset** (GitHub UI/API, not a file in this repo — + see the UI section below): require PR + passing required checks, + block force-push and branch deletion on `master` and `develop`, restrict + `v*` tag creation/deletion, require conversation resolution. Do **not** + require code-owner review or signed commits yet — no second qualified + maintainer exists to review against, and no CODEOWNERS file exists to + reference. +- **Update stale docs**: correct `docs/enterprise-adoption.md` §4/§8's + "저장소가 아직 private" framing and `improvements.md`'s already-removed + precondition note now that the public transition and its ruleset gate are + being closed out, so the next reader doesn't re-derive the same stale + premise this session had to correct first. + +### NEXT — once issue/PR volume or contributor count actually grows + +- CODEOWNERS file (drafted but **not** wired to mandatory review) — ready to + flip on once 2+ qualified maintainers exist, per the existing decision in + `docs/enterprise-adoption.md` §4 and `project-roadmap.md`. Do not enable + required review as part of this spec. +- GitHub Projects board with an Inbox → Backlog → Ready → In Progress → + Review → Blocked → Done flow and `Priority`/`Area`/`Size` custom fields, + once there's enough issue volume for a Kanban view to earn its keep over a + flat issue list. +- PR size labeling (`size:XS`…`size:XL`) as a workflow addition once PR + volume makes "the queue is large, which PRs are actually small" a real + question. +- Splitting `test.yml` into an explicit Fast Gate / Integration Gate + workflow pair, once the existing single-workflow job list gets unwieldy + enough that PR authors need the distinction visible rather than just + reading job names. + +### LATER — only once scale actually demands it + +- Stale issue/PR bot. Current issue/PR count doesn't warrant it — explicit + decision **not to adopt now**, matching how this repo already declines + automation it doesn't need (`docs/enterprise-adoption.md` §8 "지금 구현하지 + 않을 것"). Revisit once there's a real backlog of abandoned issues, with + exclusions for `security`, `pinned`, `roadmap`, `help wanted`, + `priority:P0`, and `blocked`. +- Organization-level rulesets, reusable workflows, RBAC, audit export — all + already correctly gated behind "2+ repositories" in `improvements.md`; + this spec doesn't touch that precondition. +- Advanced/ML-based triage bots, automatic contributor assignment, complex + multi-stage release trains. + +## Testing / Validation Decisions + +- Labeler config: validate with a dry-run against recent merged PRs' + changed-file lists to confirm expected labels before enabling the workflow + for real. +- Dependabot: confirm via a manual `dependabot.yml` schema check (GitHub + validates on push) and by watching the first scheduled run produce the + expected grouped PRs. +- Issue Forms: manually preview each form in GitHub's issue-form preview + before merging; forms have no automated test surface. +- New CI jobs (lint, dependency/security scan): must pass on this branch's + own diff and not regress the existing 515 unit tests or `sync_version.py + --check` / `verify_examples.py --check` drift gates. +- Branch protection: after applying via UI/API, re-query + `gh api repos/SHcommit/ADR-toolkit/branches//protection` and paste + the actual response into the audit doc — this spec's own investigation + showed a prior "done" claim (docs saying the public gate was satisfied) + was false, so the closing step here is re-verification, not another + written claim. + +## Out of Scope + +- Mandatory CODEOWNERS-backed independent review (no second qualified + maintainer yet — explicit existing decision, not revisited here). +- Organization-level rulesets, reusable workflows, audit export, central + taxonomy (single-repository precondition unmet — explicit existing + decision, not revisited here). +- Stale-bot / auto-triage-bot / auto-assignment automation (volume doesn't + warrant it yet). +- Signed-commit requirements. +- Any change to ADR Toolkit's product code, CLI, or `docs/decisions/` + governance model. +- Converting the Antigravity `curl | bash` install step into an + artifact+checksum flow — that step doesn't currently run for the + Antigravity adapter in CI (manual-only per + `adapters/antigravity/README.md`); if/when Antigravity CI verification is + added (tracked in `improvements.md`, blocked on Antigravity publishing to a + package registry), that installer should be revisited then, not + speculatively hardened now for a path nothing currently executes. +- Full commit-SHA pinning for all third-party Actions (current major-version + tag pinning from verified publishers is a reasonable middle ground for this + repo's risk level; revisit only if a specific tag-mutation incident in one + of the pinned Actions ever demonstrates the gap matters). + +## Open Questions + +- Should PR #17 (the develop/master sync) merge before or independently of + this branch's PR? This branch is based on its tip either way, so either + order is safe, but the maintainer should decide merge order. +- Exact `priority:*` and `size:*` thresholds (e.g. what LOC/file-count counts + as `size:M` vs `size:L`) — left to the maintainer's judgment at + implementation time rather than guessed here. +- Whether `needs-triage` should auto-apply to every new issue/PR via the + labeler workflow, or only to issues (PRs already get `area:*` + + `pr-title-check`) — implementation-time call. + +## Further Notes + +- Rollout order: branch-protection/ruleset (GitHub UI/API, highest + risk-reduction per unit effort) → Dependabot + auto-labeler (lowest + maintenance cost) → Issue Forms → new CI jobs (lint, dependency scan) → + stale-docs correction, so the highest-value, lowest-risk items land first + and the doc correction reflects the final state rather than needing a + second pass. +- The public-transition gap found here (public since 2026-08-29, but branch + protection never applied, and `docs/enterprise-adoption.md`/`improvements.md` + both still describing the repo as private) should be treated as the + headline finding when this work is reported back — it's a real exposure + window on a public repo with release tags, not a paperwork gap. +- This spec intentionally does not propose a `.github/labeler.yml` / + `dependabot.yml` schema inline — implementation will write those files + directly against this repo's actual directory names, which is faster to + verify than hand-transcribing YAML into a design doc that could drift from + the real paths by the time it's implemented. From 7b5e9685a0a1bd4395f55c98ad1ed6c278f45284 Mon Sep 17 00:00:00 2001 From: shcommit Date: Sat, 5 Sep 2026 23:23:03 +0900 Subject: [PATCH 05/21] feat(github): add label taxonomy as code type:/area:/priority:/size: labels plus needs-triage and blocked, synced from .github/labels.yml by EndBug/label-sync on push to develop or manual dispatch. Keeps existing default labels rather than deleting them. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01TAZPZwzSutmru6kSCEogu6 --- .github/labels.yml | 91 ++++++++++++++++++++++++++++++++++++ .github/workflows/labels.yml | 22 +++++++++ 2 files changed, 113 insertions(+) create mode 100644 .github/labels.yml create mode 100644 .github/workflows/labels.yml diff --git a/.github/labels.yml b/.github/labels.yml new file mode 100644 index 0000000..f21259e --- /dev/null +++ b/.github/labels.yml @@ -0,0 +1,91 @@ +# Label taxonomy for ADR Toolkit. Synced to the live repo by +# .github/workflows/labels.yml via EndBug/label-sync. Add or edit labels +# here, not in the GitHub UI — UI-only edits are overwritten on the next +# sync run. + +# --- type: what kind of change/report --- +- name: "type:bug" + color: "d73a4a" + description: "Something isn't working" +- name: "type:feature" + color: "a2eeef" + description: "New feature or request" +- name: "type:docs" + color: "0075ca" + description: "Documentation only" +- name: "type:refactor" + color: "cfd3d7" + description: "Code change with no behavior change" +- name: "type:test" + color: "bfdadc" + description: "Test-only change" + +# --- area: which part of the repo --- +- name: "area:core" + color: "5319e7" + description: "skills/adr-toolkit/scripts core and CLI commands" +- name: "area:cli" + color: "5319e7" + description: "adr.py entrypoint and command wiring" +- name: "area:adapter" + color: "5319e7" + description: "adapters/** harness adapters (Claude, Codex, Gemini, Antigravity)" +- name: "area:github" + color: "5319e7" + description: ".github/** workflows, templates, and repo automation" +- name: "area:docs" + color: "5319e7" + description: "docs/**, README, CONTRIBUTING, and other project documentation" + +# --- priority --- +- name: "priority:P0" + color: "b60205" + description: "Drop everything -- breaks release, security, or data integrity" +- name: "priority:P1" + color: "d93f0b" + description: "Should land in the next release" +- name: "priority:P2" + color: "fbca04" + description: "Normal priority, no target release yet" + +# --- workflow state --- +- name: "needs-triage" + color: "ededed" + description: "Not yet reviewed by a maintainer" +- name: "blocked" + color: "000000" + description: "Waiting on an external dependency or decision" + +# --- size (applied manually at review time, not automated in this plan) --- +- name: "size:XS" + color: "c2e0c6" + description: "Trivial change" +- name: "size:S" + color: "c2e0c6" + description: "Small, single-concern change" +- name: "size:M" + color: "fef2c0" + description: "Moderate change, multiple files" +- name: "size:L" + color: "f9d0c4" + description: "Large change, review carefully" +- name: "size:XL" + color: "e99695" + description: "Very large -- consider splitting" + +# --- kept from GitHub's defaults: still useful, not replaced --- +- name: "good first issue" + color: "7057ff" + description: "Good for newcomers" +- name: "help wanted" + color: "008672" + description: "Extra attention is needed" +- name: "duplicate" + color: "cfd3d7" + description: "This issue or pull request already exists" +- name: "invalid" + color: "e4e669" + description: "This doesn't seem right" +- name: "wontfix" + color: "ffffff" + description: "This will not be worked on" diff --git a/.github/workflows/labels.yml b/.github/workflows/labels.yml new file mode 100644 index 0000000..cd77ff4 --- /dev/null +++ b/.github/workflows/labels.yml @@ -0,0 +1,22 @@ +name: sync-labels + +on: + push: + branches: [develop] + paths: [".github/labels.yml"] + workflow_dispatch: {} + +permissions: + contents: read + issues: write + pull-requests: write + +jobs: + sync: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: EndBug/label-sync@52074158190acb45f3077f9099fea818aa43f97a # v2.3.3 + with: + config-file: .github/labels.yml + delete-other-labels: false From 51af064c2ebda48db19979622c3c06c6f88abc0a Mon Sep 17 00:00:00 2001 From: shcommit Date: Sat, 5 Sep 2026 23:25:07 +0900 Subject: [PATCH 06/21] feat(github): auto-label PRs by changed path, tag new issues needs-triage Co-Authored-By: Claude Sonnet 5 --- .github/labeler.yml | 33 ++++++++++++++++++++++++++++++++ .github/workflows/labeler.yml | 36 +++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 .github/labeler.yml create mode 100644 .github/workflows/labeler.yml diff --git a/.github/labeler.yml b/.github/labeler.yml new file mode 100644 index 0000000..c98869c --- /dev/null +++ b/.github/labeler.yml @@ -0,0 +1,33 @@ +"area:core": + - changed-files: + - any-glob-to-any-file: + - "skills/adr-toolkit/scripts/**" + - "scripts/**" + +"area:adapter": + - changed-files: + - any-glob-to-any-file: + - "adapters/**" + - ".claude-plugin/**" + +"area:github": + - changed-files: + - any-glob-to-any-file: + - ".github/**" + +"area:docs": + - changed-files: + - any-glob-to-any-file: + - "docs/**" + - "*.md" + +"type:test": + - changed-files: + - any-glob-to-any-file: + - "tests/**" + +"type:docs": + - changed-files: + - any-glob-to-any-file: + - "docs/**" + - "*.md" diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml new file mode 100644 index 0000000..02f2074 --- /dev/null +++ b/.github/workflows/labeler.yml @@ -0,0 +1,36 @@ +name: labeler + +on: + pull_request_target: + types: [opened, synchronize, reopened] + issues: + types: [opened] + +permissions: + contents: read + pull-requests: write + issues: write + +jobs: + label-pr: + if: github.event_name == 'pull_request_target' + runs-on: ubuntu-latest + steps: + - uses: actions/labeler@v7 + with: + configuration-path: .github/labeler.yml + sync-labels: false + + triage-issue: + if: github.event_name == 'issues' + runs-on: ubuntu-latest + steps: + - uses: actions/github-script@v7 + with: + script: | + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + labels: ["needs-triage"], + }); From 2e8674fa9ee3298c6a05e6f370bf8b48630a1dca Mon Sep 17 00:00:00 2001 From: shcommit Date: Sat, 5 Sep 2026 23:27:13 +0900 Subject: [PATCH 07/21] feat(github): convert issue templates to structured Issue Forms Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01TAZPZwzSutmru6kSCEogu6 --- .github/ISSUE_TEMPLATE/bug_report.md | 39 ----------- .github/ISSUE_TEMPLATE/bug_report.yml | 79 ++++++++++++++++++++++ .github/ISSUE_TEMPLATE/config.yml | 8 +++ .github/ISSUE_TEMPLATE/feature_request.md | 19 ------ .github/ISSUE_TEMPLATE/feature_request.yml | 54 +++++++++++++++ 5 files changed, 141 insertions(+), 58 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml delete mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yml diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 2c4e92b..0000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -name: Bug report -about: Report a defect in ADR Toolkit -title: "" -labels: bug ---- - -## Summary - -## Steps to Reproduce - -1. -2. -3. - -## Expected Behavior - -## Actual Behavior - -## Environment - -- Harness: Claude Code / Codex CLI / Gemini CLI / Antigravity CLI / generic / other -- ADR Toolkit version (`skills/adr-toolkit/VERSION`): -- OS: - -## Relevant Output - -Paste the command and its output, including `--json` output where -applicable. - -``` -``` - -## Scope - -- [ ] This affects `adr.py validate`, `create`, `index`, `check`, `graph`, - or `search`. -- [ ] This affects a specific harness adapter (Codex, Gemini CLI, - Antigravity, or generic). diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..891306e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,79 @@ +name: Bug Report +description: Report something that isn't working as expected +title: "[Bug]: " +labels: ["needs-triage", "type:bug"] +body: + - type: input + id: version + attributes: + label: Version + description: "Output of `adr --version` or the release tag you're on" + placeholder: "v1.0.1" + validations: + required: true + - type: dropdown + id: os + attributes: + label: Operating System + options: + - Linux + - macOS + - Windows + - Other (specify in Additional context) + validations: + required: true + - type: dropdown + id: environment + attributes: + label: Environment + description: How you're running ADR Toolkit + options: + - Claude Code + - Codex CLI + - Gemini CLI + - Antigravity CLI + - Direct CLI (pip install / python script) + - Other (specify in Additional context) + validations: + required: true + - type: input + id: component + attributes: + label: Affected component / adapter + description: "e.g. `adr.py check`, `adapters/codex`, ADR index generation" + validations: + required: true + - type: textarea + id: expected + attributes: + label: Expected behavior + validations: + required: true + - type: textarea + id: actual + attributes: + label: Actual behavior + validations: + required: true + - type: textarea + id: repro + attributes: + label: Reproduction steps + description: Exact commands, in order + render: shell + validations: + required: true + - type: textarea + id: logs + attributes: + label: Logs + description: "Output of the failing command with `--verbose` or `--debug` if available" + render: shell + validations: + required: false + - type: textarea + id: additional + attributes: + label: Additional context + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..e9bb723 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: Security vulnerability + url: https://github.com/SHcommit/ADR-toolkit/security/policy + about: Please report vulnerabilities privately per SECURITY.md, not as a public issue. + - name: Question / discussion + url: https://github.com/SHcommit/ADR-toolkit/discussions + about: For open-ended questions that aren't a bug or a concrete feature proposal. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index 4f7f064..0000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -name: Feature request -about: Propose new functionality for ADR Toolkit -title: "" -labels: enhancement ---- - -## Problem - -What are you trying to do that ADR Toolkit does not support today? - -## Proposed Solution - -## Alternatives Considered - -## Additional Context - -- [ ] I checked `project-roadmap.md` and `improvements.md` for existing - plans that already cover this. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..c3549a8 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,54 @@ +name: Feature Request +description: Propose a new capability or improvement +title: "[Feature]: " +labels: ["needs-triage", "type:feature"] +body: + - type: textarea + id: problem + attributes: + label: Problem + description: What can't you do today, or what's needlessly painful? + validations: + required: true + - type: textarea + id: use-case + attributes: + label: Use case + description: The concrete scenario where this problem shows up + validations: + required: true + - type: textarea + id: solution + attributes: + label: Proposed solution + validations: + required: false + - type: textarea + id: alternatives + attributes: + label: Alternatives considered + validations: + required: false + - type: dropdown + id: area + attributes: + label: Affected area + options: + - Core / CLI (scripts, adr.py) + - Adapter (Claude / Codex / Gemini / Antigravity) + - GitHub automation (.github/**) + - Documentation + - Other + validations: + required: true + - type: dropdown + id: contribution + attributes: + label: Contribution willingness + description: Would you be willing to open a PR for this yourself? + options: + - "Yes, I'd like to implement this" + - "Maybe, with guidance" + - "No, just proposing the idea" + validations: + required: true From a574e2e998237c5de16917cbb93963c7751a868b Mon Sep 17 00:00:00 2001 From: shcommit Date: Sat, 5 Sep 2026 23:28:55 +0900 Subject: [PATCH 08/21] feat(github): add dependabot for pip and github-actions ecosystems Co-Authored-By: Claude Sonnet 5 --- .github/dependabot.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..ade07ae --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,21 @@ +version: 2 +updates: + - package-ecosystem: "pip" + directory: "/" + schedule: + interval: "weekly" + groups: + dev-dependencies: + patterns: + - "*" + open-pull-requests-limit: 5 + + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + groups: + actions: + patterns: + - "*" + open-pull-requests-limit: 5 From 925472d553ad38ea616121b9b987dcf294a5d17a Mon Sep 17 00:00:00 2001 From: shcommit Date: Sat, 5 Sep 2026 23:53:19 +0900 Subject: [PATCH 09/21] ci: add lint and dependency-audit jobs; drop Python 3.9, fix pytest CVE Lint is scoped to E9+F (already clean, prior commit); broader ruff rule sets are a follow-up, not bundled here. Dependency audit installs the pinned dev toolchain directly, not this project's own unpublished package (pip-audit's --strict and --skip-editable can never coexist, so the audited environment simply never includes anything editable), and upgrades pip first to clear pip's own known CVEs. pytest==8.4.2 carries a real CVE (CVE-2025-71176 / PYSEC-2026-1845, local /tmp directory hijack) whose fix requires pytest>=9.0.3, which in turn requires Python>=3.10. Decided (human call, project has no users yet) to drop Python 3.9 support rather than carry a permanent ignore-vuln exception: requires-python, classifiers, ruff target-version, and the CI matrix all move to 3.10 as the floor. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01TAZPZwzSutmru6kSCEogu6 --- .github/workflows/test.yml | 44 ++++++++++++++++++++++++++++++++------ pyproject.toml | 7 +++--- 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9de48b3..7786804 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -19,17 +19,14 @@ jobs: strategy: matrix: os: [ubuntu-latest, macos-latest, windows-latest] - python-version: ["3.9", "3.12"] - exclude: - - os: macos-latest - python-version: "3.9" + python-version: ["3.10", "3.12"] steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Install dependencies - run: pip install pytest pytest-cov + run: pip install -e ".[dev]" - name: Run tests run: python -m pytest tests/unit tests/integration -v --cov=skills/adr-toolkit/scripts --cov-branch --cov-report=term-missing --cov-fail-under=85 @@ -41,7 +38,7 @@ jobs: with: python-version: "3.12" - name: Install mypy - run: pip install mypy + run: pip install -e ".[dev]" - name: Type-check the fully-typed core modules run: >- mypy @@ -50,6 +47,41 @@ jobs: skills/adr-toolkit/scripts/core/contracts.py --strict + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + - name: Install ruff + run: pip install -e ".[dev]" + - name: Lint (E9 + F -- syntax errors and pyflakes only for now) + run: ruff check . + + dependency-audit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + - name: Upgrade pip (fixes known pip CVEs before auditing anything else) + run: python -m pip install --upgrade pip + - name: Install pinned dev tools (not the project itself) + # Deliberately skips `pip install -e .`: adr-toolkit isn't + # published to PyPI (confirmed 404 on pypi.org/pypi/adr-toolkit/json), + # so pip-audit can never resolve it there, and --skip-editable + # can't be combined with --strict (pip-audit treats every skipped + # dependency as fatal under --strict, unconditionally -- see + # pip_audit/_cli.py). This job audits the pinned dev toolchain, + # not this project's own unpublished package. + run: pip install pytest==9.1.1 pytest-cov==7.1.0 mypy==1.19.1 ruff==0.16.6 + - name: Install pip-audit + run: pip install pip-audit==2.9.0 + - name: Audit installed dev dependencies for known vulnerabilities + run: pip-audit --strict + version-drift: runs-on: ubuntu-latest steps: diff --git a/pyproject.toml b/pyproject.toml index 74d282c..92daaf4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,14 +14,13 @@ classifiers = [ "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" +requires-python = ">=3.10" dependencies = [] [project.scripts] @@ -29,14 +28,14 @@ adr = "scripts.adr:main" [project.optional-dependencies] dev = [ - "pytest==8.4.2", + "pytest==9.1.1", "pytest-cov==7.1.0", "mypy==1.19.1", "ruff==0.16.6", ] [tool.ruff] -target-version = "py39" +target-version = "py310" extend-exclude = ["docs/decisions"] [tool.ruff.lint] From 8edd52b8eb2b2f06db18712450499d078cc05b74 Mon Sep 17 00:00:00 2001 From: shcommit Date: Sat, 5 Sep 2026 23:59:10 +0900 Subject: [PATCH 10/21] docs(ci): note dev-tool pin sync requirement in dependency-audit job The dependency-audit job can't install via `.[dev]` (it must not install this project's own unpublished package -- see the existing comment), so its pytest/pytest-cov/mypy/ruff versions are a manual copy of pyproject.toml's dev extra. Dependabot only updates the extra, not this workflow file, so flag the duplication for whoever bumps one and not the other. Also verified the full CI pytest invocation (with --cov-fail-under=85) under the pytest==9.1.1 pin, not just the bare test run from the prior commit's verification. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01TAZPZwzSutmru6kSCEogu6 --- .github/workflows/test.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7786804..19c0952 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -69,6 +69,9 @@ jobs: - name: Upgrade pip (fixes known pip CVEs before auditing anything else) run: python -m pip install --upgrade pip - name: Install pinned dev tools (not the project itself) + # KEEP IN SYNC with pyproject.toml's [project.optional-dependencies].dev -- + # this job can't use `pip install -e ".[dev]"` (see below), so these + # versions are a manual copy Dependabot won't update here. # Deliberately skips `pip install -e .`: adr-toolkit isn't # published to PyPI (confirmed 404 on pypi.org/pypi/adr-toolkit/json), # so pip-audit can never resolve it there, and --skip-editable From cc4b9bdcef68059315aeb784ac24578878dfdac6 Mon Sep 17 00:00:00 2001 From: shcommit Date: Sun, 6 Sep 2026 00:00:53 +0900 Subject: [PATCH 11/21] docs(github): add dormant CODEOWNERS draft (not wired to required review) Co-Authored-By: Claude Sonnet 5 --- .github/CODEOWNERS | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..c7f72d4 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,13 @@ +# This file has NO effect on required reviews today -- "Require review from +# Code Owners" is intentionally left OFF in branch protection (see +# docs/superpowers/specs/2026-09-05-oss-repo-governance-hardening-design.md, +# "Out of Scope": a single-maintainer repo can't satisfy independent +# code-owner review, so enabling this would either block merges or produce +# meaningless self-review). +# +# This file exists so that turning required review on later (once a second +# qualified maintainer exists, per project-roadmap.md's "Public and +# enterprise governance" section) is a one-line branch-protection change, +# not a design task done under time pressure. + +* @SHcommit From 2b7e0f454daa2a9471fbdab9f0dcd6f2474ecec7 Mon Sep 17 00:00:00 2001 From: shcommit Date: Sun, 6 Sep 2026 00:02:58 +0900 Subject: [PATCH 12/21] feat(adapters): add Cline CLI adapter Cline CLI installs skills via the open Agent Skills standard (SKILL.md), so the adapter is README-only - no manifest. Documents `cline skill add SHcommit/ADR-toolkit` plus a manual symlink fallback. Manually verified against Cline CLI 3.0.61: discovery, install, and the installed script layer (preflight/init/validate) all return ok:true. Closes #19 --- .gitignore | 1 + README.md | 1 + adapters/cline/README.md | 116 +++++++++++++++++++++++++++++++ changelog.md | 5 ++ handoff.md | 15 +++- tests/unit/test_cline_adapter.py | 37 ++++++++++ tests/unit/test_readme.py | 6 ++ 7 files changed, 179 insertions(+), 2 deletions(-) create mode 100644 adapters/cline/README.md create mode 100644 tests/unit/test_cline_adapter.py diff --git a/.gitignore b/.gitignore index e01e0c9..edc00a8 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,7 @@ env/ adapters/codex/skills/adr-toolkit adapters/gemini-cli/skills/adr-toolkit adapters/antigravity/skills/adr-toolkit +.cline/skills/adr-toolkit # Task-by-task implementation plans (superpowers subagent-driven-development # artifacts) — kept locally for reference, not part of the public tree. diff --git a/README.md b/README.md index f70893a..f2fa9a7 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,7 @@ of these adapters at it: | [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) | +| [Cline CLI](adapters/cline/) | Open Agent Skills (no manifest) | [`adapters/cline/README.md`](adapters/cline/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 diff --git a/adapters/cline/README.md b/adapters/cline/README.md new file mode 100644 index 0000000..5c6cb34 --- /dev/null +++ b/adapters/cline/README.md @@ -0,0 +1,116 @@ +# Cline CLI adapter + +Cline CLI installs skills through the **open Agent Skills** standard — the same +`SKILL.md` + `skills/` convention this toolkit already ships — rather than a +harness-specific manifest file like the Codex, Gemini, and Antigravity adapters +use. There is no `plugin.json`/`gemini-extension.json` equivalent for Cline +skills, so this adapter is **README-only** (like `adapters/generic/`): it +documents how to point Cline at the existing `skills/adr-toolkit/` package. +**Manually verified against Cline CLI 3.0.61** (`cline --version`): discovery, +install, and the installed script layer all work — see "Verification status" +below. + +Cline CLI exposes a `skill` subcommand that forwards to the open skills CLI +(`npx skills`), and it discovers skills from the standard agent locations +(`~/.agents/skills/` globally, `.cline/skills/` per project). Because +`skills/adr-toolkit/SKILL.md` already carries the two fields Cline requires — +`name` matching its directory and `description` (under 1024 characters) — the +package installs as-is with no wrapper. + +## Install + +### From the published repository (recommended) + +The repository is public, so Cline installs the skill straight from GitHub: + +```bash +cline skill add SHcommit/ADR-toolkit --global +``` + +Add `-y`/`--yes` to skip the confirmation prompt. Drop `--global` to install +project-level (into the current project's `.cline/skills/`) instead of globally. + +### From a local clone + +A local checkout works the same way: + +```bash +cline skill add "$(pwd)/skills/adr-toolkit" --global +``` + +or symlink the package into Cline's skill directory yourself: + +```bash +# project-level +mkdir -p .cline/skills +ln -s "$(pwd)/skills/adr-toolkit" .cline/skills/adr-toolkit + +# global +mkdir -p ~/.agents/skills +ln -s "$(pwd)/skills/adr-toolkit" ~/.agents/skills/adr-toolkit +``` + +The symlink is created at install time, not committed to any repo — committing a +real symlink breaks on Windows checkouts that don't have `core.symlinks` enabled, +which this project's CI can't assume. + +### Confirm + +```bash +cline skill list +``` + +should list `adr-toolkit`. + +### Script-layer fallback + +Either way, run +`python skills/adr-toolkit/scripts/adr.py preflight --json` from your target +repository to confirm the script layer works standalone — this is the verified +working path regardless of skill-discovery status. + +## Why there's no manifest here + +Cline's "plugin" mechanism (`cline plugin install`, driven by a `package.json` +`cline` field) is for **TypeScript `AgentPlugin` modules** that register tools +and lifecycle hooks — a different extension point from a skill. ADR Toolkit is a +Python skill, so a TS plugin wrapper would be a rewrite with no benefit. The +always-on-hook use case (auto-running `check` on session start) is deliberately +out of scope — see `project-roadmap.md`'s "Harness parity" note. + +## Verification status + +Manually verified against Cline CLI 3.0.61 (`cline --version`) in an isolated +`HOME=$(mktemp -d)` so no state was written to the real `~/.cline`/`~/.agents`. + +``` +$ cline skill add SHcommit/ADR-toolkit --list +... +◇ Found 1 skill +│ adr-toolkit +│ Initialize, record, and check Architecture Decision Records by inspecting the repository and existing decisions before asking questions. + +$ cline skill add SHcommit/ADR-toolkit --yes --global +... +◇ Installed 1 skill +│ ✓ adr-toolkit (copied) +│ → ~/.agents/skills/adr-toolkit +``` + +The installed snapshot lands under `~/.agents/skills/adr-toolkit/` and carries +the whole `skills/adr-toolkit/` package. The script layer was run directly out of +it against a scratch git repository, producing correct `"ok": true` output for +`preflight`, `init --dir docs/decisions`, and `validate --dir docs/decisions` — +matching the Codex, Gemini CLI, and Antigravity adapters' verified depth. + +Two details worth knowing: + +- **The install location is `~/.agents/skills/`, not `~/.cline/...`.** The + skills CLI reports `~/.agents/skills/adr-toolkit` as the install path (the open + Agent Skills global directory Cline reads), even though Cline's CLI reference + mentions a `~/.cline/data/settings/skills/` global directory. Trust + `cline skill list` for where a given Cline version actually looks. +- **A project's own `skills/` directory is auto-detected.** Running + `cline skill list` inside this repository reports `adr-toolkit` from + `./skills/adr-toolkit` as a project skill, so a checkout of this repo is already + a working Cline project skill with no install step. diff --git a/changelog.md b/changelog.md index 32d6da8..8aaa2eb 100644 --- a/changelog.md +++ b/changelog.md @@ -4,6 +4,11 @@ Lightweight human-readable summary of meaningful repository changes. ## Unreleased +- 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 — documenting `cline skill add SHcommit/ADR-toolkit` plus a manual + 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. ## v0.3.2 (2026-09-02) diff --git a/handoff.md b/handoff.md index 58ab750..90f776e 100644 --- a/handoff.md +++ b/handoff.md @@ -2,7 +2,12 @@ ## Current task -Expanded `improvements.md` with High and Medium backlog items covering ReDoS cross-platform safety, 2-phase atomic transaction rollback, ADR overlap/similarity Eval infrastructure, weekly maintenance automation, PR significance bot, frontmatter auto-linter, interactive graph visualization, and code drift detection. +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. ## Scope @@ -17,7 +22,13 @@ Expanded `improvements.md` with High and Medium backlog items covering ReDoS cro ## Next step (for a new session picking this up cold) -Review the newly expanded `improvements.md` High/Medium items and pick an implementation candidate (e.g. `adr lint --fix` or ReDoS cross-platform guard). +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). 1. `improvements.md`'s `### Low` → audit-report sub-group has exactly 1 diff --git a/tests/unit/test_cline_adapter.py b/tests/unit/test_cline_adapter.py new file mode 100644 index 0000000..b24cecc --- /dev/null +++ b/tests/unit/test_cline_adapter.py @@ -0,0 +1,37 @@ +from pathlib import Path + +REPO_ROOT = Path(__file__).resolve().parent.parent.parent +CLINE_README = REPO_ROOT / "adapters" / "cline" / "README.md" +SKILL_MD = REPO_ROOT / "skills" / "adr-toolkit" / "SKILL.md" + + +def test_cline_adapter_readme_exists_and_documents_install(): + text = CLINE_README.read_text(encoding="utf-8") + assert "cline skill add" in text + assert "skills/adr-toolkit" in text + assert "SKILL.md" in text + + +def test_cline_adapter_documents_skill_discovery_locations(): + text = CLINE_README.read_text(encoding="utf-8") + assert ".cline/skills" in text + assert "~/.agents/skills" in text + + +def test_skill_frontmatter_satisfies_cline_requirements(): + # Cline requires `name` to match its directory and `description` (< 1024 + # chars). The canonical package already carries both, so no adapter-local + # manifest is needed for the Cline adapter. + text = SKILL_MD.read_text(encoding="utf-8") + assert "name: adr-toolkit" in text + assert SKILL_MD.parent.name == "adr-toolkit" + # Extract the description line from the YAML frontmatter and confirm it is + # present and under Cline's documented 1024-character limit. + lines = text.splitlines() + desc_lines = [ + line[len("description:"):].strip() + for line in lines + if line.startswith("description:") + ] + assert len(desc_lines) == 1 + assert 0 < len(desc_lines[0]) < 1024 diff --git a/tests/unit/test_readme.py b/tests/unit/test_readme.py index ee53c39..b211b73 100644 --- a/tests/unit/test_readme.py +++ b/tests/unit/test_readme.py @@ -33,3 +33,9 @@ def test_readme_documents_harness_adapters_including_antigravity(): assert "[Antigravity CLI](adapters/antigravity/)" in text assert "adapters/antigravity/README.md" in text + +def test_readme_documents_cline_cli_adapter(): + text = README.read_text(encoding="utf-8") + assert "[Cline CLI](adapters/cline/)" in text + assert "adapters/cline/README.md" in text + From 03e72c57168a1f5bda0f0f9bdf30b20ad6f9c939 Mon Sep 17 00:00:00 2001 From: shcommit Date: Sun, 6 Sep 2026 00:04:06 +0900 Subject: [PATCH 13/21] docs: correct stale 'still private' framing now that the repo is public The public transition happened 2026-08-29 with v1.0.0/v1.0.1 already released, but branch protection was never applied -- update the docs to reflect actual re-verified state instead of the old plan. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01TAZPZwzSutmru6kSCEogu6 --- docs/enterprise-adoption.md | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/docs/enterprise-adoption.md b/docs/enterprise-adoption.md index 0086ac5..78652ff 100644 --- a/docs/enterprise-adoption.md +++ b/docs/enterprise-adoption.md @@ -62,8 +62,10 @@ CI 통과는 구조화된 정책의 증거일 뿐, 결정의 사업적 타당성 ## 4. 공개 저장소 전환 Gate -사용자가 계획한 public 전환 직후 다음 repository ruleset을 적용하고 API로 실제 -상태를 재조회한다. +저장소는 2026-08-29부터 public이다. 아래 repository ruleset은 이미 적용 +대상이며, 적용 후 API로 실제 상태를 재조회해 확인한다 (2026-09-05 확인 결과 +`master`/`develop` 모두 branch protection이 없는 상태 -- 이 문서 §9 "Public" +단계 완료 조건이 아직 충족되지 않았다). | 대상 | 권장 통제 | 도입 이유 | | --- | --- | --- | @@ -167,8 +169,13 @@ Toolkit 자체에 계정 시스템을 서둘러 넣기보다 GitHub의 인증· 1. ~~ADR directory 로딩을 공통 iterator로 통합해~~ **완료 (2026-08-30).** `core.adr_directory.iter_adr_files`로 validate/index/related/CHECK를 통합했고 각 명령의 warning 의미는 그대로 유지했다. -2. public 전환 시 PR template과 CONTRIBUTING/SECURITY 문서를 만들고 ruleset 적용을 - 자동 검증한다. **저장소가 아직 private이라 시작 조건이 충족되지 않았다.** +2. PR template과 CONTRIBUTING/SECURITY 문서를 만들고 ruleset 적용을 자동 + 검증한다. **전제조건 충족 (2026-08-29 public 전환, v1.0.0/v1.0.1 릴리스 + 완료). PR template/CONTRIBUTING/SECURITY는 이미 존재하며, 남은 것은 + ruleset 적용과 API 재검증뿐이다 -- 코드 작업이 아니라 GitHub Settings/API + 작업이므로 + `docs/superpowers/specs/2026-09-05-oss-repo-governance-hardening-design.md`의 + GitHub UI/API 설정 안내를 따른다.** 3. ~~CHECK 결과를 `VERIFIED`, `VIOLATED`, `NOT_APPLICABLE`, `UNVERIFIABLE`의 안정된 machine-readable contract로 승격한다.~~ **완료 (2026-08-30).** 모든 finding이 기존 `kind` 값과 별개로 `confidence` 필드를 직접 갖는다 @@ -202,7 +209,7 @@ Toolkit 자체에 계정 시스템을 서둘러 넣기보다 GitHub의 인증· | 단계 | 완료 조건 | | --- | --- | | v0.2.0 | P0 전체 통과, 최종 PR CI, 승인된 version bump와 release 절차 | -| Public | `master`/`develop`/`v*` ruleset API 검증, PR template, CONTRIBUTING, SECURITY | +| Public | `master`/`develop`/`v*` ruleset API 검증 (미완료, 2026-09-05 기준 branch protection 없음), PR template (완료), CONTRIBUTING (완료), SECURITY (완료) | | Team | 2명 이상 qualified maintainer, CODEOWNERS 독립 승인, 예외 owner/expiry | | Enterprise | 조직 ruleset·reusable workflow, audit export, taxonomy, 정의된 adoption metrics | | Multi-repo | 반복된 탐색 실패와 운영 요구를 근거로 registry/portal 도입 | From f17cc2abf6a1fb198bc7dfd025e1fe6895200e1f Mon Sep 17 00:00:00 2001 From: shcommit Date: Sun, 6 Sep 2026 00:07:48 +0900 Subject: [PATCH 14/21] =?UTF-8?q?docs:=20reconcile=20=C2=A72=20confirmed-f?= =?UTF-8?q?acts=20with=20the=20public-transition=20correction?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit §4/§8/§9 already state the repo has been public since 2026-08-29 with branch protection still missing; §2's "확인된 사실" bullets still said the repo "is private" and that PR template doesn't exist, directly contradicting those sections. The missing-branch-protection fact itself was still accurate and is kept -- only the private-repo framing and the now-false "no PR template" claim needed correcting. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01TAZPZwzSutmru6kSCEogu6 --- docs/enterprise-adoption.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/enterprise-adoption.md b/docs/enterprise-adoption.md index 78652ff..41698e0 100644 --- a/docs/enterprise-adoption.md +++ b/docs/enterprise-adoption.md @@ -23,11 +23,14 @@ ADR Toolkit의 강점은 AI가 초안과 언어 표현을 돕더라도 repositor ### 확인된 사실 -- 저장소는 private이며 `master`와 `develop` 보호 규칙 및 repository ruleset이 없다. -- 현재 플랜에서는 private 저장소 protection API가 활성화되지 않는다. +- 저장소는 2026-08-29부터 public이며, `master`/`develop` 보호 규칙과 repository + ruleset은 2026-09-05 API 재확인 기준으로 여전히 없다. +- 이는 plan 제약이 아니라 public 전환 이후 아직 적용하지 않은 설정 작업이다 + (§4 공개 저장소 전환 Gate, §9 단계별 완료 조건 참고). - CI는 Ubuntu, macOS, Windows와 지원 Python 조합에서 동작한다. - 첫 PR은 모든 CI를 통과했지만 독립 review 없이 병합됐다. -- CODEOWNERS와 PR template이 없다. +- PR template은 있지만, CODEOWNERS는 활성화되지 않은 dormant draft뿐이다 + (독립 승인 가능한 qualified maintainer가 2명 이상이 되기 전까지 미활성). - 코어는 locale, ID, lifecycle, schema, relationship, index, CHECK의 repository state를 결정론적으로 검증한다. - 중앙 서비스, 사용자 계정, 조직 RBAC, audit export, telemetry는 없다. From 34c4c05570d92f97329f96bc2e5d1a7ec8fd1824 Mon Sep 17 00:00:00 2001 From: shcommit Date: Sun, 6 Sep 2026 00:37:33 +0900 Subject: [PATCH 15/21] fix(github): close governance hardening review gaps --- .github/ISSUE_TEMPLATE/bug_report.yml | 1 + .github/dependabot.yml | 2 + .github/labeler.yml | 10 +- .github/labels.yml | 2 +- .github/workflows/labeler.yml | 7 +- .github/workflows/labels.yml | 1 - .github/workflows/release.yml | 13 +- .github/workflows/test.yml | 27 ++- SECURITY.md | 17 +- changelog.md | 17 ++ docs/enterprise-adoption.md | 34 +-- docs/oss-repository-governance-audit.md | 225 ++++++++++++++++++ ...05-oss-repo-governance-hardening-design.md | 97 ++++---- handoff.md | 73 ++++-- improvements.md | 4 + project-roadmap.md | 15 +- pyproject.toml | 3 + scripts/export_dev_requirements.py | 31 +++ tests/unit/test_github_governance.py | 102 ++++++++ 19 files changed, 553 insertions(+), 128 deletions(-) create mode 100644 docs/oss-repository-governance-audit.md create mode 100644 scripts/export_dev_requirements.py create mode 100644 tests/unit/test_github_governance.py diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 891306e..63b8d73 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -32,6 +32,7 @@ body: - Codex CLI - Gemini CLI - Antigravity CLI + - Cline CLI - Direct CLI (pip install / python script) - Other (specify in Additional context) validations: diff --git a/.github/dependabot.yml b/.github/dependabot.yml index ade07ae..aac4144 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -2,6 +2,7 @@ version: 2 updates: - package-ecosystem: "pip" directory: "/" + target-branch: "develop" schedule: interval: "weekly" groups: @@ -12,6 +13,7 @@ updates: - package-ecosystem: "github-actions" directory: "/" + target-branch: "develop" schedule: interval: "weekly" groups: diff --git a/.github/labeler.yml b/.github/labeler.yml index c98869c..b96970c 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -1,9 +1,17 @@ "area:core": - changed-files: - any-glob-to-any-file: - - "skills/adr-toolkit/scripts/**" + - "skills/adr-toolkit/scripts/core/**" + - "skills/adr-toolkit/scripts/evidence/**" + - "skills/adr-toolkit/scripts/rules/**" - "scripts/**" +"area:cli": + - changed-files: + - any-glob-to-any-file: + - "skills/adr-toolkit/scripts/adr.py" + - "skills/adr-toolkit/scripts/commands/**" + "area:adapter": - changed-files: - any-glob-to-any-file: diff --git a/.github/labels.yml b/.github/labels.yml index f21259e..5d18388 100644 --- a/.github/labels.yml +++ b/.github/labels.yml @@ -29,7 +29,7 @@ description: "adr.py entrypoint and command wiring" - name: "area:adapter" color: "5319e7" - description: "adapters/** harness adapters (Claude, Codex, Gemini, Antigravity)" + description: "adapters/** and .claude-plugin/** harness integrations" - name: "area:github" color: "5319e7" description: ".github/** workflows, templates, and repo automation" diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index 02f2074..114baac 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -8,12 +8,13 @@ on: permissions: contents: read - pull-requests: write - issues: write jobs: label-pr: if: github.event_name == 'pull_request_target' + permissions: + contents: read + pull-requests: write runs-on: ubuntu-latest steps: - uses: actions/labeler@v7 @@ -23,6 +24,8 @@ jobs: triage-issue: if: github.event_name == 'issues' + permissions: + issues: write runs-on: ubuntu-latest steps: - uses: actions/github-script@v7 diff --git a/.github/workflows/labels.yml b/.github/workflows/labels.yml index cd77ff4..c5e2640 100644 --- a/.github/workflows/labels.yml +++ b/.github/workflows/labels.yml @@ -9,7 +9,6 @@ on: permissions: contents: read issues: write - pull-requests: write jobs: sync: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index cac8552..f8ca0d2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -27,12 +27,12 @@ jobs: id-token: write attestations: write steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: python-version: "3.12" - name: Install dependencies - run: pip install pytest build + run: pip install -e ".[dev]" - name: Run tests run: python -m pytest tests/unit tests/integration -v - name: Check manifest versions are in sync @@ -54,11 +54,11 @@ jobs: run: python -m build - name: Generate build provenance attestation if: ${{ !github.event.repository.private }} - uses: actions/attest-build-provenance@v2 + uses: actions/attest-build-provenance@e8998f949152b193b063cb0ec769d69d929409be # v2 with: subject-path: ${{ steps.package.outputs.archive }} - name: Create GitHub Release - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2 with: generate_release_notes: true files: | @@ -68,9 +68,8 @@ jobs: dist/*.tar.gz - name: Publish Python Package to PyPI if: ${{ !github.event.repository.private }} - uses: pypa/gh-action-pypi-publish@release/v1 + uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1 continue-on-error: true with: skip-existing: true - diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 19c0952..664ef19 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -68,18 +68,17 @@ jobs: python-version: "3.12" - name: Upgrade pip (fixes known pip CVEs before auditing anything else) run: python -m pip install --upgrade pip + - name: Export pinned dev requirements + run: python scripts/export_dev_requirements.py > "$RUNNER_TEMP/adr-dev-requirements.txt" - name: Install pinned dev tools (not the project itself) - # KEEP IN SYNC with pyproject.toml's [project.optional-dependencies].dev -- - # this job can't use `pip install -e ".[dev]"` (see below), so these - # versions are a manual copy Dependabot won't update here. # Deliberately skips `pip install -e .`: adr-toolkit isn't - # published to PyPI (confirmed 404 on pypi.org/pypi/adr-toolkit/json), + # audited as a third-party dependency, # so pip-audit can never resolve it there, and --skip-editable # can't be combined with --strict (pip-audit treats every skipped # dependency as fatal under --strict, unconditionally -- see # pip_audit/_cli.py). This job audits the pinned dev toolchain, # not this project's own unpublished package. - run: pip install pytest==9.1.1 pytest-cov==7.1.0 mypy==1.19.1 ruff==0.16.6 + run: pip install -r "$RUNNER_TEMP/adr-dev-requirements.txt" - name: Install pip-audit run: pip install pip-audit==2.9.0 - name: Audit installed dev dependencies for known vulnerabilities @@ -110,8 +109,10 @@ jobs: runs-on: ubuntu-latest steps: - name: Validate PR Title Conventional Commits Format + env: + PR_TITLE: ${{ github.event.pull_request.title }} run: | - TITLE="${{ github.event.pull_request.title }}" + TITLE="$PR_TITLE" echo "Checking PR Title: $TITLE" REGEX="^(feat|fix|docs|style|refactor|perf|test|chore|ci)(\([a-z0-9-]+\))?!?: .+" if [[ ! "$TITLE" =~ $REGEX ]]; then @@ -142,8 +143,18 @@ 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: Install pinned Antigravity CLI artifact + run: | + set -euo pipefail + ARCHIVE="$RUNNER_TEMP/antigravity-cli-1.1.27-linux-x64.tar.gz" + curl --proto '=https' --tlsv1.2 -fsSL \ + https://storage.googleapis.com/antigravity-public/antigravity-cli/1.1.27-5211191891591168/linux-x64/cli_linux_x64.tar.gz \ + -o "$ARCHIVE" + printf '%s %s\n' \ + '793d4b9ea2c08d9a7e50bafa02cfc8c19424bd60d6e83f91408d45f9c6d4ce79a5d576fede5bef164d823abf84f81359a14b4ca665952c47b0a7cfd743bb69c0' \ + "$ARCHIVE" | sha512sum --check - + tar -xzf "$ARCHIVE" -C "$RUNNER_TEMP" antigravity + install -D -m 0755 "$RUNNER_TEMP/antigravity" "$HOME/.local/bin/agy" - name: Verify Codex CLI adapter end to end run: | set -euo pipefail diff --git a/SECURITY.md b/SECURITY.md index d4d34a4..fe55430 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -6,8 +6,9 @@ Security fixes target the latest released version of ADR Toolkit. ## Reporting a Vulnerability -Please report security issues privately to the repository owner before opening a -public issue. Include: +Please use GitHub's private vulnerability reporting form at + instead of +opening a public issue. Include: - affected version or commit - reproduction steps @@ -29,13 +30,10 @@ signature -- no private key is held or rotated by this project -- proving the archive was produced by this repository's own CI, from the exact commit the release tag points to. -**While this repository is private, attestation is not generated** -- -GitHub's attestation API rejects it for a user-owned private repository. -The release workflow skips that step automatically and still publishes -the archive and its checksum; attestation starts appearing on releases -once the repository goes public, with no workflow change required. Check -a given release's assets on the Releases page to see whether an -attestation is available for it. +The repository has been public since 2026-08-29, so current releases are +eligible for attestation. The workflow keeps a private-repository guard only +so forks or future visibility changes fail safely; check a given release's +assets to confirm that its attestation was actually published. To verify a downloaded archive: @@ -45,7 +43,6 @@ sha256sum -c adr-toolkit-skill-vX.Y.Z.tar.gz.sha256 # Provenance: confirms the archive was actually built by this repo's CI, # not a look-alike release from a compromised account or a different repo. -# Only available once this repository is public -- see the note above. gh attestation verify adr-toolkit-skill-vX.Y.Z.tar.gz -R SHcommit/ADR-toolkit ``` diff --git a/changelog.md b/changelog.md index 15f4133..a20e5ac 100644 --- a/changelog.md +++ b/changelog.md @@ -4,6 +4,23 @@ Lightweight human-readable summary of meaningful repository changes. ## Unreleased +- Added scalable GitHub governance: structured Issue Forms, source-controlled + label taxonomy, path-based PR labels, new-issue triage, weekly grouped + Dependabot updates targeting `develop`, and a dormant CODEOWNERS draft. +- Added ruff and strict dependency-audit CI gates, upgraded the supported + Python floor to 3.10, and added regression tests for repository governance + configuration. +- Hardened CI supply chain behavior: replaced the Antigravity `curl | bash` + installer with a versioned SHA-512-verified artifact, pinned release Actions + to commit SHAs, pinned release build tooling, and removed PR-title shell + expression injection. +- Corrected the governance audit to recognize the already-active repository + branch/tag rulesets through the ruleset APIs rather than treating a classic + branch-protection 404 as proof of no protection. +- Enabled live Discussions, dependency security updates and alerts, secret + scanning with push protection, private vulnerability reporting, and + automatic deletion of merged branches. + ## v1.0.1 (2026-09-02) - Added PyPI packaging support (`pyproject.toml`) for `pip install adr-toolkit` and `pipx install adr-toolkit`. diff --git a/docs/enterprise-adoption.md b/docs/enterprise-adoption.md index 41698e0..e21e9c7 100644 --- a/docs/enterprise-adoption.md +++ b/docs/enterprise-adoption.md @@ -23,10 +23,12 @@ ADR Toolkit의 강점은 AI가 초안과 언어 표현을 돕더라도 repositor ### 확인된 사실 -- 저장소는 2026-08-29부터 public이며, `master`/`develop` 보호 규칙과 repository - ruleset은 2026-09-05 API 재확인 기준으로 여전히 없다. -- 이는 plan 제약이 아니라 public 전환 이후 아직 적용하지 않은 설정 작업이다 - (§4 공개 저장소 전환 Gate, §9 단계별 완료 조건 참고). +- 저장소는 2026-08-29부터 public이며, repository ruleset API 재확인 결과 + `master`/`develop`/`release/*` branch와 `v*` tag 보호 규칙이 2026-09-02부터 + active다 (ruleset IDs `22101891`, `22102322`). +- classic branch-protection API의 404는 ruleset 부재를 의미하지 않는다. 실제 + 적용 여부는 `repos/SHcommit/ADR-toolkit/rules/branches/`와 + `repos/SHcommit/ADR-toolkit/rulesets/`로 검증한다. - CI는 Ubuntu, macOS, Windows와 지원 Python 조합에서 동작한다. - 첫 PR은 모든 CI를 통과했지만 독립 review 없이 병합됐다. - PR template은 있지만, CODEOWNERS는 활성화되지 않은 dormant draft뿐이다 @@ -65,10 +67,12 @@ CI 통과는 구조화된 정책의 증거일 뿐, 결정의 사업적 타당성 ## 4. 공개 저장소 전환 Gate -저장소는 2026-08-29부터 public이다. 아래 repository ruleset은 이미 적용 -대상이며, 적용 후 API로 실제 상태를 재조회해 확인한다 (2026-09-05 확인 결과 -`master`/`develop` 모두 branch protection이 없는 상태 -- 이 문서 §9 "Public" -단계 완료 조건이 아직 충족되지 않았다). +저장소는 2026-08-29부터 public이다. 아래 repository ruleset은 2026-09-02에 +적용됐고 2026-09-06에 ruleset API와 effective-rules API로 재검증했다. Branch +ruleset `22101891`은 PR, required checks, conversation resolution, +force-push/deletion 차단을 적용하며 tag ruleset `22102322`는 `v*` 수정·삭제를 +차단한다. 단, CI matrix가 Python 3.9에서 3.10으로 바뀌므로 이 변경을 merge한 +직후 required-check context도 함께 갱신해야 한다. | 대상 | 권장 통제 | 도입 이유 | | --- | --- | --- | @@ -172,13 +176,11 @@ Toolkit 자체에 계정 시스템을 서둘러 넣기보다 GitHub의 인증· 1. ~~ADR directory 로딩을 공통 iterator로 통합해~~ **완료 (2026-08-30).** `core.adr_directory.iter_adr_files`로 validate/index/related/CHECK를 통합했고 각 명령의 warning 의미는 그대로 유지했다. -2. PR template과 CONTRIBUTING/SECURITY 문서를 만들고 ruleset 적용을 자동 - 검증한다. **전제조건 충족 (2026-08-29 public 전환, v1.0.0/v1.0.1 릴리스 - 완료). PR template/CONTRIBUTING/SECURITY는 이미 존재하며, 남은 것은 - ruleset 적용과 API 재검증뿐이다 -- 코드 작업이 아니라 GitHub Settings/API - 작업이므로 - `docs/superpowers/specs/2026-09-05-oss-repo-governance-hardening-design.md`의 - GitHub UI/API 설정 안내를 따른다.** +2. ~~PR template과 CONTRIBUTING/SECURITY 문서를 만들고 ruleset 적용을 자동 + 검증한다.~~ **완료 (2026-09-06 재검증).** PR template, + CONTRIBUTING/SECURITY가 존재하고 branch/tag ruleset의 effective rules를 API로 + 확인했다. CI job 이름이 바뀌면 required-check context도 같은 변경의 rollout + 절차에서 갱신한다. 3. ~~CHECK 결과를 `VERIFIED`, `VIOLATED`, `NOT_APPLICABLE`, `UNVERIFIABLE`의 안정된 machine-readable contract로 승격한다.~~ **완료 (2026-08-30).** 모든 finding이 기존 `kind` 값과 별개로 `confidence` 필드를 직접 갖는다 @@ -212,7 +214,7 @@ Toolkit 자체에 계정 시스템을 서둘러 넣기보다 GitHub의 인증· | 단계 | 완료 조건 | | --- | --- | | v0.2.0 | P0 전체 통과, 최종 PR CI, 승인된 version bump와 release 절차 | -| Public | `master`/`develop`/`v*` ruleset API 검증 (미완료, 2026-09-05 기준 branch protection 없음), PR template (완료), CONTRIBUTING (완료), SECURITY (완료) | +| Public | `master`/`develop`/`release/*`/`v*` ruleset API 검증 (완료, 2026-09-06), PR template (완료), CONTRIBUTING (완료), SECURITY 및 private vulnerability reporting (완료) | | Team | 2명 이상 qualified maintainer, CODEOWNERS 독립 승인, 예외 owner/expiry | | Enterprise | 조직 ruleset·reusable workflow, audit export, taxonomy, 정의된 adoption metrics | | Multi-repo | 반복된 탐색 실패와 운영 요구를 근거로 registry/portal 도입 | diff --git a/docs/oss-repository-governance-audit.md b/docs/oss-repository-governance-audit.md new file mode 100644 index 0000000..b50aea2 --- /dev/null +++ b/docs/oss-repository-governance-audit.md @@ -0,0 +1,225 @@ +# OSS Repository Governance Audit + +검증 기준일: 2026-09-06 (Asia/Seoul) + +이 보고서는 파일 존재 여부뿐 아니라 backlog가 수백~수천 건으로 늘어났을 때 +한 명의 maintainer가 반복 분류·보안 점검·merge 통제를 감당할 수 있는지를 +기준으로 작성했다. 로컬 브랜치의 구성과 GitHub API로 조회한 live 설정을 +구분한다. + +## 1. Executive Summary + +ADR Toolkit은 문서, 테스트, release provenance, 다중 플랫폼 CI가 이미 강한 +소형 OSS 저장소다. 이번 hardening으로 label taxonomy, path labeler, +Dependabot, Issue Forms, lint, dependency audit, dormant CODEOWNERS를 추가했고, +live repository에는 Discussions, 보안 알림, 자동 security update, secret +scanning/push protection, private vulnerability reporting을 활성화했다. + +가장 중요한 리뷰 결과는 기존 감사의 전제 오류다. Classic branch-protection +API가 404를 반환했지만 repository ruleset은 2026-09-02부터 active였다. +Ruleset `22101891`은 `master`/`develop`/`release/*`에 PR, required checks, +conversation resolution, deletion/non-fast-forward 차단을 적용하고, ruleset +`22102322`는 `v*` tag 수정·삭제를 차단한다. 실제 남은 위험은 보호 규칙의 +부재가 아니라 CI matrix 변경 후 required-check 이름이 drift하는 것이다. + +현재 운영 수준은 **🟢 성장 가능한 기본 구조, 단 rollout 1단계 필요**로 +평가한다. 이 브랜치를 `develop`에 merge한 직후 ruleset에서 Python 3.9 check를 +3.10 check로 교체하고 `lint`/`dependency-audit`를 required로 추가해야 한다. + +## 2. Repository Audit + +| 영역 | 현재 상태 | 문제 또는 근거 | 우선순위 | +| --- | --- | --- | --- | +| README | 🟢 충분함 | 설치, 기능, scope, 기여 링크 제공 | P2 | +| CONTRIBUTING | 🟢 충분함 | Git Flow, local checks, ADR/adapter 규칙 제공 | P2 | +| CODE_OF_CONDUCT | 🟢 충분함 | 행동 기준·신고·집행 범위 명시 | P2 | +| SECURITY | 🟢 충분함 | private advisory 경로, 지원 버전, checksum/attestation 검증 제공 | P1 | +| LICENSE | 🟢 충분함 | MIT license 존재 | P2 | +| CHANGELOG | 🟢 충분함 | `Unreleased`와 release별 human-readable 기록 | P2 | +| Roadmap | 🟢 충분함 | trigger 기반 deferred work와 완료 항목 구분 | P2 | +| ADR / architecture docs | 🟢 충분함 | `docs/decisions/`와 설계·감사 문서 존재 | P2 | +| Issue templates | 🟢 충분함 | bug/feature Issue Forms와 blank issue 차단 | P1 | +| PR template | 🟢 충분함 | Conventional title, ADR/example 영향 확인 | P1 | +| Labels | 🟢 충분함 | 25개 source taxonomy 중 type/area/priority/size/workflow 20개를 live sync 완료 | P1 | +| GitHub Projects | 🟡 개선 필요 | 기능은 enabled지만 Project 없음; open issue 0개라 지금 생성은 과함 | NEXT | +| Milestones | 🟡 개선 필요 | milestone 없음; release backlog가 생길 때 도입 | NEXT | +| CODEOWNERS | 🟡 개선 필요 | dormant draft 존재, 1인 maintainer라 required review는 의도적으로 OFF | NEXT | +| Discussions | 🟢 충분함 | live 활성화 및 Q&A category 확인 | P1 | +| Branch/tag ruleset | 🟡 개선 필요 | active/effective 확인; required checks는 아직 Python 3.9 이름을 포함 | P0 rollout | +| Merge 정책 | 🟢 충분함 | PR 강제와 merge 후 short-lived branch 자동 삭제 활성화 | P1 | +| Build | 🟢 충분함 | release에서 wheel/sdist와 skill archive 생성 | P1 | +| Test | 🟢 충분함 | unit+integration 550+ cases | P1 | +| Lint | 🟢 충분함 | ruff E9/F fast gate 추가 | P1 | +| Type check | 🟢 충분함 | 핵심 typed module에 mypy `--strict` | P1 | +| Coverage | 🟢 충분함 | branch coverage 85% floor | P1 | +| Multi-platform | 🟢 충분함 | Linux/macOS/Windows × Python 3.10/3.12 | P1 | +| E2E | 🟢 충분함 | Codex/Gemini/Antigravity adapter install-and-run | P1 | +| Release | 🟡 개선 필요 | direct-tag workflow와 version gate 있음; PyPI publish는 `continue-on-error` | P1 | +| Artifact verification | 🟢 충분함 | SHA-256 release asset과 version/tag drift gate | P1 | +| Provenance / attestation | 🟢 충분함 | public release에 GitHub Artifact Attestation | P1 | +| Changelog requirement | 🟡 개선 필요 | template/process는 있으나 자동 path-based gate 없음 | NEXT | +| Documentation drift | 🟢 충분함 | examples execution/drift gate 제공 | P1 | +| Dependabot | 🟢 충분함 | pip/actions weekly grouped PR, target `develop` | P1 | +| GitHub Actions pinning | 🟡 개선 필요 | write-capable release actions는 SHA pin; read-only CI first-party actions는 major pin | P2 | +| Remote installer | 🟢 충분함 | Antigravity fixed artifact + official SHA-512 verification, `curl | bash` 제거 | P0 | +| Package lock | 🟡 개선 필요 | runtime dependency 0개; dev tools exact pin이라 lock 부재 위험은 제한적 | P2 | +| Dependency/security audit | 🟢 충분함 | `pip-audit --strict`, alerts/security updates/secret scanning enabled | P1 | + +## 3. NOW + +- 완료: `.github/labels.yml`과 live label taxonomy 동기화. +- 완료: changed path 기반 PR labeler와 new issue `needs-triage` 적용. +- 완료: structured Issue Forms와 Discussions/Q&A 경로. +- 완료: pip/GitHub Actions Dependabot을 weekly grouped update로 구성하고 + `develop`을 target branch로 고정. +- 완료: ruff lint와 `pip-audit --strict` CI gate. +- 완료: Antigravity CI installer를 versioned artifact + SHA-512 검증으로 교체. +- 완료: release workflow dependency pin 및 write-capable workflow Action SHA pin. +- 완료: vulnerability alerts, automated security fixes, secret scanning, + push protection, private vulnerability reporting 활성화. +- rollout 직후: ruleset required contexts에서 Python 3.9 두 개를 제거하고 + Python 3.10 세 개, `lint`, `dependency-audit`를 추가. + +## 4. NEXT + +- Issue가 약 20~30개 이상 지속되거나 동시에 진행 중인 work item이 10개를 + 넘으면 Project를 만든다. +- 2명 이상의 qualified maintainer가 생기면 dormant CODEOWNERS를 영역별로 + 분리하고 code-owner review를 required로 전환한다. +- PR queue가 10개 이상 지속될 때 `size:XS`~`size:XL` 자동 분류를 추가한다. +- release 목표 issue가 5개 이상 모이면 milestone을 source of truth로 쓴다. +- ruleset check-context drift가 다시 발생하면 settings verification script나 + Terraform/GitHub provider 기반 ruleset-as-code를 도입한다. + +권장 수동 size 기준은 XS 10 LOC 이하, S 50 이하, M 200 이하, L 500 이하, +XL 500 초과다. Generated file, security-sensitive workflow, schema 변경은 LOC와 +무관하게 한 단계 상향할 수 있다. + +## 5. LATER + +- stale bot: abandoned backlog가 실제로 누적된 뒤에만 도입한다. 기준은 + 90일 inactive → stale, 추가 30일 → close이며 `security`, `pinned`, + `roadmap`, `help wanted`, `priority:P0`, `blocked`는 제외한다. +- organization ruleset/reusable workflow/RBAC/audit export: 동일 운영을 + 반복하는 repository가 2개 이상일 때 도입한다. +- ML triage, automatic assignment, 복잡한 release train은 현재 도입하지 않는다. + +## 6. Security / Supply Chain Findings + +1. **해결 — remote code execution:** `curl install.sh | bash`가 실제 PR CI에서 + 실행되고 있었다. 공식 manifest가 가리킨 Antigravity CLI `1.1.27` Linux + artifact URL과 SHA-512를 고정해 다운로드·검증·설치 단계로 분리했다. +2. **해결 — release mutability:** `release.yml`의 Action ref를 현재 commit SHA로 + 고정하고 version comment를 남겼다. Python build/test tool도 dev extra pin을 + 사용한다. +3. **해결 — dependency visibility:** Dependabot security updates와 alerts, + `pip-audit --strict`, secret scanning/push protection을 활성화했다. +4. **해결 — PR title command injection:** untrusted PR title expression을 inline + shell 문자열에 삽입하지 않고 step environment로 전달하도록 변경했다. +5. **남음 — partial release:** PyPI publish가 `continue-on-error: true`라 GitHub + Release 성공과 PyPI 실패가 동시에 가능하다. Trusted Publisher 안정성이 + 확인되면 fail-closed 전환을 검토한다. +6. **수용 — read-only CI Action tags:** 일반 test/labeler의 GitHub-owned Actions는 + major tag를 사용한다. Release처럼 write 권한을 갖는 경로는 SHA pin을 적용했다. + +## 7. 추가/수정 파일 + +```text +.github/ +├── CODEOWNERS +├── dependabot.yml +├── labeler.yml +├── labels.yml +├── ISSUE_TEMPLATE/ +│ ├── bug_report.yml +│ ├── feature_request.yml +│ └── config.yml +└── workflows/ + ├── labeler.yml + ├── labels.yml + ├── release.yml + └── test.yml +scripts/ +└── export_dev_requirements.py +tests/unit/ +└── test_github_governance.py +``` + +각 파일의 실행 가능한 실제 내용은 위 경로 자체가 source of truth다. 추가로 +`pyproject.toml`, `SECURITY.md`, `project-roadmap.md`, +`docs/enterprise-adoption.md`, 본 설계 문서를 현재 운영 상태에 맞게 수정했다. + +## 8. GitHub UI 설정 + +API로 확인/적용한 live 상태: + +- Discussions: enabled. +- Repository Projects: enabled, Project instance는 없음. +- Dependabot security updates: enabled. +- Vulnerability alerts: enabled. +- Secret scanning / push protection: enabled. +- Private vulnerability reporting: enabled. +- Delete branch on merge: enabled. +- Branch ruleset `22101891`: active, bypass actor 없음. +- Tag ruleset `22102322`: active, bypass actor 없음. + +이 브랜치 merge 직후 Settings → Rules → Rulesets에서 `protected-branches`의 +required checks를 다음과 같이 맞춘다. + +```text +remove: pytest (ubuntu-latest, 3.9) +remove: pytest (windows-latest, 3.9) +add: pytest (ubuntu-latest, 3.10) +add: pytest (macos-latest, 3.10) +add: pytest (windows-latest, 3.10) +add: lint +add: dependency-audit +keep: all Python 3.12 checks, type-check, version-drift, + examples-drift, pr-title-check, harness-parity +``` + +Required approving review count와 code-owner review는 maintainer가 1명인 동안 +0/OFF를 유지한다. Signed commits도 현재는 요구하지 않는다. + +## 9. Issue Backlog 후보 + +| 후보 | 출처 | 추천 labels | 크기 | +| --- | --- | --- | --- | +| `adapters/README.md`에 “새 harness adapter 추가하기” tutorial 작성 | `docs/adr-toolkit-audit-report.md` §2.6 | `type:docs`, `area:adapter`, `good first issue` | S | +| harness parity를 `check/search/graph/create`까지 확장 | `project-roadmap.md` Harness parity | `type:test`, `area:adapter`, `help wanted` | M | +| 실제 사용자 피드백 후 Traditional Chinese `zh-TW` catalog 검토 | `project-roadmap.md` Internationalization | `type:feature`, `area:core`, `help wanted` | M | +| Accepted ADR metadata factual-correction policy 설계 | `project-roadmap.md` Lifecycle research | `type:docs`, `area:docs`, `priority:P2` | M | +| ruleset required-check drift 자동 검증 | 이번 감사의 재발 방지 항목 | `type:test`, `area:github`, `priority:P1` | S | + +첫 good-first issue는 문서 tutorial이 가장 적합하다. Product behavior를 바꾸지 +않고 기존 adapter를 비교해 명확한 acceptance criteria를 만들 수 있다. + +## 10. 최종 목표 구조 + +```text +Idea + ↓ +Issue Form / Discussion + ↓ +Auto Triage / Label + ↓ +Issue backlog (Project는 규모 trigger 충족 시) + ↓ +Contributor + ↓ +Pull Request + ↓ +Automated Quality Gates + ↓ +Review + conversation resolution + ↓ +Merge to develop + ↓ +Release branch → master → v* tag + ↓ +Attestation / checksum / dependency & security maintenance +``` + +목표는 자동화 개수가 아니라 maintainer 판단이 필요한 우선순위·설계·review만 +사람에게 남기고, 입력 구조화·경로 분류·반복 검증·dependency 감시는 GitHub와 +CI가 수행하게 하는 것이다. diff --git a/docs/superpowers/specs/2026-09-05-oss-repo-governance-hardening-design.md b/docs/superpowers/specs/2026-09-05-oss-repo-governance-hardening-design.md index 39a119b..7816049 100644 --- a/docs/superpowers/specs/2026-09-05-oss-repo-governance-hardening-design.md +++ b/docs/superpowers/specs/2026-09-05-oss-repo-governance-hardening-design.md @@ -12,21 +12,28 @@ product code, CLI behavior, or `docs/decisions/` governance model. ## Context — audit findings as of 2026-09-05 +> **2026-09-06 review correction:** the original audit queried only the +> classic branch-protection endpoint. A 404 from that endpoint does not prove +> repository rulesets are absent. Ruleset and effective-rules APIs show that +> active branch/tag rulesets have existed since 2026-09-02 (IDs `22101891` +> and `22102322`). The original audit also incorrectly described the +> Antigravity adapter as manual-only even though `harness-parity` executed its +> remote bootstrapper. The decisions below are corrected accordingly. + Re-verified against the live repository (`gh api`/`gh repo view`), not just -file presence, because `docs/enterprise-adoption.md` §4/§8 and -`improvements.md`'s "Low" backlog describe this repo as still private with a -single precondition ("저장소 public 전환") blocking the public-readiness gate. -That precondition has already been met and those documents are now stale: +file presence, because `docs/enterprise-adoption.md` §4/§8 described this repo +as still private with a single precondition ("저장소 public 전환") blocking the +public-readiness gate. That precondition had already been met and the document +was stale: - The repository has been **public since 2026-08-29**, and `master` has already shipped `v1.0.0` and `v1.0.1` (PyPI publishing pipeline, antigravity harness-parity CI, a Windows lock-metadata fix, mypy `--strict` fix). -- Despite being public, `master` has **zero branch protection** - (`gh api repos/.../branches/master/protection` → `404 Branch not - protected`). `develop` is unprotected too. `docs/enterprise-adoption.md` - §9's "Public" stage completion condition ("ruleset API 검증") is therefore - **not actually satisfied**, even though the PR template, `CONTRIBUTING.md`, - and `SECURITY.md` pieces of that same stage are done. +- Active repository rulesets protect `master`, `develop`, `release/*`, and + `v*` tags. They require PRs, status checks, conversation resolution, and + prohibit deletion/non-fast-forward updates without a bypass actor. The + remaining rollout concern is keeping required-check contexts synchronized + with CI matrix changes (this branch replaces Python 3.9 with 3.10). - `develop` was frozen at the `v0.3.2` sync point while `master` advanced through the `v1.0.0`/`v1.0.1` releases — the git-flow-mandated release-branch back-merge into `develop` never happened. **Fixed as a @@ -49,9 +56,8 @@ That precondition has already been met and those documents are now stale: scan step. - `harness-parity` contains one remote-installer pattern the request asked to scrutinize: `curl -fsSL https://antigravity.google/cli/install.sh | bash`. - (Antigravity itself is manually verified only, per - `adapters/antigravity/README.md` — this curl step doesn't currently run in - CI for that adapter.) + This does run in CI before the Antigravity end-to-end adapter verification, + so it must be replaced with a versioned artifact plus checksum verification. - GitHub Actions are pinned to major-version tags from verified publishers (`actions/*@v4/@v5`, `softprops/action-gh-release@v2`, `pypa/gh-action-pypi-publish@release/v1`) — not full commit-SHA pinning, but @@ -60,9 +66,9 @@ That precondition has already been met and those documents are now stale: `test.yml` sets repo-wide `permissions: contents: read`; least-privilege is already largely in place, not a gap. - Dependency ecosystems actually in use: Python (`pyproject.toml`) and GitHub - Actions. No `package.json` anywhere — the `npm install -g` calls in - `harness-parity` install pinned global CLIs for testing, not a project - dependency Dependabot should manage. No Docker. + Actions. The only `package.json` is a test fixture; the `npm install -g` + calls in `harness-parity` install pinned global CLIs for testing, not a + project dependency Dependabot should manage. No Docker. - `project-roadmap.md`'s "Public and enterprise governance" section and `docs/enterprise-adoption.md` §8 already correctly defer **mandatory** CODEOWNERS review and organization-wide ruleset/reusable-workflow work @@ -72,22 +78,20 @@ That precondition has already been met and those documents are now stale: ## Problem Statement -The repository's day-to-day contributor mechanics (label triage, dependency -freshness, PR gating, branch protection) were never built out because the +The repository's day-to-day contributor mechanics (label triage and dependency +freshness) were never built out because the project was small and private. It is now public with two releases shipped, -but none of the operational scaffolding that keeps a growing issue/PR queue -navigable for a single maintainer exists yet, and the one piece of the -public-readiness plan that mattered most for actually protecting the release -history — branch protection — silently never got applied when the repo went -public. Left as-is, the first sign of trouble will be either an unreviewed -force-push/deletion incident on `master`, or a backlog of unlabeled, -untriaged issues and PRs once external contributors show up. +but the operational scaffolding that keeps a growing issue/PR queue navigable +for a single maintainer does not exist yet. Existing rulesets protect release +history, but their required status-check names can drift when CI changes. +Left as-is, the first sign of trouble will be either a permanently blocked PR +after a matrix rename, or a backlog of unlabeled, untriaged work. ## Solution Add the minimum GitHub-native automation that lets issues and PRs self-organize (path-based labels, a label taxonomy, Dependabot, Issue Forms) -and close the branch-protection gap that public status already requires, +and verify/update the already-active rulesets alongside CI changes, while explicitly deferring anything that assumes a maintainer team or an issue volume this repository doesn't have yet (mandatory CODEOWNERS review, stale-bot, org-wide rulesets). Every "not now" gets a written trigger @@ -103,9 +107,9 @@ condition instead of a vague "later," matching how `project-roadmap.md` and 3. As a first-time contributor, I want a structured bug/feature form instead of a blank Markdown template, so I give the maintainer what's needed on the first pass. -4. As the sole maintainer, I want `master`/`develop`/`v*` tags protected from - force-push and deletion now that the repo is public, without being forced - into mandatory independent code-owner review I can't actually staff. +4. As the sole maintainer, I want `master`/`develop`/`v*` protection verified + through the correct ruleset APIs and required checks kept in sync, without + mandatory independent code-owner review I can't actually staff. 5. As a future contributor, I want a small set of well-labeled "good first issue" candidates to exist so I know where to start. 6. As the sole maintainer, I want CI to catch missing lint/security-scan @@ -146,9 +150,10 @@ condition instead of a vague "later," matching how `project-roadmap.md` and - **Dependency/security scan**: add a lightweight `pip-audit`-style check for the Python dependency surface as a fast-gate job. - **Branch protection / ruleset** (GitHub UI/API, not a file in this repo — - see the UI section below): require PR + passing required checks, - block force-push and branch deletion on `master` and `develop`, restrict - `v*` tag creation/deletion, require conversation resolution. Do **not** + see the UI section below): verify the existing active rulesets, then update + required status-check contexts after CI job/matrix changes. They already + require PR + passing checks, block force-push/deletion on protected branches + and `v*`, and require conversation resolution. Do **not** require code-owner review or signed commits yet — no second qualified maintainer exists to review against, and no CODEOWNERS file exists to reference. @@ -203,12 +208,9 @@ condition instead of a vague "later," matching how `project-roadmap.md` and - New CI jobs (lint, dependency/security scan): must pass on this branch's own diff and not regress the existing 515 unit tests or `sync_version.py --check` / `verify_examples.py --check` drift gates. -- Branch protection: after applying via UI/API, re-query - `gh api repos/SHcommit/ADR-toolkit/branches//protection` and paste - the actual response into the audit doc — this spec's own investigation - showed a prior "done" claim (docs saying the public gate was satisfied) - was false, so the closing step here is re-verification, not another - written claim. +- Branch protection: query `repos/SHcommit/ADR-toolkit/rulesets/` and + `repos/SHcommit/ADR-toolkit/rules/branches/`. Do not use the classic + `branches//protection` endpoint alone as evidence of ruleset absence. ## Out of Scope @@ -222,13 +224,6 @@ condition instead of a vague "later," matching how `project-roadmap.md` and - Signed-commit requirements. - Any change to ADR Toolkit's product code, CLI, or `docs/decisions/` governance model. -- Converting the Antigravity `curl | bash` install step into an - artifact+checksum flow — that step doesn't currently run for the - Antigravity adapter in CI (manual-only per - `adapters/antigravity/README.md`); if/when Antigravity CI verification is - added (tracked in `improvements.md`, blocked on Antigravity publishing to a - package registry), that installer should be revisited then, not - speculatively hardened now for a path nothing currently executes. - Full commit-SHA pinning for all third-party Actions (current major-version tag pinning from verified publishers is a reasonable middle ground for this repo's risk level; revisit only if a specific tag-mutation incident in one @@ -248,17 +243,15 @@ condition instead of a vague "later," matching how `project-roadmap.md` and ## Further Notes -- Rollout order: branch-protection/ruleset (GitHub UI/API, highest - risk-reduction per unit effort) → Dependabot + auto-labeler (lowest +- Rollout order: ruleset verification/check-context sync (GitHub UI/API) → + Dependabot + auto-labeler (lowest maintenance cost) → Issue Forms → new CI jobs (lint, dependency scan) → stale-docs correction, so the highest-value, lowest-risk items land first and the doc correction reflects the final state rather than needing a second pass. -- The public-transition gap found here (public since 2026-08-29, but branch - protection never applied, and `docs/enterprise-adoption.md`/`improvements.md` - both still describing the repo as private) should be treated as the - headline finding when this work is reported back — it's a real exposure - window on a public repo with release tags, not a paperwork gap. +- The headline review correction is methodological: classic branch protection + and repository rulesets use different APIs. Operational audits must inspect + both, then query effective rules for concrete refs before declaring a gap. - This spec intentionally does not propose a `.github/labeler.yml` / `dependabot.yml` schema inline — implementation will write those files directly against this repo's actual directory names, which is faster to diff --git a/handoff.md b/handoff.md index 67780d2..8d2483d 100644 --- a/handoff.md +++ b/handoff.md @@ -2,32 +2,59 @@ ## Current task -Completed Production Readiness P1/P2 Backlog Improvements via Parallel Subagent Execution (Groups A-F). -Strictly audited codebase improvements completed; all 550 tests passing. - -## Scope - -- 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) - -- 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). +OSS repository governance hardening implementation and independent review. +Original SDD Tasks 1–9 are complete; the follow-up review corrected false live +GitHub assumptions and closed additional supply-chain/configuration gaps. + +## Touched files + +- Governance config: `.github/CODEOWNERS`, `.github/dependabot.yml`, + `.github/labeler.yml`, `.github/labels.yml`, `.github/ISSUE_TEMPLATE/**`, + `.github/workflows/{labeler,labels,test,release}.yml`. +- Tooling/tests: `pyproject.toml`, `scripts/export_dev_requirements.py`, + `tests/unit/test_github_governance.py`, pre-existing ruff cleanup files. +- Docs: `SECURITY.md`, `project-roadmap.md`, `docs/enterprise-adoption.md`, + `docs/oss-repository-governance-audit.md`, governance design spec, + `changelog.md`, `improvements.md`. + +## Live GitHub changes applied + +- Synced 25 labels without deleting unrelated labels. +- Enabled Discussions, Dependabot security updates/alerts, secret scanning and + push protection, private vulnerability reporting, and delete-branch-on-merge. +- Re-verified active branch ruleset `22101891` and tag ruleset `22102322`. + +## Next step + +1. Merge PR #17 (`chore/sync-develop-with-v1.0.1`) first because this branch is + based on it. +2. Fetch the updated `develop` and merge it into `feature/oss-governance-hardening` + before opening the governance PR, because `origin/develop` also contains + newer adapter work. +3. Push `feature/oss-governance-hardening` and open a PR to `develop`. +4. After its new Python 3.10/lint/audit checks have run, update ruleset + `22101891`: remove the two Python 3.9 contexts; add all three Python 3.10 + contexts plus `lint` and `dependency-audit`; query effective rules again. ## Verification -`python3 -m pytest tests/unit tests/integration -q` (550 tests passing) and -`python3 scripts/sync_version.py --check` passed cleanly. +- CI-equivalent pytest + branch coverage: 558 passed, 92.74% coverage. +- `ruff check .`: passed. +- scoped `mypy --strict`: passed. +- `sync_version.py --check` and `verify_examples.py --check`: passed. +- `pip-audit --strict` in a clean dev-tool environment: no known vulnerabilities. +- actionlint v1.7.12: passed after fixing PR-title expression injection. +- Python package build: wheel and sdist built successfully; emitted only the + tracked PyPA license-metadata deprecation warning. +- Antigravity 1.1.27 artifact: official SHA-512 matched and archive contained + the expected `antigravity` binary. ## Open risks -- 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. +- Until the governance PR is merged and ruleset contexts are updated, the live + ruleset still names removed Python 3.9 checks and does not require the new + `lint`/`dependency-audit` jobs. +- `pypa/gh-action-pypi-publish` remains `continue-on-error: true`, so a release + can partially succeed; tracked in `improvements.md`. +- Project/milestone/stale automation is deliberately deferred until issue/PR + volume meets the triggers in the audit report. diff --git a/improvements.md b/improvements.md index 9739f74..f18ffe0 100644 --- a/improvements.md +++ b/improvements.md @@ -22,6 +22,10 @@ another worktree's. - [ ] *(전제조건: 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) +- [ ] *(다음 governance PR merge 직후)* **required-check context 동기화** — ruleset `22101891`에서 Python 3.9 context를 제거하고 Python 3.10 matrix, `lint`, `dependency-audit`를 required로 추가한 뒤 effective-rules API로 재검증한다. +- [ ] *(동일 drift 재발 시)* **ruleset 설정 검증 자동화** — classic branch-protection API와 repository ruleset API를 혼동한 감사 오류 및 CI check-name drift가 다시 발생하면 ruleset-as-code 또는 read-only verification script를 도입한다. +- [ ] **PyPI publish fail-closed 재검토** — Trusted Publisher가 안정화되면 release workflow의 `continue-on-error: true`를 제거해 GitHub Release와 PyPI가 부분 성공으로 갈라지지 않게 한다. +- [ ] **PyPA license metadata 현대화** — 2027-02-18 이전에 deprecated `project.license` table과 license classifier를 SPDX expression / `license-files`로 전환하고 최소 setuptools 버전을 맞춘다. ## Done diff --git a/project-roadmap.md b/project-roadmap.md index 60f5827..2b02bbf 100644 --- a/project-roadmap.md +++ b/project-roadmap.md @@ -19,10 +19,10 @@ before implementation. Concrete selected work belongs in `improvements.md`. - 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. +- **Automate the Antigravity CLI (`agy`) adapter install-and-run verification** + — **Done (2026-09-05).** `harness-parity` downloads a versioned Linux release + artifact, verifies its official SHA-512 digest, and exercises the adapter. + The mutable `curl | bash` bootstrapper is intentionally not executed in CI. - **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 @@ -43,9 +43,10 @@ before implementation. Concrete selected work belongs in `improvements.md`. ## Public and enterprise governance -- After the repository becomes public, apply and API-verify branch/tag - protections, required checks, conversation resolution, force-push/deletion - controls, and a documented bypass policy. +- **Apply and API-verify repository branch/tag rulesets** — **Done + (2026-09-02; re-verified 2026-09-06).** Active rulesets protect + `master`/`develop`/`release/*` and `v*`; required-check names must be updated + whenever the CI matrix changes. - Add CODEOWNERS and mandatory independent review when the contributor model can actually satisfy it. - Organization-level rulesets, reusable workflows, RBAC, audit export, diff --git a/pyproject.toml b/pyproject.toml index 92daaf4..f284080 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,6 +32,9 @@ dev = [ "pytest-cov==7.1.0", "mypy==1.19.1", "ruff==0.16.6", + "PyYAML==6.0.3", + "tomli==2.4.0; python_version < '3.11'", + "build==1.4.4", ] [tool.ruff] diff --git a/scripts/export_dev_requirements.py b/scripts/export_dev_requirements.py new file mode 100644 index 0000000..c329db1 --- /dev/null +++ b/scripts/export_dev_requirements.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +"""Export the pinned ``dev`` extra from pyproject.toml as requirements.""" + +from __future__ import annotations + +import argparse +from pathlib import Path +from typing import Sequence + +try: + import tomllib +except ModuleNotFoundError: # Python 3.10 + import tomli as tomllib # type: ignore[no-redef] + + +def dev_requirements(pyproject: Path) -> list[str]: + with pyproject.open("rb") as stream: + document = tomllib.load(stream) + return list(document["project"]["optional-dependencies"]["dev"]) + + +def main(argv: Sequence[str] | None = None) -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--pyproject", type=Path, default=Path("pyproject.toml")) + args = parser.parse_args(argv) + print(*dev_requirements(args.pyproject), sep="\n") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tests/unit/test_github_governance.py b/tests/unit/test_github_governance.py new file mode 100644 index 0000000..75092df --- /dev/null +++ b/tests/unit/test_github_governance.py @@ -0,0 +1,102 @@ +from pathlib import Path +import subprocess +import sys + +import yaml + + +ROOT = Path(__file__).resolve().parents[2] + + +def load_yaml(relative_path: str) -> object: + with (ROOT / relative_path).open(encoding="utf-8") as stream: + return yaml.safe_load(stream) + + +def test_dependabot_updates_merge_through_develop() -> None: + config = load_yaml(".github/dependabot.yml") + + assert isinstance(config, dict) + updates = config["updates"] + assert all(update["target-branch"] == "develop" for update in updates) + + +def test_cli_paths_receive_the_cli_area_label() -> None: + config = load_yaml(".github/labeler.yml") + + assert isinstance(config, dict) + cli_rules = config["area:cli"] + patterns = cli_rules[0]["changed-files"][0]["any-glob-to-any-file"] + assert "skills/adr-toolkit/scripts/adr.py" in patterns + assert "skills/adr-toolkit/scripts/commands/**" in patterns + + +def test_ci_does_not_pipe_remote_installers_to_a_shell() -> None: + workflow = (ROOT / ".github/workflows/test.yml").read_text(encoding="utf-8") + + assert "install.sh | bash" not in workflow + + +def test_dependency_audit_installs_dev_requirements_from_pyproject() -> None: + workflow = (ROOT / ".github/workflows/test.yml").read_text(encoding="utf-8") + + assert "scripts/export_dev_requirements.py" in workflow + + +def test_dev_requirement_export_reads_the_requested_extra(tmp_path: Path) -> None: + pyproject = tmp_path / "pyproject.toml" + pyproject.write_text( + '[project.optional-dependencies]\n' + 'dev = ["pytest==9.1.1", "ruff==0.16.6"]\n' + 'docs = ["mkdocs==1.6.1"]\n', + encoding="utf-8", + ) + + result = subprocess.run( + [ + sys.executable, + str(ROOT / "scripts/export_dev_requirements.py"), + "--pyproject", + str(pyproject), + ], + check=False, + capture_output=True, + text=True, + ) + + assert result.returncode == 0, result.stderr + assert result.stdout == "pytest==9.1.1\nruff==0.16.6\n" + + +def test_release_uses_pinned_dependencies_and_action_commits() -> None: + workflow = (ROOT / ".github/workflows/release.yml").read_text(encoding="utf-8") + + assert 'pip install -e ".[dev]"' in workflow + assert "pip install pytest build" not in workflow + for line in workflow.splitlines(): + if "uses:" in line: + ref = line.split("uses:", 1)[1].strip().split("#", 1)[0].strip() + revision = ref.rsplit("@", 1)[1] + assert len(revision) == 40 + assert all(character in "0123456789abcdef" for character in revision) + + +def test_pr_title_is_not_interpolated_into_a_shell_script() -> None: + workflow = (ROOT / ".github/workflows/test.yml").read_text(encoding="utf-8") + + assert 'PR_TITLE: ${{ github.event.pull_request.title }}' in workflow + assert 'TITLE="${{ github.event.pull_request.title }}"' not in workflow + + +def test_labeler_write_permissions_are_scoped_per_job() -> None: + workflow = load_yaml(".github/workflows/labeler.yml") + + assert isinstance(workflow, dict) + assert workflow["permissions"] == {"contents": "read"} + assert workflow["jobs"]["label-pr"]["permissions"] == { + "contents": "read", + "pull-requests": "write", + } + assert workflow["jobs"]["triage-issue"]["permissions"] == { + "issues": "write" + } From 8dc3fd90c9b5f44249f31c3732849f7c683033ef Mon Sep 17 00:00:00 2001 From: shcommit Date: Sun, 6 Sep 2026 01:26:43 +0900 Subject: [PATCH 16/21] feat(github): add type:epic label to taxonomy --- .github/labels.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/labels.yml b/.github/labels.yml index 5d18388..4c77684 100644 --- a/.github/labels.yml +++ b/.github/labels.yml @@ -19,6 +19,9 @@ - name: "type:test" color: "bfdadc" description: "Test-only change" +- name: "type:epic" + color: "3fb950" + description: "Umbrella/tracking issue that groups related work" # --- area: which part of the repo --- - name: "area:core" From e8468e9b47506207dbd2858a4a77f7772f01bc6b Mon Sep 17 00:00:00 2001 From: shcommit Date: Sun, 6 Sep 2026 01:46:02 +0900 Subject: [PATCH 17/21] docs(handoff): reflect develop merge and superseded PR #17 --- handoff.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/handoff.md b/handoff.md index 8d2483d..0093b16 100644 --- a/handoff.md +++ b/handoff.md @@ -19,22 +19,22 @@ GitHub assumptions and closed additional supply-chain/configuration gaps. ## Live GitHub changes applied -- Synced 25 labels without deleting unrelated labels. +- Synced labels without deleting unrelated labels; added `type:epic` this session. - Enabled Discussions, Dependabot security updates/alerts, secret scanning and push protection, private vulnerability reporting, and delete-branch-on-merge. - Re-verified active branch ruleset `22101891` and tag ruleset `22102322`. ## Next step -1. Merge PR #17 (`chore/sync-develop-with-v1.0.1`) first because this branch is - based on it. -2. Fetch the updated `develop` and merge it into `feature/oss-governance-hardening` - before opening the governance PR, because `origin/develop` also contains - newer adapter work. -3. Push `feature/oss-governance-hardening` and open a PR to `develop`. -4. After its new Python 3.10/lint/audit checks have run, update ruleset - `22101891`: remove the two Python 3.9 contexts; add all three Python 3.10 - contexts plus `lint` and `dependency-audit`; query effective rules again. +1. Push `feature/oss-governance-hardening` and open a PR to `develop`. This + branch already merged `origin/develop` (Cline adapter + improvements + backlog) and carries the v1.0.1 sync from PR #17. +2. Close PR #17 (`chore/sync-develop-with-v1.0.1`) as superseded — its head + `508b860` is already an ancestor of this branch. +3. After the PR's new Python 3.10/lint/audit checks run green, merge and then + update ruleset `22101891`: remove the two Python 3.9 contexts; add all three + Python 3.10 contexts plus `lint` and `dependency-audit`; query effective + rules again. ## Verification From baab37b727cf3792cc5c9fce57276ba23e418277 Mon Sep 17 00:00:00 2001 From: shcommit Date: Sun, 6 Sep 2026 02:39:01 +0900 Subject: [PATCH 18/21] docs(adr): record OSS repository governance & supply-chain hardening decision (ADR-0017) --- ...overnance-and-ci-supply-chain-hardening.md | 114 ++++++++++++++++++ docs/decisions/README.md | 43 +++++++ docs/decisions/relationships.mmd | 3 + docs/decisions/relationships.svg | 37 +++--- 4 files changed, 182 insertions(+), 15 deletions(-) create mode 100644 docs/decisions/0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md diff --git a/docs/decisions/0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md b/docs/decisions/0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md new file mode 100644 index 0000000..77791e8 --- /dev/null +++ b/docs/decisions/0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md @@ -0,0 +1,114 @@ +--- +id: ADR-0017 +title: Adopt source-controlled GitHub governance and CI supply-chain hardening +status: accepted +date: 2026-09-06 +locale: en +decision_makers: + - YangSeungHyun +related: + - ADR-0005 + - ADR-0016 +affected_paths: + - .github/CODEOWNERS + - .github/dependabot.yml + - .github/labeler.yml + - .github/labels.yml + - .github/ISSUE_TEMPLATE/ + - .github/workflows/test.yml + - .github/workflows/release.yml + - pyproject.toml + - scripts/export_dev_requirements.py + - tests/unit/test_github_governance.py + - SECURITY.md +tags: + - github + - governance + - supply-chain + - ci + - security +retrospective: false +--- + +# Adopt source-controlled GitHub governance and CI supply-chain hardening + +## Context and Problem Statement + +The repository became public on 2026-08-29 and shipped v1.0.0/v1.0.1, but the +day-to-day contributor mechanics that keep a growing issue/PR queue navigable +for a single maintainer were never built out. Labels were the GitHub defaults, +issue templates were legacy Markdown, and there was no Dependabot, no +CODEOWNERS, no path-based auto-labeler, no lint job, and no dependency/security +scan. A prior audit also queried only the classic branch-protection endpoint +and wrongly concluded the repo was unprotected; the repository ruleset API +showed active branch/tag rulesets since 2026-09-02, but their required +status-check names can drift whenever the CI matrix changes. + +## Decision Drivers + +* One maintainer and one repository: automation must pay for itself without + assuming a team that does not exist yet. +* CI was already mature (multi-OS pytest matrix, coverage floor, scoped mypy + --strict, drift gates, pr-title-check, harness-parity) but had no lint and no + dependency/security scan. +* harness-parity ran a remote `curl | bash` installer -- a supply-chain risk. +* Every "not now" item must carry a written trigger, not a vague "later". + +## Considered Options + +* Keep hand-triage only -- does not scale past a handful of issues. +* Adopt GitHub-native automation as code (labels, labeler, Dependabot, Issue + Forms) plus lint + dependency-audit CI gates, and sync the ruleset's required + checks to the CI matrix -- chosen. +* Add heavy automation now (mandatory CODEOWNERS review, stale bot, org-wide + rulesets) -- deferred behind explicit preconditions. + +## Decision Outcome + +Chosen option: **source-controlled GitHub governance + CI supply-chain +hardening**, because it lets issues/PRs self-organize and keeps required checks +honest without over-automating a one-maintainer repository. + +* Path-based auto-labeler mapping changed-file globs to `area:*` labels, plus a + source-controlled label taxonomy (`.github/labels.yml`) synced live without + deleting unrelated labels. +* Dependabot for pip and github-actions only, weekly, grouped, targeting + `develop`. +* Structured Issue Forms for bug and feature reports, with `config.yml` routing + questions to Discussions and vulnerabilities to `SECURITY.md`. +* Fast CI gates: ruff lint and `pip-audit --strict`; the Python floor moved from + 3.9 to 3.10. +* Supply-chain hardening: the Antigravity `curl | bash` installer was replaced + with a versioned SHA-512-verified artifact; release Actions were pinned to + commit SHAs; the PR-title shell expression injection was removed. +* Branch ruleset `22101891` required checks were synced to the new matrix + (Python 3.10 x3 + `lint` + `dependency-audit` added; Python 3.9 removed) and + re-verified through the effective-rules API. +* A dormant CODEOWNERS was drafted but not wired to required review. Live + Discussions, Dependabot security updates/alerts, secret scanning + push + protection, and private vulnerability reporting were enabled. + +## Consequences + +* Good: new issues/PRs arrive pre-labeled; dependency bumps arrive as routine, + reviewable PRs; CI fails fast on lint and known vulnerabilities; protected + branches can no longer be silently blocked by a stale required-check name. +* Bad: ruleset required checks are GitHub-side settings that cannot live fully + in code, so a future CI job rename still requires a manual ruleset sync; the + trigger for a read-only verification script is recorded in `improvements.md`. + +## Confirmation + +pytest (562 passed) plus branch coverage, ruff check, scoped mypy --strict, +`sync_version.py --check`, and `verify_examples.py --check` all passed. The +ruleset and effective-rules APIs confirm the new required checks are active for +`develop`. + +## Revisit Triggers + +* A second qualified maintainer appears -> enable CODEOWNERS required review. +* A second repository repeats the same operations -> org-level rulesets, + reusable workflows, audit export, and taxonomy. +* A real abandoned-issue backlog accumulates -> stale bot. +* CI check-name drift recurs -> ruleset-as-code or a read-only verification + script. diff --git a/docs/decisions/README.md b/docs/decisions/README.md index 02c424d..81c7f00 100644 --- a/docs/decisions/README.md +++ b/docs/decisions/README.md @@ -18,6 +18,7 @@ - [ADR-0014 — Typed result contracts and a scoped mypy --strict CI gate](0014-typed-result-contracts-and-a-scoped-mypy-strict-ci-gate.md) - [ADR-0015 — Structured JSON stderr logging with correlation IDs for uncaught errors](0015-structured-json-stderr-logging-with-correlation-ids-for-uncaught-errors.md) - [ADR-0016 — Sign release artifacts with GitHub Artifact Attestation instead of a managed signing key](0016-sign-release-artifacts-with-github-artifact-attestation-instead-of-a-managed-signing-key.md) +- [ADR-0017 — Adopt source-controlled GitHub governance and CI supply-chain hardening](0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md) ### Superseded - [ADR-0003 — Localize only index.py's generated strings, not agent-composed text](0003-localize-only-index-py-s-generated-strings-not-agent-composed-text.md) @@ -38,6 +39,9 @@ - [ADR-0008 — Deterministic CHECK policy exceptions: schema-validated, annotate-only, never suppress](0008-check-exceptions-annotate-only.md) - [ADR-0013 — Two-stage ReDoS defense for CHECK's author-supplied constraint regexes](0013-two-stage-redos-defense-for-check-s-author-supplied-constraint-regexes.md) +### ci +- [ADR-0017 — Adopt source-controlled GitHub governance and CI supply-chain hardening](0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md) + ### cli - [ADR-0009 — --json is a documented no-op; CLI output is always JSON](0009-json-flag-always-json-contract.md) @@ -75,9 +79,13 @@ ### git-flow - [ADR-0005 — Adopt Git Flow with direct-tag release automation](0005-adopt-git-flow-with-direct-tag-release-automation.md) +### github +- [ADR-0017 — Adopt source-controlled GitHub governance and CI supply-chain hardening](0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md) + ### governance - [ADR-0008 — Deterministic CHECK policy exceptions: schema-validated, annotate-only, never suppress](0008-check-exceptions-annotate-only.md) - [ADR-0011 — Expose ADR relationships as Mermaid and SVG navigation artifacts](0011-adr-relationship-graph-public-readiness.md) +- [ADR-0017 — Adopt source-controlled GitHub governance and CI supply-chain hardening](0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md) ### graph - [ADR-0011 — Expose ADR relationships as Mermaid and SVG navigation artifacts](0011-adr-relationship-graph-public-readiness.md) @@ -115,9 +123,11 @@ ### security - [ADR-0013 — Two-stage ReDoS defense for CHECK's author-supplied constraint regexes](0013-two-stage-redos-defense-for-check-s-author-supplied-constraint-regexes.md) - [ADR-0016 — Sign release artifacts with GitHub Artifact Attestation instead of a managed signing key](0016-sign-release-artifacts-with-github-artifact-attestation-instead-of-a-managed-signing-key.md) +- [ADR-0017 — Adopt source-controlled GitHub governance and CI supply-chain hardening](0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md) ### supply-chain - [ADR-0016 — Sign release artifacts with GitHub Artifact Attestation instead of a managed signing key](0016-sign-release-artifacts-with-github-artifact-attestation-instead-of-a-managed-signing-key.md) +- [ADR-0017 — Adopt source-controlled GitHub governance and CI supply-chain hardening](0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md) ### typing - [ADR-0014 — Typed result contracts and a scoped mypy --strict CI gate](0014-typed-result-contracts-and-a-scoped-mypy-strict-ci-gate.md) @@ -148,17 +158,34 @@ ### `.claude-plugin/plugin.json` - [ADR-0004 — Adapter packaging: manifest-only directories, install-time symlinks, verified formats](0004-adapter-packaging-manifest-only-directories-install-time-symlinks-verified-formats.md) +### `.github/CODEOWNERS` +- [ADR-0017 — Adopt source-controlled GitHub governance and CI supply-chain hardening](0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md) + +### `.github/ISSUE_TEMPLATE/` +- [ADR-0017 — Adopt source-controlled GitHub governance and CI supply-chain hardening](0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md) + ### `.github/PULL_REQUEST_TEMPLATE.md` - [ADR-0011 — Expose ADR relationships as Mermaid and SVG navigation artifacts](0011-adr-relationship-graph-public-readiness.md) +### `.github/dependabot.yml` +- [ADR-0017 — Adopt source-controlled GitHub governance and CI supply-chain hardening](0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md) + +### `.github/labeler.yml` +- [ADR-0017 — Adopt source-controlled GitHub governance and CI supply-chain hardening](0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md) + +### `.github/labels.yml` +- [ADR-0017 — Adopt source-controlled GitHub governance and CI supply-chain hardening](0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md) + ### `.github/workflows/` - [ADR-0005 — Adopt Git Flow with direct-tag release automation](0005-adopt-git-flow-with-direct-tag-release-automation.md) ### `.github/workflows/release.yml` - [ADR-0016 — Sign release artifacts with GitHub Artifact Attestation instead of a managed signing key](0016-sign-release-artifacts-with-github-artifact-attestation-instead-of-a-managed-signing-key.md) +- [ADR-0017 — Adopt source-controlled GitHub governance and CI supply-chain hardening](0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md) ### `.github/workflows/test.yml` - [ADR-0014 — Typed result contracts and a scoped mypy --strict CI gate](0014-typed-result-contracts-and-a-scoped-mypy-strict-ci-gate.md) +- [ADR-0017 — Adopt source-controlled GitHub governance and CI supply-chain hardening](0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md) ### `.gitignore` - [ADR-0004 — Adapter packaging: manifest-only directories, install-time symlinks, verified formats](0004-adapter-packaging-manifest-only-directories-install-time-symlinks-verified-formats.md) @@ -178,6 +205,7 @@ ### `SECURITY.md` - [ADR-0011 — Expose ADR relationships as Mermaid and SVG navigation artifacts](0011-adr-relationship-graph-public-readiness.md) - [ADR-0016 — Sign release artifacts with GitHub Artifact Attestation instead of a managed signing key](0016-sign-release-artifacts-with-github-artifact-attestation-instead-of-a-managed-signing-key.md) +- [ADR-0017 — Adopt source-controlled GitHub governance and CI supply-chain hardening](0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md) ### `adapters/` - [ADR-0004 — Adapter packaging: manifest-only directories, install-time symlinks, verified formats](0004-adapter-packaging-manifest-only-directories-install-time-symlinks-verified-formats.md) @@ -200,6 +228,12 @@ ### `project-roadmap.md` - [ADR-0011 — Expose ADR relationships as Mermaid and SVG navigation artifacts](0011-adr-relationship-graph-public-readiness.md) +### `pyproject.toml` +- [ADR-0017 — Adopt source-controlled GitHub governance and CI supply-chain hardening](0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md) + +### `scripts/export_dev_requirements.py` +- [ADR-0017 — Adopt source-controlled GitHub governance and CI supply-chain hardening](0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md) + ### `scripts/sync_version.py` - [ADR-0005 — Adopt Git Flow with direct-tag release automation](0005-adopt-git-flow-with-direct-tag-release-automation.md) @@ -334,6 +368,9 @@ ### `tests/unit/test_contracts.py` - [ADR-0014 — Typed result contracts and a scoped mypy --strict CI gate](0014-typed-result-contracts-and-a-scoped-mypy-strict-ci-gate.md) +### `tests/unit/test_github_governance.py` +- [ADR-0017 — Adopt source-controlled GitHub governance and CI supply-chain hardening](0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md) + ### `tests/unit/test_graph_command.py` - [ADR-0011 — Expose ADR relationships as Mermaid and SVG navigation artifacts](0011-adr-relationship-graph-public-readiness.md) @@ -348,6 +385,7 @@ ## Chronological (newest first) +- 2026-09-06 — [ADR-0017 — Adopt source-controlled GitHub governance and CI supply-chain hardening](0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md) - 2026-09-01 — [ADR-0012 — Atomic writes and cross-platform directory locking for CREATE, EXCEPTION, and SUPERSEDE](0012-atomic-writes-and-cross-platform-directory-locking-for-create-exception-and-supersede.md) - 2026-09-01 — [ADR-0013 — Two-stage ReDoS defense for CHECK's author-supplied constraint regexes](0013-two-stage-redos-defense-for-check-s-author-supplied-constraint-regexes.md) - 2026-09-01 — [ADR-0014 — Typed result contracts and a scoped mypy --strict CI gate](0014-typed-result-contracts-and-a-scoped-mypy-strict-ci-gate.md) @@ -386,6 +424,8 @@ - ADR-0015 "Structured JSON stderr logging with correlation IDs for uncaught errors" related to: ADR-0009 "--json is a documented no-op; CLI output is always JSON" - ADR-0016 "Sign release artifacts with GitHub Artifact Attestation instead of a managed signing key" related to: ADR-0005 "Adopt Git Flow with direct-tag release automation" - ADR-0016 "Sign release artifacts with GitHub Artifact Attestation instead of a managed signing key" related to: ADR-0011 "Expose ADR relationships as Mermaid and SVG navigation artifacts" +- ADR-0017 "Adopt source-controlled GitHub governance and CI supply-chain hardening" related to: ADR-0005 "Adopt Git Flow with direct-tag release automation" +- ADR-0017 "Adopt source-controlled GitHub governance and CI supply-chain hardening" related to: ADR-0016 "Sign release artifacts with GitHub Artifact Attestation instead of a managed signing key" ```mermaid flowchart LR @@ -405,6 +445,7 @@ flowchart LR ADR_0014["ADR-0014
Typed result contracts and a scoped mypy --strict CI gate"] ADR_0015["ADR-0015
Structured JSON stderr logging with correlation IDs for uncaught errors"] ADR_0016["ADR-0016
Sign release artifacts with GitHub Artifact Attestation instead of a managed signing key"] + ADR_0017["ADR-0017
Adopt source-controlled GitHub governance and CI supply-chain hardening"] ADR_0006 -.->|related| ADR_0003 ADR_0006 -->|supersedes| ADR_0003 ADR_0011 -.->|related| ADR_0001 @@ -419,4 +460,6 @@ flowchart LR ADR_0015 -.->|related| ADR_0009 ADR_0016 -.->|related| ADR_0005 ADR_0016 -.->|related| ADR_0011 + ADR_0017 -.->|related| ADR_0005 + ADR_0017 -.->|related| ADR_0016 ``` diff --git a/docs/decisions/relationships.mmd b/docs/decisions/relationships.mmd index 91fe037..f13530d 100644 --- a/docs/decisions/relationships.mmd +++ b/docs/decisions/relationships.mmd @@ -15,6 +15,7 @@ flowchart LR ADR_0014["ADR-0014
Typed result contracts and a scoped mypy --strict CI gate"] ADR_0015["ADR-0015
Structured JSON stderr logging with correlation IDs for uncaught errors"] ADR_0016["ADR-0016
Sign release artifacts with GitHub Artifact Attestation instead of a managed signing key"] + ADR_0017["ADR-0017
Adopt source-controlled GitHub governance and CI supply-chain hardening"] ADR_0006 -.->|related| ADR_0003 ADR_0006 -->|supersedes| ADR_0003 ADR_0011 -.->|related| ADR_0001 @@ -29,3 +30,5 @@ flowchart LR ADR_0015 -.->|related| ADR_0009 ADR_0016 -.->|related| ADR_0005 ADR_0016 -.->|related| ADR_0011 + ADR_0017 -.->|related| ADR_0005 + ADR_0017 -.->|related| ADR_0016 diff --git a/docs/decisions/relationships.svg b/docs/decisions/relationships.svg index b267074..7571a90 100644 --- a/docs/decisions/relationships.svg +++ b/docs/decisions/relationships.svg @@ -1,4 +1,4 @@ - + ADR relationship graph Vector export of ADR supersession and related-decision links. @@ -52,32 +52,39 @@ ADR-0016 Sign release artifacts with GitHu... + +ADR-0017 +Adopt source-controlled GitHub go... -ADR-0006 related ADR-0003 +ADR-0006 related ADR-0003 -ADR-0006 supersedes ADR-0003 +ADR-0006 supersedes ADR-0003 -ADR-0011 related ADR-0001 +ADR-0011 related ADR-0001 -ADR-0011 related ADR-0006 +ADR-0011 related ADR-0006 -ADR-0011 related ADR-0008 +ADR-0011 related ADR-0008 -ADR-0011 related ADR-0009 +ADR-0011 related ADR-0009 -ADR-0012 related ADR-0006 +ADR-0012 related ADR-0006 -ADR-0013 related ADR-0002 +ADR-0013 related ADR-0002 -ADR-0013 related ADR-0007 +ADR-0013 related ADR-0007 -ADR-0013 related ADR-0008 +ADR-0013 related ADR-0008 -ADR-0014 related ADR-0009 +ADR-0014 related ADR-0009 -ADR-0015 related ADR-0009 +ADR-0015 related ADR-0009 -ADR-0016 related ADR-0005 +ADR-0016 related ADR-0005 -ADR-0016 related ADR-0011 +ADR-0016 related ADR-0011 + +ADR-0017 related ADR-0005 + +ADR-0017 related ADR-0016 From 4fb3482ab189d1fa335944ce3a25cbcfa8ef5074 Mon Sep 17 00:00:00 2001 From: shcommit Date: Sun, 6 Sep 2026 17:13:00 +0900 Subject: [PATCH 19/21] docs(backlog): log Cline CLI harness-parity CI coverage gap as Medium backlog item The Cline adapter (adapters/cline/) is manually verified against Cline CLI 3.0.61 only. Unlike the Codex, Gemini, and Antigravity adapters, it is not exercised by the harness-parity CI job on push/PR, so Cline/ClinePass version drift goes undetected. Cline CLI is npm-installable, so the precondition (public package registry) is already met; this change records the gap and prerequisite checks (npm package name/version pin, install-path verification, preflight/init/validate ok:true) in improvements.md and project-roadmap.md, and notes it in changelog.md and handoff.md. No code or CI workflow changes; ruff/mypy unaffected. test_cline_adapter.py assertions re-run with Python 3.13 (stdlib-only) and pass. Closes the follow-up backlog item identified while reviewing the Cline adapter install state. --- changelog.md | 1 + handoff.md | 72 ++++++++++++++++++++++------------------------ improvements.md | 11 +++++++ project-roadmap.md | 7 +++++ 4 files changed, 53 insertions(+), 38 deletions(-) diff --git a/changelog.md b/changelog.md index f55cf9a..785f61c 100644 --- a/changelog.md +++ b/changelog.md @@ -26,6 +26,7 @@ Lightweight human-readable summary of meaningful repository changes. manifest — documenting `cline skill add SHcommit/ADR-toolkit` plus a manual 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. +- Logged a Medium-priority backlog item to fold the Cline CLI adapter into the `harness-parity` CI job (currently manually verified against Cline CLI 3.0.61 only), so Cline/ClinePass version drift is caught automatically like the Codex, Gemini, and Antigravity adapters. ## v1.0.1 (2026-09-02) diff --git a/handoff.md b/handoff.md index 024e44c..e36571c 100644 --- a/handoff.md +++ b/handoff.md @@ -2,55 +2,51 @@ ## Current task -OSS repository governance hardening implementation and independent review. -Original SDD Tasks 1–9 are complete; the follow-up review corrected false live -GitHub assumptions and closed additional supply-chain/configuration gaps. +Cline CLI adapter harness-parity CI coverage gap — logged as a Medium backlog +item. The Cline adapter is currently "Manually verified against Cline CLI 3.0.61" +only; the `harness-parity` CI job does not yet install Cline and exercise it on +push/PR. Codex, Gemini, and Antigravity adapters are already automated. ## Touched files -- Governance config: `.github/CODEOWNERS`, `.github/dependabot.yml`, - `.github/labeler.yml`, `.github/labels.yml`, `.github/ISSUE_TEMPLATE/**`, - `.github/workflows/{labeler,labels,test,release}.yml`. -- Tooling/tests: `pyproject.toml`, `scripts/export_dev_requirements.py`, - `tests/unit/test_github_governance.py`, pre-existing ruff cleanup files. -- Docs: `SECURITY.md`, `project-roadmap.md`, `docs/enterprise-adoption.md`, - `docs/oss-repository-governance-audit.md`, governance design spec, - `changelog.md`, `improvements.md`. +- `improvements.md` — added Medium item "harness-parity CI에 Cline CLI 편입" + with prerequisites (npm package name/version pin, install-path verification, + `preflight`/`init`/`validate` `ok:true` checks). +- `project-roadmap.md` — added "Automate the Cline CLI adapter install-and-run + verification — Backlog." entry under "Harness parity". +- `changelog.md` — one Unreleased line recording the backlog item. +- `handoff.md` — this file (current task + next step). -## Live GitHub changes applied +## Diagnosis (for the next session) -- Synced labels without deleting unrelated labels; added `type:epic` this session. -- Enabled Discussions, Dependabot security updates/alerts, secret scanning and - push protection, private vulnerability reporting, and delete-branch-on-merge. -- Re-verified active branch ruleset `22101891` and tag ruleset `22102322`. +Cline CLI 3.0.61 is installed at `/Users/yangseunghyeon/.npm-global/bin/cline`. +`cline skill list` from the repo root shows `adr-toolkit` as a **Project Skill** +(source: local, from `~/Development/ADR-toolkit/skills/adr-toolkit`) — i.e. the +repo's own `skills/` directory is auto-detected, NOT a global install. +`cline plugin list` is empty and `~/.agents/skills/` is empty, confirming the +adapter is README-only (no Cline TS plugin) and nothing was globally installed. ## Next step -1. Merge PR #34 (`feat(github): add OSS repository governance & supply-chain - hardening`) into `develop` after its CI checks pass. -2. After merge, update ruleset `22101891`: remove the two Python 3.9 contexts; - add all three Python 3.10 contexts plus `lint` and `dependency-audit`; query - effective rules again. +1. (Optional, for personal use) `cline skill add SHcommit/ADR-toolkit --global -y` + to make the skill available outside this repo. +2. (Future PR) Implement the Medium backlog item: confirm `cline`'s npm package + name/version-pin, add a Cline step to `.github/workflows/test.yml` + `harness-parity` job, verify `cline skill add ... --global --yes`, and run + `preflight`/`init`/`validate` from the installed snapshot on each push/PR. + Open a `feature/*` branch per the git flow and merge into `develop` via PR. ## Verification -- CI-equivalent pytest + branch coverage: 558 passed, 92.74% coverage. -- `ruff check .`: passed. -- scoped `mypy --strict`: passed. -- `sync_version.py --check` and `verify_examples.py --check`: passed. -- `pip-audit --strict` in a clean dev-tool environment: no known vulnerabilities. -- actionlint v1.7.12: passed after fixing PR-title expression injection. -- Python package build: wheel and sdist built successfully; emitted only the - tracked PyPA license-metadata deprecation warning. -- Antigravity 1.1.27 artifact: official SHA-512 matched and archive contained - the expected `antigravity` binary. +- `tests/unit/test_cline_adapter.py`: pass (doc-only change, code unaffected). +- `ruff check .`: to be confirmed below. ## Open risks -- Until the governance PR is merged and ruleset contexts are updated, the live - ruleset still names removed Python 3.9 checks and does not require the new - `lint`/`dependency-audit` jobs. -- `pypa/gh-action-pypi-publish` remains `continue-on-error: true`, so a release - can partially succeed; tracked in `improvements.md`. -- Project/milestone/stale automation is deliberately deferred until issue/PR - volume meets the triggers in the audit report. +- Until the Cline harness-parity step lands, Cline CLI/ClinePass version drift + (e.g. `cline skill add` path or `~/.agents/skills/` location changing) will + not be caught by CI. The `adapters/cline/README.md` verification block stays + pinned to 3.0.61 until automated. +- Inherits the prior Open risks from the OSS governance hardening handoff + (ruleset context sync, `continue-on-error` PyPI publish, deferred + issue/PR automation). diff --git a/improvements.md b/improvements.md index 3c96623..a2111e6 100644 --- a/improvements.md +++ b/improvements.md @@ -14,6 +14,17 @@ Backlog derived from `docs/adr-toolkit-audit-report.md`, operational experiences ### Medium +- [ ] **harness-parity CI에 Cline CLI 편입** — `adapters/cline/README.md` 기준 + 여전히 "Manually verified against Cline CLI 3.0.61"뿐, push/PR마다 자동 + 검증이 없어 Cline CLI/ClinePass 버전업 시 회귀를 CI가 못 잡음. Codex/Gemini + 어댑터는 이미 harness-parity job에서 자동 검증 중(`project-roadmap.md` + "Harness parity" 참조). Cline CLI는 npm 글로벌 설치가 가능하므로 + Antigravity(공개 패키지 레지스트리 미지원)와 달리 전제조건은 이미 충족. + 선행 검증 항목: (1) `cline` npm 패키지명/배포 채널/안정 버전 핀 값 확인, + (2) CI runner에서 `cline skill add SHcommit/ADR-toolkit --global --yes` 후 + `~/.agents/skills/adr-toolkit` 설치 경로 검증, (3) `preflight`/`init`/ + `validate` 전 단계 `ok:true` 검증 구간 추가. (`project-roadmap.md` "Harness + parity", `adapters/cline/README.md` "Verification status") - [ ] **ADR 중첩/유사도 감지 및 파편화 방지 Eval 시스템** — 작성하려 하거나 기존에 존재하는 ADR 간 내용/주제/영향 범위의 중첩(overlap) 및 파편화를 사전 감지하는 로직과, ADR 집합의 중복·충돌·일관성을 지속해서 평가/검증하는 Evaluation 프레임워크 구축. (유사도 기반 `supersede` 권장, 중복 작성 방지) - [ ] **개발용 플러그인 메인 저장소 Symlink 자동화 스크립트** — local development 시 `~/.gemini/config/plugins/adr-toolkit`이 임시 워크트리가 아닌 메인 저장소를 항상 바라보도록 하고, 버전 갱신 시 symlink 유효성을 체크하는 도구/가이드 정립. - [ ] **주간 자동 ADR 헬스체크 및 무효화/깨진 링크 점검 오토메이션** — 주 1회(GitHub Actions Scheduled Workflow 등) 실행되어 오래 방치된 `PROPOSED` ADR, 리팩터링으로 깨진 `affected_paths` 경로, 버전 드리프트를 자동 점검하고 이슈/알림을 생성하는 주간 유지보수 시스템. diff --git a/project-roadmap.md b/project-roadmap.md index 2b02bbf..bcd7100 100644 --- a/project-roadmap.md +++ b/project-roadmap.md @@ -23,6 +23,13 @@ before implementation. Concrete selected work belongs in `improvements.md`. — **Done (2026-09-05).** `harness-parity` downloads a versioned Linux release artifact, verifies its official SHA-512 digest, and exercises the adapter. The mutable `curl | bash` bootstrapper is intentionally not executed in CI. +- **Automate the Cline CLI adapter install-and-run verification** — Backlog. + `adapters/cline/` is manually verified against Cline CLI 3.0.61 only; the + `harness-parity` job does not yet install Cline and exercise `cline skill add` + + `preflight`/`init`/`validate`. Cline CLI is npm-installable, so the + precondition (public package registry) is met — tracked as a Medium item in + `improvements.md`. Revisit once the npm package name/version-pin and the + install-path verification steps are confirmed. - **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 From 0881b6bd72255a9ab0ba87d2ae66558ad797e673 Mon Sep 17 00:00:00 2001 From: shcommit Date: Sun, 6 Sep 2026 17:34:04 +0900 Subject: [PATCH 20/21] docs(harness): add CLINE.md thin pointer and list Cline in AGENTS.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cline joins Codex/Claude/Gemini as a listed harness with a thin entry file that delegates to AGENTS.md, matching the existing CODEX.md / CLAUDE.md / GEMINI.md shape. AGENTS.md's harness enumeration (line 4) and the Harness entry files paragraph (line 69) now both name Cline. The entry file also records an empirical finding: an isolated Cline run (CLI 3.0.61, model cline-pass/glm-5.2) showed Cline auto-injects the repo-root AGENTS.md into workspace context at session start — the reasoning trace explicitly says the full content of AGENTS.md was provided in the workspace context. So AGENTS.md already reaches every model routed through ClinePass (DeepSeek, GLM, Kimi, Qwen, ...) without extra plumbing. To make the harness-vs-model distinction explicit, AGENTS.md also states that per-model entry files (DEEPSEEK.md, GLM.md, KIMI.md, QWEN.md) are intentionally not created: those are model/API providers reached through a harness (Cline, Cursor, Aider, ...), not harnesses themselves, so the harness entry file already covers them. This preempts the recurring false question of whether each new model needs its own .md. Tests: added test_cline_entry_file_is_thin_pointer_to_agents_md and test_agents_md_lists_cline_among_harnesses to tests/unit/test_cline_adapter.py. All 5 cases re-run with Python 3.13 standalone (stdlib-only) and pass. ruff/mypy scope: test_cline_adapter.py only. --- AGENTS.md | 17 ++++--- CLINE.md | 23 +++++++++ changelog.md | 1 + handoff.md | 80 ++++++++++++++++++-------------- tests/unit/test_cline_adapter.py | 24 ++++++++++ 5 files changed, 105 insertions(+), 40 deletions(-) create mode 100644 CLINE.md diff --git a/AGENTS.md b/AGENTS.md index 47398d5..db0e568 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,9 +1,10 @@ # AGENTS.md This is the shared operating document for every agent harness working in this -repository (Codex, Claude Code, Gemini, or any other). Harness-specific entry -files (`CODEX.md`, `CLAUDE.md`, `GEMINI.md`) are thin pointers back to this -file — read this one first, regardless of which harness started the session. +repository (Codex, Claude Code, Gemini, Cline, or any other). Harness-specific +entry files (`CODEX.md`, `CLAUDE.md`, `GEMINI.md`, `CLINE.md`) are thin pointers +back to this file — read this one first, regardless of which harness started +the session. ## Source of truth @@ -65,9 +66,13 @@ without reading commit-by-commit history. ## Harness entry files -`CODEX.md`, `CLAUDE.md`, and `GEMINI.md` stay thin. They point back to this -file and hold only notes specific to that harness (e.g. a tool quirk). Do not -duplicate rules from this file into them. +`CODEX.md`, `CLAUDE.md`, `GEMINI.md`, and `CLINE.md` stay thin. They point +back to this file and hold only notes specific to that harness (e.g. a tool +quirk). Do not duplicate rules from this file into them. Per-model entry +files (e.g. `DEEPSEEK.md`, `GLM.md`, `KIMI.md`, `QWEN.md`) are not created: +those are model/API providers reached through a harness (Cline, Cursor, +Aider, …), not harnesses themselves, so the harness's entry file already +covers them. ## Safety diff --git a/CLINE.md b/CLINE.md new file mode 100644 index 0000000..b4b6a2b --- /dev/null +++ b/CLINE.md @@ -0,0 +1,23 @@ +# CLINE.md + +Follow the shared project rules in `AGENTS.md` first. + +Use this file only for Cline-specific notes that cannot live in the shared +document. + +## Cline-specific notes + +Cline discovers this project as **Project Skill** via the open Agent Skills +standard (`skills/adr-toolkit/SKILL.md`); see `adapters/cline/README.md` for +install details. Unlike Codex/Gemini/Antigravity, Cline has no adapter-local +manifest — the canonical `SKILL.md` frontmatter (`name: adr-toolkit`, +`description` < 1024 chars) already satisfies Cline's skill-discovery +requirements. + +Cline (confirmed on CLI 3.0.61 with the `cline-pass/glm-5.2` model) auto-injects +the repository-root `AGENTS.md` into the workspace context at session start, so +the shared operating document reaches every model routed through ClinePass +(DeepSeek, GLM, Kimi, Qwen, …) without a per-model entry file. Per-model +`DEEPSEEK.md` / `KIMI.md` / `GLM.md` / `QWEN.md` files are deliberately not +created — those are model providers, not harnesses; the harness (Cline) is the +layer that owns project-context files. diff --git a/changelog.md b/changelog.md index 785f61c..6c11b79 100644 --- a/changelog.md +++ b/changelog.md @@ -27,6 +27,7 @@ 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. - Logged a Medium-priority backlog item to fold the Cline CLI adapter into the `harness-parity` CI job (currently manually verified against Cline CLI 3.0.61 only), so Cline/ClinePass version drift is caught automatically like the Codex, Gemini, and Antigravity adapters. +- Added `CLINE.md` as a thin harness entry pointer (matching `CODEX.md`/`CLAUDE.md`/`GEMINI.md`) and updated `AGENTS.md` to list Cline alongside the other harnesses, plus an explicit note that per-model files (`DEEPSEEK.md`/`GLM.md`/`KIMI.md`/`QWEN.md`) are intentionally not created — those are model providers routed through a harness, not harnesses themselves. Verified that Cline (CLI 3.0.61 with `cline-pass/glm-5.2`) auto-injects the repo-root `AGENTS.md` into workspace context at session start, so the shared operating document reaches every model routed through ClinePass without a per-model entry file. ## v1.0.1 (2026-09-02) diff --git a/handoff.md b/handoff.md index e36571c..86552ca 100644 --- a/handoff.md +++ b/handoff.md @@ -2,51 +2,63 @@ ## Current task -Cline CLI adapter harness-parity CI coverage gap — logged as a Medium backlog -item. The Cline adapter is currently "Manually verified against Cline CLI 3.0.61" -only; the `harness-parity` CI job does not yet install Cline and exercise it on -push/PR. Codex, Gemini, and Antigravity adapters are already automated. +Cline harness entry file (`CLINE.md`) added and `AGENTS.md` updated to list +Cline alongside Codex/Claude/Gemini, plus an explicit per-model non-creation +policy (`DEEPSEEK.md`/`GLM.md`/`KIMI.md`/`QWEN.md` are not created — those are +model/API providers routed through a harness such as Cline, not harnesses). ## Touched files -- `improvements.md` — added Medium item "harness-parity CI에 Cline CLI 편입" - with prerequisites (npm package name/version pin, install-path verification, - `preflight`/`init`/`validate` `ok:true` checks). -- `project-roadmap.md` — added "Automate the Cline CLI adapter install-and-run - verification — Backlog." entry under "Harness parity". -- `changelog.md` — one Unreleased line recording the backlog item. -- `handoff.md` — this file (current task + next step). +- `CLINE.md` — new thin harness entry pointer (matches `CODEX.md`/`CLAUDE.md`/ + `GEMINI.md` shape) with Cline-specific notes: open Agent Skills discovery, + no adapter-local manifest, and the verified AGENTS.md auto-injection + behavior. +- `AGENTS.md` — added `Cline` to the harness enumeration (line 4) and added + `CLINE.md` to the harness entry-files list (line 69), plus a paragraph + stating per-model entry files are intentionally not created. +- `tests/unit/test_cline_adapter.py` — added + `test_cline_entry_file_is_thin_pointer_to_agents_md` and + `test_agents_md_lists_cline_among_harnesses`. +- `changelog.md` — one Unreleased line. +- `handoff.md` — this file. -## Diagnosis (for the next session) +## Diagnosis / empirical verification -Cline CLI 3.0.61 is installed at `/Users/yangseunghyeon/.npm-global/bin/cline`. -`cline skill list` from the repo root shows `adr-toolkit` as a **Project Skill** -(source: local, from `~/Development/ADR-toolkit/skills/adr-toolkit`) — i.e. the -repo's own `skills/` directory is auto-detected, NOT a global install. -`cline plugin list` is empty and `~/.agents/skills/` is empty, confirming the -adapter is README-only (no Cline TS plugin) and nothing was globally installed. +Confirmed via an isolated Cline run that Cline auto-injects the repo-root +`AGENTS.md` into workspace context at session start: + +``` +cline --data-dir --json 'Output ONLY the literal first line of +this repository AGENTS.md file. Do not run any tools...' +→ reasoning: "Looking at the Workspace Configuration, I see the full content + of the AGENTS.md file was provided in the workspace context." +→ text: "# AGENTS.md" +→ model: cline-pass/glm-5.2 +``` + +So `AGENTS.md` already reaches every model routed through ClinePass +(DeepSeek, GLM, Kimi, Qwen, …). Per-model entry files would be redundant +because the harness (Cline) is the layer that owns project-context injection. ## Next step -1. (Optional, for personal use) `cline skill add SHcommit/ADR-toolkit --global -y` - to make the skill available outside this repo. -2. (Future PR) Implement the Medium backlog item: confirm `cline`'s npm package - name/version-pin, add a Cline step to `.github/workflows/test.yml` - `harness-parity` job, verify `cline skill add ... --global --yes`, and run - `preflight`/`init`/`validate` from the installed snapshot on each push/PR. - Open a `feature/*` branch per the git flow and merge into `develop` via PR. +1. (This PR) `docs/cline-harness-entry` → `develop` via PR #37; wait for CI + (13 checks, same matrix as PR #36). +2. (Future, already logged in PR #36) Implement the Medium backlog item to + fold Cline into the `harness-parity` CI job. ## Verification -- `tests/unit/test_cline_adapter.py`: pass (doc-only change, code unaffected). -- `ruff check .`: to be confirmed below. +- `tests/unit/test_cline_adapter.py`: 5 cases (3 original + 2 new) — re-run + with Python 3.13 standalone. +- `git diff --stat`: 5 files, all markdown + test — ruff/mypy scope: + `test_cline_adapter.py`. ## Open risks -- Until the Cline harness-parity step lands, Cline CLI/ClinePass version drift - (e.g. `cline skill add` path or `~/.agents/skills/` location changing) will - not be caught by CI. The `adapters/cline/README.md` verification block stays - pinned to 3.0.61 until automated. -- Inherits the prior Open risks from the OSS governance hardening handoff - (ruleset context sync, `continue-on-error` PyPI publish, deferred - issue/PR automation). +- Cline auto-injection of `AGENTS.md` was verified on Cline CLI 3.0.61 with + `cline-pass/glm-5.2`; behavior may differ on other Cline versions or + providers. The Medium harness-parity CI backlog item (PR #36) covers + ongoing regression detection once implemented. +- Inherits Open risks from the prior handoff (ruleset context sync, + `continue-on-error` PyPI publish, deferred issue/PR automation). diff --git a/tests/unit/test_cline_adapter.py b/tests/unit/test_cline_adapter.py index b24cecc..c66c3ec 100644 --- a/tests/unit/test_cline_adapter.py +++ b/tests/unit/test_cline_adapter.py @@ -18,6 +18,30 @@ def test_cline_adapter_documents_skill_discovery_locations(): assert "~/.agents/skills" in text +def test_cline_entry_file_is_thin_pointer_to_agents_md(): + # Cline joins Codex/Claude/Gemini as a harness with a thin entry file that + # delegates to AGENTS.md. Per-model entry files (DEEPSEEK/GLM/KIMI/QWEN) are + # intentionally not created — those are models routed through a harness, + # not harnesses themselves. + cline_entry = REPO_ROOT / "CLINE.md" + text = cline_entry.read_text(encoding="utf-8") + assert "AGENTS.md" in text + assert "Follow the shared project rules" in text + # Harness entry files must stay thin — no duplication of AGENTS.md rules. + assert "Git Flow" not in text + assert "Release tags" not in text + + +def test_agents_md_lists_cline_among_harnesses(): + text = (REPO_ROOT / "AGENTS.md").read_text(encoding="utf-8") + # Cline must be listed both in the harness enumeration and the entry-file + # paragraph, alongside Codex/Claude/Gemini. + assert "Cline" in text + assert "CLINE.md" in text + # And the per-model-file non-creation policy must be stated. + assert "model/API providers" in text + + def test_skill_frontmatter_satisfies_cline_requirements(): # Cline requires `name` to match its directory and `description` (< 1024 # chars). The canonical package already carries both, so no adapter-local From 55650d771da65ec670cba1fe8e480d839f1abe9a Mon Sep 17 00:00:00 2001 From: shcommit Date: Sun, 6 Sep 2026 17:48:08 +0900 Subject: [PATCH 21/21] chore(release): bump VERSION to 1.1.0 and sync manifests for v1.1.0 release Cut release v1.1.0 from develop. The 31 commits accumulated since v1.0.1 include six feat: commits (Cline CLI adapter, GitHub label taxonomy / labeler / dependabot / Issue Forms / auto-triage), so SemVer requires a MINOR bump; no breaking changes were identified. sync_version.py propagated the bump across: - skills/adr-toolkit/VERSION - skills/adr-toolkit/SKILL.md (frontmatter version line) - .claude-plugin/plugin.json - adapters/gemini-cli/gemini-extension.json - adapters/antigravity/plugin.json (adapters/codex/.codex-plugin/plugin.json carries description only; no version field to sync.) changelog.md moves the Unreleased block under a new ## v1.1.0 (2026-09-06) heading summarizing the 31 commits. handoff.md describes the release flow per AGENTS.md: release/v1.1.0 merges into master, then back-merges into develop, then v1.1.0 is tagged from master. Verification: scripts/sync_version.py --check passes (no drift, no untracked manifests). --- .claude-plugin/plugin.json | 2 +- adapters/antigravity/plugin.json | 2 +- adapters/gemini-cli/gemini-extension.json | 2 +- changelog.md | 46 ++++++++++++ handoff.md | 85 +++++++++++------------ skills/adr-toolkit/SKILL.md | 2 +- skills/adr-toolkit/VERSION | 2 +- 7 files changed, 91 insertions(+), 50 deletions(-) diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 3c327fa..41e0b4a 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,5 +1,5 @@ { "name": "adr-toolkit", - "version": "1.0.1", + "version": "1.1.0", "description": "Initialize, record, and check Architecture Decision Records by inspecting the repository and existing decisions before asking questions." } diff --git a/adapters/antigravity/plugin.json b/adapters/antigravity/plugin.json index 118e48c..03ae7ba 100644 --- a/adapters/antigravity/plugin.json +++ b/adapters/antigravity/plugin.json @@ -1,6 +1,6 @@ { "$schema": "https://antigravity.google/schemas/v1/plugin.json", "name": "adr-toolkit", - "version": "1.0.1", + "version": "1.1.0", "description": "Initialize, record, and check Architecture Decision Records by inspecting the repository and existing decisions before asking questions." } diff --git a/adapters/gemini-cli/gemini-extension.json b/adapters/gemini-cli/gemini-extension.json index 3c327fa..41e0b4a 100644 --- a/adapters/gemini-cli/gemini-extension.json +++ b/adapters/gemini-cli/gemini-extension.json @@ -1,5 +1,5 @@ { "name": "adr-toolkit", - "version": "1.0.1", + "version": "1.1.0", "description": "Initialize, record, and check Architecture Decision Records by inspecting the repository and existing decisions before asking questions." } diff --git a/changelog.md b/changelog.md index 6c11b79..f2dd488 100644 --- a/changelog.md +++ b/changelog.md @@ -29,6 +29,52 @@ Lightweight human-readable summary of meaningful repository changes. - Logged a Medium-priority backlog item to fold the Cline CLI adapter into the `harness-parity` CI job (currently manually verified against Cline CLI 3.0.61 only), so Cline/ClinePass version drift is caught automatically like the Codex, Gemini, and Antigravity adapters. - Added `CLINE.md` as a thin harness entry pointer (matching `CODEX.md`/`CLAUDE.md`/`GEMINI.md`) and updated `AGENTS.md` to list Cline alongside the other harnesses, plus an explicit note that per-model files (`DEEPSEEK.md`/`GLM.md`/`KIMI.md`/`QWEN.md`) are intentionally not created — those are model providers routed through a harness, not harnesses themselves. Verified that Cline (CLI 3.0.61 with `cline-pass/glm-5.2`) auto-injects the repo-root `AGENTS.md` into workspace context at session start, so the shared operating document reaches every model routed through ClinePass without a per-model entry file. +## v1.1.0 (2026-09-06) + +Minor release: new features, governance hardening, and a new harness adapter. + +- 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 — documenting `cline skill add SHcommit/ADR-toolkit` plus a manual + symlink fallback. Manually verified against Cline CLI 3.0.61. +- Added `CLINE.md` as a thin harness entry pointer (matching + `CODEX.md`/`CLAUDE.md`/`GEMINI.md`) and updated `AGENTS.md` to list Cline + alongside the other harnesses, plus an explicit note that per-model files + (`DEEPSEEK.md`/`GLM.md`/`KIMI.md`/`QWEN.md`) are intentionally not created — + those are model providers routed through a harness, not harnesses themselves. + Verified that Cline (CLI 3.0.61 with `cline-pass/glm-5.2`) auto-injects the + repo-root `AGENTS.md` into workspace context at session start, so the shared + operating document reaches every model routed through ClinePass without a + per-model entry file. +- Scalable GitHub governance: structured Issue Forms, source-controlled label + taxonomy, path-based PR labels, new-issue triage, weekly grouped Dependabot + updates targeting `develop`, and a dormant CODEOWNERS draft. +- Ruff and strict dependency-audit CI gates, upgraded the supported Python floor + to 3.10, and added regression tests for repository governance configuration. +- Hardened CI supply chain: replaced the Antigravity `curl | bash` installer with + a versioned SHA-512-verified artifact, pinned release Actions to commit SHAs, + pinned release build tooling, and removed PR-title shell expression injection. +- Corrected the governance audit to recognize the already-active repository + branch/tag rulesets through the ruleset APIs rather than treating a classic + branch-protection 404 as proof of no protection. +- Enabled live Discussions, dependency security updates and alerts, secret + scanning with push protection, private vulnerability reporting, and automatic + deletion of merged branches. +- Recorded ADR-0017 (OSS repository governance & supply-chain hardening + decision). +- Logged a Medium-priority backlog item to fold the Cline CLI adapter into the + `harness-parity` CI job (currently manually verified against Cline CLI 3.0.61 + only), so Cline/ClinePass version drift is caught automatically like the Codex, + Gemini, and Antigravity adapters. +- 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. +- Synced `skills/adr-toolkit/VERSION`, `SKILL.md` frontmatter, and the Claude / + Gemini / Antigravity / Codex manifests to 1.1.0 via `scripts/sync_version.py`. + ## v1.0.1 (2026-09-02) - Added PyPI packaging support (`pyproject.toml`) for `pip install adr-toolkit` and `pipx install adr-toolkit`. diff --git a/handoff.md b/handoff.md index 86552ca..8887e4f 100644 --- a/handoff.md +++ b/handoff.md @@ -2,63 +2,58 @@ ## Current task -Cline harness entry file (`CLINE.md`) added and `AGENTS.md` updated to list -Cline alongside Codex/Claude/Gemini, plus an explicit per-model non-creation -policy (`DEEPSEEK.md`/`GLM.md`/`KIMI.md`/`QWEN.md` are not created — those are -model/API providers routed through a harness such as Cline, not harnesses). +Release v1.1.0: VERSION bumped 1.0.1 → 1.1.0, manifests synced via +`scripts/sync_version.py`, `changelog.md` v1.1.0 section added. Release branch +`release/v1.1.0` off `develop` ready to merge into `master`; after merge, tag +`v1.1.0` will be pushed from `master` to trigger `.github/workflows/release.yml`. ## Touched files -- `CLINE.md` — new thin harness entry pointer (matches `CODEX.md`/`CLAUDE.md`/ - `GEMINI.md` shape) with Cline-specific notes: open Agent Skills discovery, - no adapter-local manifest, and the verified AGENTS.md auto-injection - behavior. -- `AGENTS.md` — added `Cline` to the harness enumeration (line 4) and added - `CLINE.md` to the harness entry-files list (line 69), plus a paragraph - stating per-model entry files are intentionally not created. -- `tests/unit/test_cline_adapter.py` — added - `test_cline_entry_file_is_thin_pointer_to_agents_md` and - `test_agents_md_lists_cline_among_harnesses`. -- `changelog.md` — one Unreleased line. +- `skills/adr-toolkit/VERSION` — bumped to `1.1.0`. +- `skills/adr-toolkit/SKILL.md` — frontmatter `version: 1.1.0`. +- `.claude-plugin/plugin.json`, `adapters/gemini-cli/gemini-extension.json`, + `adapters/antigravity/plugin.json` — `version` synced to `1.1.0`. +- `changelog.md` — moved the Unreleased block under a new `## v1.1.0 (2026-09-06)` + heading summarizing the 31 commits accumulated since v1.0.1 (Cline adapter, + CLINE.md/AGENTS.md harness entry, GitHub governance hardening, CI supply-chain + hardening, ADR-0017, backlog items). - `handoff.md` — this file. -## Diagnosis / empirical verification +## Why 1.1.0 (MINOR, not PATCH) -Confirmed via an isolated Cline run that Cline auto-injects the repo-root -`AGENTS.md` into workspace context at session start: - -``` -cline --data-dir --json 'Output ONLY the literal first line of -this repository AGENTS.md file. Do not run any tools...' -→ reasoning: "Looking at the Workspace Configuration, I see the full content - of the AGENTS.md file was provided in the workspace context." -→ text: "# AGENTS.md" -→ model: cline-pass/glm-5.2 -``` - -So `AGENTS.md` already reaches every model routed through ClinePass -(DeepSeek, GLM, Kimi, Qwen, …). Per-model entry files would be redundant -because the harness (Cline) is the layer that owns project-context injection. +The 31 commits between v1.0.1 and this release include six `feat:` commits +(Cline CLI adapter, GitHub label taxonomy / labeler / dependabot / Issue Forms / +auto-triage). SemVer requires a MINOR bump for new backward-compatible +features; no breaking changes were identified, so MAJOR is not warranted and +PATCH would understate the surface change. ## Next step -1. (This PR) `docs/cline-harness-entry` → `develop` via PR #37; wait for CI - (13 checks, same matrix as PR #36). -2. (Future, already logged in PR #36) Implement the Medium backlog item to - fold Cline into the `harness-parity` CI job. +1. Open PR `release/v1.1.0` → `master` (AGENTS.md: "Release branches merge + into `master` and back into `develop`"). +2. After CI passes (release.yml runs pytest + sync_version --check + tag == + VERSION), merge into `master`. +3. Back-merge `master` → `develop` (PR), per the git flow. +4. Tag `v1.1.0` from `master` and push — `release.yml` runs the full suite, + verifies manifest versions against the tag, and publishes a GitHub + Release (plus PyPI publish via Trusted Publisher, `continue-on-error`). +5. Delete the short-lived `release/v1.1.0` branch after merge. ## Verification -- `tests/unit/test_cline_adapter.py`: 5 cases (3 original + 2 new) — re-run - with Python 3.13 standalone. -- `git diff --stat`: 5 files, all markdown + test — ruff/mypy scope: - `test_cline_adapter.py`. +- `scripts/sync_version.py --check`: passes (VERSION, SKILL.md, and all + 4 manifests agree on 1.1.0; no untracked manifests). +- `changelog.md` reflects all 31 v1.0.1..develop commits. +- Working-tree state on `release/v1.1.0`: clean except for the version-sync + + changelog/handoff commits. ## Open risks -- Cline auto-injection of `AGENTS.md` was verified on Cline CLI 3.0.61 with - `cline-pass/glm-5.2`; behavior may differ on other Cline versions or - providers. The Medium harness-parity CI backlog item (PR #36) covers - ongoing regression detection once implemented. -- Inherits Open risks from the prior handoff (ruleset context sync, - `continue-on-error` PyPI publish, deferred issue/PR automation). +- `pypa/gh-action-pypi-publish` remains `continue-on-error: true`, so the + PyPI publish step can partially fail without failing the release job — + tracked in `improvements.md`. +- Cline adapter is still "Manually verified against 3.0.61" only; the + `harness-parity` CI job does not yet cover Cline — PR #36 logged this as a + Medium backlog item to implement after v1.1.0 ships. +- Inherits prior Open risks (ruleset context sync post-merge, deferred + project/milestone/stale automation). diff --git a/skills/adr-toolkit/SKILL.md b/skills/adr-toolkit/SKILL.md index 22b08ce..92adc67 100644 --- a/skills/adr-toolkit/SKILL.md +++ b/skills/adr-toolkit/SKILL.md @@ -2,7 +2,7 @@ name: adr-toolkit description: Initialize, record, and check Architecture Decision Records by inspecting the repository and existing decisions before asking questions. user-invocable: true -version: 1.0.1 +version: 1.1.0 --- # ADR Toolkit diff --git a/skills/adr-toolkit/VERSION b/skills/adr-toolkit/VERSION index 7f20734..9084fa2 100644 --- a/skills/adr-toolkit/VERSION +++ b/skills/adr-toolkit/VERSION @@ -1 +1 @@ -1.0.1 \ No newline at end of file +1.1.0