diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 5cd377674..23f289035 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -2,7 +2,7 @@ "name": "perun", "description": "Perun: a suite of skills for building with AI agents. Deep code review, token and cost tools (spend reports, auto-compact with handoff, model-tier guidance), gated agentic delivery (merge train, lanes, destructive-command guard, auto-update), an idea critic, and product, growth, positioning, business-ops and output-safety specialists.", "skills": "./.claude/skills", - "version": "1.626.0", + "version": "1.627.0", "author": { "name": "deep-code-review contributors" }, diff --git a/.claude/skills/agentic-delivery/SKILL.md b/.claude/skills/agentic-delivery/SKILL.md index e35440c64..3f7bc95fc 100644 --- a/.claude/skills/agentic-delivery/SKILL.md +++ b/.claude/skills/agentic-delivery/SKILL.md @@ -8,7 +8,7 @@ description: >- license: MIT metadata: author: deep-code-review contributors - version: "1.626.0" + version: "1.627.0" --- # Agentic delivery diff --git a/.claude/skills/agentic-delivery/VERSION b/.claude/skills/agentic-delivery/VERSION index 575f722ed..88af80c98 100644 --- a/.claude/skills/agentic-delivery/VERSION +++ b/.claude/skills/agentic-delivery/VERSION @@ -1 +1 @@ -1.626.0 +1.627.0 diff --git a/.claude/skills/deep-code-review/SKILL.md b/.claude/skills/deep-code-review/SKILL.md index 64c71c167..f2722dc45 100644 --- a/.claude/skills/deep-code-review/SKILL.md +++ b/.claude/skills/deep-code-review/SKILL.md @@ -8,7 +8,7 @@ description: >- license: MIT metadata: author: deep-code-review contributors - version: "1.626.0" + version: "1.627.0" --- # Deep Code Review diff --git a/.claude/skills/deep-code-review/VERSION b/.claude/skills/deep-code-review/VERSION index 575f722ed..88af80c98 100644 --- a/.claude/skills/deep-code-review/VERSION +++ b/.claude/skills/deep-code-review/VERSION @@ -1 +1 @@ -1.626.0 +1.627.0 diff --git a/.claude/skills/idea-critic/SKILL.md b/.claude/skills/idea-critic/SKILL.md index bed36cf4e..1768ac84a 100644 --- a/.claude/skills/idea-critic/SKILL.md +++ b/.claude/skills/idea-critic/SKILL.md @@ -8,7 +8,7 @@ description: >- license: MIT metadata: author: deep-code-review contributors - version: "1.626.0" + version: "1.627.0" --- # Veles: the evil twin (idea-critic) diff --git a/.claude/skills/idea-critic/VERSION b/.claude/skills/idea-critic/VERSION index 575f722ed..88af80c98 100644 --- a/.claude/skills/idea-critic/VERSION +++ b/.claude/skills/idea-critic/VERSION @@ -1 +1 @@ -1.626.0 +1.627.0 diff --git a/.codex-plugin/plugin.json b/.codex-plugin/plugin.json index c4f8a959c..203524cff 100644 --- a/.codex-plugin/plugin.json +++ b/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "perun", - "version": "1.626.0", + "version": "1.627.0", "description": "Perun: a skill suite for AI-agent teams: deep code review, token and cost tools, gated delivery, an idea critic and product specialists.", "skills": "./.claude/skills", "interface": { diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d06f4444..a331062db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,24 @@ All notable changes to this repository are documented here. Format loosely follows Keep a Changelog; versioning follows Semantic Versioning. +## [1.627.0] — 2026-10-30 + +### Added +- `ci_cost_advisor.py ROOT --diff BASE`: lists every `pull_request` workflow job the committed diff `BASE...HEAD` fires, with its `run:` lines, so a fix lane knows which CI jobs to run locally (or name `left to CI`) before it pushes to a repo it does not own. It applies the same `types`, `branches`, `paths` and `paths-ignore` rules as the cost model, counts a renamed file under both its paths, reads a lone-string filter as one pattern, joins a backslash-continued command and a folded `run: >` body into one line, and tags a job that builds an image, starts containers or declares `services:` or `container:` (`docker build`, `docker buildx`, `docker compose up`, `build-push-action`) `[runtime]`. BASE is the branch the PR targets: `branches:` and `branches-ignore:` filters are matched against the branch BASE names (`dev`, `origin/dev` and `refs/remotes/origin/dev` all mean `dev`), never against `--default-branch`, so a repo whose PRs target `development` keeps its `development`-filtered jobs. A sha or tag BASE names no branch, so each job a branch filter gates is listed tagged `(branches: unchecked)` instead of dropped. A workflow the parser cannot read but that names `pull_request` (a BOM before `on:`, say) is listed as `UNPARSED` rather than dropped, and one last line names the workflows that start only on `push`, `merge_group` or `workflow_run`, which are not evaluated. An unusable BASE (unknown, empty or option-shaped) exits 2 with no job list. It is read-only and offline: it returns before the visibility probe and never calls the network. `DiffJobs` in `scripts/test_ci_cost_advisor.py` covers each rule. +- One routed bullet in `references/parallel-audit.md` section 6: pass the branch the PR targets, run the listed jobs locally, or name each `left to CI` under the PR body's `How to verify`; a green unit run says nothing about a `[runtime]` job. + +### Fixed +- A `**/` at the start of a path segment in a `paths:` filter now also matches no directory, as GitHub's filter pattern cheat sheet specifies, so `**/Dockerfile` matches a root `Dockerfile` (it still does not match `MyDockerfile`). The fix is in the glob matcher shared with the cost model, so the cost estimate stops dropping those workflows too. `Triggers` covers it, and the source and fetch date are logged in `docs/standards-index.md`. +- `scripts/test_ci_cost_advisor.py` no longer leaves a `ci-advisor-test-*` directory in `$TMPDIR` on every run. Each temp dir now comes from one registry that `tearDownModule` removes, and `NoTempLeak` runs the whole file in a child process with a private `TMPDIR` and fails if anything is left behind. +size-budget-raise: .claude/skills/deep-code-review/references/parallel-audit.md 39795→40669 one routed bullet: run the CI jobs a fix diff fires, or name them left to CI + +### Added +- `.claude/skills/agentic-delivery/scripts/repo_settings_audit.py OWNER/NAME... [--repos-file FILE] [--json]`: a read-only audit of the GitHub settings a diff review cannot see. Per repository it reads the default branch's classic protection and rulesets together (no protection, force pushes allowed, fewer than 1 required review, no required checks, admins exempt), the Actions token default, review approval and allowed actions, collaborator counts (admins, outside), deploy keys with write, webhooks with `insecure_ssl` or plain http, environments without protection rules, and secret scanning and push protection. Each row is repo, check, severity and a one-line fix. A 403 or 404 is a `not checked (needs admin)` row, never a clean result; so is a reply that lacks a field the check reads, a list holding an item that is not an object, and a list of 1000 or more (lists, rulesets included, are read 100 a page). A 404 `Branch not protected` is a finding only when the repository reply shows `permissions.admin` true. The secret scanning and push protection fixes say a private or internal organization repository needs GitHub Secret Protection. Output is counts and booleans: no login, email, key title, hook URL or API message text is printed. It calls `pipeline_hub.gh_get` (bare `gh api` GETs, TLS fallback through `gh_rest.fallback`), so the getter is injectable, and it writes nothing. Exit 0 once the audit ran; 2 for a bad slug, no repository, an unreadable `--repos-file` or `gh` missing. +- `scripts/test_repo_settings_audit.py` (55 offline tests on fictional acme/widgets fixtures, wired in `scripts/ci-tests.d/repo-settings-audit.sh`): every check, the not-checked rows (a 403 or 404, a missing field, an unreadable item, 1000 or more items), pagination, every wrong-shaped API reply (each must give a not-checked row, never a clean one), the privacy rule on text and JSON output, the CLI, and the default getter end to end through `gh api`. +- A route row in `agentic-delivery/SKILL.md`, one `repo_settings_audit.py` row in `references/tool-hub.md` naming `legitify` (needs an `admin:org` token) and OpenSSF Scorecard as the OSS options, and the GitHub REST pages, the secret scanning and push protection pages, `legitify` and Scorecard sources with their 2026-10-30 fetch date in `docs/standards-index.md`. +size-budget-raise: .claude/skills/agentic-delivery/SKILL.md 7202→7457 one route row for repo_settings_audit.py +size-budget-raise: .claude/skills/deep-code-review/references/tool-hub.md 14455→15368 one Repo settings section holding the repo_settings_audit.py row and its OSS options + ## [1.626.0] — 2026-10-30 ### Added diff --git a/SHA256SUMS b/SHA256SUMS index b4eed95a1..563429640 100644 --- a/SHA256SUMS +++ b/SHA256SUMS @@ -20,8 +20,8 @@ ef9e423362b12d0dd73c8e165faf32e9f53c4d4ac215b57c2e34002a88713838 .claude/skills 9521b057ff3db92d1e60923ebd88170713914f7e235ceb45717eb39419daf811 .claude/skills/agentic-ceo/scripts/weekly_receipt.py 001b7b0a350ff5b7d4e5b85ca2bc6060514410377461a4def7579a92ab7f187a .claude/skills/agentic-delivery/INDEX-scripts.md 29ffa479167c28a166aa0fe2cf189bb12335186256e391eccec68208fd5b36a0 .claude/skills/agentic-delivery/INDEX.md -d21c5d4d2e5ce1106cd7ea0a3c6a23ba96b65d1c7712e51ed612d5b0e2d3cf70 .claude/skills/agentic-delivery/SKILL.md -b2dcfd5d3e07a7f9fd383376ed4d95e26fe3af6a279f147f48aa6a2e4c7106b3 .claude/skills/agentic-delivery/VERSION +04982647fd4125802d46d991ca23ce7fa648a6b2b71074ebbf2c71e6d483619e .claude/skills/agentic-delivery/SKILL.md +73e93e5ff760a52ccc7044d782e1db000a421b043567d8de6ed00a922ffc5959 .claude/skills/agentic-delivery/VERSION 94144c101f82399eb6c18f688321a00e1c195dd0ab334f3a5daa2543b40ff9f5 .claude/skills/agentic-delivery/evals/evals.json fba7699a2d0836b51b7c838d019b1f0cd20570522a362e8a32b8dacfb911298e .claude/skills/agentic-delivery/evals/triggers.json 39140ac0b40907dc2279bb3234ce1d8ffb4db56e8658c7f89cc370f777df0592 .claude/skills/agentic-delivery/references/cost-quality-guardrails.md @@ -205,8 +205,8 @@ d98f3e4380da3496061ba63be7beebe75017ab4ee1734eda9a3e798e19007b0e .claude/skills 18f20db537ab784460ad33cf218f7a01ac0a172fc38413f14c0e19e1ce6821cc .claude/skills/contribution/scripts/share_learning.py 63e7d07ffa54b224a83abee280456f6a24dc8222b9b55f6e249b10ea0c7f5afc .claude/skills/deep-code-review/INDEX-scripts.md 848ddf8c618da617b98bbe76808e775e6ef4f25ccc71954a868a093411d5e9d4 .claude/skills/deep-code-review/INDEX.md -a5bd5b6dc031e2d10a635c05b265c5766aab4ceb3cbd99c4b6e5215b17df4709 .claude/skills/deep-code-review/SKILL.md -b2dcfd5d3e07a7f9fd383376ed4d95e26fe3af6a279f147f48aa6a2e4c7106b3 .claude/skills/deep-code-review/VERSION +a44ec08c8bd85b4adb4ce9c18e01e8c01a500f6efaceaf4bc79e2c396f4393d3 .claude/skills/deep-code-review/SKILL.md +73e93e5ff760a52ccc7044d782e1db000a421b043567d8de6ed00a922ffc5959 .claude/skills/deep-code-review/VERSION b97d95bc93cc23a8bc689e2e23db261a138367bcbc69d2f8a0452d5c2c6dfb68 .claude/skills/deep-code-review/evals/evals.json 13dbb52e4bf61b1093302e094151def167371d26e7cf67a026f3beeb09d34378 .claude/skills/deep-code-review/evals/triggers.json b84e3a2b88dc189f041784e76b97e68ad879915814e00f4b37cd27513746d6f1 .claude/skills/deep-code-review/references/a11y-aria.md @@ -424,8 +424,8 @@ e951eaa63fd0d1870701d69c89c29ef4fe74dbad9b680ab6ef0a4e993fb8bc20 .claude/skills fd316c63bbf1cc0ea64322d7d923d66692eaf7b545c056367bfecca35146c862 .claude/skills/growth-analytics/references/full-map.md 2f1d7499e9ed7ae59f550b5c00043e465b2a4e885821ad153438e2e33fcccb45 .claude/skills/growth-analytics/scripts/readout_check.py 67e71ec40535ad0b3931c51f3decf323bce809ed4c9586c6d422b7ad5698129f .claude/skills/idea-critic/INDEX.md -d45fd9cc927928e26724ae8f69dcca4c6420fd052899efa04197bc8a6d9dbbe9 .claude/skills/idea-critic/SKILL.md -b2dcfd5d3e07a7f9fd383376ed4d95e26fe3af6a279f147f48aa6a2e4c7106b3 .claude/skills/idea-critic/VERSION +e3cdda9db7b41e503ee77eec138198bc4fc86781ee95c910d13cc5e78ca5c1f1 .claude/skills/idea-critic/SKILL.md +73e93e5ff760a52ccc7044d782e1db000a421b043567d8de6ed00a922ffc5959 .claude/skills/idea-critic/VERSION 9f77d5d6d13c99fd16cd8c398795d8be226d74bae5a5bf65369ed94a59fa56b7 .claude/skills/idea-critic/evals/evals.json 0e1c0db300661a1ab1a427a7157c75e2ed67130ab24d5c6cb02ec3ff9e793f58 .claude/skills/idea-critic/evals/heldout.json d8098c5ced63e8b8608867dd144091049563a0553cf62d27ce05b9d52ac54266 .claude/skills/idea-critic/evals/triggers.json diff --git a/changelog.d/ci-jobs-for-diff.md b/changelog.d/ci-jobs-for-diff.md deleted file mode 100644 index ba70f8e50..000000000 --- a/changelog.d/ci-jobs-for-diff.md +++ /dev/null @@ -1,8 +0,0 @@ -### Added -- `ci_cost_advisor.py ROOT --diff BASE`: lists every `pull_request` workflow job the committed diff `BASE...HEAD` fires, with its `run:` lines, so a fix lane knows which CI jobs to run locally (or name `left to CI`) before it pushes to a repo it does not own. It applies the same `types`, `branches`, `paths` and `paths-ignore` rules as the cost model, counts a renamed file under both its paths, reads a lone-string filter as one pattern, joins a backslash-continued command and a folded `run: >` body into one line, and tags a job that builds an image, starts containers or declares `services:` or `container:` (`docker build`, `docker buildx`, `docker compose up`, `build-push-action`) `[runtime]`. BASE is the branch the PR targets: `branches:` and `branches-ignore:` filters are matched against the branch BASE names (`dev`, `origin/dev` and `refs/remotes/origin/dev` all mean `dev`), never against `--default-branch`, so a repo whose PRs target `development` keeps its `development`-filtered jobs. A sha or tag BASE names no branch, so each job a branch filter gates is listed tagged `(branches: unchecked)` instead of dropped. A workflow the parser cannot read but that names `pull_request` (a BOM before `on:`, say) is listed as `UNPARSED` rather than dropped, and one last line names the workflows that start only on `push`, `merge_group` or `workflow_run`, which are not evaluated. An unusable BASE (unknown, empty or option-shaped) exits 2 with no job list. It is read-only and offline: it returns before the visibility probe and never calls the network. `DiffJobs` in `scripts/test_ci_cost_advisor.py` covers each rule. -- One routed bullet in `references/parallel-audit.md` section 6: pass the branch the PR targets, run the listed jobs locally, or name each `left to CI` under the PR body's `How to verify`; a green unit run says nothing about a `[runtime]` job. - -### Fixed -- A `**/` at the start of a path segment in a `paths:` filter now also matches no directory, as GitHub's filter pattern cheat sheet specifies, so `**/Dockerfile` matches a root `Dockerfile` (it still does not match `MyDockerfile`). The fix is in the glob matcher shared with the cost model, so the cost estimate stops dropping those workflows too. `Triggers` covers it, and the source and fetch date are logged in `docs/standards-index.md`. -- `scripts/test_ci_cost_advisor.py` no longer leaves a `ci-advisor-test-*` directory in `$TMPDIR` on every run. Each temp dir now comes from one registry that `tearDownModule` removes, and `NoTempLeak` runs the whole file in a child process with a private `TMPDIR` and fails if anything is left behind. -size-budget-raise: .claude/skills/deep-code-review/references/parallel-audit.md 39795→40669 one routed bullet: run the CI jobs a fix diff fires, or name them left to CI diff --git a/changelog.d/repo-settings-audit.md b/changelog.d/repo-settings-audit.md deleted file mode 100644 index f4d8f50ca..000000000 --- a/changelog.d/repo-settings-audit.md +++ /dev/null @@ -1,6 +0,0 @@ -### Added -- `.claude/skills/agentic-delivery/scripts/repo_settings_audit.py OWNER/NAME... [--repos-file FILE] [--json]`: a read-only audit of the GitHub settings a diff review cannot see. Per repository it reads the default branch's classic protection and rulesets together (no protection, force pushes allowed, fewer than 1 required review, no required checks, admins exempt), the Actions token default, review approval and allowed actions, collaborator counts (admins, outside), deploy keys with write, webhooks with `insecure_ssl` or plain http, environments without protection rules, and secret scanning and push protection. Each row is repo, check, severity and a one-line fix. A 403 or 404 is a `not checked (needs admin)` row, never a clean result; so is a reply that lacks a field the check reads, a list holding an item that is not an object, and a list of 1000 or more (lists, rulesets included, are read 100 a page). A 404 `Branch not protected` is a finding only when the repository reply shows `permissions.admin` true. The secret scanning and push protection fixes say a private or internal organization repository needs GitHub Secret Protection. Output is counts and booleans: no login, email, key title, hook URL or API message text is printed. It calls `pipeline_hub.gh_get` (bare `gh api` GETs, TLS fallback through `gh_rest.fallback`), so the getter is injectable, and it writes nothing. Exit 0 once the audit ran; 2 for a bad slug, no repository, an unreadable `--repos-file` or `gh` missing. -- `scripts/test_repo_settings_audit.py` (55 offline tests on fictional acme/widgets fixtures, wired in `scripts/ci-tests.d/repo-settings-audit.sh`): every check, the not-checked rows (a 403 or 404, a missing field, an unreadable item, 1000 or more items), pagination, every wrong-shaped API reply (each must give a not-checked row, never a clean one), the privacy rule on text and JSON output, the CLI, and the default getter end to end through `gh api`. -- A route row in `agentic-delivery/SKILL.md`, one `repo_settings_audit.py` row in `references/tool-hub.md` naming `legitify` (needs an `admin:org` token) and OpenSSF Scorecard as the OSS options, and the GitHub REST pages, the secret scanning and push protection pages, `legitify` and Scorecard sources with their 2026-10-30 fetch date in `docs/standards-index.md`. -size-budget-raise: .claude/skills/agentic-delivery/SKILL.md 7202→7457 one route row for repo_settings_audit.py -size-budget-raise: .claude/skills/deep-code-review/references/tool-hub.md 14455→15368 one Repo settings section holding the repo_settings_audit.py row and its OSS options diff --git a/gemini-extension.json b/gemini-extension.json index af2232125..bfc82ecd2 100644 --- a/gemini-extension.json +++ b/gemini-extension.json @@ -1,6 +1,6 @@ { "name": "perun", - "version": "1.626.0", + "version": "1.627.0", "description": "Perun: a skill suite for AI-agent teams: deep code review, token and cost tools, gated delivery, an idea critic and product specialists.", "contextFileName": "AGENTS.md" }