M1: Implement normalized capacity contract v1 #4

Closed
opened 2026-09-02 12:25:52 +00:00 by creatidy · 0 comments
creatidy commented 2026-09-02 12:25:52 +00:00 (Migrated from github.com)

M1: Implement normalized capacity contract v1

Objective

Provide one small, provider-independent Python implementation that:

  • represents a v1 normalized capacity snapshot (a point-in-time observation);
  • validates its invariants and fails closed on contract violations;
  • serializes deterministically to the documented internal v1 JSON shape;
  • distinguishes known zero from absent/unknown;
  • supports quota-based providers (OpenAI/Z.ai shapes) and Ollama-style local runtime facts;
  • represents unknown semantics explicitly (resource/kind unknown);
  • contains no provider parsing, credential access, network or subprocess behavior.

This is the implementation target for later provider adapters (the Z.ai/Codex parsers are separate, follow-on tasks that emit this model).

Contract reference (authoritative for schema v1): docs/capacity-model.md — the "Freeze normalized capacity contract v1" work, accepted as decision U-002 in docs/decisions.md and shipped on origin/main via PR #2.

Exact scope

A new small Python module (standard library only) that defines and enforces the frozen v1 schema:

  • schema_version integer 1 (reject any other value or type);
  • top-level fields exactly as documented: provider, source, plan (optional), retrieved_at, status, windows, optional local_runtime, diagnostics;
  • the six frozen provider statuses (ok, unavailable, auth_required, unsupported, schema_changed, unknown) — provider-specific error types must not appear as new statuses;
  • the 13-code diagnostic allowlist, with window-scoped codes (window_id allowed) vs. snapshot-scoped codes (must have no window_id), and the required status-to-code coupling for non-ok snapshots;
  • canonical UTC timestamp format YYYY-MM-DDTHH:MM:SS.sssZ (exactly three fractional digits, literal Z); reject offsets, local times, and non-canonical forms;
  • quota windows: independent resource (tokens | time | unknown) and kind (five_hour | weekly | unknown); optional duration_seconds (positive integer; fixed 18000 for five_hour and 604800 for weekly); optional complementary used_percent/remaining_percent pair; optional canonical resets_at; optional safe provider_metadata.window_id;
  • the percentage invariant: both present or both absent; both integers in 0..100; exact complement; used=0/remaining=100 (known empty) and used=100/remaining=0 (known exhausted) are distinct from an omitted pair (unknown);
  • failure-state invariants: unavailable, auth_required, unsupported, schema_changed snapshots must have an empty windows array;
  • local runtime facts (reachability, model presence, safe model name, optional configured/effective context) — never a fake quota or "unlimited";
  • safe identifier validation (non-empty ASCII, [a-z0-9][a-z0-9._:-]*, max 64 chars) for provider, source, plan, model_name, window_id;
  • deterministic JSON-compatible serialization: optional unknown values omitted, zeros preserved, enum values emitted as frozen strings, canonical timestamps, no Python implementation detail, and the serialized record round-trips through validation.

Explicit non-scope

  • No Z.ai parser, Codex parser, or Ollama acquisition;
  • No credential access, HTTP calls, or subprocess communication;
  • No status, doctor, select or any CLI/REST/MCP command;
  • No freshness policy, caching, or selector/scarcity logic;
  • No capability catalog or profile logic;
  • No provider fixture parsing in this task (the existing Z.ai fixtures remain the evidence input for the later adapter task and are not modified).

Does not resolve U-001, U-003, U-005, U-006, or U-007. U-004 evidence is input, not work for this change.

Tests required

Deterministic, self-contained tests covering the contract invariants. At minimum:

Valid cases

  1. OpenAI-like healthy snapshot with five-hour and weekly windows;
  2. Z.ai-like healthy snapshot with known windows plus an unknown-semantic window;
  3. Ollama-like reachable local snapshot with no quota windows;
  4. used_percent = 0 (known empty window);
  5. remaining_percent = 0 (known exhausted window);
  6. Snapshot with percentage pair genuinely omitted (unknown);
  7. Canonical reset and retrieval timestamps;
  8. Deterministic serialization / round-trip through validation.

Invalid cases (must be rejected)

  1. Unsupported schema_version;
  2. Invalid provider status (outside the frozen six);
  3. Only one of used_percent / remaining_percent present;
  4. Percentage value outside 0..100 (including non-integer, boolean, or negative);
  5. Contradictory used_percent/remaining_percent pair (sum not 100);
  6. Invalid or non-canonical timestamp (offset, local time, or extra/missing fraction);
  7. Quota windows attached to auth_required, unsupported, or schema_changed;
  8. A local runtime represented as a fake quota percentage;
  9. An unsafe identifier value (uppercase, leading punctuation, over-length, or containing a credential-shaped fragment);
  10. A diagnostic code outside the 13-code allowlist.

Additionally, tests must demonstrate explicitly that these are distinct states: a known used_percent = 0, a known remaining_percent = 0, and an absent percentage pair.

AGENTS workflow hardening (corrective governance change)

The M1 reconnaissance task left valuable uncommitted work on main that a dependent agent then bypassed with a secondary worktree. AGENTS.md gains a concise repository workflow section so this cannot silently recur. Invariants to be captured:

  • no substantive file modification while checked out on main;
  • an issue must exist and a feature branch created before the first task-related file edit;
  • one issue to one feature branch to one PR, targeting main;
  • the agent leaves its PR open for human review and does not merge it;
  • if uncommitted, unmerged work from an earlier project task blocks a later task, that earlier work must be resolved through its own issue/branch/PR first;
  • a clean secondary worktree is permitted only for genuinely unrelated user changes, never as a bypass for an unmet dependency;
  • unrelated user work is preserved untouched;
  • before completion, verify origin/main..HEAD contains only this task's diff (no unintended merge commits, no unrelated files).

Acceptance criteria

  1. A new Python package (standard library only, Python 3.12+) with the v1 model, validation, and deterministic serialization described above.
  2. The tests listed under "Tests required" pass deterministically.
  3. Full existing test suite (if any) continues to pass.
  4. git diff --check clean over the changed/new files; secret-pattern scan over the changed/new files is clean.
  5. AGENTS.md contains the new repository-workflow section with the invariants above.
  6. origin/main..HEAD contains only this issue's changes, no merge commit, no unrelated files, and no credential or raw sensitive provider material.
  7. Exactly one open PR targeting main, left unmerged, with Closes #<issue> in its body.
# M1: Implement normalized capacity contract v1 ## Objective Provide one small, provider-independent Python implementation that: - represents a v1 normalized capacity snapshot (a point-in-time observation); - validates its invariants and fails closed on contract violations; - serializes deterministically to the documented internal v1 JSON shape; - distinguishes **known zero** from **absent/unknown**; - supports quota-based providers (OpenAI/Z.ai shapes) and Ollama-style local runtime facts; - represents unknown semantics explicitly (resource/kind `unknown`); - contains **no** provider parsing, credential access, network or subprocess behavior. This is the implementation target for later provider adapters (the Z.ai/Codex parsers are separate, follow-on tasks that emit this model). Contract reference (authoritative for schema v1): `docs/capacity-model.md` — the "Freeze normalized capacity contract v1" work, accepted as decision `U-002` in `docs/decisions.md` and shipped on `origin/main` via PR #2. ## Exact scope A new small Python module (standard library only) that defines and enforces the frozen v1 schema: - `schema_version` integer `1` (reject any other value or type); - top-level fields exactly as documented: `provider`, `source`, `plan` (optional), `retrieved_at`, `status`, `windows`, optional `local_runtime`, `diagnostics`; - the six frozen provider statuses (`ok`, `unavailable`, `auth_required`, `unsupported`, `schema_changed`, `unknown`) — provider-specific error types must not appear as new statuses; - the 13-code diagnostic allowlist, with window-scoped codes (`window_id` allowed) vs. snapshot-scoped codes (must have no `window_id`), and the required status-to-code coupling for non-`ok` snapshots; - canonical UTC timestamp format `YYYY-MM-DDTHH:MM:SS.sssZ` (exactly three fractional digits, literal `Z`); reject offsets, local times, and non-canonical forms; - quota windows: independent `resource` (`tokens` | `time` | `unknown`) and `kind` (`five_hour` | `weekly` | `unknown`); optional `duration_seconds` (positive integer; fixed 18000 for `five_hour` and 604800 for `weekly`); optional complementary `used_percent`/`remaining_percent` pair; optional canonical `resets_at`; optional safe `provider_metadata.window_id`; - the percentage invariant: both present or both absent; both integers in 0..100; exact complement; `used=0`/`remaining=100` (known empty) and `used=100`/`remaining=0` (known exhausted) are distinct from an **omitted** pair (unknown); - failure-state invariants: `unavailable`, `auth_required`, `unsupported`, `schema_changed` snapshots must have an **empty** `windows` array; - local runtime facts (reachability, model presence, safe model name, optional configured/effective context) — never a fake quota or "unlimited"; - safe identifier validation (non-empty ASCII, `[a-z0-9][a-z0-9._:-]*`, max 64 chars) for `provider`, `source`, `plan`, `model_name`, `window_id`; - deterministic JSON-compatible serialization: optional unknown values omitted, zeros preserved, enum values emitted as frozen strings, canonical timestamps, no Python implementation detail, and the serialized record round-trips through validation. ## Explicit non-scope - No Z.ai parser, Codex parser, or Ollama acquisition; - No credential access, HTTP calls, or subprocess communication; - No `status`, `doctor`, `select` or any CLI/REST/MCP command; - No freshness policy, caching, or selector/scarcity logic; - No capability catalog or profile logic; - No provider fixture parsing in this task (the existing Z.ai fixtures remain the evidence input for the later adapter task and are not modified). Does **not** resolve `U-001`, `U-003`, `U-005`, `U-006`, or `U-007`. `U-004` evidence is input, not work for this change. ## Tests required Deterministic, self-contained tests covering the contract invariants. At minimum: **Valid cases** 1. OpenAI-like healthy snapshot with five-hour and weekly windows; 2. Z.ai-like healthy snapshot with known windows plus an unknown-semantic window; 3. Ollama-like reachable local snapshot with no quota windows; 4. `used_percent = 0` (known empty window); 5. `remaining_percent = 0` (known exhausted window); 6. Snapshot with percentage pair genuinely omitted (unknown); 7. Canonical reset and retrieval timestamps; 8. Deterministic serialization / round-trip through validation. **Invalid cases** (must be rejected) 1. Unsupported `schema_version`; 2. Invalid provider status (outside the frozen six); 3. Only one of `used_percent` / `remaining_percent` present; 4. Percentage value outside 0..100 (including non-integer, boolean, or negative); 5. Contradictory `used_percent`/`remaining_percent` pair (sum not 100); 6. Invalid or non-canonical timestamp (offset, local time, or extra/missing fraction); 7. Quota windows attached to `auth_required`, `unsupported`, or `schema_changed`; 8. A local runtime represented as a fake quota percentage; 9. An unsafe identifier value (uppercase, leading punctuation, over-length, or containing a credential-shaped fragment); 10. A diagnostic code outside the 13-code allowlist. Additionally, tests must demonstrate explicitly that these are **distinct states**: a known `used_percent = 0`, a known `remaining_percent = 0`, and an absent percentage pair. ## AGENTS workflow hardening (corrective governance change) The M1 reconnaissance task left valuable uncommitted work on `main` that a dependent agent then bypassed with a secondary worktree. `AGENTS.md` gains a concise **repository workflow** section so this cannot silently recur. Invariants to be captured: - no substantive file modification while checked out on `main`; - an issue must exist and a feature branch created before the first task-related file edit; - one issue to one feature branch to one PR, targeting `main`; - the agent leaves its PR open for human review and does not merge it; - if uncommitted, unmerged work from an earlier project task blocks a later task, that earlier work must be resolved through its own issue/branch/PR first; - a clean secondary worktree is permitted only for genuinely unrelated user changes, never as a bypass for an unmet dependency; - unrelated user work is preserved untouched; - before completion, verify `origin/main..HEAD` contains only this task's diff (no unintended merge commits, no unrelated files). ## Acceptance criteria 1. A new Python package (standard library only, Python 3.12+) with the v1 model, validation, and deterministic serialization described above. 2. The tests listed under "Tests required" pass deterministically. 3. Full existing test suite (if any) continues to pass. 4. `git diff --check` clean over the changed/new files; secret-pattern scan over the changed/new files is clean. 5. `AGENTS.md` contains the new repository-workflow section with the invariants above. 6. `origin/main..HEAD` contains only this issue's changes, no merge commit, no unrelated files, and no credential or raw sensitive provider material. 7. Exactly one open PR targeting `main`, left unmerged, with `Closes #<issue>` in its body.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Creatidy/scarcity-router#4
No description provided.