Repository navigation
debt_ratchet.py is only the CI entry; the pinned audit owns every measure - #3606
Merged
Merged
Conversation
…sure tools/debt_ratchet.py was 2,919 lines and 95 classes, a second audit engine beside the refactor-audit this repository pins. The engine, its measures and its report moved to refactor-audit (OpenHCSDev/refactor-audit#7). agent-comms' own facts are that package's audit/agent_comms_project.py, derived from their owners here, and the pool and runner stay ForkedProcessPool and SpawnedProcess. The entry is now argparse for --root/--base/--head/--workers and one call to audit.ratchet.ratchet(): 32 lines, 0 classes. The report, the stderr lines and the exit status are unchanged, and both workflows run as before. - The submodule pin moves to refactor-audit 45b7fc27 (the PR head; the pin moves to the reviewed commit before merge). - tools/typing_names.py moved to audit.typing_names; module_layers imports it from there. - repairs.py, test_boundary_decoding.py and test_carry.py import their measures from the audit owner directly. - pinned_audit takes ForeignAbsenceProbe from audit.source_measures, and phase_evidence calls its occurrences(node). - PlainStrIdRatchetPhase and LockCensusPhase kept grepping tools/debt_ratchet.py, which no longer holds those classes. The new PinnedPatternPresent reads the submodule tree main pins, at the commit its gitlink names (MainTree.pinned). - tests/guards/test_debt_ratchet.py: the generic suite moved to refactor-audit. What only agent-comms declares stays here as test_agent_comms_ratchet.py: lock owners, the boundary decoder, codec modules, done phases, the stored-record probe, the pool's process tree and the CLI's merged log. The lock-owner test had asserted two owners since 1ab5bde added process_claim as a third; it now asserts the three the declaration derives. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RnH6dS2Kmg1WxNnAc78YHA
|
debt-tools at 8b20ff7, every finding: |
|
debt-src at 8b20ff7, every finding: |
…wners claude-code's review of 292f2dd: - PinnedPatternPresent carried the submodule as a str field, and plan_phases.py wrote the same path twice more. pinned_audit already derives the skill directory, so it now declares SKILL once. The new AuditPatternPresent(pattern) finds the gitlink from agent_comms.skills' module path plus SKILL's name, and the package from audit's own location under SKILL. - MainTree.pinned matched ls-tree's "commit" type string, which grew StringIdentity. It now reads the gitlink with rev-parse <commit>:<path>. - The lock-owner test hand-wrote the three owners lock_owners() derives. It now asserts every derived owner exists and counts nothing there. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RnH6dS2Kmg1WxNnAc78YHA
AgentCommsProject and ClientTypeErrors move out of the pinned audit into tools/, beside the entry: agent-comms' facts change in agent-comms. debt_ratchet.py is raise SystemExit(main(AgentCommsProject(Path.cwd()))); the audit owns the command line. Every `from audit import agent_comms_project` side-effect import is gone; repairs and the tests measure an AgentCommsProject instance. A carry step is a module under STEPS whose class derives from the Carry family, not a file named carry_*. GodFunction's limit is LongFunction's. The submodule pins refactor-audit 03ed7a0e (#7's head). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RnH6dS2Kmg1WxNnAc78YHA
…rces fix carried() bound only Carry and its direct subclasses, so a step deriving from another step's base (carry_toad_arrow_keys.py's ToadSettingsCarry, 0f896c5) read as no carry. It binds the whole family now: 0f896c5, 0455ac6 and 01cc13c read carried, merge 4ca5c19 does not. The content-cache test reads measuring_sources. The submodule pins refactor-audit 48b33bb0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RnH6dS2Kmg1WxNnAc78YHA
…import order Review round 3 (claude-code e95b7b02ff80): tools and tests read every audit name as audit.<module>.<Name> through `from agent_comms.pinned_audit import audit`, so no module needs another to have put the scripts dir on sys.path first; module_layers' import is now used. AuditPatternPresent reads the skills dir from the loaded package, not a stripped '.py'. The hoist repair builds its AgentCommsProject once. The submodule pins refactor-audit b024c5f8. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RnH6dS2Kmg1WxNnAc78YHA
…es to Project debt-tools on db41b7f refused tools/agent_comms_project.py: StringSubscript +4 and RawRecordShapes +1 for match["path"/"line"/"message"] in ClientTypeErrors, and TypeErrors +3 (Mapping env, an abstract Carry in a type[Carry] list, parts narrowing repo to AgentCommsProject). The client check reads audit's TypeErrors.reported(); ClientTypeErrors types its repo as the audit Project; run takes a dict env. The submodule pins ca1670f7. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RnH6dS2Kmg1WxNnAc78YHA
…ern goes Review round 4 (claude-code ce65f96693c8): carry_family reads Carry's members and takes each one's MRO up to Carry, instead of calling members_with only to import the steps and then walking subclasses. ClientTypeErrors' `finding` was read by nothing since the check reads TypeErrors.reported(). The submodule pins the round-4 audit head. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RnH6dS2Kmg1WxNnAc78YHA
claude-code's run of the ratchet's own tests (which CI never runs) found two crashes and one regression: - stored_formats archived tools/stored_formats.py at any revision; at a revision before the reader (164c80c) git archive died on the pathspec. That revision declares no stored format: it answers {}. The fixtures that model agent-comms now ship the reader the way the repository does (test_carry, test_agent_comms_ratchet). - AuditPatternPresent asked git for the submodule pin at a commit with no submodule. A commit that pins no audit holds none of its patterns. - Pin bump to refactor-audit 342e2690: CensusRun takes its mechanism owners; Undeclared answers no project. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RnH6dS2Kmg1WxNnAc78YHA
…eads audit.lexical The audit's Project renames absence_decoders to absence_boundaries (a decoder or an encoder marks where absence meets the outside) and moves DecoratorBinding into audit.lexical (refactor-audit#7, ceb14906). This head needs the pin bump to that audit merge: at the current pin the abstract method is still absence_decoders. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RnH6dS2Kmg1WxNnAc78YHA
refactor-audit 3a3a8378 moves module facts to audit.lexical.ModuleScope and DecoratorBinding.of takes it; one walk serves every Carry family. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RnH6dS2Kmg1WxNnAc78YHA
refactor-audit#7 merged as d7401d6797feb839b014a258b9a44b9aba4d14c4 (reviewed head 785659a7, root 114/114 controls). Its Project declares absence_boundaries and ModuleScope, which AgentCommsProject already implements on this branch, so debt-src and debt-tools stop failing on the missing absence_decoders. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RnH6dS2Kmg1WxNnAc78YHA
…mpty answer
AgentCommsProject.stored_formats probed each revision for tools/stored_formats.py and
answered {} when it was missing, so a client repo (Toad ships no reader) had its
stored-format check measure nothing and report clean on every run.
- StoredFormatReader family: RevisionReader (agent-comms measuring itself: each
revision runs its own reader, since a head reader may import head-only modules;
a revision without one fails loud) and CheckoutReader (a client repo borrows the
ratchet checkout's reader, importing agent_comms from that checkout).
- AgentCommsProject.reader declares it, RevisionReader by default; the tracks()
probe and the {} are deleted.
- tools/client_ratchet.py: the client entry, AgentCommsProject(cwd, CheckoutReader()).
Toad's workflow switches its one ratchet line to it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RnH6dS2Kmg1WxNnAc78YHA
…once claude-code #3606 review (9734177925da): StoredForm.of built required as a list at :39/:41, a __post_init__ patched it into the frozenset the field declares, and json.dumps(default=sorted) sorted anything JSON could not encode. - StoredForm.of builds frozenset at both construction sites; __post_init__ deleted. - StoredForm.wire() is the one JSON encoder (required as a sorted list, since JSON has no set); default=sorted deleted. - AgentCommsProject decodes the list into frozenset once. The audit field becomes frozenset[str] in refactor-audit#8; the pin moves after it merges. Encoder probe on a real versioned record: required arrives as a sorted list. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RnH6dS2Kmg1WxNnAc78YHA
trissim
marked this pull request as ready for review
October 29, 2026 23:54
trissim
enabled auto-merge
October 29, 2026 23:54
There was a problem hiding this comment.
Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.
An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.
The merge queue ran debt-tools on a fresh main commit and failed: stored_formats extracts the base revision with git archive, which leaves the audit submodule out, so the base's pinned_audit imported this checkout's audit and died on ForeignAbsenceProbe (moved by refactor-audit#7). The stamp died first, but the reader imports base modules that reach pinned_audit too (phase_evidence.py:28), so any fresh base would have died the same way. - PinnedAudit (this checkout's audit clone) places the audit at a revision's pin into the extracted tree, fetching the pin first when the clone lacks it. - RevisionReader places the revision's reader and its pinned audit. Replay: stored_formats at origin/main (audit pin 5a969d3a) from this checkout at d7401d67 now returns instead of raising ImportError. Also merges origin/main. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RnH6dS2Kmg1WxNnAc78YHA
trissim
disabled auto-merge
October 30, 2026 00:06
Pin refactor-audit 705ebb65 (audit #10 carrying #9). - tools/stored_formats.py: StoredForm deleted. It restated the audit's StoredFormat (three fields) to carry its own wire form, and treated only the top-level required as a set, so #3607's nested RegistryDocument required list reordering read as a format change. stored_format(record) builds StoredFormat.declared, and the audit owns sets at every depth and wire(). claude-code 8bfa094055fd, 580764ff8059, d98616a29150. - tools/agent_comms_project.py: the probe output decodes through StoredFormat.declared(**form), with no subscripts. PinnedAudit.has and its bare subprocess git are deleted for Repository.has. - ClientTypeErrors.findings runs mypy each comparison. The client commit read and the src identity, which existed only for the memo key, are gone. Mypy reads PEP 561 packages on PYTHONPATH that no content key names. Codex 1a5fa2bdbb7a, 073483f8114b; carrier 3d3a357. - tests: test_type_counts_follow_the_installed_dependency_not_a_stored_count is carried from 3d3a357 onto the TypeErrors/ClientTypeErrors CheckerSite API, for source and client. The 12-case test_declared_decoder_boundary_is_shared_by_both_contextual_absence_measures (imported, aliased, qualified, module, relative, undecorated, different-owner, duplicate, conditional, star, class-shadowed, parameter-shadowed) is carried for NoneAbsence and ForeignAbsenceProbe through AgentCommsProject.absence_boundaries. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RnH6dS2Kmg1WxNnAc78YHA
…ched plan reading by path claude-code BACK on f25539d (033285452d9a): - tools/stored_formats.py: "is this record versioned" was answered three times (`vars(record).get("version") is not None`, `return None`, `form is not None`) and debt-tools counted the new NoneAbsence. stored_format(record) now yields zero or one StoredFormat, matching the class's own `version` attribute and the schema in one match; stored_formats is a comprehension over it. All three None tests and the `| None` are deleted. - tools/agent_comms_project.py: ClientTypeErrors.checked folded into findings, so the one-line forwarder is gone. reading is a staticmethod cache over (path, commit), like carry_family (B019). - I001 import blocks sorted in agent_comms_project.py, client_ratchet.py and repairs.py. - Audit pin d1b1f1d1: unordered writes every nested required as a sorted list, and the listed encoder that re-tested frozensets is deleted (BOUND-1, project.py:80). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RnH6dS2Kmg1WxNnAc78YHA
…ormats ignore schema annotations P918's derived text descriptions reword the documentation inside the ActiveRoute, WakeClaim and RegistryDocument record schemas; the audit's StoredFormat now drops description/title/examples/$comment, so that is not a format change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RnH6dS2Kmg1WxNnAc78YHA
Replaces the orphan pin 8659f603 (claude-code d2452ae823e2) with the merge commit of refactor-audit #11: stored formats drop schema annotations and keep default/enum/const values as written. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RnH6dS2Kmg1WxNnAc78YHA
trissim
added a commit
that referenced
this pull request
Oct 30, 2026
- order.py, todos.py: take main's CommanderProject.linkable check (#3625 shape); the per-call Repo.selected validation is gone. - observation.py: keep #3566's ReadOperation(UiRead); main's added hud.require_current() moves into CommanderUnitRead.read_as (order_tools.py). - manual_compaction_bridge.py: main's completion.transcript_changed(partial(...)) with #3566's UnreadTranscriptCursor(). - order_tools.py, phase_evidence.py: union of imports, unused ones dropped. - tools/debt_ratchet.py: main's #3606 entry-only shape; tests/guards/test_debt_ratchet.py stays deleted as on main. #3566's ratchet edits are superseded by refactor-audit c69c4daf. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RnH6dR85kyFKcc2tQAJLhK
trissim
added a commit
that referenced
this pull request
Oct 30, 2026
Main's #3606 made tools/debt_ratchet.py the entry over the pinned audit, with no --ci-inputs argument; the merge kept #3566's workflow lines passing it, so debt-src and debt-tools exited 2 on argparse. checker_stack.py and module_layers.py still declare it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RnH6dR85kyFKcc2tQAJLhK
trissim
added a commit
that referenced
this pull request
Oct 30, 2026
…fetched #3566 made StackClient.fetched (module_layers.py:371) require uv, python and commands to acquire each client's metadata; main's #3606 caller at agent_comms_project.py:252 kept the old two-argument call, so debt-src died with TypeError after the merge. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RnH6dR85kyFKcc2tQAJLhK
trissim
added a commit
that referenced
this pull request
Oct 30, 2026
…s CI's cuts #3606 moved ClientTypeErrors into AgentCommsProject with a fresh stack clone and no way to read the integration entrypoint's materialized cuts, so #3566 had to drop --ci-inputs from debt_ratchet.py (a974c0f). AgentCommsProject now holds one ClientSources (default: the head's declared stack, cloned once); AgentCommsProject.from_arguments decodes --ci-inputs into MaterializedClients. ClientTypeErrors.parts asks it per compared side and also runs when the source requires clients (a companion can change while Core does not). The static clone in ClientTypeErrors.clients is deleted. Two tests still importing the deleted debt_ratchet.ClientTypeErrors/compare now build the project with its clients. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RnH6dS2Kmg1WxNnAc78YHA
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.
P872, items C and D, plus agent-comms' half of E and F.
tools/debt_ratchet.pyis now only the CI entry. The engine, every measure, the comparison and the report moved to the refactor-audit this repository pins (OpenHCSDev/refactor-audit#7), and this PR moves the pin to that head.Summary in numbers
tools/debt_ratchet.py: 2,919 lines and 95 classes → 14 lines, 0 ClassDefs, 0 FunctionDefs:raise SystemExit(main(AgentCommsProject(Path.cwd()))).tools/agent_comms_project.py(new, 241 lines): agent-comms' own facts andClientTypeErrors, moved out of the pinned audit so they change here.from audit import agent_comms_projectside-effect imports: 6 → 0.tools/typing_names.py: 151 lines → 0 (moved toaudit.typing_names).tests/guards/test_debt_ratchet.py: 1,512 lines → 0. The generic suite moved to the audit owner. What only agent-comms declares istests/guards/test_agent_comms_ratchet.py, with 10 tests plus the broad-swallow budget.The entry and its contract
The one fact the entry owns is which project it measures.
audit.ratchet.main(project)owns the command line.--root/--base/--head/--workersare unchanged, and so are.github/workflows/debt-ratchet.ymlanddebt-ratchet-cache.yml.root,base_revision,head_revision,paths,base,head,introduced,foundanddelta, using the same keys (Measure[:path[::member]]) and shapes.grew/found/introducedlines. Afoundchecker site readspath:line (message)(item F).int(failed). The cache stays at~/.cache/agent-comms/debt-ratchet.agent-comms' facts are
AgentCommsProject(Project[PlanPhase])intools/agent_comms_project.py, an instance of this checkout passed to every measure. Each fact derives from its owner here.store_files,locked_storeandprocess_claim.boundary_decoder. The mechanism modules arefield_codec,typed_tableandcoordination_schema, plus Toad'sagent_schema.pyanddb.py.DeclaredFamily.member_named. Guards arePlanPhasemembers, typed (no cast).tools/stored_formats.pyandWheelStamp. A carry step is an added module underinstaller.carry.STEPSwith a class whose base this module binds to theCarryfamily. The oldstem.startswith("carry_")check is deleted.ClientTypeErrorsreadsStackClient.ForkedProcessPoolandSpawnedProcess.run, so pool workers, format probes and checkers still die with the ratchet.test_compare_timeout_retires_pool_probe_and_defiant_grandchildstays here to prove it.repairs.pyand the tests measure anAgentCommsProjectinstance.phase_evidencereadsGodFunction.threshold(), which isLongFunction.lines.Importing that module declares the project; with no declaration, the comparison refuses.
pinned_auditnever imports it, so there is no cycle.Consumers migrated directly (no re-export)
tools/repairs.py:28from debt_ratchet import FunctionLocalImport, LocatedSource, compare, production_pathsaudit.ratchet,audit.source_measures,audit.repository(Repository(repo).production_paths,compare(Repository(repo), ...))tests/test_boundary_decoding.py:81from debt_ratchet import RawRecordShapesfrom audit.source_measures import RawRecordShapestests/test_carry.py:14from debt_ratchet import UncarriedRecordFormat, gitaudit.project_measures.UncarriedRecordFormat,audit.repository.Repository(...).readtools/module_layers.py:42from typing_names import ...from audit.typing_names import ...src/agent_comms/pinned_audit.pyaudit.measures.ForeignAbsenceProbeaudit.source_measures.ForeignAbsenceProbesrc/agent_comms/phase_evidence.py:671ForeignAbsenceProbe.count(node)ForeignAbsenceProbe.occurrences(node)(the census capability)Two done phases that would have broken silently
PlainStrIdRatchetPhase(plan_phases.py:554) andLockCensusPhase(:1022) werePatternPresent(r"^class X\(", ("tools/debt_ratchet.py",)). Those classes now live in the submodule, which is one gitlink in this tree. Both phases would have flipped to "no longer holds", andDonePhaseBrokenwould have blamed every change after this one.Fixed at the evidence owner.
MainTree.pinned(path)returns the tree of the submodule main pins, read at exactly the commit its gitlink names, from that repository's own objects. It still never reads a worktree.PinnedPatternPresentgreps that tree, so both phases now readscripts/auditof the pinned refactor-audit.A red test found on the way
test_store_lock_calls_skip_the_store_ownersasserted two lock owners. Commit 1ab5bde (2026-10-25) addedprocess_claimas a third and never updated it, so the test has been red for four days. It now asserts the three owners the declaration derives.Tests here
tests/guards/test_agent_comms_ratchet.pycovers:boundary_decoderexemption;Not run by me: P872 forbids the author pytest and mypy. Verification is in-memory compilation of every changed module, an AST name check (the only hits are the side-effect imports that put the pinned audit on the path and declare the project) and the entry's ClassDef inventory.
Assumed
metaclass-registry,typing_extensions) are already in this environment through the existingpip install -e src/agent_comms/skills/refactor-audit.Round 5 (19de7bc): absent reader and absent pin answer, git no longer crashes
claude-code ran the ratchet's own tests, which CI never runs:
stored_formats(tools/agent_comms_project.py) archivedtools/stored_formats.pyat every revision. Before the reader existed (164c80c) git archive died on the pathspec. That revision declares no stored format, so it answers{}. Main was red on the same crash in the 11test_a_stored_record_format_*cases: their fixtures copied onlysrc/agent_comms. Those fixtures now ship the reader.AuditPatternPresentasked git for the submodule pin at a commit with no submodule. A commit that pins no audit holds none of its patterns.{}, with the reader the probe record reads version 7; no pin reads False, the real pin reads True. debt-src and debt-tools are green on 19de7bc (run 40929342095).Review round 3 (claude-code e95b7b02ff80)
auditfromagent_comms.pinned_auditand read every name asaudit.<module>.<Name>. No module depends on another having put the pinned scripts dir onsys.pathfirst, and module_layers' import is now one it reads.skillspackage, relative toagent_comms' source root. It no longer derives it by stripping.pyfrom a module path.AgentCommsProjectonce instead of once per file.Round 6 (f25539d): one stored-format record, fresh type counts (Codex 1a5fa2bdbb7a, claude-code 8bfa094055fd)
Pin 705ebb65 = refactor-audit #10 carrying #9.
requiredwas a set, so Acquire display identities and relationship inputs through their declared owners #3607's nested RegistryDocument reorder read asgrew UncarriedRecordFormat +1. NowStoredFormat.declaredis the one constructor and the one decoder, withrequireda set at every depth;:179decodes asStoredFormat.declared(**form)with no subscripts.subprocess.run(["git", ...])is gone in favour ofRepository.hason the audit's one git runner.ClientTypeErrors.findingsreturnsside, cls.checked(...), and the audit'sCheckedRevision.findingsruns the checker. OnlyLintFindingsmemoizes. Mypy reads PEP 561 packages on PYTHONPATH that no content key names.test_type_counts_follow_the_installed_dependency_not_a_stored_count(source + client), and the 12-casetest_declared_decoder_boundary_is_shared_by_both_contextual_absence_measuresfor NoneAbsence + ForeignAbsenceProbe.🤖 Generated with Claude Code
https://claude.ai/code/session_01RnH6dS2Kmg1WxNnAc78YHA