Skip to content

ci: read the ops-cadence price date from price_table.py - #847

Merged
bmdhodl merged 2 commits into
mainfrom
claude/ops-cadence-price-check
Oct 5, 2026
Merged

bmdhodl merged 2 commits into
mainfrom
claude/ops-cadence-price-check

Conversation

@bmdhodl

@bmdhodl bmdhodl commented Oct 5, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • ops-cadence.yml reads the price-table date from "last_updated" in sdk/agentguard/price_table.py. Since Merge the two price tables and fix current-model pricing #792, cost.py only has LAST_UPDATED = DEFAULT_PRICE_TABLE["last_updated"], so the old sed for a literal date printed nothing and every weekday run would post a false "missing or unparseable" warning.
  • The warning and reminder text name price_table.py and the DEFAULT_PRICE_TABLE markers (version, last_updated, verified) instead of cost.py and LAST_UPDATED.
  • New regression test test_ops_cadence_reads_the_price_table_date in sdk/tests/test_ci_guardrails.py. It takes the sed pattern and file from the workflow and checks that they give exactly DEFAULT_PRICE_TABLE["last_updated"]. If the date moves again, CI fails.
  • ops/FOLLOWUP.md: the price-check defect entry is replaced by a short note that the workflow stays disabled until the owner turns it on.

Goal: a correct price-age check when the workflow runs again. Scope: one sed line and five message lines in ops-cadence.yml, one test, one follow-up note. Non-goals: turning the workflow on, changing prices or price_table.py, changing the 90-day rule. Done: the check reads the real date, the regression test fails before and passes after, the checks below pass, and the proof is saved (ops/04-DEFINITION_OF_DONE.md).

Related Issues

Follow-up recorded in #846 (ops/FOLLOWUP.md). The date moved in #792.

Proof

Saved under proof/ops-cadence-price-check/ (Windows 11, Python 3.13.2, Git Bash 5.2.37; make is not installed, so each command ran directly).

Command Result
new test and verify.py on the unchanged workflow both fail; the sed finds []
run block of ops-cadence.yml, extracted with PyYAML, gh stubbed (guarded), Monday forced today: price_date=2026-09-26 price_age=9, no warning; +100 days: "109 days since last hand-verify" reminder; key renamed in a copy: warning plus "missing or unparseable"
python scripts/sdk_preflight.py exit 0
python scripts/review_readiness_guard.py exit 0
python scripts/ci_tools_requirements_guard.py exit 0
pytest sdk/tests/test_architecture.py 9 passed
pytest sdk/tests/test_ci_guardrails.py sdk/tests/test_cost.py 37 passed
ruff check on sdk/agentguard/ and the changed test exit 0
python scripts/sdk_release_guard.py Release guard passed
pytest sdk/tests/ --cov=agentguard --cov-fail-under=80 1592 passed, 3 skipped; coverage 93%
python proof/ops-cadence-price-check/verify.py Verified ops-cadence price check

Not run here: actionlint and shellcheck are not installed on this host. The Actionlint workflow runs both on this PR.

showwork session ops-cadence-price-check: VERIFIED, all checks green, with verify.py as the declared acceptance check.

Review Readiness

  • Public positioning claims have a source/fact ledger. N/A, no positioning change.
  • State, lock, file, or process-concurrency changes include cross-platform failure proof. N/A.
  • External API collectors include response-shape, pagination, null, and partial-failure tests. N/A.
  • Proof artifacts include command, exit code, platform, and regenerated-after-review status. Yes, as listed above; not yet regenerated after review.
  • Workflow changes explain trigger scope, timeouts, concurrency, artifacts, and spend impact. Only the file that one sed reads and the issue text change. Trigger (weekday cron plus manual dispatch), permissions, timeouts, concurrency, artifacts and spend do not change. The workflow is disabled_manually (last run 2026-06-11), so nothing runs until someone turns it on.

Risk And Rollback

Low. If price_table.py changes the "last_updated" line format, the workflow posts the "missing or unparseable" warning (fail loud), and the new test fails in CI first. To roll back, revert this commit.

Tradeoff: sed on the source line keeps the step free of a Python setup and an SDK import. Reading the value through Python would survive any reformat, but the test already catches a reformat.

Scope

  • Related ops/doc(s): N/A (ops automation; ops/FOLLOWUP.md)
  • Does this change the public API? No.
  • Does this shift roadmap priority? No.

Checklist

  • make check passes: 1592 passed, 3 skipped, coverage 93%; ruff exit 0
  • make structural passes (9 passed)
  • make security passes: not run, no SDK runtime code changed
  • New functionality has tests: regression test, verify.py, stubbed workflow-step runs
  • No new hard dependencies in core SDK
  • No hardcoded absolute paths
  • If __init__.py exports changed, ops/02-ARCHITECTURE.md updated. N/A.

🤖 Generated with Claude Code


Note

Low Risk
CI workflow and guardrail test only; no SDK runtime or pricing logic changes, and the workflow stays disabled.

Overview
Fixes a broken ops-cadence price staleness check: after #792 moved the canonical date to DEFAULT_PRICE_TABLE["last_updated"] in sdk/agentguard/price_table.py, the workflow still sed'd a literal LAST_UPDATED line in cost.py, got nothing, and would have filed false "missing or unparseable" warnings on every run.

