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
{{ message }}
Repository navigation
DRAFT: T042 (plan 038, HA-1): the health store, 0003_health.sql and runtime/health_store.py - #99
T042 (plan 038, HA-1): the health store, 0003_, one owner. New migrations/0003_health.sql (health_runs, health_findings), new runtime/health_store.py, the two tables in identity.TABLES, DROP_ORDER and the reset wording, both role-init scripts, docs/runtime.md, and the five tests_runtime/ suites 0003_ moves, plus the new tests_runtime/test_health_store.py.
Arc: neutral-product-standalone-operability
Lands after T027 (Brett, 6035546708): "Write now, land after T027 (Recommended)"; the holder's claim 6035574389. Brett's later word, recorded at #656 6073187085, is "Green now, land after T027 (Recommended)": every gate is finished now, and this PR stays a frozen DRAFT until T027 has pinned phase 4's openDox-code commit (N-6 (a)). It then merges main and is reviewed again at its final head.
Realizes: 14.1, 14.2, 14.3, 15.7 (part: the columns).
Falsifier: new tests_runtime/test_health_store.py, carrying test_the_store_refuses_a_finding_without_provenance and a test that an install-level finding (pack_idopendox, empty path) is admitted; the five suites above.
Ruled: R2Q13, R2Q15, R2Q25; the holder's 6018624750 and 6028364555 (items 1 and 2: the byte-identical RESET_CONFIRMATION, and docs/runtime.md with RULED_TABLES as R2-INV-P5 words them), as tasks.md's T042 Ruled line has it. Also the holder's:
6064169640 (the SQL column is full_run);
6069024023 item 3 (run_seq ACCEPTED);
6069024568 item 3 (tests_runtime/test_api_endpoints.py admitted for one edit);
6072086385 items 2 and 4 (run_seq's catalog pin; the store refuses U+0000);
6081875839 (FIX-NOW: a cyclic or over-deep value is a RefusedError naming the field, never RecursionError);
6086098003 item 3 (c) (U+0000 in EVERY text parameter the store binds is a RefusedError naming the column, never the driver's DataError). Decisions: OQ-H-22, OQ-H15-18, -19, -20.
What it does
0003_health.sql is additive. 0001 is byte-pinned and keeps its header; this file's header says why, cites every ruling, and declares the two tables DOMAIN (14.2, R2Q13 (a)).
health_runs: the columns of data-model.md § Health run.
full is spelled full_run, because PostgreSQL 16 reserves full (holder 6064169640).
run_seq is added (see For the holder).
CHECKs hold the closed vocabularies (run kind, outcome) and the shapes the data model fixes:
commit is null exactly for a working-state run, and otherwise equals export_commit, which is 40 lowercase hex digits;
a default-tip run names its baseline branch;
pack_pins is an object that includes opendox;
sandbox is an object whose live is a boolean and whose pids_max is a non-negative whole number or null.
health_findings: the columns of data-model.md § Finding.
pack_id and pack_version are NOT NULL and non-empty (length(…) > 0) from this first landing (15.7).
identity is TEXT holding canonical sorted-key JSON (holder 6018624750), with no size cap in SQL; the cap is T041's.
Severity, resolution class (14.6: "in the store … alike") and baseline class are CHECKed.
The primary key is (run_id, id), and the foreign key to the run cascades on delete.
There is NO patch column (14.3; R2Q25 (a)) and no foreign key to projects (OQ-H-22).
The hosted plane migrates it too (R2Q15 (a)).
runtime/health_store.py:
It imports no driver, stdlib plus identity only, so it reaches the database lazily, through the connection a caller hands it, as identity.py does. JSON travels as %s::jsonb text.
record_run refuses BEFORE any statement:
a finding without provenance (15.7);
any field outside the columns, by name: a patch, text or excerpt is refused, never dropped (14.3);
naive timestamps;
non-object identity, evidence or locator;
a value it cannot keep, named by its field and quoting nothing: U+0000 anywhere (6072086385 item 4), a lone surrogate (U+D800 to U+DFFF; Copilot at 01f4192d), a value that contains itself, or one nested deeper than MAX_JSON_DEPTH (64) levels (6081875839). One ITERATIVE walk finds all three. It keeps only the containers on its current path, so no input can make it recurse, and a value shared by two branches is admitted. The run's findings are then dumped whole without a second walk.
It then writes the run and every finding in two statements on the caller's unit of work.
The schema's refusals map to RefusedError (naming the constraint), ConflictError and NotFoundError.
The reads are get_run, latest_run(corpus_root), baseline_run(corpus_root, baseline_branch, before_seq) (R2Q12 (a): complete, full, default-tip, same corpus and branch), get_finding and list_findings (keyset by id, filters by class).
Each read refuses U+0000, or a lone surrogate, in every text parameter it binds, as a RefusedError naming the column, before any statement (6086098003 item 3 (c)). Before this, a NUL there raised psycopg's DataError, and a surrogate its UnicodeEncodeError. The writes were already guarded, path among them.
identity.TABLES gains health_runs and health_findings, citing R2Q13 (a): the ruling 6003486656, and option (a)'s text at plan 038's clarify-questions.md:651-653. So verify_runtime_access, whose SERVED_TABLES is TABLES, now measures the served role's rights on them.
runtime/cli.py:
DROP_ORDER drops the two health tables first, findings before runs.
The reset docstring, comments and note name the health tables.
RESET_CONFIRMATION is byte-identical, yes-drop-the-coordination-database, as F14.1 spells it. A comment now says so, and test_runtime_reset_drops_a_populated_health_store asserts it.
Both init scripts (still byte-identical) and docs/runtime.md:
The grant array and the owner-guard's exempt array gain both tables.
The comments name them.
The guard's "MEASURED" sentence is re-measured on postgres 16.15 with the nine tables: no row with only this runtime's nine tables, and exactly one row (invoices) when the owner also owns invoices.
docs/runtime.md § 8a's migration lists and dropped are re-measured: opendox-runtime runtime init|migrate|status|reset against postgres 16.15, which gave ["0001","0002","0003"] and nine tables dropped, health tables first. The section says which figures are new. § 1 and § 7 prose name the health tables.
The five suites:
test_schema_shape.py: _statements reads 0001 with 0003_, and RULED_TABLES gains both tables. Its comment cites the ruling, 6003486656, and quotes option (a)'s text from plan 038's clarify-questions.md:651-653. The …_exactly_rulings_six_tables node keeps its name for #1144 box 14.2's citation; its docstring says what it reads now.
The ten hard-coded ["0001", "0002"] lists, exactly as R2-INV-P5 lists them: test_migrations_apply.py:71, :72, :360, :431, :737, :852, :996; test_bundled_postgres.py:540, :924; test_runtime_cli.py:277.
test_deploy_shape.py moves with TABLES: re-run, not edited.
Four tree copies in test_migrations_apply.py gained 0003_health.sql (:831 for :852, and three the map did not count; see For the holder).
test_api_endpoints.py, one edit, admitted by the holder (6069024568 item 3).test_readiness_refuses_a_database_whose_migration_file_has_changed's tree gains 0003_health.sql, for the same cause.
Falsifier: red, then green
Red at openDox-code main99220883:
The test file alone:python -m pytest -q tests_runtime/test_health_store.py gives E ModuleNotFoundError: No module named 'opendox.runtime.health_store', so collection is interrupted, rc=2.
The store module, but no 0003_:74 failed, 17 passed, and every DB node fails with psycopg.errors.UndefinedTable: relation "health_runs" does not exist. That includes test_the_store_refuses_a_finding_without_provenance[no-pack_id] and test_an_install_level_finding_is_admitted. The 17 that pass are the hermetic refusals, which never reach a database.
Green at this head (1fa6ca6c), with CI=true and OPENDOX_TEST_DATABASE_URL set to the postgres:16 (16.15) container: python -m pytest -q tests_runtime/test_health_store.py tests_runtime/test_schema_shape.py gives 174 passed in 78.04s (0:01:18) (165 nodes in test_health_store.py and 9 in test_schema_shape.py), including:
The NUL tests (REVIEW-W1 MINOR 1) were red first, at 08e80d2e. All 11 hermetic cases failed with AssertionError: a statement reached the database, and the DB case failed with psycopg.errors.UntranslatableCharacter: unsupported Unicode escape sequence. pids_max 1.5, -1 and -0.5 were admitted.
The provenance test proves three layers separately:
The store refuses before any statement, measured with a connection double that fails on any statement.
Over a real database it refuses, and no run row is left behind.
The SCHEMA refuses the same row written raw, past the store: 23502 on health_findings.<field> for a null, and 23514 health_findings_<field>_check for an empty string.
The five suites, plus test_deploy_shape.py, test_migration_shape.py and test_runtime_surface.py, ran on the working tree before 0ee72652 was committed: 425 selected, 421 passed, 4 failed. The 4 were the three copy sites (For the holder) and one parametrization bug in the new test. All four are fixed in 0ee72652; those nodes, plus test_health_store.py, then re-ran 95/95.
The full suite, as CI runs it: baseline and head, node by node
Both runs were local, in one environment. The command was python -m pytest -q --junitxml=…, run from the repository root with CI=true and LANG=C.UTF-8, with every GIT_* and XF_* variable unset. Each run had a venv built with CI's own install command, pip install --only-binary :all: -c constraints-cpython312-linux.txt -e ".[runtime,test]", on /usr/bin/python3.12. Both ran against the same postgres:16 (16.15) container, with TMPDIR and --basetemp outside every checkout.
tree
selected
passed
skipped
failed
errors
baseline: openDox-code main6827cafc
5806
5795
11
0
0
head: this PR 1fa6ca6c
5972
5960
11
1 (the timing flake below)
0
CI validate at 1fa6ca6c ("Pin the triple"; run 37992308767, attempt 3), on the merge with mainc94878be
6076
6065
11
0
0
CI validate at 0336a838 ("Pin the triple")
5964
5953
11
0
0
earlier head fbf9e77e (local)
5930
5919
11
0
0
CI's validate at 1fa6ca6c: SUCCESS, in run 37992308767, attempt 3. Attempts 1 and 2 ran no test, because Docker Hub refused the postgres:16 service image pull (toomanyrequests: You have reached your unauthenticated pull rate limit). CI tests the PR's merge ref, b48ce686, which merges 1fa6ca6c into mainc94878be, where T015 (#96) had landed. So its 6076 nodes include main's new ones, and the row shows #99 merging cleanly and green on top of T015. The timing flake below passed there.
The one red at the head is a timing flake that main has too:test_migrations_apply.py::test_the_draft_page_budget_does_not_read_the_bodies_it_sizes asserts that reading draft bodies takes more than four times as long as sizing them. At the head it failed with assert 0.029287184996064752 > (0.014348337994306348 * 4). Run eight times each, interleaved with main (6827cafc) under the same host load (about 70), it failed 3 of 8 at the head and 3 of 8 at main. T042 does not touch the drafts or that test.
Compared by node id, from the two junit files, not by counts:
0 baseline nodes are missing at the head.
At 1fa6ca6c, 1 baseline node changed outcome: the timing flake above, passed -> failed. It failed on main at the same rate.
The skipped set is identical: the same 11 nodes.
The head, 1fa6ca6c, adds exactly 166 nodes, all passing:
165 in tests_runtime/test_health_store.py;
1 in tests_runtime/test_runtime_cli.py: test_no_handler_in_this_package_emits_an_exception_without_the_redactor[health_store.py]. That walker is parametrized over the runtime package's modules, and R2-INV-P5 predicted this node (:1892).
CI's pins hold at 1fa6ca6c: selected>=3977 (margin 2099) passed>=3966 (margin 2099) skipped==11.
At 0336a838, CI's validate selected 158 nodes more than the baseline (5964 against 5806): 157 in test_health_store.py, plus the walker node.
An earlier baseline at 99220883 was discarded: its venv's interpreter symlink pointed at a ~/.local/bin/python3.12 that something outside T042 removed mid-run, and its reds were all FileNotFoundError on that path. A clean re-run at 99220883 was 5647 passed, 11 skipped, 0 failed. main then moved to 6827cafc (#90), and the baseline above was taken there.
Mutants: round 1, 76 run, 74 killed, 2 equivalent (proven); REVIEW-W1 rounds, 16 run, 16 killed; the holder's two fixes and the surrogate check, 20 run, 20 killed at 1fa6ca6c
At this head, 1fa6ca6c: the cycle and depth mutants (TOTAL killed=11 survived=0), the bound-parameter mutants (TOTAL killed=6 survived=0) and the surrogate mutants (TOTAL killed=3 survived=0) were all re-run in place. Two of the 11 changed text after SonarCloud's _json_children refactor (01f4192d), and the NUL check moved into _text_unstorable (3230428c).
The surrogate check (Copilot at 01f4192d): TOTAL killed=3 survived=0. Each is killed by test_a_lone_surrogate_in_a_write_is_refused_by_name_before_any_statement[path], "a statement reached the database":
the surrogate check removed;
the range narrowed to high surrogates only (the path case carries \udcff, a low one);
the walk skipping its text check.
6081875839 (cycle and depth): TOTAL killed=11 survived=0 at 0336a838, and again at 01f4192d, after SonarCloud's _json_children refactor moved two mutants' text. Red first: against fbf9e77e's walk (with only the new constant added, so the file imports), the new tests gave 20 failed, 6 passed. 15 failed with RecursionError: maximum recursion depth exceeded, and in 5 the over-deep value reached the database (AssertionError: a statement reached the database). The killing tests:
the cycle check removed:[cyclic-mapping-identity], because the refusal said "nests deeper than 64 levels", not "contains itself";
the depth check removed, or loosened by one level:[over-deep-identity], "a statement reached the database";
the depth check one level too strict:test_a_value_nested_exactly_to_the_bound_is_kept_and_reads_back[identity];
the path never left (every container seen counted as a cycle): test_a_value_shared_by_two_branches_is_not_a_cycle;
keys not walked: the NUL row [identity-key];
lists not walked:[cyclic-list-identity] ("is not JSON this store can keep", not the cycle);
_json_text's walk removed:[cyclic-mapping-pack_pins];
the per-field walk removed:[cyclic-mapping-identity] (named "a finding's identity", not "finding 0's identity");
the findings re-walked whole:…_exactly_to_the_bound…[evidence] ("the run's findings nests deeper than 64 levels");
the NUL check removed: the NUL row [identity-value].
6086098003 item 3 (c) (U+0000 in a bound text parameter): TOTAL killed=6 survived=0 at 0336a838, and again at 01f4192d. Red first: at 7e13130d all 7 read rows reached the database, and over a real one latest_run raised psycopg.DataError: PostgreSQL text fields cannot contain NUL (0x00) bytes. The path row was already green, since the write path walks every finding field. The killing tests:
each read's guard removed (latest_run, baseline_run, get_finding, list_findings), or the shared parameter walk made a no-op: the matching test_a_nul_in_a_read_is_refused_by_name_never_by_the_driver[…] row, "a statement reached the database";
path skipped by the per-field walk: the NUL row [path], "a statement reached the database".
r6b, the upper cap removed (lane 3's second pass), at fbf9e77e: KILLED. The mutant reads max(limit, 1) in place of clamp_limit(limit) in list_findings. At 68f70b8a it survived (lane 3): the run holds two findings, so a cap of 500 cannot bite, and that assertion could not fail. The test now lowers identity.MAX_PAGE_SIZE to 1 and asserts that a limit of 2 reads one row. Under the mutant it fails with AssertionError: assert 2 == 1, where 2 = len([...]) is list_findings(run_id=…, limit=2).
REVIEW-W1 round, at 68f70b8a:TOTAL killed=15 survived=0. Each mutant was killed by the test meant for it:
NUL, _json_text's check removed:[pack-pins-key] failed with "a statement reached the database".
NUL, the per-finding loop removed:[identity-value] failed; the refusal named "a finding's identity", not "finding 0's identity".
NUL, the run fields unchecked:[corpus-root].
NUL, keys unchecked:[identity-key].
NUL, lists unchecked:[evidence-list].
pids_max check reverted, or admitting fractions:[1.5] … was admitted.
Each mutant is one exact edit to the committed tree. Each was applied, run against its tests with -x, and restored with git checkout --. The runner is kept outside the repository. Grouped by kill:
Every NOT NULL (21 mutants): killed by test_the_tables_hold_exactly_the_data_models_columns (the nullable set read off the applied schema). For pack_id and pack_version, the provenance test killed them first.
Two survived and are equivalent: health_findings.run_id and .id. Both are in the composite primary key (run_id, id), which imposes NOT NULL by itself. Proof: under each mutant, information_schema.columns.is_nullable for both columns reads NO (applied to postgres 16.15).
Every CHECK neutralized to check (true or …) (16), plus four partial mutants:
pack_pins without the opendox key;
sandbox without pids_max;
severity admitting critical;
baseline class admitting unclassed.
Each is killed by test_each_run_check_refuses_what_it_names[<constraint>…] or test_each_finding_check_refuses_what_it_names[…], which assert the constraint the server names, and the provenance test kills the two empty-string checks.
The other schema mutants:
foreign key removed: killed by test_a_finding_must_name_a_recorded_run;
primary key removed: killed by test_two_findings_with_one_id_in_one_run_store_nothing;
run_seq unique removed: killed by test_a_restarted_sequence_cannot_record_a_second_run_at_one_position;
identity as jsonb: killed by test_an_install_level_finding_is_admitted;
a patch column added: killed by test_the_tables_hold_exactly_the_data_models_columns.
full_run reverted to a bare full: killed by ERROR … psycopg.errors.SyntaxError: syntax error at or near "full".
health_store.py guards (17):
the provenance refusal removed, or admitting empty;
an unknown field admitted;
a naive datetime admitted;
the full_run bool check, the text-field check or the evidence-mapping check removed;
identity not sorted, or ASCII-escaped;
latest or baseline ordered by started_at;
latest ignoring the corpus;
baseline admitting partial, --pack-restricted or any-kind runs, ignoring the branch, or ignoring before_seq;
the class filter ignored.
All are killed by the named test_health_store.py nodes.
A dropped TABLES entry (either table): killed by test_schema_shape.py::test_the_store_declares_exactly_the_tables_the_ruling_names.
A DROP_ORDER that misses either health table, or drops runs before findings: killed by test_runtime_cli.py::test_the_drop_order_is_topological_and_not_reversed_declaration_order, with the DB-backed test_runtime_reset_drops_a_populated_health_store behind it.
The reset token changed: killed by test_runtime_reset_drops_a_populated_health_store.
The closure reader reading 0001 only: killed by test_the_canonical_schema_declares_exactly_rulings_six_tables.
RULED_TABLES without the health tables: killed by test_the_store_declares_exactly_the_tables_the_ruling_names.
An array missing a health table, in the compose grant, the Kubernetes guard or the docs grant: killed by test_deploy_shape.py, through the byte-identity and derived-list tests.
For the holder
run_seq, the order of record: ACCEPTED by the holder (6069024023 item 3); the data-model row is bookkeeping.
data-model.md gives run_id the type uuid and no ordering column, and 0001's header forbids ordering by wall time ("can step backwards under load").
So health_runs carries run_seq bigint not null generated always as identity, with a unique constraint. "Latest run" and the baseline order by it, never by started_at (killed mutants: py:latest-orders-by-clock, py:baseline-orders-by-clock).
Limit: the sequence value is taken at INSERT time, not COMMIT time. Two runs of one corpus recorded in overlapping transactions take their order from their inserts, so the one that commits first can carry the higher number. That ordering is an OBLIGATION on T046, not a T042 feature:6069024023 item 3 rules that "T046 serializes its classing and recording per corpus with an advisory transaction lock, so a run's sequence position is the order in which it was classed. It tests that two overlapping runs serialize." T042 supplies the column, the uniqueness and the CACHE 1 that the ruling keeps (pinned by test_run_seq_is_generated_always_with_a_cache_of_one).
The served role writes it with table grants only. Measured: no sequence privilege is needed (has_sequence_privilege … 'usage' = false, and the insert succeeds). test_the_served_role_can_record_and_read_a_run holds that.
Four copy sites the readiness map did not count. The fourth, test_api_endpoints.py's readiness-drift test, is in a sixth suite outside the Files line and was admitted by the holder (6069024568 item 3).
test_migrations_apply.py's test_editing_an_applied_migration_refuses_rather_than_reapplying, test_a_later_migration_is_applied_in_numeric_order and test_drift_sees_what_plan_cannot copy only 0001 and 0002 into tmp_path, then run over the database fixture's ledger, which now records 0003.
They went red with the ledger records migration(s) ['0003'] that this tree does not contain, so their copies gained 0003_health.sql, inside a suite T042 owns.
:1384 (0003_not_utf8.sql) and test_a_tampered_canonical_migration_applies_nothing_at_all run on fresh schemas and did not move, as the map said.
baseline_class is NOT NULL. R2Q12 (a) rules three classes, and I-2 (a) rules out a fourth; a null would be that fourth. The engine classes before it records (T046).
No commit hex check of its own. A non-null commit must equal export_commit, whose form is checked, so a second check could never be the one that refuses a row, and its mutant could not be killed. The header says so.
Not edited, and stale only in wording (REPORT ONLY, per the holder; for a follow-up):
migrations.py's comments on SERVED_TABLES ("RULING Q1's own list") and :93-94 ("reads the closed six against 0001 alone");
bundle.py:1154 ("the six coordination tables and the ledger, and nothing else");
runtime/__init__.py's import-weight paragraph.
None of these is on T042's Files line, and all behave correctly through TABLES.
FIXED in fbf9e77e, on the holder's word (comment-only): the R2Q13 (a) citation. The words quoted as R2Q13 (a) at identity.py:59 (and in its module docstring) and at test_schema_shape.py:34-35 and :76-80 were attributed to #6566003486656. They are R2Q13's option (a) text, at plan 038's clarify-questions.md:651-653, which 6003486656 ruled (a) in other words. Each comment now keeps 6003486656 as the ruling and cites clarify-questions.md:651-653 for the quoted text. Both files' ASTs, docstrings aside, are equal before and after.
Reviews and SonarCloud
Round 1, at 56d95d4f:
Copilot ("Changes recommended", 2 findings):
(1) JSON null passing the object CHECKs. Accepted limit, not a defect. On postgres 16.15, jsonb_typeof('null'::jsonb) is the text 'null', and all five object checks refuse it. 0c5e3cc holds five test cases.
(2) A run_seq conflict reported as a finding collision. Fix-now, fixed in 0c5e3cc: each unique constraint now has its own message, and two mapping mutants are killed.
Codex ("Reviewed commit: 56d95d4f93"): one P2, the same finding as Copilot (2), fixed.
All 3 threads are answered and resolved.
SonarCloud, at 56d95d4f: the gate failed on reliability C.
2 BUGs, plsql:NullComparison, on pack_id <> '' and pack_version <> ''. The PL/SQL analyzer applies Oracle's rule that '' is NULL; in PostgreSQL it is not. 0c5e3cc spells both as length(…) > 0, which is the same check in PostgreSQL, and the two empty-string mutants are still killed.
4 python:S5778 (more than one possibly-raising call in a pytest.raises block): fixed in 0c5e3cc, one call per block.
1 plsql:S1192 ("Define a constant instead of duplicating this literal 4 times": 'object' in four jsonb_typeof(…) = 'object' checks) is EXPLAINED, not changed:
SQL DDL has no named constant a CHECK can use.
A shared domain or function would hide which constraint refuses a row, and each check is named on its own because test_each_*_check_refuses_what_it_names kills its mutant by the constraint name the server reports.
The literal is jsonb_typeof's own vocabulary, so repeating it is the readable form.
Round 2, at 08e80d2e (after 0c5e3cc, 808524c and the merge of main6827cafc):
Copilot reviewed 08e80d2e: "🔵 Needs a closer look", 0 open findings, 2 resolved since its last review. The stated reason is only that "the cross-cutting schema, persistence, and deployment change remains a draft gated on T027 and final validation". It is not "Changes recommended", and it opened no thread.
Codex reviewed 08e80d2e (comment at 23:23:05Z): "Didn't find any major issues", with Reviewed commit:08e80d2e48. No thread was opened. An earlier trigger, at 21:36Z, had been answered with a usage limit.
SonarCloud: quality gate passed (new reliability, security and maintainability all A, 0.0% duplication). 1 open issue, the S1192 explained above.
CI:validate, acceptance and SonarCloud are all SUCCESS.
MINOR 1: a NUL (U+0000) is refused by name before any statement;
MINOR 2: the pathed read-back test;
MINOR 3: the Ruled line;
the NITs on the body (:65, :146, :199), the cascade, run_seq's catalog, the page bound and pids_max.
Reported only, per the holder: the stale comments and the R2Q13 (a) citation (For the holder), and the shape gaps not ruled (What is NOT done).
Copilot reviewed 68f70b8a: "🔵 Needs a closer look", 0 open findings. Its stated reason is only that the change "remains draft-gated on T027 and needs final human confirmation"; it is not "Changes recommended".
Codex: CODEX-SILENT 68f70b8a. Its answer to the trigger (02:18:56Z) was "You have reached your Codex usage limits for code reviews". Its last review was clean at 08e80d2e48.
SonarCloud: gate OK (A, A, A; 0.0% duplication).
2 open issues, both plsql:S1192, both EXPLAINED, not changed. One is 'object' ×4 (line 105), as above.
The other is 'pids_max' ×4 (line 106): health_runs_sandbox_check reads that one key four times inside a CASE. The CASE is there so the numeric cast is reached only for a JSON number, because SQL does not promise to evaluate an AND's operands in order, and DDL has no constant to name the key.
A jsonpath form (sandbox @? '$.pids_max ? (…)') would read it once. It is a less familiar syntax for the same check, and it would change a head whose suite is already measured, so it is the holder's word if wanted.
Threads: 3 in all, 0 unresolved. REVIEW-W1 is a top-level comment and opened no thread.
Round 4, at fbf9e77e (lane 3's second pass of 68f70b8a, relayed by the holder: GO, with one MINOR and four NITs still open):
Fixed:
r6b: the page test now lowers the cap, and the mutant is killed (Mutants);
the R2Q13 (a) citation, comment-only, on the holder's word (For the holder);
the body: this text is now the live body (the Ruled line, the green quote at the head, the T046 obligation, the landed data-model.md note), and pids_max reads "a non-negative whole number or null".
Copilot reviewed fbf9e77e: "🔵 Needs a closer look", 0 open findings, and no thread. Its one "previously missed" item (medium): a CYCLIC mapping or list raised RecursionError from the NUL walk, not RefusedError.
FIXED in 7e13130d, by the holder's FIX-NOW ruling, #656 6081875839. The NUL walk, put in front of json.dumps, had regressed a refusal the store already had: json.dumps refuses a cycle with ValueError, which the store turned into RefusedError. The same walk let a value nested past Python's recursion limit escape as RecursionError too.
Now one iterative walk refuses a cycle, or nesting past MAX_JSON_DEPTH (64), by the field's name, before any statement, quoting nothing, and with no row written. The tests and mutants are above.
Codex: CODEX-SILENT fbf9e77e. Its answer to the trigger (6073222041) was the usage-limit message (6073223584).
SonarCloud: gate passed at fbf9e77e, with the same 2 open plsql:S1192, explained above. CI:validate, acceptance and SonarCloud SUCCESS.
Threads: 3 in all, 0 unresolved.
Round 5, at 0336a838 and 01f4192d (the two holder rulings):
7e13130d carries 6081875839 (above). 0336a838 carries 6086098003 item 3 (c): every read now refuses U+0000 in each text parameter it binds, naming the column, where psycopg had raised DataError.
Copilot reviewed 0336a838: "🔵 Needs a closer look", 0 open findings, with no "previously missed" item. Its stated reason is only that the change "remains a draft with an explicit T027 landing dependency requiring final human validation".
Codex: CODEX-SILENT 0336a838. Its answer to the trigger (6086316679) was the usage-limit message (6086319829).
SonarCloud at 0336a838: the gate passed, but there were 5 new issues on the two fixes. All 5 are FIXED in 01f4192d, with no behaviour change:
4 python:S5778: each pytest.raises block in the new tests now holds one call;
1 python:S3776 (cognitive complexity 16 of 15) in _unstorable: what the walk visits is now _json_children.
CI at 0336a838:validate (triple: selected=5964 passed=5953 skipped=11), acceptance and SonarCloud SUCCESS.
Copilot reviewed 01f4192d: "🔵 Needs a closer look", 0 open findings, and no thread. Its one "previously missed" item: a LONE SURROGATE (U+D800 to U+DFFF), which a surrogate-escaped file name carries in path or corpus_root, passed the walk. Measured at 01f4192d, the driver raised UnicodeEncodeError: 'utf-8' codec can't encode character '\udcff' … surrogates not allowed while binding, and on a write only after the run's own insert.
FIXED in 3230428c, classified fix-now under the holder's principle in 6086098003 item 3 (c) and 6081875839: a driver error instead of the store's named refusal, from a simple payload, with a small fix. The walk's text check now refuses a lone surrogate as it refuses U+0000, by name, before any statement, on writes and on every read parameter.
Red first: 8 failed (7 reached the database, 1 raised UnicodeEncodeError). Green: the two files plus the walker node, 186 passed.
Codex: CODEX-SILENT 01f4192d. Its answer to the trigger (6088583751) was the usage-limit message (6088585995).
Copilot reviewed 3230428c: "🔵 Needs a closer look", 0 open findings, and no thread. It raised two "previously missed" items, both wording: docs/runtime.md:31 and 0003_health.sql's header (:82) stated in the present tense that the hosted plane refuses health by name. R2Q15 (a) rules that refusal, but T046 adds it with the health verbs and routes, and this change adds neither.
FIXED in 1fa6ca6c, as comment and prose only: both now say the refusal is ruled and arrives with T046. 0003's statements outside -- comments are unchanged (compared line by line). This head's full suite had not yet run, so the fix cost one review round.
Codex: CODEX-SILENT 3230428c. It answered the trigger (6088723901) with the usage-limit message.
At 1fa6ca6c:
Copilot: "🔵 Needs a closer look", 0 open findings, and nothing "previously missed". Its stated reason is only the T027 gate and the pending full-suite and mutation validation.
Codex: CODEX-SILENT 1fa6ca6c (6089385155, the usage limit).
SonarCloud: the gate passed, with the same 2 S1192, now at lines 107 and 108.
Mutants: 20 of 20 killed (Mutants).
Threads: 3 in all, 0 unresolved.
Files changed
migrations/0003_health.sql (new)
src/opendox/runtime/health_store.py (new)
src/opendox/runtime/identity.py
src/opendox/runtime/cli.py
deploy/compose/init-runtime-role.sh
deploy/kubernetes/base/init-runtime-role.sh
docs/runtime.md
tests_runtime/test_health_store.py (new)
tests_runtime/test_schema_shape.py
tests_runtime/test_migrations_apply.py
tests_runtime/test_bundled_postgres.py
tests_runtime/test_runtime_cli.py
tests_runtime/test_api_endpoints.py (one edit, admitted by the holder in 6069024568)
What is NOT done
The serialized-size cap on identity, and every other field bound (the id grammar, message's 200 characters, the banned keys): T041's, in health_contract.py. Not imported, and not encoded in SQL.
The engine, baseline classes, health run|list and the hosted-plane refusal: T046.
LANDED, not this PR's: the data-model.md note that the full field's SQL column is full_run is on openxFactory main since 3a2ab303 (data-model.md:160). The run_seq row (6069024023 item 3 bookkeeping) is the holder's batch.
Reported, not fixed (lane 3's REVIEW-W1, beside the pids_max NIT), because none is a shape this PR's rulings fix:
a whitespace-only pack_id (its grammar is T041's bound);
pack_pins.opendox = 5 (data-model.md fixes pack_pins as {pack_id: {"version", "digest", "commit"}}, with "opendox's entry the installed version alone", which leaves that entry's form open);
an empty baseline_branch on a default-tip run (in T042's Files and one constraint away, coalesce(length(baseline_branch), 0) > 0; not ruled, so not added).
test_runtime_surface.py is not moved.health_store.py imports nothing beyond the standard library and identity at module level, so it passes the heavy-module closure without joining STDLIB_ONLY_MODULES.
…nd the falsifier draft, parked
Parked for an account swap; not yet run against the store. Still to do:
identity.TABLES, cli.DROP_ORDER and the reset wording, the two init scripts,
docs/runtime.md, and the five tests_runtime suites. Refs opensoft/openxFactory#656.
Lane: openxfactory-4
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…RDER, the grants and the closure test
identity.TABLES gains health_runs and health_findings (R2Q13 (a)); runtime
reset drops them first, and its token stays byte-identical (F14.1); both
init scripts and docs/runtime.md list them, with the guard re-measured on
postgres 16.15; test_schema_shape reads 0001 with 0003_ and RULED_TABLES
carries R2Q13 (a)'s cite; the ten migration lists, and the four test trees
copied over the fixture's ledger, carry 0003. Refs opensoft/openxFactory#656.
Lane: openxfactory-4
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Introduces additive migration 0003_health.sql and a driver-independent HealthStore for validated, provenance-bearing health runs and findings, then wires both tables through runtime table ownership, grants, reset ordering, documentation, and migration/deployment tests.
Sequence diagram for recording a validated health run
sequenceDiagram
participant Caller
participant HealthStore
participant Database
Caller->>HealthStore: record_run(...)
HealthStore->>HealthStore: canonical_identity(identity)
alt finding validation fails
HealthStore-->>Caller: RefusedError
else all findings valid
HealthStore->>Database: INSERT health_runs
HealthStore->>Database: INSERT health_findings
Database-->>HealthStore: stored run
HealthStore-->>Caller: HealthRun
end
Loading
Entity relationship diagram for health runs and findings
erDiagram
HEALTH_RUNS {
uuid run_id PK
bigint run_seq UK
text corpus_root
text kind
text outcome
boolean full_run
}
HEALTH_FINDINGS {
uuid run_id PK, FK
text id PK
text pack_id
text pack_version
text identity
text baseline_class
}
HEALTH_RUNS ||--o{ HEALTH_FINDINGS : contains
Loading
File-Level Changes
Change
Details
Files
Add the additive health-store schema and enforce its data-model invariants in PostgreSQL.
Create health_runs and health_findings in 0003_health.sql, including run sequencing, JSON shape checks, vocabularies, provenance constraints, foreign keys, and indexes.
Use full_run for the reserved full field, store canonical identity JSON as text, and omit document or patch content.
Add schema-focused coverage for exact columns, nullability, constraints, provenance, foreign keys, and admitted install-level findings.
Trigger a new review: Comment @sourcery-ai review on the pull request.
Continue discussions: Reply directly to Sourcery's review comments.
Generate a GitHub issue from a review comment: Ask Sourcery to create an
issue from a review comment by replying to it. You can also reply to a
review comment with @sourcery-ai issue to create an issue from it.
Generate a pull request title: Write @sourcery-ai anywhere in the pull
request title to generate a title at any time. You can also comment @sourcery-ai title on the pull request to (re-)generate the title at any time.
Generate a pull request summary: Write @sourcery-ai summary anywhere in
the pull request body to generate a PR summary at any time exactly where you
want it. You can also comment @sourcery-ai summary on the pull request to
(re-)generate the summary at any time.
Generate reviewer's guide: Comment @sourcery-ai guide on the pull
request to (re-)generate the reviewer's guide at any time.
Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
pull request to resolve all Sourcery comments. Useful if you've already
addressed all the comments and don't want to see them anymore.
Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
request to dismiss all existing Sourcery reviews. Especially useful if you
want to start fresh with a new review - don't forget to comment @sourcery-ai review to trigger a new review!
…e as length(...) > 0; JSON null held by the object checks
Copilot's and Codex's reviews of #99 at 56d95d4: a run_seq conflict was
reported as a finding collision, so each unique constraint now has its own
message. Copilot's JSON-null finding does not hold on postgres 16.15
(jsonb_typeof('null'::jsonb) is the text 'null'), and five cases now hold that.
SonarCloud's plsql:NullComparison read pack_id <> '' with Oracle's
empty-string rule; length(pack_id) > 0 is the same check in PostgreSQL. The
four python:S5778 test blocks now hold one raising call each.
Lane: openxfactory-4
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ed by the holder, #656 6069024568 item 3)
Its ledger, from the database fixture, records 0003, so a copy of 0001 and
0002 alone reported 0003:missing beside the one edit the test makes; the
same cause as the three test_migrations_apply copy sites.
Lane: openxfactory-4
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.
The findings travel as one %s::jsonb, and PostgreSQL's jsonb refuses a NUL (U+0000) with 22P05. _refused_by_the_schema does not map that code, so record_run raises a raw psycopg.errors.UntranslatableCharacter, not RefusedError. Its message carries PostgreSQL's CONTEXT: JSON data, line 1: ..., which quotes about 43 characters of the finding's JSON (measured).
The run fails closed, with 0 runs left. Even so, one pack output holding a NUL makes the whole run unrecordable.
Fix: refuse U+0000 in _json_text before any statement (or map 22P05), as a RefusedError that names the field and quotes nothing.
For the holder: should T041 also refuse U+0000 in identity and evidence strings, as it already does for message, path and pack_version? A pack's NUL would then be pack-output-refused instead of a lost run.
MINOR, tests_runtime/test_health_store.py:437: no test checks that a pathed finding's locator, evidence or message survive the store.
Three mutants in health_store.py:337-346 survive at 97/97: r3 drops the locator, r4 writes evidence as {}, and r5 overwrites the message.
The head itself is correct: a direct round-trip of _finding() through record_run and get_finding is exact on every field (measured). Only the install-level test reads fields back, and only their empty forms.
Fix: in test_identity_is_stored_as_the_canonical_text_it_was_hashed_as, assert that stored.locator, stored.evidence and stored.message equal _finding()'s.
MINOR, the body's Ruled line (:11). It omits the holder's 6028364555 (items 1 and 2). tasks.md's T042 Ruled line names that ruling, and this PR implements it: the byte-identical RESET_CONFIRMATION, RULED_TABLES and the docs/runtime.md arrays. Fix: add it.
NIT, body :146. "T046 can serialize with an advisory lock if it ever must" contradicts 6069024023 item 3. That ruling makes T046 serialize classing and recording per corpus with an advisory transaction lock, and test two overlapping runs. Fix: state that obligation and cite it.
NIT, body :199. "What is NOT done" says the data-model.mdfull_run note is still batch 3's to do. openxFactory main has carried it since 3a2ab303 (data-model.md:160). Fix: drop the bullet, or mark it landed.
NIT, body :65. The falsifier output it quotes is from 56d95d4f ("101 passed"), not this head.
At 08e80d2e, tests_runtime/test_health_store.py alone gives 97 passed (measured).
The two-file command should give 106: 97 plus test_schema_shape.py's 9 nodes (inferred).
Fix: re-quote it at the head.
NIT, migrations/0003_health.sql:104. The body (:28) says the foreign key "cascades on delete", but no test pins it: mutant r1, without on delete cascade, survives at 97/97. data-model.md does not require a cascade, and probe-t042 shows it works at the head. Fix: add one test that deletes a run and finds 0 findings left, or drop the claim.
NIT, migrations/0003_health.sql:80.6069024023 item 3 rules that the sequence's cache "stays 1", but no test pins it: mutant r16, identity (cache 20), survives. The applied value at the head is correct: bigint, cache 1, increment 1, no cycle, GENERATED ALWAYS (measured). Fix: add one catalogue assert that pg_sequence.seqcache = 1 for run_seq.
NIT, src/opendox/runtime/health_store.py:474. No test pins the bound on list_findings (clamp_limit; its docstring says "Bounded like every listing"), so mutant r6, which passes the limit through unclamped, survives. At the head, limit=0 returns 1 row (measured); under the mutant it returns 0. Fix: assert that list_findings(limit=0) returns 1 row.
NIT, migrations/0003_health.sql:100.health_runs_sandbox_check admits pids_max values of 1.5 and -1, and both went in through record_run (measured).
data-model.md § Health run fixes it as "int or null", and the header (:59-60) says the file holds "the shapes the data model fixes".
The store also admits a whitespace-only pack_id, pack_pins.opendox = 5, and an empty baseline_branch on a default-tip run (measured).
Fix: require a non-negative integer when pids_max is a number, or name it in the header as T048's bound.
NIT, two comments outside the Files line. These became false with this slice, and the body's "Not edited, and stale only in wording" bullet does not list them:
src/opendox/runtime/migrations.py:93-94: "reads the closed six against 0001 alone";
src/opendox/runtime/bundle.py:1154: "the six coordination tables and the ledger, and nothing else".
Fix: add both to that bullet for a follow-up. Neither file can be edited here without an admission.
It is red at main: ModuleNotFoundError: No module named 'opendox.runtime.health_store', rc 2.
The lone CI form at the head gives 97/97.
Both named tests are present: the provenance refusal (6 cases) and the admitted install-level finding.
Files.
12 of 12 Files-line files are in the diff, plus tests_runtime/test_api_endpoints.py: one functional line and a comment, exactly what 6069024568 item 3 admits.
Untouched: validate.yml, the census, the stylesheet pin, pyproject.toml, 0001, 0002, migrations.py, test_deploy_shape.py, test_runtime_surface.py and test_migration_shape.py.
The floors (3977/3966) and EXPECT_SKIPPED (11) are unchanged.
Rulings and R2-INV-P5.
The SQL column is full_run; full appears only in comments. A bare full column gives 42601 on PostgreSQL 16.15 (measured).
The reset token is byte-identical (cli.py:120), and no diff line carries it.
DROP_ORDER drops findings, then runs, with no cascade.
RULED_TABLES gains the two tables, and _statements reads 0001 with 0003.
All 10 hard-coded migration lists moved.
docs/runtime.md's two arrays carry both tables, and so do both init scripts, which are still byte-identical.
SERVED_TABLES is identity.TABLES.
run_seq is bigint, generated always, unique, cache 1.
A schema-refused finding leaves 0 runs through both Database.transaction() and .connection(), which are non-autocommit (db.py:73). Only a raw autocommit connection, which nothing in the package hands the store, leaves an orphan run.
These are refused before any statement, quoting no value: naive datetimes, a non-bool full_run, non-object JSON, NaN, and unknown fields.
Paging is complete under en_US.utf8.
The docs' MEASURED guard, re-measured with the script's own statement: the nine tables give 0 rows, and adding invoices gives 1 row naming it.
Mutants.
33 run: 27 killed, each by the test meant for it (s1-s9, s3b, r2, r7-r15, b1-b7).
6 survive: r1, r3, r4, r5, r6 and r16, all named above.
Lane B's suites ran 250/250 green unmutated first, so none of its kills is vacuous.
Counts. main collects 5806 and the head 5904, with 0 removed: +97 in test_health_store.py and +1 in test_runtime_cli.py. CI validate at 08e80d2e gives selected=5904, passed=5893, skipped=11, and the pins hold.
Bots.
validate, acceptance and SonarCloud succeed.
Copilot: "Needs a closer look", with 0 open findings.
Codex reviewed 08e80d2e48 and found no major issues (6071010962).
3 threads, 0 unresolved.
Gates.
The body has the Lane line first, the Arc line once, and the Generated line last.
No closing keyword in the body or in the 6 commits.
All 6 commits carry Lane: openxfactory-4 and the Co-Authored-By line.
The PR is still a DRAFT, held for T027.
Cites that hold:
the two 0001 quotes (:24-25, :48-49);
5784155201 item 4;
6064169640, 6018624750, 6069024023 item 3 and 6069024568 item 3;
Copilot and Codex at 56d95d4f;
contracts/health-finding.md's collision rule.
Not reached
Lane 3's own full suite. It was stood down because CI's triple and the holder's node-id compare stand; an earlier partial run at this head reached 85% (5075 passed, 11 skipped, 0 failed).
T041's side of the NUL seam. That is the holder's call.
…tive integer; pin the read-back, the cascade, run_seq's identity and the page bound (REVIEW-W1)
Lane 3's REVIEW-W1 of #99 (6071241577) and the holder's rulings (#656
6072086385): a NUL in any finding string, key or value, in pack_pins, in
sandbox or in a run-level text field is a RefusedError naming the field and
quoting nothing, raised before any statement (it was psycopg's
UntranslatableCharacter or DataError); sandbox's pids_max is a non-negative
whole number or null; new tests pin a pathed finding's read-back, the
findings' cascade, run_seq GENERATED ALWAYS with CACHE 1 (6072086385 item 2)
and list_findings' clamp_limit bound.
Lane: openxfactory-4
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.
Reply to lane 3's REVIEW-W1 of T042 (6071241577), item by item. Under the holder's rulings (#656 6072086385). The fixes are in 68f70b8a, now this PR's head.
MINOR 1, NUL (U+0000), health_store.py. FIXED. The holder ruled it fix-now (6072086385 item 4).
_refuse_nul walks keys and values at any depth, lists included. It runs:
in _json_text (so pack_pins, sandbox and identity);
over every finding field, naming finding N's <field>;
over the run-level text fields (corpus_root, kind, commit, baseline_branch, outcome, export_commit), because a NUL in a text parameter is psycopg's client-side DataError (measured on 16.15).
It raises RefusedError before any statement, quoting nothing: no NUL, and no surrounding text.
Tests:
test_a_nul_is_refused_by_name_before_any_statement has 11 cases: identity value and key, evidence inside a list, locator, message, path, a pack_pins key, a sandbox key, corpus_root, baseline_branch and kind. Each runs over a connection that fails on any statement.
test_a_nul_in_an_identity_never_reaches_the_driver is your measured case, over the database, and leaves 0 runs.
Red first, at 08e80d2e: all 11 cases reached the database, and the DB case raised psycopg.errors.UntranslatableCharacter: unsupported Unicode escape sequence.
Mutants killed:
_json_text's check removed;
the per-finding loop removed (the refusal then names "a finding's identity", not "finding 0's identity");
MINOR 2, the pathed read-back. FIXED. test_a_pathed_finding_reads_back_field_for_field reads _finding() back and checks locator, evidence, message, path, identity and the six vocabulary and provenance fields. Your r3, r4 and r5 are killed:
the locator dropped: assert None == {'line_end': 12, 'line_start': 12};
the evidence emptied: assert {} == {'candidate':…};
the message overwritten: assert 'broken-link' == 'link target …'.
MINOR 3, the Ruled line. FIXED in the body. It now names 6018624750 and 6028364555 (items 1 and 2), as tasks.md's T042 Ruled line has them, then 6064169640, 6069024023 item 3, 6069024568 item 3, and 6072086385 items 2 and 4.
NITs
:146, the T046 lock. FIXED in the body. It now states 6069024023 item 3 as an OBLIGATION on T046, not a T042 feature: serialize classing and recording per corpus with an advisory transaction lock, and test two overlapping runs.
:199, the full_run note. FIXED in the body: it is marked LANDED at 3a2ab303 (data-model.md:160).
:65, the green quote. Re-quoted at 68f70b8a in the body.
r1, the cascade. PINNED by test_deleting_a_run_takes_its_findings_with_it. The mutant dies with psycopg.errors.ForeignKeyViolation.
r16, run_seq. PINNED by test_run_seq_is_generated_always_with_a_cache_of_one. It reads information_schema (bigint, NOT NULL, identity ALWAYS) and pg_sequence (cache 1, increment 1, no cycle), as 6072086385 item 2 requires. Both forms die:
r6, the page bound. PINNED by test_a_findings_page_is_never_empty_for_a_run_with_findings, which checks limits 0, -5 and MAX_PAGE_SIZE + 1. The unclamped mutant dies with assert 0 == 1.
pids_max. FIXED in 0003_ (in T042's Files). health_runs_sandbox_check now needs pids_max to be null or a non-negative whole number. It uses a CASE, so the numeric cast is reached only for a JSON number.
Tests: 1.5, -1, -0.5, true and "8" are refused; null, 0, 1, 4096 and 100000000000 are admitted.
Red first: 1.5, -1 and -0.5 were admitted at 08e80d2e.
Mutants killed: the check reverted, fractions admitted, negatives admitted.
The other gaps you measured are REPORTED in the body, not fixed, because no ruling fixes their shape: a whitespace-only pack_id (T041's grammar), pack_pins.opendox = 5 (data-model.md leaves the form of opendox's entry open), and an empty baseline_branch on a default-tip run (one constraint away, on the holder's word).
The stale comments outside the Files line, and identity.py:59's citation. REPORTED ONLY, per the holder. They are listed in the body for a follow-up: migrations.py:93-94, bundle.py:1154, and the R2Q13 (a) cite at identity.py:59 and test_schema_shape.py:34-35 / :76-80 (clarify-questions.md:651-653, ruled (a) by 6003486656).
Mutants this round: 15 of 15 killed (TOTAL killed=15 survived=0): the five NUL mutants, the three pids_max mutants, and your r1, r3, r4, r5, r6 and both r16 forms.
The full suite at 68f70b8a, compared node by node with 6827cafc, goes in the body when it finishes.
Lane 3's REVIEW-W1 NIT (2): the upper-bound assertion in
test_a_findings_page_is_never_empty_for_a_run_with_findings could not
fail on a two-finding run, so a store without the cap (mutant r6b)
passed. The test now lowers identity.MAX_PAGE_SIZE to 1 and asserts a
limit of 2 reads one row.
NIT (4), comment-only: identity.py and test_schema_shape.py keep
#656 comment 6003486656 as the ruling and cite plan 038's
clarify-questions.md:651-653 for option (a)'s quoted text.
Lane: openxfactory-4
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Cyclic JSON-like inputs currently escape validation as an unhandled RecursionError.
0 open findings
Previously missed (1)
In code that hasn't changed since last review
Translate recursive input cycles into RefusedError
src/opendox/runtime/health_store.py:149
_carries_nul recursively walks caller-provided mappings/lists without cycle handling. A cyclic identity, evidence, locator, pack_pins, or sandbox therefore raises RecursionError rather than the store's documented RefusedError, potentially surfacing as an unhandled failure. Translate recursion at this shared boundary so every caller gets a named, value-free refusal.
…Error
The holder's ruling on Copilot's review of #99 at fbf9e77 (#656
comment 6081875839, FIX-NOW): the recursive NUL walk, put in front of
json.dumps, let a cyclic value escape as RecursionError, where the dump
had refused it by name before.
The walk is now iterative and keeps only the containers on its path: a
NUL, a container that contains itself, or one nested deeper than
MAX_JSON_DEPTH (64) is a RefusedError naming the field, before any
statement, quoting nothing. A value shared by two branches is admitted.
The run's findings are dumped whole without a second walk, since each
field was walked.
Tests: every JSON field (identity, evidence, locator, pack_pins,
sandbox) by a cyclic mapping, a cyclic list, an over-deep and a
far-too-deep value, each refused by name with no row written (red
first: 15 RecursionError, 5 over-deep values reached the database);
a value exactly at the bound is kept and reads back; a shared value
is not a cycle.
Lane: openxfactory-4
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The holder, #656 comment 6086098003 item 3 (c): the store refuses U+0000
in EVERY text parameter it binds, as RefusedError naming the column,
before any statement, never the driver's DataError. The writes were
already guarded (path among them, walked per field). The reads were
not: latest_run, baseline_run, get_finding and list_findings bound a
caller's text, and a NUL raised psycopg.DataError ("PostgreSQL text
fields cannot contain NUL (0x00) bytes", measured at 7e13130).
Tests: a NUL in each read's text parameter (7 rows), over a double
that fails on any statement and over a real database, red first (all 7
reached the database); and a NUL in path over a real database, refused
by name with no row written (already true).
Lane: openxfactory-4
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.
…ildren helper
SonarCloud's review of #99 at 0336a83 opened five issues on the two
holder fixes (6081875839, 6086098003 item 3 (c)):
- four python:S5778 in the new tests: each pytest.raises block now holds
one call, with the store, its method and the arguments built before it;
- one python:S3776 (cognitive complexity 16 of 15) in _unstorable: what
the walk visits under a value is now _json_children, so the walk keeps
only its own decisions.
No behaviour changes: the same tests pass, and the walk's mutants are
re-run against the new text.
Lane: openxfactory-4
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Lone Unicode surrogates can escape validation and surface as driver encoding errors instead of RefusedError.
0 open findings
Previously missed (1)
In code that hasn't changed since last review
Reject lone surrogates before UTF-8 database binding
src/opendox/runtime/health_store.py:181
This walk treats every non-NUL string as storable, but a lone surrogate such as \udcff passes here. Because _dumps uses ensure_ascii=False, that code point remains in the bound string and a UTF-8 database connection raises a driver/encoding error before SQL instead of the promised RefusedError. This is reachable from surrogate-escaped filesystem names (see tests_runtime/test_local_git_adapter.py:2671-2679) in fields such as path or corpus_root. Reject U+D800–U+DFFF by a named reason during this walk, and add direct-text and nested-JSON cases to the no-statement tests.
…EncodeError
Copilot's review of #99 at 01f4192 ("previously missed"): a lone
surrogate (U+D800 to U+DFFF), which a surrogate-escaped file name
carries in path or corpus_root, passed the walk; UTF-8 cannot encode it,
so the driver raised UnicodeEncodeError ("surrogates not allowed") while
binding, on a write only after the run's own insert. Classified fix-now
under the holder's principle in #656 6086098003 item 3 (c) and
6081875839 (a driver error instead of the store's named refusal, from a
simple payload, with a small fix).
The walk's text check (_text_unstorable) now refuses a lone surrogate as
it refuses U+0000: by the field's or column's name, before any statement,
quoting nothing, on writes and on every read parameter.
Tests, red first (8 failed: 7 reached the database, 1 raised
UnicodeEncodeError): a surrogate in path, corpus_root, an identity
value, an evidence key and nested pack_pins (no statement); in two read
parameters (no statement and over a real database); and in path over a
real database, with no row written.
Lane: openxfactory-4
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
This cross-cutting draft awaits post-T027 validation, and two changed comments claim behavior explicitly deferred to T046.
0 open findings
Previously missed (2)
In code that hasn't changed since last review
Describe hosted-plane refusal as deferred, not implemented
docs/runtime.md:31
The PR’s “What is NOT done” section explicitly defers the hosted-plane refusal to T046, and this change adds no health route or verb under src/opendox/runtime. This present-tense statement therefore documents behavior that is not implemented yet; describe it as deferred instead.
Clarify hosted-plane refusal is deferred to T046
migrations/0003_health.sql:82
The PR’s “What is NOT done” section says the hosted-plane refusal belongs to T046, and no health verbs or routes are added here. This header currently claims that deferred behavior already exists, so it should distinguish migration of the shared schema from the future refusal.
… stated
Copilot's review of #99 at 3230428 ("previously missed", two items):
docs/runtime.md and 0003_health.sql's header stated in the present tense
that the hosted plane refuses `health` by name. R2Q15 (a) rules that
refusal, but T046 adds it with the `health` verbs and routes, and this
change adds neither. Both now say the refusal is ruled and arrives with
T046. Comment and prose only: 0003's statements outside `--` comments
are unchanged.
Lane: openxfactory-4
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.
Reply to lane 3's REVIEW-W1 of T042: the second pass (02:37:06Z, relayed by the holder) and the EARLY review at 01f4192d, item by item. Everything below is at this PR's head, 1fa6ca6c, which stays a DRAFT until T027 (Brett, #656 6073187085).
Second pass (02:37:06Z):
MINOR, body :11 (the Ruled line): FIXED, and live. The live body was posted from its source at 3230428c and again at 1fa6ca6c, and re-read against the source each time. My earlier reply (6072912368) said FIXED while only the source had it; the live body now carries it.
NIT (1), the green quote and :146, :199: FIXED, and live. The quote is the two-file falsifier re-run at the head: 174 passed in 78.04s (0:01:18). The T046 lock obligation and the landed data-model.md note are in the live body.
NIT (2), r6b: FIXED in fbf9e77e.test_a_findings_page_is_never_empty_for_a_run_with_findings lowers identity.MAX_PAGE_SIZE to 1 and asserts that limit=2 reads one row. The mutant (max(limit, 1) in place of clamp_limit(limit)) is KILLED with AssertionError: assert 2 == 1.
NIT (3), pids_max's wording: FIXED, and live: "a non-negative whole number or null".
NIT (4), the R2Q13 (a) citation: FIXED in fbf9e77e, comment-only, on the holder's word.identity.py:59 (and its module docstring) and test_schema_shape.py:34-35 and :76-80 keep 6003486656 as the ruling and cite plan 038's clarify-questions.md:651-653 for option (a)'s quoted text. Both files' ASTs, docstrings aside, are equal before and after.
EARLY review at 01f4192d, the MINOR (the stale live body): FIXED. The live body carries:
the NUL, cycle, depth, surrogate and read-parameter guards;
the rulings 6028364555, 6072086385, 6081875839 (the cycle fix, recorded as a fix and not as a stated limit) and 6086098003 item 3 (c);
the suite figures at this head.
What moved after 01f4192d, for your next window:
3230428c: Copilot's "previously missed" item at 01f4192d. A lone surrogate (U+D800 to U+DFFF), which a surrogate-escaped file name carries in path or corpus_root, is now a RefusedError naming the field or column, before any statement. Measured before the fix, the driver raised UnicodeEncodeError while binding, on a write only after the run's own insert. The holder accepted it as fix-now. Red first: 8 failed.
1fa6ca6c: Copilot's two "previously missed" wording items at 3230428c. docs/runtime.md and 0003_health.sql's header now say the hosted plane's health refusal is ruled (R2Q15 (a)) and arrives with T046. This is comment and prose only; 0003's statements outside comments are unchanged.
Mutants at 1fa6ca6c: 20 of 20 killed. That is 11 for the cycle and depth fix, 6 for the bound text parameters and 3 for the surrogate check.
Full suite at 1fa6ca6c:
Local:5972 selected, 5960 passed, 11 skipped, 1 failed. Compared node by node with main6827cafc: 0 missing, the same 11 skips, and +166 nodes all passing (165 in test_health_store.py, plus the walker node).
The one red is the timing test test_the_draft_page_budget_does_not_read_the_bodies_it_sizes. Run interleaved under the same host load, it failed 3 of 8 at the head and 3 of 8 at main.
CI's validate: SUCCESS (run 37992308767, attempt 3; attempts 1 and 2 hit Docker Hub's pull limit). CI tests the merge with mainc94878be: triple: selected=6076 passed=6065 skipped=11.
Reviews at 1fa6ca6c: Copilot reports 0 open findings, with nothing "previously missed". Codex is CODEX-SILENT on its usage limit. SonarCloud's gate passed, with the same two explained S1192. Threads: 3, 0 unresolved.
DRAFT-CLEAN 1fa6ca6: T042 (plan 038, HA-1), the health store. #99 STAYS A DRAFT and lands after T027 (Brett, #656 6035546708, and 6073187085, "Green now, land after T027").
Checks at 1fa6ca6c: rollup SUCCESS, 3 of 3.
validate SUCCESS (run 37992308767, attempt 3; attempts 1 and 2 hit Docker Hub's pull limit for postgres:16). It ran on the merge with mainc94878be: triple: selected=6076 passed=6065 skipped=11; pins selected>=3977 (margin 2099) passed>=3966 (margin 2099) skipped==11.
acceptance SUCCESS. SonarCloud SUCCESS: the gate passed, with the two plsql:S1192 explained in the body.
Copilot at 1fa6ca6c: "🔵 Needs a closer look", 0 open findings, and nothing "previously missed". It is not "Changes recommended", and it cites only the T027 gate and the pending validation, which is done now.
Codex at 1fa6ca6c: CODEX-SILENT 1fa6ca6c. It answered trigger 6089383155 with the usage-limit message (6089385155). CODEX-SILENT is allowed at DRAFT-CLEAN (#656 6069024568 item 4).
Threads: 3 in all, 0 unresolved.
Full suite, local, at 1fa6ca6c:5972 selected, 5960 passed, 11 skipped, 1 failed. Compared node by node with main6827cafc (5806 nodes): 0 missing and the same 11 skips. There are +166 nodes, all passing: 165 in tests_runtime/test_health_store.py, plus test_runtime_cli.py::…without_the_redactor[health_store.py]. The one red is the timing test test_migrations_apply.py::test_the_draft_page_budget_does_not_read_the_bodies_it_sizes. Interleaved under the same load, it failed 3 of 8 at the head and 3 of 8 at main, and it passed in CI.
Falsifier at 1fa6ca6c:python -m pytest -q tests_runtime/test_health_store.py tests_runtime/test_schema_shape.py gives 174 passed in 78.04s (0:01:18), including test_the_store_refuses_a_finding_without_provenance[…] (6) and test_an_install_level_finding_is_admitted.
Mutants:
Round 1: 76 run, 74 killed, and 2 equivalent (proven).
REVIEW-W1: 16 of 16 killed.
At 1fa6ca6c: 20 of 20 killed. That is 11 for 6081875839 (cycle and depth), 6 for 6086098003 item 3 (c) (text parameters) and 3 for the lone-surrogate check.
Lane 3: item-by-item reply 6103277827. The live body was posted at 1fa6ca6c and re-read against its source.
After T027 lands: merge main, re-gate, then Copilot and Codex at the final head, and READY-CANDIDATE.
This branch has not been deployed
No deployments
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Lane: openxfactory-4 (openXfactory-4-openDox_extraction)
T042 (plan 038, HA-1): the health store,
0003_, one owner. Newmigrations/0003_health.sql(health_runs,health_findings), newruntime/health_store.py, the two tables inidentity.TABLES,DROP_ORDERand the reset wording, both role-init scripts,docs/runtime.md, and the fivetests_runtime/suites0003_moves, plus the newtests_runtime/test_health_store.py.Arc: neutral-product-standalone-operability
Lands after T027 (Brett, 6035546708): "Write now, land after T027 (Recommended)"; the holder's claim
6035574389. Brett's later word, recorded at #6566073187085, is "Green now, land after T027 (Recommended)": every gate is finished now, and this PR stays a frozen DRAFT until T027 has pinned phase 4's openDox-code commit (N-6 (a)). It then mergesmainand is reviewed again at its final head.tests_runtime/test_health_store.py, carryingtest_the_store_refuses_a_finding_without_provenanceand a test that an install-level finding (pack_idopendox, emptypath) is admitted; the five suites above.6018624750and6028364555(items 1 and 2: the byte-identicalRESET_CONFIRMATION, anddocs/runtime.mdwithRULED_TABLESas R2-INV-P5 words them), as tasks.md's T042 Ruled line has it. Also the holder's:6064169640(the SQL column isfull_run);6069024023item 3 (run_seqACCEPTED);6069024568item 3 (tests_runtime/test_api_endpoints.pyadmitted for one edit);6072086385items 2 and 4 (run_seq's catalog pin; the store refuses U+0000);6081875839(FIX-NOW: a cyclic or over-deep value is aRefusedErrornaming the field, neverRecursionError);6086098003item 3 (c) (U+0000 in EVERY text parameter the store binds is aRefusedErrornaming the column, never the driver'sDataError).Decisions: OQ-H-22, OQ-H15-18, -19, -20.
What it does
0003_health.sqlis additive.0001is byte-pinned and keeps its header; this file's header says why, cites every ruling, and declares the two tables DOMAIN (14.2, R2Q13 (a)).health_runs: the columns of data-model.md § Health run.fullis spelledfull_run, because PostgreSQL 16 reservesfull(holder6064169640).run_seqis added (see For the holder).commitis null exactly for a working-state run, and otherwise equalsexport_commit, which is 40 lowercase hex digits;pack_pinsis an object that includesopendox;sandboxis an object whoseliveis a boolean and whosepids_maxis a non-negative whole number or null.health_findings: the columns of data-model.md § Finding.pack_idandpack_versionare NOT NULL and non-empty (length(…) > 0) from this first landing (15.7).identityis TEXT holding canonical sorted-key JSON (holder6018624750), with no size cap in SQL; the cap is T041's.(run_id, id), and the foreign key to the run cascades on delete.projects(OQ-H-22).runtime/health_store.py:identityonly, so it reaches the database lazily, through the connection a caller hands it, asidentity.pydoes. JSON travels as%s::jsonbtext.record_runrefuses BEFORE any statement:patch,textorexcerptis refused, never dropped (14.3);identity,evidenceorlocator;6072086385item 4), a lone surrogate (U+D800 to U+DFFF; Copilot at01f4192d), a value that contains itself, or one nested deeper thanMAX_JSON_DEPTH(64) levels (6081875839). One ITERATIVE walk finds all three. It keeps only the containers on its current path, so no input can make it recurse, and a value shared by two branches is admitted. The run's findings are then dumped whole without a second walk.RefusedError(naming the constraint),ConflictErrorandNotFoundError.get_run,latest_run(corpus_root),baseline_run(corpus_root, baseline_branch, before_seq)(R2Q12 (a): complete, full, default-tip, same corpus and branch),get_findingandlist_findings(keyset by id, filters by class).RefusedErrornaming the column, before any statement (6086098003item 3 (c)). Before this, a NUL there raised psycopg'sDataError, and a surrogate itsUnicodeEncodeError. The writes were already guarded,pathamong them.identity.TABLESgainshealth_runsandhealth_findings, citing R2Q13 (a): the ruling6003486656, and option (a)'s text at plan 038'sclarify-questions.md:651-653. Soverify_runtime_access, whoseSERVED_TABLESisTABLES, now measures the served role's rights on them.runtime/cli.py:DROP_ORDERdrops the two health tables first, findings before runs.RESET_CONFIRMATIONis byte-identical,yes-drop-the-coordination-database, as F14.1 spells it. A comment now says so, andtest_runtime_reset_drops_a_populated_health_storeasserts it.docs/runtime.md:invoices) when the owner also ownsinvoices.docs/runtime.md§ 8a's migration lists anddroppedare re-measured:opendox-runtime runtime init|migrate|status|resetagainst postgres 16.15, which gave["0001","0002","0003"]and nine tables dropped, health tables first. The section says which figures are new. § 1 and § 7 prose name the health tables.test_schema_shape.py:_statementsreads0001with0003_, andRULED_TABLESgains both tables. Its comment cites the ruling,6003486656, and quotes option (a)'s text from plan 038'sclarify-questions.md:651-653. The…_exactly_rulings_six_tablesnode keeps its name for #1144 box 14.2's citation; its docstring says what it reads now.["0001", "0002"]lists, exactly as R2-INV-P5 lists them:test_migrations_apply.py:71,:72,:360,:431,:737,:852,:996;test_bundled_postgres.py:540,:924;test_runtime_cli.py:277.test_runtime_cli.py:342's reference map gainshealth_findings → health_runs.test_deploy_shape.pymoves withTABLES: re-run, not edited.test_migrations_apply.pygained0003_health.sql(:831for:852, and three the map did not count; see For the holder).test_api_endpoints.py, one edit, admitted by the holder (6069024568item 3).test_readiness_refuses_a_database_whose_migration_file_has_changed's tree gains0003_health.sql, for the same cause.Falsifier: red, then green
Red at openDox-code
main99220883:python -m pytest -q tests_runtime/test_health_store.pygivesE ModuleNotFoundError: No module named 'opendox.runtime.health_store', so collection is interrupted, rc=2.0003_:74 failed, 17 passed, and every DB node fails withpsycopg.errors.UndefinedTable: relation "health_runs" does not exist. That includestest_the_store_refuses_a_finding_without_provenance[no-pack_id]andtest_an_install_level_finding_is_admitted. The 17 that pass are the hermetic refusals, which never reach a database.Green at this head (
1fa6ca6c), withCI=trueandOPENDOX_TEST_DATABASE_URLset to thepostgres:16(16.15) container:python -m pytest -q tests_runtime/test_health_store.py tests_runtime/test_schema_shape.pygives174 passed in 78.04s (0:01:18)(165 nodes intest_health_store.pyand 9 intest_schema_shape.py), including:The NUL tests (REVIEW-W1 MINOR 1) were red first, at
08e80d2e. All 11 hermetic cases failed withAssertionError: a statement reached the database, and the DB case failed withpsycopg.errors.UntranslatableCharacter: unsupported Unicode escape sequence.pids_max1.5, -1 and -0.5 were admitted.The provenance test proves three layers separately:
23502onhealth_findings.<field>for a null, and23514 health_findings_<field>_checkfor an empty string.The five suites, plus
test_deploy_shape.py,test_migration_shape.pyandtest_runtime_surface.py, ran on the working tree before0ee72652was committed: 425 selected, 421 passed, 4 failed. The 4 were the three copy sites (For the holder) and one parametrization bug in the new test. All four are fixed in0ee72652; those nodes, plustest_health_store.py, then re-ran 95/95.The full suite, as CI runs it: baseline and head, node by node
Both runs were local, in one environment. The command was
python -m pytest -q --junitxml=…, run from the repository root withCI=trueandLANG=C.UTF-8, with everyGIT_*andXF_*variable unset. Each run had a venv built with CI's own install command,pip install --only-binary :all: -c constraints-cpython312-linux.txt -e ".[runtime,test]", on/usr/bin/python3.12. Both ran against the samepostgres:16(16.15) container, with TMPDIR and--basetempoutside every checkout.main6827cafc1fa6ca6cvalidateat1fa6ca6c("Pin the triple"; run37992308767, attempt 3), on the merge withmainc94878bevalidateat0336a838("Pin the triple")fbf9e77e(local)CI's
validateat1fa6ca6c: SUCCESS, in run37992308767, attempt 3. Attempts 1 and 2 ran no test, because Docker Hub refused thepostgres:16service image pull (toomanyrequests: You have reached your unauthenticated pull rate limit). CI tests the PR's merge ref,b48ce686, which merges1fa6ca6cintomainc94878be, where T015 (#96) had landed. So its 6076 nodes includemain's new ones, and the row shows #99 merging cleanly and green on top of T015. The timing flake below passed there.The one red at the head is a timing flake that
mainhas too:test_migrations_apply.py::test_the_draft_page_budget_does_not_read_the_bodies_it_sizesasserts that reading draft bodies takes more than four times as long as sizing them. At the head it failed withassert 0.029287184996064752 > (0.014348337994306348 * 4). Run eight times each, interleaved withmain(6827cafc) under the same host load (about 70), it failed 3 of 8 at the head and 3 of 8 atmain. T042 does not touch the drafts or that test.Compared by node id, from the two junit files, not by counts:
1fa6ca6c, 1 baseline node changed outcome: the timing flake above,passed -> failed. It failed onmainat the same rate.1fa6ca6c, adds exactly 166 nodes, all passing:tests_runtime/test_health_store.py;tests_runtime/test_runtime_cli.py:test_no_handler_in_this_package_emits_an_exception_without_the_redactor[health_store.py]. That walker is parametrized over the runtime package's modules, and R2-INV-P5 predicted this node (:1892).1fa6ca6c:selected>=3977 (margin 2099) passed>=3966 (margin 2099) skipped==11.0336a838, CI'svalidateselected 158 nodes more than the baseline (5964 against 5806): 157 intest_health_store.py, plus the walker node.An earlier baseline at
99220883was discarded: its venv's interpreter symlink pointed at a~/.local/bin/python3.12that something outside T042 removed mid-run, and its reds were allFileNotFoundErroron that path. A clean re-run at99220883was 5647 passed, 11 skipped, 0 failed.mainthen moved to6827cafc(#90), and the baseline above was taken there.Mutants: round 1, 76 run, 74 killed, 2 equivalent (proven); REVIEW-W1 rounds, 16 run, 16 killed; the holder's two fixes and the surrogate check, 20 run, 20 killed at
1fa6ca6cAt this head,
1fa6ca6c: the cycle and depth mutants (TOTAL killed=11 survived=0), the bound-parameter mutants (TOTAL killed=6 survived=0) and the surrogate mutants (TOTAL killed=3 survived=0) were all re-run in place. Two of the 11 changed text after SonarCloud's_json_childrenrefactor (01f4192d), and the NUL check moved into_text_unstorable(3230428c).The surrogate check (Copilot at
01f4192d):TOTAL killed=3 survived=0. Each is killed bytest_a_lone_surrogate_in_a_write_is_refused_by_name_before_any_statement[path], "a statement reached the database":pathcase carries\udcff, a low one);6081875839(cycle and depth):TOTAL killed=11 survived=0at0336a838, and again at01f4192d, after SonarCloud's_json_childrenrefactor moved two mutants' text. Red first: againstfbf9e77e's walk (with only the new constant added, so the file imports), the new tests gave20 failed, 6 passed. 15 failed withRecursionError: maximum recursion depth exceeded, and in 5 the over-deep value reached the database (AssertionError: a statement reached the database). The killing tests:[cyclic-mapping-identity], because the refusal said "nests deeper than 64 levels", not "contains itself";[over-deep-identity], "a statement reached the database";test_a_value_nested_exactly_to_the_bound_is_kept_and_reads_back[identity];test_a_value_shared_by_two_branches_is_not_a_cycle;[identity-key];[cyclic-list-identity]("is not JSON this store can keep", not the cycle);_json_text's walk removed:[cyclic-mapping-pack_pins];[cyclic-mapping-identity](named "a finding's identity", not "finding 0's identity");…_exactly_to_the_bound…[evidence]("the run's findings nests deeper than 64 levels");[identity-value].6086098003item 3 (c) (U+0000 in a bound text parameter):TOTAL killed=6 survived=0at0336a838, and again at01f4192d. Red first: at7e13130dall 7 read rows reached the database, and over a real onelatest_runraisedpsycopg.DataError: PostgreSQL text fields cannot contain NUL (0x00) bytes. Thepathrow was already green, since the write path walks every finding field. The killing tests:latest_run,baseline_run,get_finding,list_findings), or the shared parameter walk made a no-op: the matchingtest_a_nul_in_a_read_is_refused_by_name_never_by_the_driver[…]row, "a statement reached the database";pathskipped by the per-field walk: the NUL row[path], "a statement reached the database".r6b, the upper cap removed (lane 3's second pass), at
fbf9e77e: KILLED. The mutant readsmax(limit, 1)in place ofclamp_limit(limit)inlist_findings. At68f70b8ait survived (lane 3): the run holds two findings, so a cap of 500 cannot bite, and that assertion could not fail. The test now lowersidentity.MAX_PAGE_SIZEto 1 and asserts that a limit of 2 reads one row. Under the mutant it fails withAssertionError: assert 2 == 1, where2 = len([...])islist_findings(run_id=…, limit=2).REVIEW-W1 round, at
68f70b8a:TOTAL killed=15 survived=0. Each mutant was killed by the test meant for it:_json_text's check removed:[pack-pins-key]failed with "a statement reached the database".[identity-value]failed; the refusal named "a finding's identity", not "finding 0's identity".[corpus-root].[identity-key].[evidence-list].pids_maxcheck reverted, or admitting fractions:[1.5] … was admitted.pids_maxadmitting negatives:[-1] … was admitted.psycopg.errors.ForeignKeyViolation.assert None == {'line_end': 12, 'line_start': 12}.assert {} == {'candidate':…}.assert 'broken-link' == 'link target …'.assert 0 == 1.… 'BY DEFAULT') == (….assert (20, 1, False) == (1, 1, False).Round 1 follows.
Each mutant is one exact edit to the committed tree. Each was applied, run against its tests with
-x, and restored withgit checkout --. The runner is kept outside the repository. Grouped by kill:test_the_tables_hold_exactly_the_data_models_columns(the nullable set read off the applied schema). Forpack_idandpack_version, the provenance test killed them first.health_findings.run_idand.id. Both are in the composite primary key(run_id, id), which imposes NOT NULL by itself. Proof: under each mutant,information_schema.columns.is_nullablefor both columns readsNO(applied to postgres 16.15).check (true or …)(16), plus four partial mutants:pack_pinswithout theopendoxkey;sandboxwithoutpids_max;critical;unclassed.test_each_run_check_refuses_what_it_names[<constraint>…]ortest_each_finding_check_refuses_what_it_names[…], which assert the constraint the server names, and the provenance test kills the two empty-string checks.test_a_finding_must_name_a_recorded_run;test_two_findings_with_one_id_in_one_run_store_nothing;run_sequnique removed: killed bytest_a_restarted_sequence_cannot_record_a_second_run_at_one_position;identityasjsonb: killed bytest_an_install_level_finding_is_admitted;patchcolumn added: killed bytest_the_tables_hold_exactly_the_data_models_columns.full_runreverted to a barefull: killed byERROR … psycopg.errors.SyntaxError: syntax error at or near "full".health_store.pyguards (17):full_runbool check, the text-field check or the evidence-mapping check removed;started_at;--pack-restricted or any-kind runs, ignoring the branch, or ignoringbefore_seq;test_health_store.pynodes.TABLESentry (either table): killed bytest_schema_shape.py::test_the_store_declares_exactly_the_tables_the_ruling_names.DROP_ORDERthat misses either health table, or drops runs before findings: killed bytest_runtime_cli.py::test_the_drop_order_is_topological_and_not_reversed_declaration_order, with the DB-backedtest_runtime_reset_drops_a_populated_health_storebehind it.test_runtime_reset_drops_a_populated_health_store.0001only: killed bytest_the_canonical_schema_declares_exactly_rulings_six_tables.RULED_TABLESwithout the health tables: killed bytest_the_store_declares_exactly_the_tables_the_ruling_names.test_deploy_shape.py, through the byte-identity and derived-list tests.For the holder
run_seq, the order of record: ACCEPTED by the holder (6069024023item 3); the data-model row is bookkeeping.run_idthe type uuid and no ordering column, and0001's header forbids ordering by wall time ("can step backwards under load").health_runscarriesrun_seq bigint not null generated always as identity, with a unique constraint. "Latest run" and the baseline order by it, never bystarted_at(killed mutants:py:latest-orders-by-clock,py:baseline-orders-by-clock).6069024023item 3 rules that "T046 serializes its classing and recording per corpus with an advisory transaction lock, so a run's sequence position is the order in which it was classed. It tests that two overlapping runs serialize." T042 supplies the column, the uniqueness and the CACHE 1 that the ruling keeps (pinned bytest_run_seq_is_generated_always_with_a_cache_of_one).has_sequence_privilege … 'usage'= false, and the insert succeeds).test_the_served_role_can_record_and_read_a_runholds that.test_api_endpoints.py's readiness-drift test, is in a sixth suite outside the Files line and was admitted by the holder (6069024568item 3).test_migrations_apply.py'stest_editing_an_applied_migration_refuses_rather_than_reapplying,test_a_later_migration_is_applied_in_numeric_orderandtest_drift_sees_what_plan_cannotcopy only0001and0002intotmp_path, then run over thedatabasefixture's ledger, which now records0003.the ledger records migration(s) ['0003'] that this tree does not contain, so their copies gained0003_health.sql, inside a suite T042 owns.:1384(0003_not_utf8.sql) andtest_a_tampered_canonical_migration_applies_nothing_at_allrun on fresh schemas and did not move, as the map said.baseline_classis NOT NULL. R2Q12 (a) rules three classes, and I-2 (a) rules out a fourth; a null would be that fourth. The engine classes before it records (T046).commithex check of its own. A non-nullcommitmust equalexport_commit, whose form is checked, so a second check could never be the one that refuses a row, and its mutant could not be killed. The header says so.migrations.py's comments onSERVED_TABLES("RULING Q1's own list") and:93-94("reads the closed six against0001alone");bundle.py:1154("the six coordination tables and the ledger, and nothing else");runtime/__init__.py's import-weight paragraph.TABLES.fbf9e77e, on the holder's word (comment-only): the R2Q13 (a) citation. The words quoted as R2Q13 (a) atidentity.py:59(and in its module docstring) and attest_schema_shape.py:34-35and:76-80were attributed to#6566003486656. They are R2Q13's option (a) text, at plan 038'sclarify-questions.md:651-653, which6003486656ruled (a) in other words. Each comment now keeps6003486656as the ruling and citesclarify-questions.md:651-653for the quoted text. Both files' ASTs, docstrings aside, are equal before and after.Reviews and SonarCloud
Round 1, at
56d95d4f:nullpassing the object CHECKs. Accepted limit, not a defect. On postgres 16.15,jsonb_typeof('null'::jsonb)is the text'null', and all five object checks refuse it.0c5e3ccholds five test cases.run_seqconflict reported as a finding collision. Fix-now, fixed in0c5e3cc: each unique constraint now has its own message, and two mapping mutants are killed.56d95d4f93"): one P2, the same finding as Copilot (2), fixed.SonarCloud, at
56d95d4f: the gate failed on reliability C.plsql:NullComparison, onpack_id <> ''andpack_version <> ''. The PL/SQL analyzer applies Oracle's rule that''is NULL; in PostgreSQL it is not.0c5e3ccspells both aslength(…) > 0, which is the same check in PostgreSQL, and the two empty-string mutants are still killed.python:S5778(more than one possibly-raising call in apytest.raisesblock): fixed in0c5e3cc, one call per block.plsql:S1192("Define a constant instead of duplicating this literal 4 times":'object'in fourjsonb_typeof(…) = 'object'checks) is EXPLAINED, not changed:test_each_*_check_refuses_what_it_nameskills its mutant by the constraint name the server reports.jsonb_typeof's own vocabulary, so repeating it is the readable form.Round 2, at
08e80d2e(after0c5e3cc,808524cand the merge ofmain6827cafc):08e80d2e: "🔵 Needs a closer look", 0 open findings, 2 resolved since its last review. The stated reason is only that "the cross-cutting schema, persistence, and deployment change remains a draft gated on T027 and final validation". It is not "Changes recommended", and it opened no thread.08e80d2e(comment at 23:23:05Z): "Didn't find any major issues", with Reviewed commit:08e80d2e48. No thread was opened. An earlier trigger, at 21:36Z, had been answered with a usage limit.S1192explained above.validate,acceptanceand SonarCloud are all SUCCESS.Round 3, at
68f70b8a(lane 3's REVIEW-W1 of08e80d2e, DRAFT: T042 (plan 038, HA-1): the health store, 0003_health.sql and runtime/health_store.py #996071241577: GO, with 0 BLOCKER, 0 MAJOR, 3 MINOR and 9 NIT; the holder's rulings, #6566072086385; item-by-item reply6072912368):run_seq's catalog, the page bound andpids_max.68f70b8a: "🔵 Needs a closer look", 0 open findings. Its stated reason is only that the change "remains draft-gated on T027 and needs final human confirmation"; it is not "Changes recommended".68f70b8a. Its answer to the trigger (02:18:56Z) was "You have reached your Codex usage limits for code reviews". Its last review was clean at08e80d2e48.plsql:S1192, both EXPLAINED, not changed. One is'object'×4 (line 105), as above.'pids_max'×4 (line 106):health_runs_sandbox_checkreads that one key four times inside a CASE. The CASE is there so the numeric cast is reached only for a JSON number, because SQL does not promise to evaluate an AND's operands in order, and DDL has no constant to name the key.jsonpathform (sandbox @? '$.pids_max ? (…)') would read it once. It is a less familiar syntax for the same check, and it would change a head whose suite is already measured, so it is the holder's word if wanted.Round 4, at
fbf9e77e(lane 3's second pass of68f70b8a, relayed by the holder: GO, with one MINOR and four NITs still open):data-model.mdnote), andpids_maxreads "a non-negative whole number or null".fbf9e77e: "🔵 Needs a closer look", 0 open findings, and no thread. Its one "previously missed" item (medium): a CYCLIC mapping or list raisedRecursionErrorfrom the NUL walk, notRefusedError.7e13130d, by the holder's FIX-NOW ruling, #6566081875839. The NUL walk, put in front ofjson.dumps, had regressed a refusal the store already had:json.dumpsrefuses a cycle withValueError, which the store turned intoRefusedError. The same walk let a value nested past Python's recursion limit escape asRecursionErrortoo.MAX_JSON_DEPTH(64), by the field's name, before any statement, quoting nothing, and with no row written. The tests and mutants are above.fbf9e77e. Its answer to the trigger (6073222041) was the usage-limit message (6073223584).fbf9e77e, with the same 2 openplsql:S1192, explained above. CI:validate,acceptanceand SonarCloud SUCCESS.Round 5, at
0336a838and01f4192d(the two holder rulings):7e13130dcarries6081875839(above).0336a838carries6086098003item 3 (c): every read now refuses U+0000 in each text parameter it binds, naming the column, where psycopg had raisedDataError.0336a838: "🔵 Needs a closer look", 0 open findings, with no "previously missed" item. Its stated reason is only that the change "remains a draft with an explicit T027 landing dependency requiring final human validation".0336a838. Its answer to the trigger (6086316679) was the usage-limit message (6086319829).0336a838: the gate passed, but there were 5 new issues on the two fixes. All 5 are FIXED in01f4192d, with no behaviour change:python:S5778: eachpytest.raisesblock in the new tests now holds one call;python:S3776(cognitive complexity 16 of 15) in_unstorable: what the walk visits is now_json_children.0336a838:validate(triple: selected=5964 passed=5953 skipped=11),acceptanceand SonarCloud SUCCESS.01f4192d: "🔵 Needs a closer look", 0 open findings, and no thread. Its one "previously missed" item: a LONE SURROGATE (U+D800 to U+DFFF), which a surrogate-escaped file name carries inpathorcorpus_root, passed the walk. Measured at01f4192d, the driver raisedUnicodeEncodeError: 'utf-8' codec can't encode character '\udcff' … surrogates not allowedwhile binding, and on a write only after the run's own insert.3230428c, classified fix-now under the holder's principle in6086098003item 3 (c) and6081875839: a driver error instead of the store's named refusal, from a simple payload, with a small fix. The walk's text check now refuses a lone surrogate as it refuses U+0000, by name, before any statement, on writes and on every read parameter.UnicodeEncodeError). Green: the two files plus the walker node,186 passed.01f4192d. Its answer to the trigger (6088583751) was the usage-limit message (6088585995).3230428c: "🔵 Needs a closer look", 0 open findings, and no thread. It raised two "previously missed" items, both wording:docs/runtime.md:31and0003_health.sql's header (:82) stated in the present tense that the hosted plane refuseshealthby name. R2Q15 (a) rules that refusal, but T046 adds it with thehealthverbs and routes, and this change adds neither.1fa6ca6c, as comment and prose only: both now say the refusal is ruled and arrives with T046.0003's statements outside--comments are unchanged (compared line by line). This head's full suite had not yet run, so the fix cost one review round.3230428c. It answered the trigger (6088723901) with the usage-limit message.1fa6ca6c:1fa6ca6c(6089385155, the usage limit).S1192, now at lines 107 and 108.Files changed
migrations/0003_health.sql(new)src/opendox/runtime/health_store.py(new)src/opendox/runtime/identity.pysrc/opendox/runtime/cli.pydeploy/compose/init-runtime-role.shdeploy/kubernetes/base/init-runtime-role.shdocs/runtime.mdtests_runtime/test_health_store.py(new)tests_runtime/test_schema_shape.pytests_runtime/test_migrations_apply.pytests_runtime/test_bundled_postgres.pytests_runtime/test_runtime_cli.pytests_runtime/test_api_endpoints.py(one edit, admitted by the holder in6069024568)What is NOT done
identity, and every other field bound (the id grammar,message's 200 characters, the banned keys): T041's, inhealth_contract.py. Not imported, and not encoded in SQL.health run|listand the hosted-plane refusal: T046.data-model.mdnote that thefullfield's SQL column isfull_runis on openxFactory main since3a2ab303(data-model.md:160). Therun_seqrow (6069024023item 3 bookkeeping) is the holder's batch.pids_maxNIT), because none is a shape this PR's rulings fix:pack_id(its grammar is T041's bound);pack_pins.opendox= 5 (data-model.md fixespack_pinsas{pack_id: {"version", "digest", "commit"}}, with "opendox's entry the installed version alone", which leaves that entry's form open);baseline_branchon a default-tip run (in T042's Files and one constraint away,coalesce(length(baseline_branch), 0) > 0; not ruled, so not added).test_runtime_surface.pyis not moved.health_store.pyimports nothing beyond the standard library andidentityat module level, so it passes the heavy-module closure without joiningSTDLIB_ONLY_MODULES.🤖 Generated with Claude Code