Skip to content

Extend contracts/constants.json to other triplicated constants #116

@scoropeza

Description

@scoropeza

Follow-up from PR #88contracts/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)
  • TypeScript synth (CDK constructs, cdk/src/constructs/blueprint.ts reads JSON directly)

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)
  • Polling intervals (POLL_FAST_INTERVAL_S, POLL_SLOW_INTERVAL_S, etc.)
  • CACHE_MAX_ENTRIES, CACHE_TTL_S
  • APPROVAL_RATE_LIMIT, APPROVAL_RATE_WINDOW_S

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:

  1. Add to contracts/constants.json under a new key (e.g. approval_timeout_s.{min,max,default}).
  2. Update agent/src/policy.py (or hooks.py) to read from _SHARED_CONSTANTS (the existing loader).
  3. Update cdk/src/handlers/shared/types.ts to import from JSON.
  4. Add the new owned name to OWNED_PYTHON_PATTERNS in scripts/check-constants-sync.ts.
  5. 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:

  1. Batch 1 (~30 min): APPROVAL_TIMEOUT_S_MIN/MAX/DEFAULT — same shape as the existing approval_gate_cap; trivially generalizable.
  2. Batch 2: poll intervals — group as a single polling.{fast_interval_s,slow_duration_s,slow_interval_s} object.
  3. 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.
  • Sweeping CLI-side constants (different concern).

References

  • contracts/constants.json (existing source-of-truth)
  • contracts/constants.md (schema doc)
  • scripts/check-constants-sync.ts (drift check)
  • PR feat: Cedar HITL approval gates for agent tool use #88 commit 03e9b39 (the establishing commit)
  • 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions