Skip to content

Phase 5: English codebase, main.py split, step() in stages, one timestamp parser - #5

Merged
kutsibalci merged 7 commits into
mainfrom
faz-5/duzen-ve-ceviri
Oct 22, 2026
Merged

kutsibalci merged 7 commits into
mainfrom
faz-5/duzen-ve-ceviri

Conversation

@kutsibalci

Copy link
Copy Markdown
Owner

Stacked on #4. Merge order: #1 → #2 → #3 → #4 → this.

What changed, and how each change was proven

Change Proof
Every code comment and docstring translated from Turkish to English (~1,200 lines in 37 files) New tools/check_code_unchanged.py: 36/36 files have an identical syntax tree once docstrings are removed, so no code changed
User-facing messages in English (API and simulator errors, test messages, tool output) Tests pass; tools checked with ruff only, since they make live calls
apps/api/main.py (1,170 lines) split into main (264), security, runtime, models, scheduler, demo Cut by script at section markers, not retyped. Tests now patch the owning modules
policy.step() (364 lines) split into named stages; step() is now ~45 lines The full JSON of all six demo scenarios (7 MB: every report, ledger row and explain[] entry) is byte-identical before and after
Five timestamp parsers replaced by one (rules/timeutil.py) Same 7 MB snapshot identical. One improvement: a CloudEvent with an empty time returned 500 and is now applied at the current time (test added, and it fails on the old code)

The console was checked again in headless Chrome after the split: all six scenarios replay to completion with no errors.

evidence/ is untouched; evidence files are never edited.

Left for a decision

  • Unused client code. NacClient still carries about 15 methods the product never calls (KYC, SIM/device swap, number verification, call forwarding, roaming), along with their fixtures and simulator routes. The README already says these are deliberately unused.
  • tools/verify_live.py. It probes them, and still has portfolio-era table-patching code.

Removing the methods is the data-minimisation-consistent choice, but it changes the probe that produced the committed 9 Sep evidence. That is the owner's call.

Tests

197 passed, ruff clean.

🤖 Generated with Claude Code

kutsibalci and others added 7 commits September 27, 2026 14:13
Compares each file's syntax tree, docstrings removed, against a git
revision. Used to verify the comment translation in this phase.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
About 1,200 comment and docstring lines across 37 files: apps/, packages/,
tests/, tools/, the web console, .env.example and the run scripts. The
public docs were already English; now the code is as well.

Proof that only comments and docstrings changed:
tools/check_code_unchanged.py reports 36/36 Python files with a syntax tree
identical to the previous commit once docstrings are removed. ruff passes
and all 195 tests pass.

Evidence files are untouched (evidence is never edited). The .env.example
header was also corrected: it described the portfolio-era layout, where
only the probe read it and each project had its own copy.

Turkish user-facing string literals (error messages, tool output) are code,
so they are handled in a separate commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…l output

- Error messages the API or simulator can return: an invalid phone number,
  a timeout, a missing subscription or session, a missing phone number or
  token, an injected fault.
- Test assertion messages and parametrize ids.
- Console output of the six measurement tools. In diagnose_lv.py the case
  label and its startswith() check change together (TERS -> SWAPPED).

No test depended on the old wording. The tools were checked with ruff, not
run, because they call live APIs. verify_live.py keeps its strings until its
refactor, because some of them are matched against document text.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- main.py (264 lines): the app, lifespan, security headers, the
  site/worker/sweep routes and the webhook sink.
- security.py: tokens, access dependencies and the rate limiter.
- runtime.py: configuration, the demo roster, the operator client, the
  store and its locking rules, and site/worker setup.
- models.py: request bodies.
- scheduler.py: the agent's clock.
- demo.py: the six scenarios and their report blocks, as an APIRouter.

The blocks were cut by script at their section markers, not copied by
hand. Mutable settings are read through their module (security.API_TOKEN,
runtime.CFG, runtime.DEDUPE_WINDOW), so patching them in one place takes
effect everywhere. Tests now patch those modules; a mis-targeted patch
would fail loudly (401s, wrong jurisdiction), not pass silently.

Unchanged: all 195 tests pass, and the six demo scenarios produce output
identical to the hackathon baseline.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
step() was one 364-line function. It is now about 45 lines that read as
the agent loop:

  _new_report → _quiet_sweep (Move 1) → breach start + roster
  reconciliation → _score_and_plan (Move 2) → _execute_plan (Move 3:
  _run_location_verify / _run_reachability / _run_location_retrieve)
  → _classify_silent (§9, _request_qod) → _prolonged_exposure →
  _finish_report

The stages were moved by script as exact line ranges and re-indented,
not retyped. The only structural edit: _run_reachability returns whether
the device went silent, instead of appending to the caller's list.

Proof of no behaviour change: the complete JSON of all six demo scenarios
(7 MB: every report, ledger row and explain[] entry; random ids and
wall-clock stamps normalised) is byte-identical before and after. All
195 tests pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
rules/timeutil.py (to_utc, iso_z) replaces rules._dt, rules._iso_or_none,
policy._dt, policy._iso, runtime._parse_dt and runtime._iso. nac_client keeps
its own small parser because it sits below rules and must not depend on it.

The variants differed at the edges. The shared one handles None, "",
naive datetimes, bare dates and ISO strings with Z. One visible effect:
runtime._parse_dt raised on "", so a geofence CloudEvent with an empty time
field returned a 500; it is now applied at the current time, with a
regression test.

The full six-scenario demo JSON is byte-identical; 197 tests pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kutsibalci
kutsibalci changed the base branch from faz-4/altyapi to main October 22, 2026 21:47
@kutsibalci
kutsibalci merged commit 77fe1e8 into main Oct 22, 2026
3 checks passed
@kutsibalci
kutsibalci deleted the faz-5/duzen-ve-ceviri branch October 22, 2026 22:10
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.

1 participant