The workflow now parses "last_updated" from price_table.py and updates issue/reminder copy to point at DEFAULT_PRICE_TABLE (version, last_updated, verified) instead of cost.py / LAST_UPDATED. A regression test in test_ci_guardrails.py mirrors the workflow sed and asserts it matches DEFAULT_PRICE_TABLE["last_updated"]. ops/FOLLOWUP.md records the fix; the workflow remains manually disabled until an owner re-enables it.

Proof lives under proof/ops-cadence-price-check/ (verify.py, stubbed Git Bash runs, showwork receipts).

Reviewed by Cursor Bugbot for commit 6b90b4a. Bugbot is set up for automated code reviews on this repo. Configure here.

Since #792, cost.py only aliases LAST_UPDATED to
DEFAULT_PRICE_TABLE["last_updated"], so the sed for a literal date printed
nothing and every weekday run would post a false "missing or unparseable"
price warning. The sed now reads "last_updated" from price_table.py, and the
warning and reminder text name that file and its markers.

A regression test takes the sed pattern and file from the workflow and
checks they give exactly DEFAULT_PRICE_TABLE["last_updated"]. The workflow
stays disabled_manually; turning it on is the owner's call.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 5, 2026 17:33
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@bmdhodl
bmdhodl enabled auto-merge (squash) October 5, 2026 17:34
@cursor

cursor Bot commented Oct 5, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: f2bfa08f-32ec-44a4-9681-cc28cf06fc84)

@github-actions

github-actions Bot commented Oct 5, 2026

Copy link
Copy Markdown

🤖 Claude review

No blocking issues. One minor quality note.

Review

Core change — .github/workflows/ops-cadence.yml

The sed rewrite is correct:

# before
sed -n 's/^LAST_UPDATED = "\(.*\)"/\1/p' sdk/agentguard/cost.py

# after
sed -n 's/^ *"last_updated": "\([^"]*\)".*/\1/p' sdk/agentguard/price_table.py

The BRE is well-formed: ^ * handles Python dict indentation, [^"]* bounds the capture correctly, ".* consumes the trailing comma. The three failure-mode branches (missing/future/stale) are updated consistently. No logic changes outside the sed target.

Regression test — sdk/tests/test_ci_guardrails.py:304

The test extracts the live sed pattern from the workflow file and replays it in Python. The BRE→Python conversion (\( → (, \) → )) is correct. fullmatch with the trailing .* handles dict line suffixes (commas, etc.). The test would fail in CI if the workflow sed drifts from price_table.py again. Sound.

proof/ops-cadence-price-check/price_step.py

This script requires import yaml (PyYAML) with no comment or README note that it needs an extra install. It's a local proof helper, not a CI job, so it won't break anything — but a future maintainer running it on a bare Python install will get a silent ModuleNotFoundError. Consider adding a comment or the README could note pip install pyyaml before running it.

Security

verify.py uses subprocess.run with a list (no shell=True), cwd derived from __file__ — no injection surface. Workflow reads a repo-local file; [^"]* caps the capture. Nothing of concern.


The one note above (price_step.py undocumented yaml dep) is non-blocking. Everything else is clean.

Answers the Claude review note on #847: price_step.py imports yaml, which is
not an SDK dependency. The docstring and the proof README now say so.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@bmdhodl

bmdhodl commented Oct 5, 2026

Copy link
Copy Markdown
Owner Author

Re the Claude review note on price_step.py (#847 (comment)): fixed in 6b90b4a. The docstring and the proof README now say it needs PyYAML (pip install pyyaml), which is not an SDK dependency. No behavior change; verify.py still passes (showwork session ops-cadence-price-check-review: VERIFIED).

🤖 Addressed by Claude Code

@cursor

cursor Bot commented Oct 5, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: 4c2bf139-6cb0-4c3e-8973-c4383e4b2713)

@github-actions

github-actions Bot commented Oct 5, 2026

Copy link
Copy Markdown

🤖 Claude review

LGTM - no blocking issues.

The change is a targeted, correct fix: the sed pattern is updated from the stale LAST_UPDATED = "..." literal in cost.py to "last_updated": "..." in price_table.py, the regression test correctly simulates sed's BRE substitution via Python fullmatch, proof artifacts cover before/after and all three failure modes, and the FOLLOWUP entry is updated accurately.

One minor observation worth noting for future maintainers, not blocking:

sdk/tests/test_ci_guardrails.py:305 — the regex used to extract the sed pattern from the workflow ('s/(.+)/\\1/p') assumes the sed replacement is always exactly \1. If the replacement were ever \1\2 or similar, the regex would fail to match and the test would assert found is not None — which is the desired failure mode, so the behavior is correct. Just a tight coupling to be aware of if the sed command changes shape.

@bmdhodl

bmdhodl commented Oct 5, 2026

Copy link
Copy Markdown
Owner Author

Re the second Claude review note (the test regex expects a \1 replacement): no change. That coupling is on purpose. If the sed command changes shape, the test fails on found is not None with "ops-cadence.yml must read the price date with one sed substitution", so the person who changes it must update the test too.

🤖 Addressed by Claude Code

@bmdhodl
bmdhodl merged commit bb511ac into main Oct 5, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants