diff --git a/.claude/commands/adopt.md b/.claude/commands/adopt.md index 31bd92c..cf9c606 100644 --- a/.claude/commands/adopt.md +++ b/.claude/commands/adopt.md @@ -1,3 +1,7 @@ +--- +description: Selectively adopt agentic-dev-kit into an existing repo — inspect what's already present, propose an install plan the operator confirms, then install only the missing pieces without clobbering existing files. Use when integrating the kit into a mature repository rather than a fresh one. +--- + Selectively adopt agentic-dev-kit into an **existing** repo — install only the pieces the repo lacks, point the config at conventions it already has, and never clobber a file. The counterpart to `init.sh` (which assumes a fresh/near-empty repo). Runs diff --git a/.claude/commands/parallel.md b/.claude/commands/parallel.md index 57c1ee4..8b64847 100644 --- a/.claude/commands/parallel.md +++ b/.claude/commands/parallel.md @@ -1,3 +1,8 @@ +--- +description: Plan, launch, inspect, reconcile, and remove isolated development lanes backed by Git worktrees and per-lane state sandboxes. Use when work can be split into disjoint file footprints, when the user requests parallel development, or when inspecting existing agent lanes. +argument-hint: "[list|plan|new|pr-watch|merge|rm|path] [args...]" +--- + Read `docs/agentic-dev-kit/workflows/parallel.md` completely and follow it. Treat `$ARGUMENTS` as the requested parallel-development action and arguments. diff --git a/.claude/commands/post-merge-systemize.md b/.claude/commands/post-merge-systemize.md index b88df16..ca51841 100644 --- a/.claude/commands/post-merge-systemize.md +++ b/.claude/commands/post-merge-systemize.md @@ -1,9 +1,19 @@ -> **v0 kit status — engine not yet vendored.** This skill documents the *doctrine* and the -> pattern-finding pipeline, but its deterministic engine — the merged-PR fetch/digest scripts -> and pipeline config it references (`scripts/…`, `config/…`) — is **not shipped in kit v0** -> (they depend on a forge/PR client and a tracker client that are project-specific). Until a -> later kit revision vendors them, either wire your own engine against this prose or run the -> skill in a lighter LLM-only mode. The four fully-wired skills (`session-start`, `wrap-up`, +--- +description: Weekly pattern-finding across the last 7 days of merged PRs — cluster review findings by root cause, and route patterns spanning ≥2 PRs to a CLAUDE.md/skill-prompt PR, single high-severity incidents to the tracker, and everything else to the friction log. Use for scheduled post-merge retros, not ad hoc single-PR review. +argument-hint: "[backfill|test]" +--- + +> **Engine tracked, not yet vendored — this is a blocked dependency, not unwritten +> work.** This skill documents the *doctrine* and the pattern-finding pipeline. A +> working deterministic engine — the merged-PR fetch/digest scripts and pipeline +> config it references (`scripts/…`, `config/…`) — already exists (in the kit +> maintainer's own toolkit repo) but isn't vendored into kit v0 yet: it's blocked on +> a tracker-adapter abstraction so the engine can target any configured +> `tracker.backend` rather than one hardcoded tracker client (it already talks to a +> forge/PR client generically). Tracked in +> [agentic-dev-kit#7](https://github.com/topij/agentic-dev-kit/issues/7). Until that +> lands, either wire your own engine against this prose or run the skill in a lighter +> LLM-only mode. The four fully-wired skills (`session-start`, `wrap-up`, > `parallel`, `pr-watch`) ship their engines and work out of the box. Weekly pattern-finding across the last 7 days of merged PRs: read each PR's review diff --git a/.claude/commands/pr-watch.md b/.claude/commands/pr-watch.md index c732d5a..24dfdad 100644 --- a/.claude/commands/pr-watch.md +++ b/.claude/commands/pr-watch.md @@ -1,3 +1,8 @@ +--- +description: Drive a pull request through the deterministic poll, fix, acknowledge, and re-poll loop until CI is green and review findings are resolved. Use after opening or updating a pull request, when asked to watch CI or reviews, or when a task must continue until its PR is green and clean. +argument-hint: "[pr-number]" +--- + Read `docs/agentic-dev-kit/workflows/pr-watch.md` completely and follow it. Treat `$ARGUMENTS` as the optional PR number or additional watch context. Resolve diff --git a/.claude/commands/session-start.md b/.claude/commands/session-start.md index faebf35..3449432 100644 --- a/.claude/commands/session-start.md +++ b/.claude/commands/session-start.md @@ -1,3 +1,7 @@ +--- +description: Build a concise start-of-session briefing from the living handoff, friction log, repository state, open pull requests, CI, and configured tracker. Use at the beginning of a development session, when resuming work after a gap, or when asked what the repository should do next. +--- + Read `docs/agentic-dev-kit/workflows/session-start.md` completely and follow it. Treat `$ARGUMENTS` as additional session context. Resolve all configured paths from diff --git a/.claude/commands/triage-friction-log.md b/.claude/commands/triage-friction-log.md index 6375983..f3315cd 100644 --- a/.claude/commands/triage-friction-log.md +++ b/.claude/commands/triage-friction-log.md @@ -1,9 +1,18 @@ -> **v0 kit status — engine not yet vendored.** This skill documents the *doctrine* and the -> intended two-session (draft → operator approval → finalize) mechanism, but its -> deterministic engine — the parse/draft/finalize scripts and pipeline config it references -> (`scripts/…`, `config/…`) — is **not shipped in kit v0** (they depend on a tracker client, -> a notify channel, and a state-machine that are project-specific). Until a later kit revision -> vendors them, either wire your own engine against this prose or run the skill in a lighter +--- +description: Triage the friction-log inbox into tracker tickets — draft tracker-issue payloads from un-graduated entries, get operator approval via DM, then file approved tickets and open a draft PR sweeping them into the archive. Use to graduate accumulated friction-log entries into the tracker. +argument-hint: "[resume|new|test]" +--- + +> **Engine tracked, not yet vendored — this is a blocked dependency, not unwritten +> work.** This skill documents the *doctrine* and the intended two-session (draft → +> operator approval → finalize) mechanism. A working deterministic engine — the +> parse/draft/finalize scripts and pipeline config it references (`scripts/…`, +> `config/…`) — already exists (in the kit maintainer's own toolkit repo) but isn't +> vendored into kit v0 yet: it's blocked on a tracker-adapter abstraction so the +> engine can target any configured `tracker.backend` rather than one hardcoded +> tracker client. Tracked in +> [agentic-dev-kit#6](https://github.com/topij/agentic-dev-kit/issues/6). Until that +> lands, either wire your own engine against this prose or run the skill in a lighter > LLM-only mode. The four fully-wired skills (`session-start`, `wrap-up`, `parallel`, > `pr-watch`) ship their engines and work out of the box. diff --git a/.claude/commands/wrap-up.md b/.claude/commands/wrap-up.md index 0804091..ddd344f 100644 --- a/.claude/commands/wrap-up.md +++ b/.claude/commands/wrap-up.md @@ -1,3 +1,7 @@ +--- +description: Close a meaningful development session by updating the living handoff, capturing workflow friction, checking document budgets, and preserving one clear next step. Use when the user asks to wrap up, hand off, end a session, or record what shipped for the next agent. +--- + Read `docs/agentic-dev-kit/workflows/wrap-up.md` completely and follow it. Treat `$ARGUMENTS` as additional wrap-up context. Resolve all configured paths from diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000..58d3adb --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,43 @@ +{ + "permissions": { + "allow": [ + "Bash(gh pr view:*)", + "Bash(gh pr list:*)", + "Bash(gh pr checks:*)", + "Bash(gh run view:*)", + "Bash(uv run scripts/pr_watch.py:*)" + ] + }, + "hooks": { + "SessionStart": [ + { + "matcher": "startup", + "hooks": [ + { + "type": "command", + "command": "[ -z \"$JOB_NAME\" ] && cd \"$CLAUDE_PROJECT_DIR\" && uv run --script scripts/check_doc_budget.py --quiet || true", + "timeout": 15 + }, + { + "type": "command", + "command": "[ -z \"$JOB_NAME\" ] && cd \"$CLAUDE_PROJECT_DIR\" && uv run --script scripts/check_memory_budget.py --quiet || true", + "timeout": 15 + } + ] + } + ], + "PostToolUse": [ + { + "matcher": "Bash", + "hooks": [ + { + "type": "command", + "command": "python3 \"$CLAUDE_PROJECT_DIR/scripts/hooks/pr_followup_hook.py\"", + "if": "Bash(gh pr *)", + "timeout": 10 + } + ] + } + ] + } +} diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..eb1fca0 --- /dev/null +++ b/Makefile @@ -0,0 +1,32 @@ +# Makefile — thin entry points: `make install-hooks` and `make test`. +# +# install-hooks +# ------------- +# Does NOT reimplement the pre-push hook shim installer. `init.sh`'s own +# install_hooks() (git-worktree-aware, honors `core.hooksPath`, regenerates a +# shim rather than copying the hook body or symlinking it — see init.sh's own +# comments on why) is the single source of truth. Running the whole of +# `./init.sh` here would also re-trigger its interactive project/tracker +# prompts and its docs/ narrative-template seeding step — well outside what a +# target named "install-hooks" should touch, and on a repo whose narrative +# docs still carry the `devkit-template: unrendered` marker (this kit's own +# repo, before an adopter has claimed them) it would rewrite docs/** as a +# side effect. So this target extracts and runs just the install_hooks() +# function body straight out of init.sh — it always reflects init.sh's +# current logic, never a stale/diverged copy — after resolving +# `paths.engines` the same way init.sh does (via config/dev-model.yaml, +# falling back to `scripts`), reusing scripts/lib/kitconfig.py to read it. +# +# test +# ---- +# Runs the same suites the lane contract's local gate runs before every push. + +.PHONY: install-hooks test + +install-hooks: + @engines_dir="$$(python3 -c "import sys; sys.path.insert(0, 'scripts/lib'); import kitconfig; c = kitconfig.load_config(); print(kitconfig.get(c, 'paths.engines', 'scripts'))" 2>/dev/null || echo scripts)"; \ + eval "$$(sed -n '/^install_hooks() {/,/^}/p' init.sh)"; \ + install_hooks + +test: + uv run --with pytest --with pyyaml python -m pytest scripts/lib/state_paths/tests scripts/tests -q diff --git a/scripts/check_memory_budget.py b/scripts/check_memory_budget.py new file mode 100755 index 0000000..1967f83 --- /dev/null +++ b/scripts/check_memory_budget.py @@ -0,0 +1,222 @@ +#!/usr/bin/env python3 +# /// script +# requires-python = ">=3.12" +# dependencies = [] +# /// +"""Warn-only tripwire: nudge a memory-index review when Claude Code's agent +memory grows too large. + +Claude Code's own per-project auto-memory index (``MEMORY.md`` — one pointer +line per saved memory) is loaded into context at every session start. Past a +size limit the loader **truncates** it — the oldest/least-relevant index +lines silently fall out of context, so a real memory becomes unrecallable. +``docs/handoff.md`` and ``docs/friction-log.md`` get a line-count budget +tripwire from ``check_doc_budget.py`` (Principle #1 in ``PRINCIPLES.md``); +this is the analogous guard for the memory index — the Claude-runtime +counterpart, since this artifact is Claude Code-specific and has no Codex +equivalent. + +Two signals, mirroring ``check_doc_budget.py``: + +* **Total size** vs a byte budget set just under the observed SessionStart + load limit, so the warning fires while there's still room to act rather + than after lines have already been dropped. +* **Per-line length** — any index pointer over ~200 chars. The index is meant + to be one terse "[Title](file.md) — hook" line each; an over-long line is a + hook that should be tightened (or the memory pruned). These also + disproportionately eat the byte budget. + +**Warn-only by design** — always exits 0 (a SessionStart hook should *nudge*, +never block). ``--strict`` makes it exit 1 when over budget (soft CI signal). + +Why this isn't driven by ``config/dev-model.yaml``'s ``doc_budgets`` list +(unlike ``check_doc_budget.py``): that list is iterated unconditionally by +``check_doc_budget.py`` — every entry's ``path`` is resolved relative to the +repo root and required to exist, with mandatory ``archive``/``remedy`` +fields. The memory index lives *outside* the repo at a path keyed by this +machine's Claude Code config dir and this repo's absolute path (not portable +across clones/machines, and not swept to an in-repo archive file), so adding +it as a ``doc_budgets`` entry would make every ``check_doc_budget.py`` run +fail loudly with "configured doc not found" wherever no memory has been +saved yet — including the very SessionStart hook this check itself rides +alongside. The byte/line-length budgets below are therefore kept as +documented platform constants (overridable via ``--max-bytes`` / +``--max-line-chars``), the same way ``check_doc_budget.py`` keeps its own +`MAX_BYTES`-equivalent tuning out of adopter config. ``scripts/lib/kitconfig`` +is still reused, for the one thing that *is* config-shaped here: portable +repo-root discovery (walking up for ``.git`` rather than assuming a fixed +``scripts/