From 6d087dc5b95c3ef691d870b31b7531b4bf93789f Mon Sep 17 00:00:00 2001
From: VantaNode <208094903+VantaNode@users.noreply.github.com>
Date: Thu, 16 Jul 2026 23:09:13 -0700
Subject: [PATCH] fix(orgtrack): verify Codex hooks on session start
Pre-commit hook ran. Total eslint: 0, total circular: 2
---
.../agent-cli/src/session_provenance.rs | 41 +++++++++++++------
.../sessionProvenanceSchemas.test.ts | 4 +-
src/api/tauri/rpc/schemas/agentOrgs.ts | 2 +-
src/i18n/locales/de/integrations.json | 14 ++++---
src/i18n/locales/en/integrations.json | 8 ++--
src/i18n/locales/es/integrations.json | 14 ++++---
src/i18n/locales/fr/integrations.json | 14 ++++---
src/i18n/locales/ja/integrations.json | 14 ++++---
src/i18n/locales/ko/integrations.json | 14 ++++---
src/i18n/locales/pl/integrations.json | 14 ++++---
src/i18n/locales/pt/integrations.json | 14 ++++---
src/i18n/locales/ru/integrations.json | 14 ++++---
src/i18n/locales/tr/integrations.json | 14 ++++---
src/i18n/locales/vi/integrations.json | 14 ++++---
src/i18n/locales/zh-Hant/integrations.json | 10 +++--
src/i18n/locales/zh/integrations.json | 8 ++--
.../SessionProvenanceHooksPanel.tsx | 27 ++++++------
.../core/session-launch-wiring-ui.spec.mjs | 20 ++++-----
18 files changed, 147 insertions(+), 113 deletions(-)
diff --git a/src-tauri/crates/agent-cli/src/session_provenance.rs b/src-tauri/crates/agent-cli/src/session_provenance.rs
index a7ef34d6a..c611a4d80 100644
--- a/src-tauri/crates/agent-cli/src/session_provenance.rs
+++ b/src-tauri/crates/agent-cli/src/session_provenance.rs
@@ -54,10 +54,14 @@ const CLAUDE_CODE_LIFECYCLE_EVENTS: &[(&str, Option<&str>)] = &[
("PreToolUse", Some("*")),
("PostToolUseFailure", Some("*")),
];
-// Codex lifecycle events (all matcher-less; SessionStart doubles as the
-// resume signal and PreToolUse is the per-tool working heartbeat).
+// Codex events required whenever provenance capture is enabled. SessionStart
+// proves that Codex accepted and executed the current managed definitions;
+// the subagent events preserve exact actor attribution.
+const CODEX_REQUIRED_EVENTS: &[&str] = &["SessionStart", "SubagentStart", "SubagentStop"];
+// Optional Codex lifecycle events (all matcher-less). SessionStart remains
+// installed when live status is off because it also drives hook activation;
+// PreToolUse is the per-tool working heartbeat when live status is on.
const CODEX_LIFECYCLE_EVENTS: &[&str] = &[
- "SessionStart",
"UserPromptSubmit",
"PreToolUse",
"PermissionRequest",
@@ -358,7 +362,7 @@ pub struct SessionProvenanceHookStatus {
#[serde(rename_all = "snake_case")]
pub enum SessionProvenanceHookActivationState {
Inactive,
- AwaitingApproval,
+ AwaitingVerification,
Active,
}
@@ -597,7 +601,7 @@ fn update_codex_platform(
unix_command,
windows_command,
)?;
- for event_name in ["SubagentStart", "SubagentStop"] {
+ for event_name in CODEX_REQUIRED_EVENTS {
update_nested_event(
config,
event_name,
@@ -1473,8 +1477,9 @@ fn config_has_complete_managed_hooks(
platform,
"PostToolUse",
Some(CODEX_POST_TOOL_USE_MATCHER),
- ) && nested_event_has_managed_hook(config, platform, "SubagentStart", None)
- && nested_event_has_managed_hook(config, platform, "SubagentStop", None)
+ ) && CODEX_REQUIRED_EVENTS
+ .iter()
+ .all(|event_name| nested_event_has_managed_hook(config, platform, event_name, None))
&& (!live_status
|| CODEX_LIFECYCLE_EVENTS.iter().all(|event_name| {
nested_event_has_managed_hook(config, platform, event_name, None)
@@ -1642,7 +1647,10 @@ fn codex_activation_from_receipt(
Some(receipt.activated_at),
)
} else {
- (SessionProvenanceHookActivationState::AwaitingApproval, None)
+ (
+ SessionProvenanceHookActivationState::AwaitingVerification,
+ None,
+ )
}
}
@@ -1709,7 +1717,7 @@ fn build_hook_status(
/// Record proof that Codex invoked the current ORG2-managed hook definition.
/// A matching receipt is the only state that upgrades the UI from
-/// `awaiting_approval` to `active`.
+/// `awaiting_verification` to `active`.
pub fn record_session_provenance_hook_activation(source: &str) -> Result {
if source != SessionProvenanceHookPlatform::Codex.source_arg() {
return Ok(false);
@@ -2057,7 +2065,7 @@ mod tests {
}
#[test]
- fn codex_config_installs_and_removes_actor_lifecycle_hooks() {
+ fn codex_config_installs_and_removes_required_hooks() {
let mut config = json!({
"hooks": {
"SubagentStop": [{
@@ -2076,6 +2084,7 @@ mod tests {
.expect("enable Codex hooks");
assert_eq!(config["hooks"]["PostToolUse"].as_array().unwrap().len(), 1);
+ assert_eq!(config["hooks"]["SessionStart"].as_array().unwrap().len(), 1);
assert_eq!(
config["hooks"]["SubagentStart"].as_array().unwrap().len(),
1
@@ -2087,7 +2096,7 @@ mod tests {
false
));
- config["hooks"]["SubagentStart"] = json!([]);
+ config["hooks"]["SessionStart"] = json!([]);
assert!(!config_has_complete_managed_hooks(
&config,
SessionProvenanceHookPlatform::Codex,
@@ -2169,11 +2178,17 @@ mod tests {
};
assert_eq!(
codex_activation_from_receipt("current", None),
- (SessionProvenanceHookActivationState::AwaitingApproval, None)
+ (
+ SessionProvenanceHookActivationState::AwaitingVerification,
+ None
+ )
);
assert_eq!(
codex_activation_from_receipt("stale", Some(receipt.clone())),
- (SessionProvenanceHookActivationState::AwaitingApproval, None)
+ (
+ SessionProvenanceHookActivationState::AwaitingVerification,
+ None
+ )
);
assert_eq!(
codex_activation_from_receipt("current", Some(receipt)),
diff --git a/src/api/tauri/rpc/__tests__/sessionProvenanceSchemas.test.ts b/src/api/tauri/rpc/__tests__/sessionProvenanceSchemas.test.ts
index 85be7838a..dd26caaab 100644
--- a/src/api/tauri/rpc/__tests__/sessionProvenanceSchemas.test.ts
+++ b/src/api/tauri/rpc/__tests__/sessionProvenanceSchemas.test.ts
@@ -42,13 +42,13 @@ describe("session provenance RPC schemas", () => {
platform: "codex",
enabled: true,
desiredEnabled: true,
- activationState: "awaiting_approval",
+ activationState: "awaiting_verification",
lastActivatedAt: null,
configPath: "/Users/test/.codex/hooks.json",
error: null,
});
expect(parsed.enabled).toBe(true);
- expect(parsed.activationState).toBe("awaiting_approval");
+ expect(parsed.activationState).toBe("awaiting_verification");
});
it("parses a recent hook signal from the Rust camelCase payload", () => {
diff --git a/src/api/tauri/rpc/schemas/agentOrgs.ts b/src/api/tauri/rpc/schemas/agentOrgs.ts
index a328f26b8..d1c4d899f 100644
--- a/src/api/tauri/rpc/schemas/agentOrgs.ts
+++ b/src/api/tauri/rpc/schemas/agentOrgs.ts
@@ -34,7 +34,7 @@ export const SessionProvenanceHookPlatformSchema = z.enum([
export const SessionProvenanceHookActivationStateSchema = z.enum([
"inactive",
- "awaiting_approval",
+ "awaiting_verification",
"active",
]);
diff --git a/src/i18n/locales/de/integrations.json b/src/i18n/locales/de/integrations.json
index 68011308d..f916951be 100644
--- a/src/i18n/locales/de/integrations.json
+++ b/src/i18n/locales/de/integrations.json
@@ -1688,6 +1688,8 @@
"emptyConfigPreview": "Kein Konfigurationsinhalt"
},
"sessionProvenance": {
+ "masterToggle": "Provenienz-Hooks",
+ "masterToggleDesc": "Wenn deaktiviert, werden alle verwalteten Hooks deinstalliert und keine Signale erfasst; die Auswahl pro Plattform bleibt erhalten und wird beim erneuten Aktivieren wiederhergestellt.",
"title": "Sitzungsherkunft",
"capture": "Dateiinteraktionen erfassen",
"description": "Erfasst Lese- und Schreibzugriffe auf Dateien als Metadaten. Prompts, Werkzeugausgaben und Dateiinhalte werden nicht gespeichert.",
@@ -1704,16 +1706,16 @@
"on": "Ein",
"off": "Aus",
"repair": "Reparieren",
- "needsApproval": "Genehmigung erforderlich",
+ "awaitingVerification": "Warten auf Verifizierung",
"checking": "Wird geprüft…",
"error": "Fehler"
},
"codexApproval": {
- "title": "Approve ORG2 hooks in Codex",
- "description": "Codex has the ORG2 hooks installed, but Codex still needs your approval before it can run them.",
- "instructions": "Open Codex, review the 3 ORG2 hooks, then choose Trust all and continue. ORG2 marks this active after the first real hook signal.",
- "review": "Review in Codex",
- "verified": "Verified by a real Codex hook signal {{time}}."
+ "title": "ORG2-Hooks in Codex verifizieren",
+ "description": "Es wird darauf gewartet, dass Codex die aktuellen ORG2-Hooks genehmigt und ausführt.",
+ "instructions": "Öffne Codex, prüfe die ORG2-Hooks und wähle dann Trust all and continue. Der SessionStart-Hook bestätigt die Aktivierung automatisch, sobald die Sitzung startet.",
+ "review": "In Codex prüfen",
+ "verified": "Durch ein echtes Codex-Hook-Signal verifiziert ({{time}})."
},
"signals": {
"title": "Aktuelle Signale",
diff --git a/src/i18n/locales/en/integrations.json b/src/i18n/locales/en/integrations.json
index b76888e36..e2fb6b31a 100644
--- a/src/i18n/locales/en/integrations.json
+++ b/src/i18n/locales/en/integrations.json
@@ -2400,14 +2400,14 @@
"on": "On",
"off": "Off",
"repair": "Repair",
- "needsApproval": "Needs approval",
+ "awaitingVerification": "Awaiting verification",
"checking": "Checking…",
"error": "Error"
},
"codexApproval": {
- "title": "Approve ORG2 hooks in Codex",
- "description": "Codex has the ORG2 hooks installed, but Codex still needs your approval before it can run them.",
- "instructions": "Open Codex, review the 3 ORG2 hooks, then choose Trust all and continue. ORG2 marks this active after the first real hook signal.",
+ "title": "Verify ORG2 hooks in Codex",
+ "description": "Waiting for Codex to approve and execute the current ORG2 hooks.",
+ "instructions": "Open Codex, review the ORG2 hooks, then choose Trust all and continue. The SessionStart hook verifies activation automatically when the session starts.",
"review": "Review in Codex",
"verified": "Verified by a real Codex hook signal {{time}}."
},
diff --git a/src/i18n/locales/es/integrations.json b/src/i18n/locales/es/integrations.json
index 492742d96..426534eaa 100644
--- a/src/i18n/locales/es/integrations.json
+++ b/src/i18n/locales/es/integrations.json
@@ -1685,6 +1685,8 @@
"emptyConfigPreview": "Sin contenido de configuración"
},
"sessionProvenance": {
+ "masterToggle": "Hooks de procedencia",
+ "masterToggleDesc": "Al desactivarlos, se desinstalan todos los hooks administrados y no se captura ninguna señal; las selecciones por plataforma se conservan y se restauran al volver a activarlos.",
"title": "Procedencia de sesiones",
"capture": "Registrar interacciones con archivos",
"description": "Registra lecturas y escrituras de archivos como metadatos. No se guardan prompts, salidas de herramientas ni contenido de archivos.",
@@ -1701,16 +1703,16 @@
"on": "Activado",
"off": "Desactivado",
"repair": "Reparar",
- "needsApproval": "Requiere aprobación",
+ "awaitingVerification": "Esperando verificación",
"checking": "Comprobando…",
"error": "Error"
},
"codexApproval": {
- "title": "Approve ORG2 hooks in Codex",
- "description": "Codex has the ORG2 hooks installed, but Codex still needs your approval before it can run them.",
- "instructions": "Open Codex, review the 3 ORG2 hooks, then choose Trust all and continue. ORG2 marks this active after the first real hook signal.",
- "review": "Review in Codex",
- "verified": "Verified by a real Codex hook signal {{time}}."
+ "title": "Verificar los hooks de ORG2 en Codex",
+ "description": "Esperando a que Codex apruebe y ejecute los hooks actuales de ORG2.",
+ "instructions": "Abre Codex, revisa los hooks de ORG2 y elige Trust all and continue. El hook SessionStart verifica la activación automáticamente al iniciar la sesión.",
+ "review": "Revisar en Codex",
+ "verified": "Verificado mediante una señal real de un hook de Codex ({{time}})."
},
"signals": {
"title": "Señales recientes",
diff --git a/src/i18n/locales/fr/integrations.json b/src/i18n/locales/fr/integrations.json
index 079624132..65d1b9658 100644
--- a/src/i18n/locales/fr/integrations.json
+++ b/src/i18n/locales/fr/integrations.json
@@ -1688,6 +1688,8 @@
"emptyConfigPreview": "Aucun contenu de configuration"
},
"sessionProvenance": {
+ "masterToggle": "Hooks de provenance",
+ "masterToggleDesc": "Lorsque cette option est désactivée, tous les hooks gérés sont désinstallés et aucun signal n’est collecté ; les choix par plateforme sont conservés et restaurés à la réactivation.",
"title": "Traçabilité des sessions",
"capture": "Enregistrer les interactions avec les fichiers",
"description": "Enregistre les lectures et écritures de fichiers sous forme de métadonnées. Les prompts, les sorties d’outils et le contenu des fichiers ne sont pas stockés.",
@@ -1704,16 +1706,16 @@
"on": "Activé",
"off": "Désactivé",
"repair": "Réparer",
- "needsApproval": "Approbation requise",
+ "awaitingVerification": "En attente de vérification",
"checking": "Vérification…",
"error": "Erreur"
},
"codexApproval": {
- "title": "Approve ORG2 hooks in Codex",
- "description": "Codex has the ORG2 hooks installed, but Codex still needs your approval before it can run them.",
- "instructions": "Open Codex, review the 3 ORG2 hooks, then choose Trust all and continue. ORG2 marks this active after the first real hook signal.",
- "review": "Review in Codex",
- "verified": "Verified by a real Codex hook signal {{time}}."
+ "title": "Vérifier les hooks ORG2 dans Codex",
+ "description": "En attente de l’approbation et de l’exécution des hooks ORG2 actuels par Codex.",
+ "instructions": "Ouvrez Codex, vérifiez les hooks ORG2, puis choisissez Trust all and continue. Le hook SessionStart vérifie automatiquement l’activation au démarrage de la session.",
+ "review": "Vérifier dans Codex",
+ "verified": "Vérifié par un signal réel de hook Codex ({{time}})."
},
"signals": {
"title": "Signaux récents",
diff --git a/src/i18n/locales/ja/integrations.json b/src/i18n/locales/ja/integrations.json
index c56f6114f..f50f29f53 100644
--- a/src/i18n/locales/ja/integrations.json
+++ b/src/i18n/locales/ja/integrations.json
@@ -1688,6 +1688,8 @@
"emptyConfigPreview": "設定内容がありません"
},
"sessionProvenance": {
+ "masterToggle": "プロベナンス hooks",
+ "masterToggleDesc": "オフにすると、管理対象の hooks がすべてアンインストールされ、シグナルは取得されません。プラットフォームごとの選択は保持され、再度オンにすると復元されます。",
"title": "セッションの来歴",
"capture": "ファイル操作を記録",
"description": "ファイルの読み取りと書き込みをメタデータとして記録します。プロンプト、ツール出力、ファイル内容は保存されません。",
@@ -1704,16 +1706,16 @@
"on": "オン",
"off": "オフ",
"repair": "修復",
- "needsApproval": "承認が必要",
+ "awaitingVerification": "検証待ち",
"checking": "確認中…",
"error": "エラー"
},
"codexApproval": {
- "title": "Approve ORG2 hooks in Codex",
- "description": "Codex has the ORG2 hooks installed, but Codex still needs your approval before it can run them.",
- "instructions": "Open Codex, review the 3 ORG2 hooks, then choose Trust all and continue. ORG2 marks this active after the first real hook signal.",
- "review": "Review in Codex",
- "verified": "Verified by a real Codex hook signal {{time}}."
+ "title": "Codex で ORG2 hooks を検証",
+ "description": "Codex が現在の ORG2 hooks を承認して実行するのを待っています。",
+ "instructions": "Codex を開いて ORG2 hooks を確認し、Trust all and continue を選択してください。セッションの開始時に SessionStart hook が有効化を自動検証します。",
+ "review": "Codex で確認",
+ "verified": "実際の Codex hook シグナルで検証済み({{time}})。"
},
"signals": {
"title": "最近のシグナル",
diff --git a/src/i18n/locales/ko/integrations.json b/src/i18n/locales/ko/integrations.json
index 976f070e2..f2d34bddb 100644
--- a/src/i18n/locales/ko/integrations.json
+++ b/src/i18n/locales/ko/integrations.json
@@ -1685,6 +1685,8 @@
"emptyConfigPreview": "설정 내용이 없습니다"
},
"sessionProvenance": {
+ "masterToggle": "출처 추적 hooks",
+ "masterToggleDesc": "끄면 관리되는 모든 hooks가 제거되고 신호를 수집하지 않습니다. 플랫폼별 선택은 유지되며 다시 켜면 복원됩니다.",
"title": "세션 출처",
"capture": "파일 상호작용 기록",
"description": "파일 읽기와 쓰기를 메타데이터로 기록합니다. 프롬프트, 도구 출력 및 파일 내용은 저장하지 않습니다.",
@@ -1701,16 +1703,16 @@
"on": "켜짐",
"off": "꺼짐",
"repair": "복구",
- "needsApproval": "승인 필요",
+ "awaitingVerification": "확인 대기 중",
"checking": "확인 중…",
"error": "오류"
},
"codexApproval": {
- "title": "Approve ORG2 hooks in Codex",
- "description": "Codex has the ORG2 hooks installed, but Codex still needs your approval before it can run them.",
- "instructions": "Open Codex, review the 3 ORG2 hooks, then choose Trust all and continue. ORG2 marks this active after the first real hook signal.",
- "review": "Review in Codex",
- "verified": "Verified by a real Codex hook signal {{time}}."
+ "title": "Codex에서 ORG2 hooks 확인",
+ "description": "Codex가 현재 ORG2 hooks를 승인하고 실행하기를 기다리는 중입니다.",
+ "instructions": "Codex를 열고 ORG2 hooks를 검토한 다음 Trust all and continue를 선택하세요. 세션이 시작되면 SessionStart hook이 활성화를 자동으로 확인합니다.",
+ "review": "Codex에서 검토",
+ "verified": "실제 Codex hook 신호로 확인됨({{time}})."
},
"signals": {
"title": "최근 신호",
diff --git a/src/i18n/locales/pl/integrations.json b/src/i18n/locales/pl/integrations.json
index 2e8f020cc..71929ceab 100644
--- a/src/i18n/locales/pl/integrations.json
+++ b/src/i18n/locales/pl/integrations.json
@@ -1685,6 +1685,8 @@
"emptyConfigPreview": "Brak treści konfiguracji"
},
"sessionProvenance": {
+ "masterToggle": "Hooki pochodzenia",
+ "masterToggleDesc": "Po wyłączeniu wszystkie zarządzane hooki zostaną odinstalowane i żadne sygnały nie będą zbierane; wybory dla poszczególnych platform zostaną zachowane i przywrócone po ponownym włączeniu.",
"title": "Pochodzenie sesji",
"capture": "Rejestruj interakcje z plikami",
"description": "Rejestruje odczyty i zapisy plików jako metadane. Prompty, wyniki narzędzi i zawartość plików nie są przechowywane.",
@@ -1701,16 +1703,16 @@
"on": "Wł.",
"off": "Wył.",
"repair": "Napraw",
- "needsApproval": "Wymaga zatwierdzenia",
+ "awaitingVerification": "Oczekiwanie na weryfikację",
"checking": "Sprawdzanie…",
"error": "Błąd"
},
"codexApproval": {
- "title": "Approve ORG2 hooks in Codex",
- "description": "Codex has the ORG2 hooks installed, but Codex still needs your approval before it can run them.",
- "instructions": "Open Codex, review the 3 ORG2 hooks, then choose Trust all and continue. ORG2 marks this active after the first real hook signal.",
- "review": "Review in Codex",
- "verified": "Verified by a real Codex hook signal {{time}}."
+ "title": "Weryfikacja hooków ORG2 w Codex",
+ "description": "Oczekiwanie, aż Codex zatwierdzi i uruchomi bieżące hooki ORG2.",
+ "instructions": "Otwórz Codex, sprawdź hooki ORG2, a następnie wybierz Trust all and continue. Hook SessionStart automatycznie zweryfikuje aktywację po rozpoczęciu sesji.",
+ "review": "Sprawdź w Codex",
+ "verified": "Zweryfikowano prawdziwym sygnałem hooka Codex ({{time}})."
},
"signals": {
"title": "Ostatnie sygnały",
diff --git a/src/i18n/locales/pt/integrations.json b/src/i18n/locales/pt/integrations.json
index 84bcee4b1..c48afe84a 100644
--- a/src/i18n/locales/pt/integrations.json
+++ b/src/i18n/locales/pt/integrations.json
@@ -1688,6 +1688,8 @@
"emptyConfigPreview": "Sem conteúdo de configuração"
},
"sessionProvenance": {
+ "masterToggle": "Hooks de proveniência",
+ "masterToggleDesc": "Quando desativado, todos os hooks gerenciados são desinstalados e nenhum sinal é capturado; as escolhas de cada plataforma são mantidas e restauradas ao reativar.",
"title": "Proveniência da sessão",
"capture": "Registrar interações com arquivos",
"description": "Registra leituras e gravações de arquivos como metadados. Prompts, saídas de ferramentas e conteúdo dos arquivos não são armazenados.",
@@ -1704,16 +1706,16 @@
"on": "Ativado",
"off": "Desativado",
"repair": "Reparar",
- "needsApproval": "Requer aprovação",
+ "awaitingVerification": "Aguardando verificação",
"checking": "Verificando…",
"error": "Erro"
},
"codexApproval": {
- "title": "Approve ORG2 hooks in Codex",
- "description": "Codex has the ORG2 hooks installed, but Codex still needs your approval before it can run them.",
- "instructions": "Open Codex, review the 3 ORG2 hooks, then choose Trust all and continue. ORG2 marks this active after the first real hook signal.",
- "review": "Review in Codex",
- "verified": "Verified by a real Codex hook signal {{time}}."
+ "title": "Verificar hooks do ORG2 no Codex",
+ "description": "Aguardando o Codex aprovar e executar os hooks atuais do ORG2.",
+ "instructions": "Abra o Codex, revise os hooks do ORG2 e escolha Trust all and continue. O hook SessionStart verifica a ativação automaticamente quando a sessão começa.",
+ "review": "Revisar no Codex",
+ "verified": "Verificado por um sinal real de hook do Codex ({{time}})."
},
"signals": {
"title": "Sinais recentes",
diff --git a/src/i18n/locales/ru/integrations.json b/src/i18n/locales/ru/integrations.json
index 2239a23bc..c22e242ee 100644
--- a/src/i18n/locales/ru/integrations.json
+++ b/src/i18n/locales/ru/integrations.json
@@ -1688,6 +1688,8 @@
"emptyConfigPreview": "Нет содержимого конфигурации"
},
"sessionProvenance": {
+ "masterToggle": "Хуки происхождения",
+ "masterToggleDesc": "При отключении все управляемые хуки удаляются и сигналы не собираются; выбор для каждой платформы сохраняется и восстанавливается при повторном включении.",
"title": "Происхождение сессий",
"capture": "Записывать взаимодействия с файлами",
"description": "Записывает чтение и запись файлов как метаданные. Запросы, вывод инструментов и содержимое файлов не сохраняются.",
@@ -1704,16 +1706,16 @@
"on": "Вкл.",
"off": "Выкл.",
"repair": "Восстановить",
- "needsApproval": "Требуется одобрение",
+ "awaitingVerification": "Ожидание проверки",
"checking": "Проверка…",
"error": "Ошибка"
},
"codexApproval": {
- "title": "Approve ORG2 hooks in Codex",
- "description": "Codex has the ORG2 hooks installed, but Codex still needs your approval before it can run them.",
- "instructions": "Open Codex, review the 3 ORG2 hooks, then choose Trust all and continue. ORG2 marks this active after the first real hook signal.",
- "review": "Review in Codex",
- "verified": "Verified by a real Codex hook signal {{time}}."
+ "title": "Проверить хуки ORG2 в Codex",
+ "description": "Ожидание, пока Codex одобрит и выполнит текущие хуки ORG2.",
+ "instructions": "Откройте Codex, проверьте хуки ORG2 и выберите Trust all and continue. Хук SessionStart автоматически подтвердит активацию при запуске сессии.",
+ "review": "Проверить в Codex",
+ "verified": "Проверено реальным сигналом хука Codex ({{time}})."
},
"signals": {
"title": "Недавние сигналы",
diff --git a/src/i18n/locales/tr/integrations.json b/src/i18n/locales/tr/integrations.json
index 56fdb60fa..92c82f808 100644
--- a/src/i18n/locales/tr/integrations.json
+++ b/src/i18n/locales/tr/integrations.json
@@ -1685,6 +1685,8 @@
"emptyConfigPreview": "Yapılandırma içeriği yok"
},
"sessionProvenance": {
+ "masterToggle": "Kaynak izleme hook'ları",
+ "masterToggleDesc": "Kapatıldığında tüm yönetilen hook'lar kaldırılır ve hiçbir sinyal yakalanmaz; platform seçimleri korunur ve yeniden açıldığında geri yüklenir.",
"title": "Oturum kaynağı",
"capture": "Dosya etkileşimlerini kaydet",
"description": "Dosya okuma ve yazma işlemlerini meta veri olarak kaydeder. İstemler, araç çıktıları ve dosya içerikleri saklanmaz.",
@@ -1701,16 +1703,16 @@
"on": "Açık",
"off": "Kapalı",
"repair": "Onar",
- "needsApproval": "Onay gerekli",
+ "awaitingVerification": "Doğrulama bekleniyor",
"checking": "Kontrol ediliyor…",
"error": "Hata"
},
"codexApproval": {
- "title": "Approve ORG2 hooks in Codex",
- "description": "Codex has the ORG2 hooks installed, but Codex still needs your approval before it can run them.",
- "instructions": "Open Codex, review the 3 ORG2 hooks, then choose Trust all and continue. ORG2 marks this active after the first real hook signal.",
- "review": "Review in Codex",
- "verified": "Verified by a real Codex hook signal {{time}}."
+ "title": "ORG2 hook'larını Codex'te doğrula",
+ "description": "Codex'in mevcut ORG2 hook'larını onaylayıp çalıştırması bekleniyor.",
+ "instructions": "Codex'i açın, ORG2 hook'larını inceleyin ve Trust all and continue seçeneğini seçin. SessionStart hook'u, oturum başladığında etkinleştirmeyi otomatik olarak doğrular.",
+ "review": "Codex'te incele",
+ "verified": "Gerçek bir Codex hook sinyaliyle doğrulandı ({{time}})."
},
"signals": {
"title": "Son sinyaller",
diff --git a/src/i18n/locales/vi/integrations.json b/src/i18n/locales/vi/integrations.json
index c79135e45..a2701374f 100644
--- a/src/i18n/locales/vi/integrations.json
+++ b/src/i18n/locales/vi/integrations.json
@@ -1688,6 +1688,8 @@
"emptyConfigPreview": "Không có nội dung cấu hình"
},
"sessionProvenance": {
+ "masterToggle": "Hook truy xuất nguồn gốc",
+ "masterToggleDesc": "Khi tắt, tất cả hook được quản lý sẽ bị gỡ và không có tín hiệu nào được thu thập; lựa chọn của từng nền tảng được giữ lại và khôi phục khi bật lại.",
"title": "Nguồn gốc phiên",
"capture": "Ghi lại tương tác với tệp",
"description": "Ghi các thao tác đọc và ghi tệp dưới dạng siêu dữ liệu. Không lưu câu lệnh, đầu ra công cụ hoặc nội dung tệp.",
@@ -1704,16 +1706,16 @@
"on": "Bật",
"off": "Tắt",
"repair": "Sửa",
- "needsApproval": "Cần phê duyệt",
+ "awaitingVerification": "Đang chờ xác minh",
"checking": "Đang kiểm tra…",
"error": "Lỗi"
},
"codexApproval": {
- "title": "Approve ORG2 hooks in Codex",
- "description": "Codex has the ORG2 hooks installed, but Codex still needs your approval before it can run them.",
- "instructions": "Open Codex, review the 3 ORG2 hooks, then choose Trust all and continue. ORG2 marks this active after the first real hook signal.",
- "review": "Review in Codex",
- "verified": "Verified by a real Codex hook signal {{time}}."
+ "title": "Xác minh hook ORG2 trong Codex",
+ "description": "Đang chờ Codex phê duyệt và chạy các hook ORG2 hiện tại.",
+ "instructions": "Mở Codex, xem lại các hook ORG2, rồi chọn Trust all and continue. Hook SessionStart sẽ tự động xác minh việc kích hoạt khi phiên bắt đầu.",
+ "review": "Xem lại trong Codex",
+ "verified": "Đã xác minh bằng tín hiệu hook Codex thực ({{time}})."
},
"signals": {
"title": "Tín hiệu gần đây",
diff --git a/src/i18n/locales/zh-Hant/integrations.json b/src/i18n/locales/zh-Hant/integrations.json
index d7cea37e9..9a7eeb31b 100644
--- a/src/i18n/locales/zh-Hant/integrations.json
+++ b/src/i18n/locales/zh-Hant/integrations.json
@@ -1688,6 +1688,8 @@
"emptyConfigPreview": "沒有配置內容"
},
"sessionProvenance": {
+ "masterToggle": "溯源 Hooks",
+ "masterToggleDesc": "關閉後將解除安裝所有受管理的 hook,並停止擷取任何訊號;各平台的選擇會保留,重新開啟時恢復。",
"title": "Session 來源追蹤",
"capture": "擷取檔案互動",
"description": "以中繼資料記錄檔案讀取與寫入。不會儲存提示詞、工具輸出或檔案內容。",
@@ -1704,14 +1706,14 @@
"on": "開啟",
"off": "關閉",
"repair": "修復",
- "needsApproval": "需要授權",
+ "awaitingVerification": "等待驗證",
"checking": "檢查中…",
"error": "錯誤"
},
"codexApproval": {
- "title": "在 Codex 中授權 ORG2 hooks",
- "description": "ORG2 hooks 已安裝,但 Codex 仍需要你的明確授權才能執行。",
- "instructions": "開啟 Codex,檢查 3 條 ORG2 hooks,然後選擇 Trust all and continue。收到第一條真實 hook 訊號後,ORG2 會自動標記為已啟用。",
+ "title": "在 Codex 中驗證 ORG2 hooks",
+ "description": "正在等待 Codex 授權並執行目前的 ORG2 hooks。",
+ "instructions": "開啟 Codex,檢查 ORG2 hooks,然後選擇 Trust all and continue。工作階段啟動時,SessionStart hook 會自動驗證是否已啟用。",
"review": "在 Codex 中檢查",
"verified": "已透過真實 Codex hook 訊號驗證({{time}})。"
},
diff --git a/src/i18n/locales/zh/integrations.json b/src/i18n/locales/zh/integrations.json
index 4d958b82c..5bada926f 100644
--- a/src/i18n/locales/zh/integrations.json
+++ b/src/i18n/locales/zh/integrations.json
@@ -1759,14 +1759,14 @@
"on": "开启",
"off": "关闭",
"repair": "修复",
- "needsApproval": "需要授权",
+ "awaitingVerification": "等待验证",
"checking": "检查中…",
"error": "错误"
},
"codexApproval": {
- "title": "在 Codex 中授权 ORG2 hooks",
- "description": "ORG2 hooks 已安装,但 Codex 需要你的明确授权才能运行它们。",
- "instructions": "打开 Codex,检查 3 条 ORG2 hooks,然后选择 Trust all and continue。收到第一条真实 hook 信号后,ORG2 会自动标记为已启用。",
+ "title": "在 Codex 中验证 ORG2 hooks",
+ "description": "正在等待 Codex 授权并执行当前的 ORG2 hooks。",
+ "instructions": "打开 Codex,检查 ORG2 hooks,然后选择 Trust all and continue。会话启动时,SessionStart hook 会自动验证是否已启用。",
"review": "在 Codex 中检查",
"verified": "已通过真实 Codex hook 信号验证({{time}})。"
},
diff --git a/src/modules/shared/dataSource/SessionProvenanceHooksPanel.tsx b/src/modules/shared/dataSource/SessionProvenanceHooksPanel.tsx
index 9b0a97a17..10f027b79 100644
--- a/src/modules/shared/dataSource/SessionProvenanceHooksPanel.tsx
+++ b/src/modules/shared/dataSource/SessionProvenanceHooksPanel.tsx
@@ -237,22 +237,25 @@ const HookPlatformsTable: React.FC = () => {
}, [loadStatuses]);
useEffect(() => {
- if (statuses.codex?.activationState !== "awaiting_approval") return;
+ if (statuses.codex?.activationState !== "awaiting_verification") return;
const interval = window.setInterval(() => void loadStatuses(true), 2_000);
return () => window.clearInterval(interval);
}, [loadStatuses, statuses.codex?.activationState]);
useEffect(() => {
for (const platform of PLATFORMS) {
- const awaitingApproval =
+ const awaitingVerification =
platform.id === "codex" &&
- statuses[platform.id]?.activationState === "awaiting_approval";
- if (awaitingApproval && !approvalAutoExpanded.current.has(platform.id)) {
+ statuses[platform.id]?.activationState === "awaiting_verification";
+ if (
+ awaitingVerification &&
+ !approvalAutoExpanded.current.has(platform.id)
+ ) {
approvalAutoExpanded.current.add(platform.id);
setExpandedRowKeys((current) =>
current.includes(platform.id) ? current : [...current, platform.id]
);
- } else if (!awaitingApproval) {
+ } else if (!awaitingVerification) {
approvalAutoExpanded.current.delete(platform.id);
}
}
@@ -337,8 +340,8 @@ const HookPlatformsTable: React.FC = () => {
if (status && status.desiredEnabled && !status.enabled) {
return { color: "warning", labelKey: "repair" };
}
- if (status?.activationState === "awaiting_approval") {
- return { color: "warning", labelKey: "needsApproval" };
+ if (status?.activationState === "awaiting_verification") {
+ return { color: "warning", labelKey: "awaitingVerification" };
}
return status?.enabled
? { color: "success", labelKey: "on" }
@@ -429,10 +432,10 @@ const HookPlatformsTable: React.FC = () => {
path: status.configPath,
});
}
- if (status?.activationState === "awaiting_approval") {
+ if (status?.activationState === "awaiting_verification") {
return t("agentOrgs.sessionProvenance.codexApproval.description", {
defaultValue:
- "Codex has the ORG2 hooks installed, but Codex still needs your approval before it can run them.",
+ "Waiting for Codex to approve and execute the current ORG2 hooks.",
});
}
if (status?.activationState === "active" && status.lastActivatedAt) {
@@ -565,7 +568,7 @@ const HookPlatformsTable: React.FC = () => {
{description(row)}
{row.id === "codex" &&
- row.status?.activationState === "awaiting_approval" && (
+ row.status?.activationState === "awaiting_verification" && (
{
{t(
"agentOrgs.sessionProvenance.codexApproval.title",
- { defaultValue: "Approve ORG2 hooks in Codex" }
+ { defaultValue: "Verify ORG2 hooks in Codex" }
)}
@@ -587,7 +590,7 @@ const HookPlatformsTable: React.FC = () => {
"agentOrgs.sessionProvenance.codexApproval.instructions",
{
defaultValue:
- "Open Codex, review the 3 ORG2 hooks, then choose Trust all and continue. ORG2 marks this active after the first real hook signal.",
+ "Open Codex, review the ORG2 hooks, then choose Trust all and continue. The SessionStart hook verifies activation automatically when the session starts.",
}
)}
diff --git a/tests/e2e/specs/core/session-launch-wiring-ui.spec.mjs b/tests/e2e/specs/core/session-launch-wiring-ui.spec.mjs
index 61eed18fa..04cf81cc5 100644
--- a/tests/e2e/specs/core/session-launch-wiring-ui.spec.mjs
+++ b/tests/e2e/specs/core/session-launch-wiring-ui.spec.mjs
@@ -1258,7 +1258,7 @@ describe("Session launch wiring rendered UI invariants", function () {
.trim()
.replace(/\s+/g, " ");
return (
- activationState === "awaiting_approval" &&
+ activationState === "awaiting_verification" &&
cardText.includes("ORG2 hooks") &&
cardText.includes("Trust all and continue") &&
approvalState?.[2] === true
@@ -1323,7 +1323,7 @@ describe("Session launch wiring rendered UI invariants", function () {
return false;
}
return (
- approvalOutput.includes("3 hooks are new or changed") &&
+ /\d+ hooks? (?:are|is) new or changed/.test(approvalOutput) &&
approvalOutput.includes("Trust") &&
approvalOutput.includes("continue")
);
@@ -1353,21 +1353,15 @@ describe("Session launch wiring rendered UI invariants", function () {
);
}
- // Deterministically emulate the first post-approval callback by invoking
- // the real installed hook binary and adapter path. This establishes the
- // activation receipt without automating the user's security decision.
+ // Deterministically emulate the post-approval SessionStart callback by
+ // invoking the real installed hook binary and adapter path. This proves
+ // the activation receipt no longer waits for a later tool interaction,
+ // without automating the user's security decision.
execFileSync(APP_BINARY, ["--session-provenance-hook", "codex"], {
input: JSON.stringify({
session_id: `e2e-codex-trust-${RUN_ID}`,
- turn_id: `turn-${RUN_ID}`,
cwd: E2E_REPO_PATH,
- hook_event_name: "PostToolUse",
- tool_name: "apply_patch",
- tool_use_id: `tool-${RUN_ID}`,
- tool_input: {
- command:
- "*** Begin Patch\n*** Add File: e2e-trust-proof.txt\n+proof\n*** End Patch",
- },
+ hook_event_name: "SessionStart",
}),
env: process.env,
stdio: ["pipe", "ignore", "pipe"],