You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Follow-up from PR #88 — contracts/constants.json shipped with only one constant covered (S9 / Option C); other triplicated constants should follow the same pattern.
Functional description
PR #88 commit 03e9b39 introduced contracts/constants.json as the single source of truth for constants shared across:
Python (agent runtime, agent/src/policy.py reads at import)
TypeScript runtime (CDK Lambdas, cdk/src/handlers/shared/types.ts via resolveJsonModule)
It also shipped scripts/check-constants-sync.ts as a prek hook that fails CI if anyone re-introduces a literal of the owned constants in agent/src/policy.py.
The contract works, but it covers only APPROVAL_GATE_CAP (min/max/default). Other constants live in the same triplication today and would benefit from the same treatment:
APPROVAL_TIMEOUT_S_MIN / MAX (declared in both agent/src/hooks.py and cdk/src/handlers/shared/types.ts)
Until these migrate, any future "Update branch" or upstream merge can silently bump them in one place but not the others — exactly the failure mode the contract was designed to prevent.
User-visible impact (today):
A future Cedar HITL feature that depends on a value matching across Python and TS is one merge conflict away from silent drift.
The pattern is now established but only partially applied; new contributors won't know to keep using it.
Technical context
Where to start the audit:
Run grep -rn "APPROVAL_TIMEOUT_S_M\|POLL_.*_INTERVAL\|CACHE_.*_ENTRIES\|APPROVAL_RATE" agent/src/ cdk/src/handlers/shared/types.ts. Compare values; add to JSON; wire consumers; extend scripts/check-constants-sync.ts with the new owned names.
What the migration looks like per constant:
Add to contracts/constants.json under a new key (e.g. approval_timeout_s.{min,max,default}).
Update agent/src/policy.py (or hooks.py) to read from _SHARED_CONSTANTS (the existing loader).
Update cdk/src/handlers/shared/types.ts to import from JSON.
Add the new owned name to OWNED_PYTHON_PATTERNS in scripts/check-constants-sync.ts.
Update contracts/constants.md schema section.
Estimated effort: ~30 minutes per constant, plus testing. The APPROVAL_TIMEOUT_S_MIN/MAX pair is the most valuable ROI because it pairs with the existing approval-cap constants and would have been on the original Option C migration if there'd been time.
Why this is P3:
Today's literals work; CI's drift check catches the canonical case.
The pattern is in place; future contributors can see it.
Risk of new bugs is low (each constant is value-for-value identical pre/post migration).
Proposed approach
Land in batches:
Batch 1 (~30 min):APPROVAL_TIMEOUT_S_MIN/MAX/DEFAULT — same shape as the existing approval_gate_cap; trivially generalizable.
Batch 2: poll intervals — group as a single polling.{fast_interval_s,slow_duration_s,slow_interval_s} object.
Batch 3: cache + rate-limit constants if appetite remains.
Do batch 1 in a dedicated PR to validate the pattern still scales; subsequent batches can be smaller PRs.
Acceptance criteria
Batch 1 lands: APPROVAL_TIMEOUT_S_MIN/MAX/DEFAULT migrated to contracts/constants.json
scripts/check-constants-sync.ts allowlist updated to include the new names
contracts/constants.md schema section updated
Tests on both sides reference the new names
No literal declarations remain for the migrated names (verified by the drift check)
Out of scope
Migrating non-numeric constants (the loader pattern only covers ints today; strings/lists need separate consideration).
Migrating constants that aren't actually triplicated.
Companion: this issue extends the pattern from S9; see also the cedar-parity guardrails added in commit 6a8ec95 for a sibling "we shipped the contract, didn't extend it" pattern.
Functional description
PR #88 commit
03e9b39introducedcontracts/constants.jsonas the single source of truth for constants shared across:agent/src/policy.pyreads at import)cdk/src/handlers/shared/types.tsviaresolveJsonModule)cdk/src/constructs/blueprint.tsreads JSON directly)It also shipped
scripts/check-constants-sync.tsas a prek hook that fails CI if anyone re-introduces a literal of the owned constants inagent/src/policy.py.The contract works, but it covers only
APPROVAL_GATE_CAP(min/max/default). Other constants live in the same triplication today and would benefit from the same treatment:APPROVAL_TIMEOUT_S_MIN/MAX(declared in bothagent/src/hooks.pyandcdk/src/handlers/shared/types.ts)POLL_FAST_INTERVAL_S,POLL_SLOW_INTERVAL_S, etc.)CACHE_MAX_ENTRIES,CACHE_TTL_SAPPROVAL_RATE_LIMIT,APPROVAL_RATE_WINDOW_SUntil these migrate, any future "Update branch" or upstream merge can silently bump them in one place but not the others — exactly the failure mode the contract was designed to prevent.
User-visible impact (today):
Technical context
Where to start the audit:
grep -rn "APPROVAL_TIMEOUT_S_M\|POLL_.*_INTERVAL\|CACHE_.*_ENTRIES\|APPROVAL_RATE" agent/src/ cdk/src/handlers/shared/types.ts. Compare values; add to JSON; wire consumers; extendscripts/check-constants-sync.tswith the new owned names.What the migration looks like per constant:
contracts/constants.jsonunder a new key (e.g.approval_timeout_s.{min,max,default}).agent/src/policy.py(orhooks.py) to read from_SHARED_CONSTANTS(the existing loader).cdk/src/handlers/shared/types.tsto import from JSON.OWNED_PYTHON_PATTERNSinscripts/check-constants-sync.ts.contracts/constants.mdschema section.Estimated effort: ~30 minutes per constant, plus testing. The
APPROVAL_TIMEOUT_S_MIN/MAXpair is the most valuable ROI because it pairs with the existing approval-cap constants and would have been on the original Option C migration if there'd been time.Why this is P3:
Proposed approach
Land in batches:
APPROVAL_TIMEOUT_S_MIN/MAX/DEFAULT— same shape as the existingapproval_gate_cap; trivially generalizable.polling.{fast_interval_s,slow_duration_s,slow_interval_s}object.Do batch 1 in a dedicated PR to validate the pattern still scales; subsequent batches can be smaller PRs.
Acceptance criteria
APPROVAL_TIMEOUT_S_MIN/MAX/DEFAULTmigrated tocontracts/constants.jsonscripts/check-constants-sync.tsallowlist updated to include the new namescontracts/constants.mdschema section updatedOut of scope
References
contracts/constants.json(existing source-of-truth)contracts/constants.md(schema doc)scripts/check-constants-sync.ts(drift check)03e9b39(the establishing commit)6a8ec95for a sibling "we shipped the contract, didn't extend it" pattern.