From edab53e3733bf752228f98ed43bcb87f4d2300d6 Mon Sep 17 00:00:00 2001 From: chernistry <73943355+chernistry@users.noreply.github.com> Date: Thu, 25 Jun 2026 13:07:32 +0300 Subject: [PATCH] chore(security): resolve code-scanning and Dependabot findings - ci.yml: drop unused checks:write and pull-requests:write from the test and test-macos jobs. The actions that justified them (junit-report, test-reporter) are no longer present, so the permissions and their comments were stale; the jobs now run with contents:read only. - Apply the refurb idiom fixes flagged by code scanning across 15 files (dict()/list() to .copy(), chained comparisons, operator.itemgetter, a list comprehension, and fluent-interface chaining). Behavior-preserving. - Bump vscode dev dependencies: @babel/core to 7.29.7 and js-yaml to 4.2.0 to clear the npm advisories (arbitrary file read; merge-key DoS). --- .github/workflows/ci.yml | 9 - docs/operations/ci-topology.md | 2 +- packages/vscode/package-lock.json | 239 ++++++++++-------- src/bernstein/cli/commands/cost.py | 2 +- src/bernstein/cli/commands/telemetry_cmd.py | 2 +- src/bernstein/cli/commands/verify_cmd.py | 2 +- src/bernstein/cli/commands/worktrees_cmd.py | 2 +- src/bernstein/cli/ui.py | 2 +- src/bernstein/core/approval/gate.py | 3 +- src/bernstein/core/config/home.py | 3 +- src/bernstein/core/cost/retry_budget.py | 2 +- .../core/orchestration/schedule_supervisor.py | 40 ++- src/bernstein/core/replay/gateway.py | 3 +- src/bernstein/core/routing/bandit_router.py | 2 +- .../core/security/permission_policy.py | 3 +- src/bernstein/core/skills/authoring.py | 3 +- src/bernstein/core/skills/routing.py | 2 +- src/bernstein/sdd/validator.py | 3 +- 18 files changed, 166 insertions(+), 158 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 52e736569..28e240922 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1305,14 +1305,6 @@ jobs: timeout-minutes: 90 permissions: contents: read - # Required by mikepenz/action-junit-report to create check-run - # annotations surfaced in the PR Checks tab. - checks: write - # Required by ctrf-io/github-test-reporter to post the test-result - # summary comment on the PR that triggered the run. The action no- - # ops gracefully on push events; the workflow-level Step Summary - # is always populated. - pull-requests: write env: # Single source of truth for the shard count. The `--shard i/N` # denominator below and the per-shard slice both key off this; bump @@ -1531,7 +1523,6 @@ jobs: timeout-minutes: 90 permissions: contents: read - checks: write env: # Per-push macOS runs only shard 1 of this many - a deterministic # ~1/4 subset of the file list. ci-macos-nightly.yml runs the full diff --git a/docs/operations/ci-topology.md b/docs/operations/ci-topology.md index e3c2b95ff..a8d5eee4c 100644 --- a/docs/operations/ci-topology.md +++ b/docs/operations/ci-topology.md @@ -183,7 +183,7 @@ This report lists the workflow graph surfaces reviewers need to inspect when CI | .github/workflows/ci-gate-stub.yml | workflow: {"contents": "read"}
ci-gate: {"contents": "read"} | - | | .github/workflows/ci-macos-nightly.yml | workflow: {"contents": "read"}
open-failure-issue: {"contents": "read", "issues": "write"}
test-macos-nightly: {"checks": "write", "contents": "read"} | GITHUB_TOKEN | | .github/workflows/ci-weekly-digest.yml | digest: {"contents": "read", "issues": "write"} | - | -| .github/workflows/ci.yml | workflow: {"contents": "read"}
actionlint: {"contents": "read"}
adapter-integration: {"contents": "read"}
adapter-integration-macos: {"contents": "read"}
autofix: {"contents": "write"}
bandit: {"contents": "read"}
beartype: {"contents": "read"}
ci-gate: {"contents": "read"}
close-ci-issues: {"contents": "read", "issues": "write"}
coverage-report: {"contents": "read"}
dead-code: {"contents": "read"}
determine-changes: {"contents": "read"}
diff-coverage: {"contents": "read"}
dist-size: {"contents": "read"}
install-smoke-pipx: {"contents": "read"}
install-smoke-uv: {"contents": "read"}
lineage-gate: {"contents": "read"}
lint: {"contents": "read"}
mutmut-diff: {"contents": "read"}
pip-audit: {"contents": "read"}
pr-summary: {"pull-requests": "write"}
property-tests: {"contents": "read"}
pyright-strict-zone: {"contents": "read"}
repo-hygiene: {"contents": "read"}
schemathesis-smoke: {"contents": "read"}
semgrep: {"contents": "read"}
snapshot-tests: {"contents": "read"}
spelling: {"contents": "read"}
test: {"checks": "write", "contents": "read", "pull-requests": "write"}
test-macos: {"checks": "write", "contents": "read"}
typecheck: {"contents": "read"} | CODECOV_TOKEN, GITHUB_TOKEN | +| .github/workflows/ci.yml | workflow: {"contents": "read"}
actionlint: {"contents": "read"}
adapter-integration: {"contents": "read"}
adapter-integration-macos: {"contents": "read"}
autofix: {"contents": "write"}
bandit: {"contents": "read"}
beartype: {"contents": "read"}
ci-gate: {"contents": "read"}
close-ci-issues: {"contents": "read", "issues": "write"}
coverage-report: {"contents": "read"}
dead-code: {"contents": "read"}
determine-changes: {"contents": "read"}
diff-coverage: {"contents": "read"}
dist-size: {"contents": "read"}
install-smoke-pipx: {"contents": "read"}
install-smoke-uv: {"contents": "read"}
lineage-gate: {"contents": "read"}
lint: {"contents": "read"}
mutmut-diff: {"contents": "read"}
pip-audit: {"contents": "read"}
pr-summary: {"pull-requests": "write"}
property-tests: {"contents": "read"}
pyright-strict-zone: {"contents": "read"}
repo-hygiene: {"contents": "read"}
schemathesis-smoke: {"contents": "read"}
semgrep: {"contents": "read"}
snapshot-tests: {"contents": "read"}
spelling: {"contents": "read"}
test: {"contents": "read"}
test-macos: {"contents": "read"}
typecheck: {"contents": "read"} | CODECOV_TOKEN, GITHUB_TOKEN | | .github/workflows/cifuzz-pr.yml | workflow: {"contents": "read"}
cifuzz: {"contents": "read"} | GITHUB_TOKEN | | .github/workflows/cleanup-runs.yml | workflow: {"contents": "read"}
cleanup: {"actions": "write"} | GITHUB_TOKEN | | .github/workflows/cluster-e2e.yml | workflow: {"contents": "read"} | - | diff --git a/packages/vscode/package-lock.json b/packages/vscode/package-lock.json index 887803fd5..292c9dc2a 100644 --- a/packages/vscode/package-lock.json +++ b/packages/vscode/package-lock.json @@ -210,13 +210,13 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", - "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.28.5", + "@babel/helper-validator-identifier": "^7.29.7", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" }, @@ -225,9 +225,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", - "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", "dev": true, "license": "MIT", "engines": { @@ -235,21 +235,21 @@ } }, "node_modules/@babel/core": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", - "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.29.0", - "@babel/generator": "^7.29.0", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helpers": "^7.28.6", - "@babel/parser": "^7.29.0", - "@babel/template": "^7.28.6", - "@babel/traverse": "^7.29.0", - "@babel/types": "^7.29.0", + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", @@ -276,14 +276,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.29.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", - "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.7.tgz", + "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.29.0", - "@babel/types": "^7.29.0", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" @@ -293,14 +293,14 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", - "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.28.6", - "@babel/helper-validator-option": "^7.27.1", + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -337,9 +337,9 @@ "license": "ISC" }, "node_modules/@babel/helper-globals": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", "dev": true, "license": "MIT", "engines": { @@ -347,29 +347,29 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", - "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", - "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.28.6", - "@babel/helper-validator-identifier": "^7.28.5", - "@babel/traverse": "^7.28.6" + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -389,9 +389,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", "dev": true, "license": "MIT", "engines": { @@ -399,9 +399,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", "dev": true, "license": "MIT", "engines": { @@ -409,9 +409,9 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", "dev": true, "license": "MIT", "engines": { @@ -419,27 +419,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.29.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz", - "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.28.6", - "@babel/types": "^7.29.0" + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.29.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", - "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", + "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.29.0" + "@babel/types": "^7.29.7" }, "bin": { "parser": "bin/babel-parser.js" @@ -688,33 +688,33 @@ } }, "node_modules/@babel/template": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", - "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.28.6", - "@babel/parser": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", - "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz", + "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.29.0", - "@babel/generator": "^7.29.0", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.29.0", - "@babel/template": "^7.28.6", - "@babel/types": "^7.29.0", + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7", "debug": "^4.3.1" }, "engines": { @@ -722,14 +722,14 @@ } }, "node_modules/@babel/types": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", - "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5" + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -2270,10 +2270,20 @@ "license": "Python-2.0" }, "node_modules/@textlint/linter-formatter/node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", + "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -3332,9 +3342,9 @@ "optional": true }, "node_modules/baseline-browser-mapping": { - "version": "2.10.12", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.12.tgz", - "integrity": "sha512-qyq26DxfY4awP2gIRXhhLWfwzwI+N5Nxk6iQi8EFizIaWIjqicQTE4sLnZZVdeKPRcVNoJOkkpfzoIYuvCKaIQ==", + "version": "2.10.38", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.38.tgz", + "integrity": "sha512-31/02mVB4yuQU6adKk5SlY6m+mxDwUq5KZkyYgnLrrKl7TEm1+3PyDtDBz2kOv/wxZz41GHsvV1A/u6RmiyBvw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -3412,9 +3422,9 @@ } }, "node_modules/browserslist": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", - "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "version": "4.28.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.4.tgz", + "integrity": "sha512-MTc8i/x9jBQd1iMw2CFGS+rwMa07eYjLR0CCTLDACl9xhxy+nIs3KeML/biicXtk9JrZ6dnnTatmc7ErPXIxqw==", "dev": true, "funding": [ { @@ -3432,11 +3442,11 @@ ], "license": "MIT", "dependencies": { - "baseline-browser-mapping": "^2.9.0", - "caniuse-lite": "^1.0.30001759", - "electron-to-chromium": "^1.5.263", - "node-releases": "^2.0.27", - "update-browserslist-db": "^1.2.0" + "baseline-browser-mapping": "^2.10.38", + "caniuse-lite": "^1.0.30001799", + "electron-to-chromium": "^1.5.376", + "node-releases": "^2.0.48", + "update-browserslist-db": "^1.2.3" }, "bin": { "browserslist": "cli.js" @@ -3586,9 +3596,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001781", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001781.tgz", - "integrity": "sha512-RdwNCyMsNBftLjW6w01z8bKEvT6e/5tpPVEgtn22TiLGlstHOVecsX2KHFkD5e/vRnIE4EGzpuIODb3mtswtkw==", + "version": "1.0.30001799", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001799.tgz", + "integrity": "sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw==", "dev": true, "funding": [ { @@ -4143,9 +4153,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.328", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.328.tgz", - "integrity": "sha512-QNQ5l45DzYytThO21403XN3FvK0hOkWDG8viNf6jqS42msJ8I4tGDSpBCgvDRRPnkffafiwAym2X2eHeGD2V0w==", + "version": "1.5.378", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.378.tgz", + "integrity": "sha512-VinvOAuuPmdD1guEgGv5f2Qp7/vlfqOrUOMYNnOD4wj3pit8kRsQHzfIf6teyUGWo15Tg5+bOJaRunvyltpVWQ==", "dev": true, "license": "ISC" }, @@ -6754,11 +6764,14 @@ "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.36", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz", - "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==", + "version": "2.0.50", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.50.tgz", + "integrity": "sha512-J6l92tKHX6w8Jy5nO1Vuc01NoIiRGi/d6qBKVxh+IQ8Cr3b6HbVNfKiF8ZpFKufTwpwxMmce2W3iQZ861ZRyTg==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=18" + } }, "node_modules/node-sarif-builder": { "version": "3.4.0", @@ -7405,10 +7418,20 @@ "license": "Python-2.0" }, "node_modules/rc-config-loader/node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", + "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], "license": "MIT", "dependencies": { "argparse": "^2.0.1" diff --git a/src/bernstein/cli/commands/cost.py b/src/bernstein/cli/commands/cost.py index 14f3e36ab..b921b4f95 100644 --- a/src/bernstein/cli/commands/cost.py +++ b/src/bernstein/cli/commands/cost.py @@ -935,7 +935,7 @@ def _read_envelopes_from_yaml(yaml_path: Path) -> dict[str, dict[str, Any]]: for name, payload in envelopes_block.items(): if isinstance(payload, dict): payload_d = cast("dict[str, Any]", payload) - out[name] = dict(payload_d) + out[name] = payload_d.copy() return out diff --git a/src/bernstein/cli/commands/telemetry_cmd.py b/src/bernstein/cli/commands/telemetry_cmd.py index 73e60f105..9f2a405a2 100644 --- a/src/bernstein/cli/commands/telemetry_cmd.py +++ b/src/bernstein/cli/commands/telemetry_cmd.py @@ -143,7 +143,7 @@ def telemetry_status(home: Path | None) -> None: dsn = os.environ.get(sidechannel.DSN_ENV) or "(unset)" from bernstein.core.telemetry.share import resolve_share_endpoint - share_endpoint_configured = resolve_share_endpoint(dict(os.environ)) is not None + share_endpoint_configured = resolve_share_endpoint(os.environ.copy()) is not None lines: list[str] = [ f"enabled: {str(state.enabled).lower()}", f"source: {state.source.value}", diff --git a/src/bernstein/cli/commands/verify_cmd.py b/src/bernstein/cli/commands/verify_cmd.py index 865606584..fa8883f47 100644 --- a/src/bernstein/cli/commands/verify_cmd.py +++ b/src/bernstein/cli/commands/verify_cmd.py @@ -643,7 +643,7 @@ def _verify_determinism( fingerprint = fp.compute() - if expect is None and baseline_run_id is None: + if expect is None is baseline_run_id: # Bare mode: observe-only, byte-identical to the original surface. # The entry count is only displayed in this branch, so the second WAL # scan stays scoped here rather than running for every gated call. diff --git a/src/bernstein/cli/commands/worktrees_cmd.py b/src/bernstein/cli/commands/worktrees_cmd.py index 53ae8f7e4..77ce36f85 100644 --- a/src/bernstein/cli/commands/worktrees_cmd.py +++ b/src/bernstein/cli/commands/worktrees_cmd.py @@ -318,7 +318,7 @@ def gc_cmd(workdir: Path, yes: bool, dry_run: bool, force_unsaved: bool) -> None console.print("[green]No reapable worktrees - nothing to do.[/green]") return - targets = list(reapable) + targets = reapable.copy() if force_unsaved: targets.extend(unsaved) diff --git a/src/bernstein/cli/ui.py b/src/bernstein/cli/ui.py index 99aadc73f..345e782dd 100644 --- a/src/bernstein/cli/ui.py +++ b/src/bernstein/cli/ui.py @@ -156,7 +156,7 @@ def from_dict(cls, data: str | dict[str, Any]) -> AgentInfo: role=str(data.get("role", "")), model=str(data.get("model", "")), status=str(data.get("status", "idle")), - task_ids=list(cast("list[str]", data.get("task_ids") or [])), + task_ids=cast("list[str]", data.get("task_ids") or []).copy(), runtime_s=float(data.get("runtime_s", 0.0)), abort_reason=str(data.get("abort_reason", "")), abort_detail=str(data.get("abort_detail", "")), diff --git a/src/bernstein/core/approval/gate.py b/src/bernstein/core/approval/gate.py index beb1d8f7a..e248a74f9 100644 --- a/src/bernstein/core/approval/gate.py +++ b/src/bernstein/core/approval/gate.py @@ -96,8 +96,7 @@ def load_approval_config(workdir: Path | None = None) -> ApprovalConfig: return ApprovalConfig() if not isinstance(raw, dict): return ApprovalConfig() - raw_mapping = cast("dict[str, Any]", raw) - raw_section: object = raw_mapping.get("approvals") + raw_section: object = cast("dict[str, Any]", raw).get("approvals") if not isinstance(raw_section, dict): return ApprovalConfig() section = cast("dict[str, Any]", raw_section) diff --git a/src/bernstein/core/config/home.py b/src/bernstein/core/config/home.py index 7fc16a74e..e473e6e88 100644 --- a/src/bernstein/core/config/home.py +++ b/src/bernstein/core/config/home.py @@ -208,8 +208,7 @@ def _load(self) -> dict[str, Any]: def load_raw(self) -> dict[str, object]: """Return raw persisted global settings without default expansion.""" - data = self._load() - return dict(data) + return self._load().copy() def _save(self, data: dict[str, Any]) -> None: """Persist data to config.yaml, creating home dir if needed.""" diff --git a/src/bernstein/core/cost/retry_budget.py b/src/bernstein/core/cost/retry_budget.py index 38170775e..3d6f538ff 100644 --- a/src/bernstein/core/cost/retry_budget.py +++ b/src/bernstein/core/cost/retry_budget.py @@ -524,7 +524,7 @@ def _is_criterion_name(name: str) -> bool: first = name[0] if not (first == "_" or "A" <= first <= "Z" or "a" <= first <= "z"): return False - return all(ch == "_" or ch == "-" or "0" <= ch <= "9" or "A" <= ch <= "Z" or "a" <= ch <= "z" for ch in name[1:]) + return all(ch in ("_", "-") or "0" <= ch <= "9" or "A" <= ch <= "Z" or "a" <= ch <= "z" for ch in name[1:]) def _split_retry_budget_spec(spec: str) -> tuple[int, str | None]: diff --git a/src/bernstein/core/orchestration/schedule_supervisor.py b/src/bernstein/core/orchestration/schedule_supervisor.py index 34bfa2cdb..3e24767f1 100644 --- a/src/bernstein/core/orchestration/schedule_supervisor.py +++ b/src/bernstein/core/orchestration/schedule_supervisor.py @@ -624,7 +624,7 @@ def _read_schedule_fire_entries(sdd_dir: Path) -> dict[tuple[str, int], dict[str key = (str(details["schedule_id"]), int(details["fire_time"])) except (KeyError, TypeError, ValueError): continue - enriched: dict[str, Any] = dict(details) + enriched: dict[str, Any] = details.copy() enriched["__hmac__"] = str(entry.get("hmac", "")) # Last writer wins: later daily segments override earlier ones # for the same (id, fire_time), which cannot legitimately @@ -704,26 +704,24 @@ def ok(self) -> bool: def to_json(self) -> list[dict[str, Any]]: """Return a JSON-safe per-receipt view for ``--json`` output.""" - out: list[dict[str, Any]] = [] - for r in self.results: - out.append( - { - "schedule_id": r.schedule_id, - "fire_time": r.fire_time, - "counterfactual": r.counterfactual, - "rev": r.rev, - "recorded_projection_hash": r.recorded_projection_hash, - "recomputed_projection_hash": r.recomputed_projection_hash, - "projection_match": r.projection_match, - "chain_match": r.chain_match, - "rev_skipped": r.rev_skipped, - "skipped": r.skipped, - "verified": r.verified, - "mismatch": r.mismatch, - "reasons": list(r.reasons), - }, - ) - return out + return [ + { + "schedule_id": r.schedule_id, + "fire_time": r.fire_time, + "counterfactual": r.counterfactual, + "rev": r.rev, + "recorded_projection_hash": r.recorded_projection_hash, + "recomputed_projection_hash": r.recomputed_projection_hash, + "projection_match": r.projection_match, + "chain_match": r.chain_match, + "rev_skipped": r.rev_skipped, + "skipped": r.skipped, + "verified": r.verified, + "mismatch": r.mismatch, + "reasons": list(r.reasons), + } + for r in self.results + ] def verify_receipts(sdd_dir: Path) -> AuditReport: diff --git a/src/bernstein/core/replay/gateway.py b/src/bernstein/core/replay/gateway.py index f88481c64..15c110a3c 100644 --- a/src/bernstein/core/replay/gateway.py +++ b/src/bernstein/core/replay/gateway.py @@ -25,6 +25,7 @@ import json import logging +import operator import os import threading import time @@ -319,7 +320,7 @@ def _load_fixtures(self) -> None: # Sort by (seq, file_pos) so the per-kind lists are in recorded order # even if the log was written or stitched out of strict line order. - rows.sort(key=lambda r: (r[0], r[1])) + rows.sort(key=operator.itemgetter(0, 1)) for _seq, _pos, kind, key, response in rows: ordered = self._ordered_by_kind.setdefault(kind, []) fixture = _Fixture(response=response) diff --git a/src/bernstein/core/routing/bandit_router.py b/src/bernstein/core/routing/bandit_router.py index f685b2998..bb88334b1 100644 --- a/src/bernstein/core/routing/bandit_router.py +++ b/src/bernstein/core/routing/bandit_router.py @@ -553,7 +553,7 @@ def _load_arm_matrices( if not _is_matrix(raw_matrix, FEATURE_DIM) or not _is_vector(raw_vector, FEATURE_DIM): logger.info("BanditPolicy: resetting %s because arm %s has incompatible dimensions", path, arm) return None - matrix = [list(row) for row in raw_matrix] + matrix = [row.copy() for row in raw_matrix] loaded_inv[arm] = matrix if arm in raw_inv_by_arm else _inv(matrix) loaded_vec[arm] = list(raw_vector) diff --git a/src/bernstein/core/security/permission_policy.py b/src/bernstein/core/security/permission_policy.py index 23a956d77..62aa38f90 100644 --- a/src/bernstein/core/security/permission_policy.py +++ b/src/bernstein/core/security/permission_policy.py @@ -241,8 +241,7 @@ def _load_yaml_permissions(workdir: Path) -> Mapping[str, Any] | None: return None if not isinstance(raw, dict): return None - raw_mapping = cast("Mapping[str, Any]", raw) - section = raw_mapping.get("permissions") + section = cast("Mapping[str, Any]", raw).get("permissions") if not isinstance(section, dict): return None return cast("Mapping[str, Any]", section) diff --git a/src/bernstein/core/skills/authoring.py b/src/bernstein/core/skills/authoring.py index 88d3b2bc7..7d130caa9 100644 --- a/src/bernstein/core/skills/authoring.py +++ b/src/bernstein/core/skills/authoring.py @@ -102,8 +102,7 @@ def load_trigger_suite(path: Path) -> tuple[TriggerCase, ...]: raise SkillAuthoringError(f"{path}: failed to read trigger suite: {exc}") from exc if not isinstance(loaded, dict): raise SkillAuthoringError(f"{path}: suite must be a YAML mapping") - suite_data = cast("dict[str, object]", loaded) - raw_cases = suite_data.get("cases") + raw_cases = cast("dict[str, object]", loaded).get("cases") if not isinstance(raw_cases, list): raise SkillAuthoringError(f"{path}: suite must contain a cases list") diff --git a/src/bernstein/core/skills/routing.py b/src/bernstein/core/skills/routing.py index 79f434b4e..197c7569c 100644 --- a/src/bernstein/core/skills/routing.py +++ b/src/bernstein/core/skills/routing.py @@ -158,7 +158,7 @@ def _cosine(left: dict[str, float], right: dict[str, float]) -> float: return 0.0 left_norm = math.sqrt(sum(weight * weight for weight in left.values())) right_norm = math.sqrt(sum(weight * weight for weight in right.values())) - if left_norm == 0 or right_norm == 0: + if 0 in (left_norm, right_norm): return 0.0 return numerator / (left_norm * right_norm) diff --git a/src/bernstein/sdd/validator.py b/src/bernstein/sdd/validator.py index b0f9b7455..a8e1f639b 100644 --- a/src/bernstein/sdd/validator.py +++ b/src/bernstein/sdd/validator.py @@ -174,8 +174,7 @@ def load_schema(version: str = "v1") -> dict[str, Any]: raise SchemaNotFoundError(f"schema {filename} is not valid JSON: {exc}") from exc if not isinstance(loaded_raw, dict): raise SchemaNotFoundError(f"schema {filename} is not a JSON object") - loaded_dict = cast("dict[str, Any]", loaded_raw) - loaded: dict[str, Any] = dict(loaded_dict) + loaded: dict[str, Any] = cast("dict[str, Any]", loaded_raw).copy() # Sanity-check it really is Draft-07 compatible. jsonschema.Draft7Validator.check_schema(loaded) _SCHEMA_CACHE[canonical] = loaded