Repository navigation
chore(ratchet): lower the frontend style counts to batch 2b's combined tree — batch 2b vehicle and final member (#15455) - #16596
Merged
Merged
Conversation
…posable family (#15025) Zero live callers repo-wide (verified independently: every apparent grep hit outside the file is a same-named component prop, a historical migration comment, or the eslint ban itself). GH#6487 already deprecated the family and banned new imports; GH#7446's audit already found zero active callers outside legacy test mocks. Capability parity holds per the file's own docstring: every export is a thin wrapper around useApiClient()'s get/post plus a generic withErrorHandling(), both already documented as the canonical replacement. Also: - Drop the now-pointless no-restricted-imports ban on the deleted path. - Drop the orphaned hardcoded-values baseline entry for the deleted file. - Update three developer docs that presented useApi()/useApiWithState() as a still-valid pattern (COMPOSABLE_HTTP_PATTERNS.md's Pattern A2, whose entire usage inventory was already stale -- all 8 listed composables had already migrated off it; CODE_REUSABILITY_GUIDE.md's composable inventory; frontend-testing.md's ApiClient-shape example).
…rs through getSlmApiBase() (#15761) getApiUrl() in stores/auth.ts diverged from getSlmApiBase() in DEV: it hard- returned '' regardless of VITE_API_URL, while getSlmApiBase() honoured it. They agreed only because the SLM 'dev' script happens to set no VITE_API_URL -- an incidental property of one script, not a guarantee (#13140 called this out as a latent divergence). The ESLint rule that forbids raw fetch/axios outside the client says nothing about a second base-URL resolver living beside the canonical one, so nothing caught a regression here. - APISettings.vue and BackendSettings.vue (the only two real callers, both display-only -- neither ever used it for transport) now call getSlmApiBase() instead. Removed the now-unused useAuthStore import/usage from both. - Dropped getApiUrl's definition and export from the store. - Cleaned up the five test files that mocked authStore.getApiUrl() but whose components under test never actually called it (verified each independently), plus BackendSettings.test.ts's now-pointless vi.mock('@/stores/auth', ...) block, since BackendSettings.vue no longer imports useAuthStore at all. - Added ssot-config.test.ts, pinning getSlmApiBase()'s DEV-mode resolution (standalone '/api' vs co-located '/slm/api'), so a second resolver cannot silently reintroduce the same divergence without a test noticing (AC4). - The auth-endpoint 401 opt-out (login/MFA transport, a separate code path this change never touches) already has real test coverage in auth.test.ts:315,329 -- unaffected, confirmed unchanged (AC3).
…cell-syntax-* tokens (#14853) artifact-cells/CodeCell.vue carried its own raw hljs hex palette, independent of canvas/CodeCell.vue's --codecell-syntax-* tokens (#14770). Reused those tokens rather than re-deriving a new palette, per coordinator decision (posted on #14853 before this commit, with the full before/after color table): - AC2 ('both CodeCells resolve their syntax colours from the same token set') and AC4 ('rendered colours unchanged') cannot both hold -- every category's current hex differs from the matching token's value in both themes. AC2 wins; AC4 is left unticked in the PR with that explanation. - Added the one missing category, --codecell-syntax-tag-{light,dark} (neither existing palette had one), pinned to this file's own prior values -- the only choice available that isn't a guessed 'standard' hljs-theme color. - Fixed a real pre-existing bug along the way: two light-mode rules both targeted .hljs-attr (#8000 then #0000ff), so it silently rendered blue, not green -- now one rule, one token. - Replaced a third, unrelated raw hex (.code-container's light-mode 'color: #333') with the semantic --text-primary token this exact selector already uses everywhere else in the file; required regardless to pass color-no-hex, which lints the whole file once any part of it changes. - Corrected design-tokens.css's stale #12048 comment, which still called this file's palette 'DATA, preserved literal in the component' even after #14770 already tokenised the other CodeCell -- doubly wrong now that this file converges onto the same tokens too.
…s needs (#15761 CI red) Removed as "now-pointless" on the reasoning that BackendSettings.vue no longer imports useAuthStore directly -- true, but useAutobotApi() (its connection-probe transport, #13079) does, reading authStore.token for the Authorization header. Without a mock, that's a real Pinia store with no active Pinia instance in this test file: "getActivePinia() was called but there was no active Pinia" on mount, failing all 3 tests in this file. token is the only field either caller still reads -- getApiUrl, the field the old version of this mock carried, is gone along with the store method this PR retires.
…#15528, #16495) sessions.list sends scope/team_id, knowledge.search is a POST with a JSON body, analytics.usage/performance take no arguments, and several response types now match the flat documents or DataResponse envelopes the backend actually returns instead of invented shapes. agents.updateConfig is removed -- no PUT route for it exists on either mount -- and setModel/ setEnabled are added to match the Python SDK. Every request was also missing the /api prefix entirely (#16495), the same defect #15053 already found once in the Python package; buildUrl now applies it the same way Python's api_path() does. repo_tests/sdk_ts_request_contract_test.py is a new static-analysis guard that pins both the TS source's own requests and the real backend route table (reusing sdk_request_url_test.py's oracle fixtures) since this checker cannot execute TypeScript.
… the file-coverage guard (#15528, #16495) HIGH: the static guard text-scanned each method's relative path literal but never touched client.ts, so nothing proved the /api prefix actually reaches a request -- exactly what #16495's AC2 asks for. Added libs/autobot-sdk-ts/tests/apiPrefix.test.ts: mocks global.fetch, calls one method per resource plus setEnabled's runtime-chosen segment, and asserts the captured URL starts with /api (plus one case proving apiPath() doesn't double-prefix a path that already carries it). MEDIUM: test_the_table_covers_every_resource_file_that_exists used Path.glob and asserted pinned <= on_disk, so a new resource file with unpinned methods would pass silently, and the parametrize list for the completeness test was a hardcoded 4 files. Both now derive from tools.lint._scan_helpers.tracked_paths, and the coverage assertion is on_disk == pinned in both directions. Also added, since it was sitting right next to the fields check the oracle already gave media type for: every POST/PUT row now asserts the route publishes application/json, not just that the field names match -- the same defect class #15527 fixed on the route side (a Form field beside a dict body publishes as x-www-form-urlencoded, which no JSON body can satisfy). Verified statically against agent.py's current execute_command that #15527's fix already makes this hold before adding the assertion. Non-blocking items: changelog fragment now names agents.getConfig's new required agentId and the removed updateConfig. The category-field gap in knowledge.search was filed separately (#16543, already open) and isn't touched here.
… this package's ESM preset, and record the new TS-tree glob dependency NPM Package Tests failed with "ReferenceError: jest is not defined" on every test in apiPrefix.test.ts. describe/test/expect are ambient globals under ts-jest/presets/default-esm + --experimental-vm-modules, but the jest mock-utility object is not -- it has to come from @jest/globals explicitly, unlike the CJS preset every other file in this package predates. Fixed by importing it and typing the mock as ReturnType<typeof jest.fn> instead of the CJS-only jest.Mock. Separately, python-suite shard 8/12 failed glob_declared_reads_15900_test.py: sdk_ts_request_contract_test.py's new tracked_paths(_REPO, "libs/autobot-sdk-ts/src/resources/*.ts") is a glob into a tree the python path-filter does not cover, and #15900's guard requires that dependency be written down rather than silently invisible to the filter. Added the entry to GLOB_DECLARED_UNCOVERED.
) Regression test only, no fix yet -- pushed alone so CI's own red is the evidence a real recursion exists, per the coordinator's request (same push-red-then-green pattern as #16525/#15931). Drives SearchMixin.search() down the basic vector path directly (the exact parameter shape VectorSearchEngine._CPUBackend itself uses), with the real VectorSearchEngine and real _CPUBackend running. _CPUBackend's only dependency, get_knowledge_base, is mocked to return this same counting instance -- its entire I/O boundary (knowledge/vector_search_engine.py:204-221 has no other external call). Asserts the orchestrator is entered exactly once; a capped counter avoids actually exhausting the stack so the result stays deterministic.
…15165) Adds SearchMixin.basic_vector_search() -- validate, sanitize, query ChromaDB directly, no VectorSearchEngine dispatch -- and switches VectorSearchEngine._CPUBackend.search() to call it instead of the high-level search() orchestrator it is itself reached from. Previously _CPUBackend.search() called kb.search(query=query, top_k=top_k, filters=filters), which (with no limit/tags/etc set) takes search()'s own basic vector path, which tries VectorSearchEngine again, which reaches _CPUBackend again -- no base case anywhere in the chain. Each level did real validation/ sanitization/embedding work before recursing, so the load-dependent slowness reported against a live backend (25-70s+ under concurrent load, normal latency idle) fits: a fixed, large number of recursion levels at load-sensitive per-level cost, not a hard hang. The regression test pushed in the prior commit alone (so its failure would be CI's own evidence, not an argued claim) now passes: the counting SearchMixin's entry_count drops from 4 (capped) to 1.
… an inferred one (#16495) The ESM-globals fix in the last commit cleared "jest is not defined", but NPM Package Tests then failed to even compile: TS2345, because jest.fn() called with no type argument infers Mock<never>, so mockResolvedValue(...) rejected the real response object outright. Spelled out the call signature -- jest.fn<(...args: unknown[]) => Promise<FakeFetchResponse>>(impl) -- and passed the implementation alongside it instead of chaining mockResolvedValue, so there is one generic instantiation to satisfy rather than an inferred one meeting a separate call. .mock.calls[0]'s cast to [string] is a widen from unknown[], not a narrow from a concrete tuple, for the same reason.
…ecretsManager (#16429) SecretAuditLog.vue, SecretVault.vue and ShareSecretDialog.vue had zero callers outside their own stories files. Triaged each individually rather than deleting on sight: - SecretAuditLog: genuine gap, not a duplicate. useSecretsAuditApi reads a real GET /api/audit/logs (admin-only, api/audit.py), which api/secrets.py already writes to on every secret op. Wired into the Secrets page as a new admin-only tab (views/secrets/AuditLogView.vue, secrets-audit-log route), matching the LLM API Keys tab's existing admin gate. - SecretVault: same backend as SecretsManager.vue (secretsApiClient, same /api/secrets/ routes) -- a superseded parallel implementation. Its one net-new capability, virtual scrolling for 100+ items (#4037), is ported into SecretsManager.vue's list view (grid view keeps plain rendering -- CSS grid's auto-fill column count depends on runtime container width, which useVirtualList's fixed-row model doesn't represent, and SecretVault itself never had a grid mode to port a solution from). Retired in this PR now that parity is shown. - ShareSecretDialog: depends on useSessionCollaboration, which has 5 sibling components in components/collaboration/ that are themselves unwired -- a full real-time collaborative-session UI (#608 phases 5-7, closed / #874 phase 6) built end-to-end and never connected to any view. Filed as its own implementation gap, #16443 (sub-issue of #16425, blocked_by edge from #16429). Left unticked here. Also fixed while mapping SecretVault's scope vocabulary onto the backend's canonical values: the create/edit form's Scope select offered user/session/ shared options that api/schemas_system.py's SecretCreateRequest.scope (typed ChatSecretScope) would reject with a 422 -- only general/chat were ever valid. Filed #16450 for a larger, separate finding from the same investigation: the Visibility/Organization/Team/Shared-With controls in the same form have no server-side effect at all (SecretCreateRequest doesn't carry them onto the persisted model).
…e no longer rewrites it (#16353)
…rt inertly (#16198) The first landable piece of #13539, and the one its design puts first because it is the only piece that sizes itself: V5 -- the fresh-interpreter import sweep before a release flips -- is mandatory and cannot run until the import offenders are fixed, and the offender list is unbounded until this guard runs once (B12). The third member of an existing family. collected_modules_inert_on_import_test asks whether a module calls sys.exit at import; first_party_imports_resolve_test asks whether its imports resolve. Both read the source. This one asks the question neither can -- does the module actually import, and does it do anything on the way -- which needs a real import in a real interpreter. The sandbox is what makes running it safe. Each import happens in a subprocess whose generated sitecustomize installs a sys.addaudithook handler that RAISES on socket.connect, subprocess.Popen, os.system and writes outside the tree, so a module with an import-time side effect fails the probe instead of performing the side effect. That property is load-bearing rather than decorative: one module here starts an Ollama client at import (#16188). One module per interpreter, deliberately. Batching would be ~40x faster and would break the property being asserted -- module A's import can leave sys.modules entries, monkeypatches or atexit handlers that decide whether B imports cleanly, and a sweep that cannot tell "B is inert" from "B is inert after A ran" is not measuring hermeticity. Population 606, derived and declared with a floor of 590 so a sweep that stops matching fails instead of reporting a clean empty result. _discover returns an empty list on an empty tree and never raises, per #16154. The sweep itself is gated behind AUTOBOT_IMPORT_HERMETICITY_SWEEP. Two reasons, both measured rather than assumed: 606 interpreter startups do not fit the pre-push budget, and a guard that makes every push time out is disabled within a week. Second, and the one that decides where the offender list must come from -- this machine has 98 of 205 declared dependency versions unsatisfied, so a local sweep would report every module importing one of them as an offender. The enumeration is only meaningful from CI, which installs the declared set. Controls, all three green: a planted module opening a socket at import is caught as a HERMETIC_VIOLATION, an inert module passes, and an unimportable module fails with a legible reason rather than reading as clean. Without them a sandbox that hooked an event name that does not exist would report all 606 modules clean and look like a green guard.
…ads it as test IDs (#16198) `Check nosec annotations reach bandit intact (#13521)` failed on both annotations in the new guard. The form used was: # nosec B404 - the sandboxed probe IS the subject of this guard # nosec B603 - fixed argv, no shell bandit parses everything after `nosec` as a whitespace-separated list of test IDs, so a dash separator does not end the parse -- "the", "sandboxed", "probe" and the rest are each read as an ID. The suppression still applies for B404/B603, but it silently widens to a list of nonsense IDs, which is why the repo checks the shape rather than trusting it. The accepted form puts prose behind a second `#`, which is what actually terminates bandit's parse: # nosec B404 # the sandboxed probe IS the subject of this guard Regex that catches it: scripts/check_nosec_format.py:88.
…t actually gets produced (#16198) The guard landed in the previous commit with its sweep gated behind AUTOBOT_IMPORT_HERMETICITY_SWEEP, and nothing set it. So the instrument existed and the thing it was built to produce -- the enumeration of modules with import-time side effects -- would never have been produced. #16198's acceptance criterion "the first full run's offender list is posted on this issue" was unreachable by construction. Deliberately NOT on pull_request. The sweep starts 606 interpreters, and a base merge already multiplies every workflow by the number of open PRs -- measured at ~200 runs per merge across 8 parked branches (#16203). This asks a question about the TREE, not about a diff, so a PR trigger would pay the multiplier for an answer that cannot change between two PRs. Schedule plus workflow_dispatch instead. Installs requirements-ci.txt plus an editable autobot_shared, matching startup-import-smoke.yml, which asks the closest question in the repo. Not autobot-backend/requirements.txt: that pulls torch>=2.11.0 with transitive vllm 0.19.x requiring torch==2.10.0, an unsatisfiable resolver state (#7018). Getting this wrong is not cosmetic here -- a module importing an unsatisfied requirement is indistinguishable from a module with an import-time side effect, so a bad install produces a false offender list, which is the exact failure the whole workflow exists to avoid. The offender list publishes with `if: always()`, to the step summary and as an artifact. A red sweep that discarded its enumeration would make the run worth nothing, and the enumeration is the deliverable rather than the exit code. The job is expected to be RED until the offenders are fixed, and that is correct rather than tolerated: they are real findings. It gates no PR, so being red blocks nobody -- which is what makes landing the guard before the fixes honest instead of a hole.
Both found by the review pass on this PR, both reproduced live by it rather than
argued, and both in the leg of the hook I wrote least carefully.
1. `_outside_tree` compared with a bare string prefix, so
"<tree>-malicious/evil.txt".startswith("<tree>") -> True
and a sibling directory whose name merely EXTENDS the repo root read as
inside the tree. Not hypothetical: this repository names worktrees
`<repo>-<slug>`, so the exact shape that defeats a prefix check is one it
produces routinely. Now compares against `_TREE + os.sep`, with the root
itself handled separately.
2. The `open` audit event reports `(path, mode, flags)`. `open()` fills in the
mode string; **`os.open()` passes mode=None and puts the intent in flags**.
The check read only mode, so `if mode` short-circuited and every `os.open`
write went through unexamined. Verified by the reviewer: `os.open(path,
O_WRONLY|O_CREAT)` outside the tree exited 0 while the identical `open(path,
"w")` raised. Two spellings of one act, one of them caught. `_is_write` now
reads flags when mode is absent.
Both were in the "writes outside the tree" arm only. The socket / subprocess /
os.system detection -- the motivating case, #16188's Ollama client at import --
was confirmed sound by the same pass, which also verified empirically that the
audit event names fire and that `sitecustomize` actually loads. That last check
is the one that mattered most: a hook keyed on a misspelled event reports every
module clean and looks like a passing guard.
Each fix carries a control, and each control was verified to FAIL against the
pre-fix logic before being kept -- a test that passes with and without the fix
proves nothing about either.
Also drops an unused `tmp_path` fixture the review flagged.
…cks that cannot fail (#16198) The re-review confirmed both sandbox bypasses are closed -- traced analytically and confirmed empirically against real CPython audit-event shapes (os.open with O_WRONLY|O_CREAT reports flags 524353, masked 65; O_RDONLY reports 524288, masked 0 and correctly not flagged). It also found this: sibling = str(_REPO_ROOT) + "-sibling" assert sibling.startswith(str(_REPO_ROOT)), "the fixture must be a prefix..." True by construction. A string built by appending to X always starts with X, so the assertion holds for every possible _REPO_ROOT and verifies nothing. I wrote it believing it guarded the fixture's validity. The property that makes the fixture discriminating is the opposite: a prefix that is NOT a child. That is exactly what the old bare `startswith` misclassified, and the only reason the control exercises the fix. Were the fixture ever to become a genuine child, the test would still pass, for the wrong reason, silently. Now asserts `not sibling.startswith(_REPO_ROOT + os.sep)`, which can fail. Left as-is deliberately: `os.path.abspath` does not resolve symlinks, so a symlink under the tree pointing outside reads as inside. Immaterial here -- this guard catches accidental import-time writes in first-party source, not an adversarial boundary, and `realpath` would slow all 606 probes to close a hole nothing in this threat model reaches through.
#16199 review (hold): the sweep runs only on schedule and dispatch, with no failure step, issue or alert, so a PR introducing an import side effect merges green and the 04:00 run goes red with nobody told. Same shape as ratchet-base-guard.yml: the sweep step captures pytest's rc instead of aborting, then - an offender run opens or updates ONE automation-labelled issue carrying the report (passed through the environment, never interpolated into JS), - a clean run closes it, - a run that failed before examining anything (checkout, setup, install) opens a separate "could not run" issue, so a sweep that never looked does not read as a clean night, - and the run still fails when there are offenders.
…16198) #16199 review: floor=590/growth=20 against a live population of 608 left two modules of headroom, and reach_declarations_test fails any PR that pushes the population past floor+growth. Measured with the sweep's own predicate over git history: 504 (~12 Jul), 556 (~11 Aug), 608 (10 Sep), about 52 modules per 30 days -- a band of 20 would fail an unrelated PR within days. floor=600, growth=60: just under today's count, and a little over a month of measured growth. Root loss stays caught by the every-root-contributes assertion.
…shape (#16198, #16237) Steps with no shell: key run under bash -e, and set -uo pipefail does not clear -e, so a bare failing command aborted the step before rc=$? or rc=${PIPESTATUS[0]} ran. Four steps carried it: the hermeticity sweep (set +e around the pipeline), the ratchet base audit and the watchdog classifier (rc=0 then cmd || rc=$?), and the parked-branch merger's merge_rc, introduced by #16128 after the issue's sweep. ratchet-base-guard gains a failure() issue step, placed before the step that fails the run on purpose. The sweep also runs on pull_request, because a schedule runs the default branch's copy (#16221); its issue steps are gated off pull_request. repo_tests/workflow_rc_capture_test.py sweeps every run block under an errexit shell (reach floor 330, measured 335). It self-tests on synthetic workflows and runs the three fixed steps under bash -e with a planted failure, beside pre-fix controls. The python filter now covers the three pinned workflows, and the uncovered-reads and glob records are updated.
Both readers now file a second issue when the job fails before it measures anything. A later clean run closed only the violation issue, so a could-not-run report outlived the fault it described. The close step now closes either title.
… a shrink-only baseline (#16198) The sweep's first full run (34564055823) found 54 of 608 modules failing on base, so merged as it stood it would turn every backend PR red, and at 15m43s of pytest it is too slow to run in full on each one. - Failure records carry their tree. They are compared with a frozen baseline, repo_tests/import_hermeticity_known_offenders.py, in two categories: 53 with an import effect (51 SLM, 2 backend) and 1 that does not import. A failure it does not list fails the run; a full run also fails on an entry that passes. - On a pull request the workflow runs FULL when the sweep's own files change, SUBSET (the changed swept modules plus their direct importers, from an AST import graph) when swept modules change, and NONE otherwise: no install, no pytest, and a summary saying nothing was examined. Push to Dev_new_gui, schedule and dispatch run FULL. - The scope logic lives in repo_tests/_import_hermeticity_scope.py, shared by the workflow and the test, which also lists what a subset cannot reach. Drain: #16262.
… cleanly (#16198) Staleness was judged on full runs only, so a pull request fixing a listed module passed its subset run, merged, and turned the next full run on base red until someone removed the entry. The sweep now judges every baseline entry the run probed: a full run judges all of them, a subset the ones it examined, and each one that no longer fails the way it is listed fails with "remove it from the baseline in this PR; the list only shrinks". Entries a subset did not probe are still judged only by the full run. Drain: #16262.
…e an absent path, so two repo guards stop reading test fixtures as repo state (#16198) stranded_recorder_entries_test read the module-level _TREE dict as a recorder whose repo-rooted entries were stranded (shard 10). python_filter_covers_its_guards_test counted the "docs/README.md" literal as an uncovered input, 39 against a pinned 38 (shard 12). Both paths exist only inside tmp_path.
…d tree (#15455) Batch 2b's twelve members each lowered or held the frontend style counts on their own. Together they remove more than any one of them recorded: the combined tree measures css_rule_declarations 9401 (baseline 9405) and distinct_class_names 5619 (baseline 5623). The ratchet only moves down and has to equal the measured count, so the baselines follow the combined tree here, on the batch's own tree, where these are the true counts.
Contributor
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Advanced Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This was referenced Sep 13, 2026
Contributor
Contributor
✅ SSOT Configuration Compliance: Passing🎉 No new hardcoded values of either class — Known backlog in |
This was referenced Sep 13, 2026
…2b's combined count (#15455) The batch 2b vehicle's CI measured the frontend API-contract ratchet's inline_generics at 564 for autobot-frontend against a baseline of 577: the twelve members together remove 13 inline generic assertions. Same combined-tree reason as the fragmentation baselines in the previous commit; the value is the ratchet test's own report on this tree. Touching the file makes the whole-file black hook reformat two generator expressions in it to the configured 120-column style.
This was referenced Sep 13, 2026
Closed
…ut from one shard setting (#16516) A hung test used a shard's whole hour and printed nothing, because the shards run -q and set no faulthandler_timeout. Both python-shard pytest invocations now pass -o faulthandler_timeout from the job-level PYTEST_FAULTHANDLER_TIMEOUT_S (600s; the slowest recorded test is 180.6s in .test_durations_slm). A repo test pins the wiring by reading the setting's name from ci.yml, never restating its value.
# Conflicts: # .github/filters/python-paths.yml
…ssue-15455-ratchet-2b
This was referenced Sep 13, 2026
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Refs #15455
Single-issue rationale: a one-line ratchet correction that exists only because of batch 2b's combined tree. It isn't a fix for #15455 (the ratchet's size-versus-duplication design), only a baseline move within it.
This PR is batch 2b's test vehicle AND its final member.
main(995e135) plus the 12 approved member heads (fix(ci): keep line numbers out of the secrets baseline, so a line move no longer rewrites it (#16353) #16362, guard(imports): every module under api/ and autobot_shared/ must import inertly (#16198) #16199, fix(infra): clear the debt blocking the last four branch-name swaps, and default install.sh to main (#16540) #16558, security(research): treat fetched repos and pages as untrusted data (#16488) #16492, feat(preflight): run every reproducible required check through the workflow's own command (#15933) #16416, fix(sdk): TypeScript SDK request/response parity + missing /api prefix (#15528, #16495) #16497, fix(knowledge): give _CPUBackend a non-recursive vector-search leaf (#15165) #16564, feat(secrets): wire in SecretAuditLog, consolidate SecretVault into SecretsManager (#16485) #16486, chore(slm-frontend): retire getApiUrl(), route its display-only callers through getSlmApiBase() (#15761) #16432, fix(knowledge): wire real grounding:stats counters, replacing the hardcoded claim_sources split (#14981) #16434, fix(frontend): point artifact-cells/CodeCell.vue at the shared --codecell-syntax-* tokens (#14853) #16437, chore(frontend): retire useApi.ts, the deprecated useApiWithState composable family (#15025) #16424), each merged at its approved SHA, plus ONE commit of its own.mainis the one baseline line, because the member changes are identical on both sides.Thinking Path
repo_tests/frontend_fragmentation_ratchet_test.pyrequires each counted dimension to equal its baseline, and to move only down.css_rule_declarations = 9401(baseline9405) anddistinct_class_names = 5619(baseline5623) in the fragmentation ratchet, and autobot-frontendinline_generics = 564(baseline577) in the API-contract ratchet. The pre-push run caught the first two one at a time, because it stops at the first failure. This PR's own CI (shard 4) caught the third.maindoesn't work. Onmainalone the count is 9405, so a 9401 baseline would read as growth. Merging the 12 and fixing afterwards leavesmainred until the follow-up's CI passes. Carrying the baseline on the batch's own tree is the one place 9401 is true before and after the merge.What Changed
repo_tests/frontend_fragmentation_ratchet_test.py:"css_rule_declarations": 9405→9401, and"distinct_class_names": 5623→5619.repo_tests/frontend_api_contract_ratchet_test.py: autobot-frontend"inline_generics": 577→564. Nothing else in this PR's own commits.Verification
mainmust show onlyrepo_tests/frontend_fragmentation_ratchet_test.pyandrepo_tests/frontend_api_contract_ratchet_test.py.Model Used
Claude Opus 5 (
claude-opus-5)