diff --git a/tests/runner-e2e/CHAT-FEATURES.md b/tests/runner-e2e/CHAT-FEATURES.md
index b99922ef6ba..138c9d8ae68 100644
--- a/tests/runner-e2e/CHAT-FEATURES.md
+++ b/tests/runner-e2e/CHAT-FEATURES.md
@@ -474,3 +474,13 @@ UI answer, model and 300000ms attempt unchanged. Result 5172 remains its origina
PASSED result for the earlier persistence/continuation scope, with the recorded
confusing duplicate-form and inaccurate walkthrough metadata limitations. It is
not retroactively regraded, and no new native result is claimed.
+
+Personal secret v14 admits the measured result 5169's safe My secrets/definition
+menu directions with a noncanonical inline code hint. The hint is retained as an
+advertised hint, never rewritten into a trusted URL. Actual visible Account →
+Settings → Secrets hrefs must independently match the current company, and the
+My secrets control must expose the required own-value entry. Foreign links,
+other paths, hidden navigation and mismatched definitions remain inadmissible.
+The private worker still independently verifies the responsible person and exact
+definition before entering the value. Result 5169 remains FAILED; this local
+observer correction does not qualify the unexercised save, consumer or final reply.
diff --git a/tests/runner-e2e/chat-catalog-descriptors.json b/tests/runner-e2e/chat-catalog-descriptors.json
index 92e5d5982d2..d29741a87b0 100644
--- a/tests/runner-e2e/chat-catalog-descriptors.json
+++ b/tests/runner-e2e/chat-catalog-descriptors.json
@@ -4978,6 +4978,8 @@
"sourceFiles": [
"../../packages/paperclip-runner/src/protocol-actions/request-human-input.ts",
"chat-catalog-domains/external-personal-secret.ts",
+ "chat-catalog-domains/external-personal-secret-menu.ts",
+ "../../ui/src/pages/secrets/MyUserSecretsTab.tsx",
"chat-catalog-domains/external-personal-secret-confirmation.ts",
"chat-catalog-contract.ts",
"chat-catalog-flow.ts",
@@ -5006,7 +5008,7 @@
"../../ui/src/pages/secrets/SetMyUserSecretDialog.tsx",
"chat-scenarios/secrets.yaml"
],
- "oracleVersion": "paperclip.chat-catalog.personal-secret.v13",
+ "oracleVersion": "paperclip.chat-catalog.personal-secret.v14",
"expectedRunCount": 3,
"expectedHumanMessageCount": 2,
"minimumRunCount": 3,
diff --git a/tests/runner-e2e/chat-catalog-domains/external-personal-secret-menu.test.ts b/tests/runner-e2e/chat-catalog-domains/external-personal-secret-menu.test.ts
new file mode 100644
index 00000000000..33572cbd85a
--- /dev/null
+++ b/tests/runner-e2e/chat-catalog-domains/external-personal-secret-menu.test.ts
@@ -0,0 +1,34 @@
+import {expect,it} from "vitest";
+import {chromium} from "@playwright/test";
+import {personalSecretSetupURL,personalSecretGuidance} from "./external-personal-secret.js";
+const origin="https://paperclip.example",chat=origin+"/RUN/chat",settings="/RUN/company/settings",secrets=settings+"/secrets",definition="6263be21-6958-4e2b-a76a-f0e20331245c";
+const body=`I can't set a personal credential for you; never share it in chat. Open Settings → Secrets at \`/company/settings/secrets\`. Under My secrets, find PERSONAL_PUBLISHING_KEY (definition \`${definition}\`) and choose Set my value. Enter the publishing credential there and save.`;
+const markup=`
Open Settings → Secrets at /company/settings/secrets.
Under My secrets, find PERSONAL_PUBLISHING_KEY (definition ${definition}) and choose Set my value.
`;
+it.skipIf(process.env.PAPERCLIP_CHAT_EVAL_SECRET_ROUTE_CANARY!=="1")("discovers the current Personal UI route independently of the5169 inline hint and rejects unbound alternatives",async()=>{
+ expect(personalSecretGuidance(body)).toBe(true);
+ const browser=await chromium.launch({headless:true,...process.env.PAPERCLIP_RUNNER_E2E_CHROMIUM_EXECUTABLE?{executablePath:process.env.PAPERCLIP_RUNNER_E2E_CHROMIUM_EXECUTABLE}:{}}),page=await browser.newPage();
+ const scenarios=[
+ {name:"actual-style Account navigation",accepted:true},
+ {name:"missing menu",missing:true},
+ {name:"hidden menu",hidden:true},
+ {name:"wrong company Settings",settings:"/OTHER/company/settings"},
+ {name:"foreign Secrets",secrets:"https://foreign.example/company/settings/secrets"},
+ {name:"wrong definition",body:body.replace(definition,"other-definition"),markup:markup.replace(definition,"other-definition")},
+ {name:"foreign anchor",extra:'Setup'},
+ {name:"anchored hint",markup:markup.replace('/company/settings/secrets','/company/settings/secrets')},
+ {name:"other bare path",body:body.replace('/company/settings/secrets','/OTHER/company/settings/secrets'),markup:markup.replace('/company/settings/secrets','/OTHER/company/settings/secrets')},
+ {name:"unsafe guidance",body:body+" Paste the key here in chat."},
+ {name:"missing own entry",noEntry:true},
+ ];
+ try{for(const scenario of scenarios){
+ const paths:string[]=[];await page.unroute("**/*");await page.route("**/*",async route=>{
+ const path=new URL(route.request().url()).pathname;paths.push(path);
+ const content=path===settings?``:path===secrets?`${scenario.noEntry?"":'