Repository navigation
Conversation
decision_context packets and material_lifecycle validation each kept their own credential alternation list beside the owner's shape detector, byte-identical to each other, under a comment that called it a "local threshold policy". A list of labels and header shapes is a shape owner, not a threshold. Both faces now make one categorized call to the shared text owner with the named CREDENTIAL_CATEGORIES policy. The owner gains COMPOUND_CREDENTIAL_FIELD_ASSIGNMENT_PATTERN, reached only through the new include_compound_field_assignment opt-in: it is the one spelling the private lists caught and every category arm misses, because those arms anchor the label with a word boundary and underscore is a word character. The opt-in stays off by default so the four migrated text owners and the publication tier change no verdict. Refs loopx-project#5136 directions 1 and 2, and the caller-facing successor loopx-project#5335 recorded. Signed-off-by: Hsuehtan <296098438+Hsuehtan@users.noreply.github.com>
…e call The first version folded the assignment value, which for a construction is the re.compile(...) call rather than its pattern, so the census reported a clean repository even with the deleted lists put back. It also keyed on any three labels, which flagged environment-name and field-name rules that decide a different question. The criterion is now an alternation that reaches for whitespace, three sites that still decide it are declared with the reason each one stays, and the probe rows state the limit out loud. Signed-off-by: Hsuehtan <296098438+Hsuehtan@users.noreply.github.com>
ruff format --check is not a gate in this repository, but a file added here should not add a new violation, so this one is formatted and reports no hunks. Signed-off-by: Hsuehtan <296098438+Hsuehtan@users.noreply.github.com>
This branch has not been deployed
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.
Goal And Delivered Outcome
#5136(open; the maintainer's four directions of 2026-09-27) andthe successor note
#5335recorded when it merged — "the remaining caller faces … each need anamed policy chosen from their destination".
loopx/capabilities/decision_context/packets.py:50andloopx/capabilities/material_lifecycle/_validation.py:25each kept a credential alternation list,byte-identical to each other, consulted beside the owner's shape detector:
SECRET_LIKE_SURFACE_PATTERN.search(text) or _CREDENTIAL_RE.search(text). The comment above bothlists said "local threshold policy only", but the list holds labels and a header shape — a shape
owner, not a threshold. So two capability faces independently decided which English spellings count
as a credential, and a fix in the shared owner silently left both behind. Consumers affected: every
Decision Context packet field and every Material Lifecycle validation field that goes through
_compact_text/compact_text.password,secretorapi_keywith no value adjacent is no longer refused; every assignment the old lists accepted still is, plus
five spellings they missed and one spelling no owner arm reached before (
db_password = "…").Proven by the
unitrows (both faces driven through their real entrypoints) and theregression_parityrow (named accepted/rejected lists recomputed over a 2,147-input grid).is closed here — directions 1-4 of that issue remain open for the faces this slice does not move.
Author Declaration
mainataa87cc019.Implemented against
loopx/public_safe_text.py; aconsumer consults it instead of keeping its own shapes", "one policy-bearing call, not an OR of
detectors") and direction 2 ("a bare
Bearer,passwordorsecretmention, and prose such as'the Bearer token expired', is not a leak"), plus direction 4 ("report newly accepted / newly
rejected per migrated face", "keep each surface's own wording and length limit"). Also the promise in
tests/control_plane/test_public_safety_credential_shape_owner.py:8-12, which after refactor(public-safety): decide credential shapes in one owner #5135 statesthat "each site keeps only its own threshold policy … and consults the owner for the shapes".
loopx/public_safe_text.pyclassify_private_texttest_no_module_outside_the_owner_keeps_a_credential_alternation_list_compact_text,compact_texttest_both_faces_reject_a_credential_label_glued_into_a_field_nameCATEGORY_CREDENTIAL_WORD,CREDENTIAL_CATEGORIEStest_both_faces_accept_a_bare_mention_with_no_value_beside_itNEWLY_ACCEPTED,NEWLY_REJECTEDunitrow belowcontains a credential-like value,max_lenunchangedtest_benign_prose_still_passes_both_facesLABELED_CREDENTIAL_ASSIGNMENT_PATTERN(named by #5335)file:///~/recognition at these facesfind_public_safe_local_pathstill called unchangedtest_public_safe_text_owner_parityre-run, unchanged verdicts(
_CATEGORIZED_PRIVATE_TEXT_PATTERNS,_SHAPE_DETECTORS) and every named policy(
TEXT_OWNER_CATEGORIES,ARTIFACT_LIFECYCLE_CATEGORIES) before choosing the mechanism; measured theaccepted/rejected delta by running the old union and the new policy over a generated grid rather than
reasoning about it; deliberately left path and URL handling exactly as it was. What is assumed, not
verified: the four migrated text owners' verdicts are held by the corpus they already pin, not
re-derived here.
Scope And Continuation
import reremoved from both files, where the list was theonly user); one categorized call per face against the named
CREDENTIAL_CATEGORIES; a new ownerarm
COMPOUND_CREDENTIAL_FIELD_ASSIGNMENT_PATTERNfor the one spelling the lists reached and everycategory arm misses — a credential label glued into a field name, invisible because the label arms
anchor with
\band_is a word character; a census guard that names any module still decidingthis question for itself.
remote_locationandlocal_pathat these two faces. Each still asksfind_public_safe_local_pathandREMOTE_LOCATION_SURFACE_PATTERNseparately, unchanged.Folding them into the same call would let this slice decide, per face, whether internal-state
text may carry a URL — the caller migration [Architecture]: two modules both claim to own "private-looking text" #5136 is still open for.
say which way; the arm has been named since fix(public-safety): separate credential words from credential values #5335 and is untouched.
extensions/presentation.pyrejects an assignment whose value is one character, which no owner arm reproduces without the
undecided item above;
control_plane/todos/handoff_note.pyalso names vendor forms(
ak/sk,access_key_id) the owner does not;loopx/contract.pyis the publication tier,whose move needs the corpus parity slice rather than two capability tables. Each is declared in
DECLARED_OPEN_SITESwith its reason, and a declaration whose site has already been convertedfails (
M9in the mutation table).benchmark_toolkit/environment_access.py(environment-variable names),control_plane/testing/model_behavior_qualification.py(field names) andregistry.py's privatetext marker list. They decide a name or a marker, not whether free text carries a credential value;
the criterion and its limit are stated in
_is_credential_text_ruleand pinned by probe rows.sites and one owner arm without touching the corpus, the TS mirror or another face. Successor: the
three declared faces, then the direction-2 short-assignment decision that unblocks the strictest one.
Validation
a875f6cdf(3 commits, 4 files, +449 −39);621b1229bproduct,a3ef532c3censusfold fix,
a875f6cdfformatting.unitpython -m pytest -q tests/control_plane/test_public_safety_credential_caller_faces.py-> 61 passed: per-face rejection of the glued-field class, the pinned newly-accepted / newly-rejected lists, the arm's load-bearing check, the census and its five probe rows (both faces driven through_compact_text/compact_text, with an unpatched positive control).unitpython -m pytest -q tests/control_plane -k "public_safety or public_safe or decision_context or material_lifecycle or maintainability"-> 604 passed / 0 failed, 6930 deselected: the owner, the classifier's 4,032-form biconditional, the cross-runtime corpus, the four migrated text owners, and both faces' own suites.integrationpython -m pytest -q tests/architecture tests/canary— head 2 failed / 1444 passed, and the same selection in an unmodified worktree at the base revision 2 failed / 1444 passed, with the two failure ids identical in both (test_top_level_module_budget…= the 148-vs-147 pin reported in #5685,test_source_session_registry_denial…). Both runs used the same interpreter and the repository's qualified Node line.staticpython -m ruff checkclean;python -m mypy->Success: no issues found in 19 source files;loopx check --scan-pathon all four changed paths ->errors=0.regression_parityBEGIN RSA PRIVATE KEYwithout its---fence, which the old substring list caught and the owner's arm requires the fence for). Every row that pairs a label with an operator still rejects. Both lists are pinned as named assertions, so a future re-widening fails a test. Mutations: 10 variants, 9 killed — a face re-adding a private list (1 red), each face dropping the opt-in (7 red each), the new arm anchored (9), the policy droppingcredential_word(3), the arm applied regardless of the opt-in (3, including the classifier's biconditional), a face stop consulting the owner (35), the word arms re-widened to substrings (5), a declared site converted without retiring its declaration (1). 1 variant survives, disclosed as the census's stated limit: an alternation constructed inside a function body rather than at module level, which the fold does not see; a fifth row pins that a word list with no whitespace test is likewise not caught.censuspython examples/semantic-vocabulary-drift-smoke.pymeasured on this head and on an unmodified worktree at the base revision, byte-for-byte the same line: same_runtime_forks=2/2 same_runtime_fork_definitions=5/5 conflicting_values=16/16 conflicting_definitions=54/54 schema_version_same_runtime_forks=0/0 multi_value_twins=8/8 multi_value_forks=2/2 multi_value_forks_semantic=1/1 multi_value_fork_definitions=6/6 same_runtime_forks_semantic=2/2 conflicting_values_semantic=0/0, twins_raw=45, generated_verified=2, independently_maintained=43/43. No registry budget and noBUDGET_ANCHORliteral moves in this PR, and the registry I/O census test inside the compared architecture selection reports the same outcome on both sides.manualruff format --checkis not a gate here, and all three product files already fail it on the unmodified base —loopx/public_safe_text.py5 hunks before / 5 after,packets.py2 / 2,_validation.py1 / 1. The new test file was formatted and reports 0 hunks.patterns, so a face that quietly stops consulting the owner goes red (mutation M7 confirms: 35). The
new arm is covered by 7 pinned spellings × both faces, and by a with/without the flag comparison that
fails if the arm ever stops being the only reason that class rejects. Gaps named plainly: (a) the
local-path and remote-location questions at these faces are unchanged and unmeasured here; (b) the
three declared faces keep their own verdicts, so "one owner for credential text" is still a program
rather than a fact after this PR; (c) the fold covers literal concatenation,
"|".join([...])andmodule-level name chains — an f-string or a function-built pattern is not folded, which is the
surviving mutation; (d) no TS surface is touched, so the two runtimes' behaviour for these two faces
is not a claim here (they are not mirrored in the Vision checkpoint path).
See validation disclosure guidance.
Frontend / Visual Evidence
Type of Change
states is not a leak
directions, quantified in the
regression_parityrowLoopX Area
Technical Direction
directions 1, 2 and 4, continues fix(public-safety): separate credential words from credential values #5335.
Shared-authority RFC fixture impact
N/A — no TypeScript control-plane migration or shared Goal Authority claim.
tests/fixtures/public_safe_text_corpus.json, the TS Vision mirror and the dual-runtime twin inventory are untouchedby this diff; the parity suite was re-run and reports the same verdicts as before.