Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions devlog/_plan/260924_l4_codex_cli_service/000_roadmap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# L4 roadmap — Codex integration, CLI and service

Branch codex/260924-l4-codex-cli-service from origin/dev be0b5294e5. One PR to dev. Merge is the coordinator's.

| Unit | Doc | Items | Method |
|---|---|---|---|
| wp1 | 010 | #5713, #5703, #5548 slice | squash-diff apply per PR, one commit each with Co-authored-by |
| wp2 | 020 | #5221 | rebuild on dev by DeepSeek writer; sibling test files |
| wp3 | 030 | #5009 | squash-diff apply, review sender/admission checks |
| wp4 | 040 | #5694 | DeepSeek writers: default-on 98% hard lock |
| wp5 | 050 | publish | rebase, validate, push, PR, checks |

Ratchet: tests/fixtures/file-size-baseline.json caps only move down; every commit re-runs tests/test-layout.test.ts and the file-size test.

20 changes: 20 additions & 0 deletions devlog/_plan/260924_l4_codex_cli_service/010_carry_ready_prs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# 010 — carry #5713, #5703, #5548 slice

## #5713 (fixes #5699) — author 정우철 <oocheol@naver.com>
Files: src/client/connect.ts, src/client/state.ts (pending-connect fingerprint marker client-connect-pending), src/service/cli.ts (removeServiceTokenAfterUninstall under client lifecycle + config mutation locks: removed|absent|retained|unverified), structure/clients/claude-desktop.md, structure/runtime.md, docs-site guides/remote-hub.md (en+ko), tests/clients/client-connect.test.ts, tests/service/service-secrets.test.ts.
Method: git diff merge-base..carry-5713 | git apply -3. Check other docs-site locales of remote-hub.md for consistency (PR touched en and ko only).
Tests: bun test tests/service/service-secrets.test.ts tests/clients/client-connect.test.ts.
Security: credential deletion boundary — uninstall deletes the service token only when client state is disconnected and no pending marker owns the fingerprint.

## #5703 (fixes #5701) — Konstantinos <37538071+konstantinosbotonakis@users.noreply.github.com>
Files: src/codex/native-residue.ts, structure/config.md, tests/codex-integration/codex-native-residue.test.ts. Check file-size caps for the test file.

## #5548 slice — Vadevious <Vadevious@users.noreply.github.com>
Only src/codex/home.ts (import expandUserPath from ../config/paths), structure/codex-home.md line, tests/codex-integration/codex-home-wsl.test.ts (new: register in layout.json explicit + test-layout-expected.json if not matched by a seed). Excluded: tests/cli/cli-help.test.ts, tests/service/service-probe-docker.test.ts, tests/service/service.test.ts.
Audit fold: codex-home-wsl.test.ts already exists on dev (from #5720) and is registered; carry only the PR's added fresh-process case into it. home.ts:4 currently imports from ../config (barrel) — the fix switches to ../config/paths.

## wp1 P (executable)
- All three squash diffs pass git apply --check -3 on 34fb6d649c (/tmp/l4-5713.diff, /tmp/l4-5703.diff, /tmp/l4-5548.diff limited to 3 files).
- Commit order: #5713, #5703, #5548 slice; each commit carries Co-authored-by for the PR author.
- #5713 docs: en/ko remote-hub.md updated by the PR; DeepSeek writer adds the same paragraph to fr, ja, ru, tr, zh-cn, zh-tw remote-hub.md next to the service-api-token paragraph.
- Focused tests: tests/service/service-secrets.test.ts tests/clients/client-connect.test.ts tests/codex-integration/codex-native-residue.test.ts tests/codex-integration/codex-home-wsl.test.ts tests/test-layout.test.ts; plus the file-size ratchet test.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# 020 — rebuild #5221 (fixes #5217) — sbc1-code <207095575+sbc1-code@users.noreply.github.com>

Change: src/adapters/identity.ts gains ROUTED_IDENTITY_RE, NEUTRAL_IDENTITY_RE, hasRoutedIdentity, repairRoutedIdentity, repairIdentityInResponsesBody, stripRoutedIdentity; identifyRoutedModel also rewrites neutral + routed lines. Catalog (src/codex/catalog/derive-entry.ts, metadata.ts) writes neutralizeIdentity instead of identifyRoutedModel. src/responses/parser.ts repairs developer items to data.model. src/adapters/openai-responses/passthrough.ts repairs raw body (routed rewrite, forward strip).
Rebuild on current dev (221 commits drift): re-read current versions of those files; keep dev behaviour elsewhere.
Tests: new tests/adapters/identity-subagent.test.ts (from PR). Catalog expectation edits: codex-catalog.test.ts is at cap, so changed expectations must not grow it; new catalog cases go to a sibling file (e.g. tests/codex-integration/codex-catalog-identity-neutral.test.ts) registered in both manifests.
Check files at cap: parser.ts, passthrough.ts, identity.ts in file-size-baseline.
Audit fold: neutralizeIdentity and NEUTRAL_IDENTITY_LINE already exist in identity.ts; the six routed-identity helpers do not. parser/passthrough/identity are uncapped (<2000 lines). codex-catalog.test.ts cap 7985 vs 7974 actual: expectation edits may not add net lines beyond headroom; new cases still go to a sibling file.

## wp2 P (executable)
- /tmp/l4-5221.diff (src, 5 files) passes git apply --check -3 on current HEAD. Current request-time callers of identifyRoutedModel: anthropic.ts:772, google.ts:300, kiro/payload.ts:145, command-code.ts:607, openai-chat/messages.ts:144 — all receive the extended rewrite (GPT line, neutral line, routed line), so a neutral catalog still names the wire model.
- Writer applies the src diff, adds tests/adapters/identity-subagent.test.ts from carry-5221, and rewrites the catalog expectations the PR changed (codex-catalog.test.ts, codex-catalog-sync-hardening.test.ts) so codex-catalog.test.ts grows by 0 net lines; any added catalog assertion goes to new tests/codex-integration/codex-catalog-identity-neutral.test.ts registered in scripts/test-layout/layout.json explicit and tests/fixtures/test-layout-expected.json.
- Writer also checks every other test that asserted a baked model id in base_instructions (rg 'powered by the' tests) and updates it.
- structure: add a line to the structure doc owning src/adapters/identity.ts (find via structure/manifest.json) describing request-time identity repair.
- Focused: bun test tests/adapters/identity-subagent.test.ts tests/adapters/identity-neutralize.test.ts tests/codex-integration/codex-catalog.test.ts tests/codex-integration/codex-catalog-sync-hardening.test.ts plus new sibling, tests/test-layout.test.ts, tests/ci-workflows/file-size-ratchet.test.ts.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# 030 — carry #5009 — Zhaofeng Li <lzfxxx@gmail.com>

Files: src/server/responses/agent-task-recovery.ts (FOLLOWUP_TASK, FINAL_ANSWER with optional Task name; author===sender check kept; recipient cross-check when task name present; JSON tuple cache key including recipient; foreign-family echo rejected), src/server/responses/encrypted-payload.ts (guard regex covers four types), structure/subagents.md, docs-site subagent-v1-default.md, configuration/agents.md, providers.md (check locales), tests/server/agent-task-recovery.test.ts, server-agent-task-recovery-replay.test.ts, v2-agent-message-failfast.test.ts, tests/helpers/agent-task-recovery.ts.
Method: squash diff from merge-base e9643875f0 applied with -3; check caps on test files (agent-task-recovery.test.ts +161).
Keep: recoveryAdmission before cache; agentTaskRecovery.enabled default-off.

## wp3 P (executable)
- /tmp/l4-5009.diff (squash from merge-base e9643875f0, 10 files) passes git apply --check -3 on HEAD af0a3713ea. Test files are below the 2000-line ratchet threshold (1128/438/907 before +163/+33/+48).
- DeepSeek writer updates item 4 of guides/subagent-v1-default.md in fr, ja, ko, ru, tr, zh-cn, zh-tw: they still say recovery loses message-type follow-ups, which contradicts the carried English text.
- Focused: bun test tests/server/agent-task-recovery.test.ts tests/server/server-agent-task-recovery-replay.test.ts tests/server/v2-agent-message-failfast.test.ts tests/responses/*encrypted* (rg for encrypted-payload tests).
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# 040 — #5694 98% main-account hard lock by default

Existing mechanism: codexMainAccountHardLock (src/types/config.ts, schema .catch(false)), MAIN_ACCOUNT_HARD_LOCK_PERCENT=99 in src/codex/quota-types.ts, getMainAccountHardLockStatus in src/codex/main-account-hard-lock.ts, consumers gate on === true in src/codex/auth-context.ts, src/codex/native-profile-startup.ts, src/server/management/config-routes.ts, gui/src/components/MainAccountHardLockSetting.tsx.
Change:
- MAIN_ACCOUNT_HARD_LOCK_PERCENT = 98.
- New resolver isMainAccountHardLockEnabled(config) = config.codexMainAccountHardLock !== false; replace every === true gate.
- Schema: invalid value -> undefined (default on), explicit false persists opt-out; management PUT false stores false (not delete), true deletes key or stores true — decide by reading config-routes semantics.
- GUI: toggle shows on when unset; copy 99% -> 98% in all locales; confirmation dialog still shown when enabling.
- Docs: providers-accounts.md (en, ko, others), configuration/providers.md, guides/providers.md, ru; structure/providers/openai-tiers.md.
- Tests: default-on status, explicit false off, 98 threshold (97.9 ready, 98 blocked), config-route round trip.
Trade-off for PR: default lock can keep main-account Luna Reserve from activating (Reserve needs exhausted normal window); opt-out by setting false.

## Audit folds (wp0 A)
- src/codex/main-account-hard-lock.ts:26 gates on !== true: switch to resolver.
- config-schema.ts:152 .catch(false) -> .catch(undefined) so malformed values fall back to the default (on).
- config-routes.ts:598 deletes the key on PUT false: must store false; PUT true deletes the key (default on). Projections at :351 and :706 become resolver-based, else GUI invariant at MainAccountHardLockSetting.tsx:14 fails.
- quota.ts:262 and :388 also use MAIN_ACCOUNT_HARD_LOCK_PERCENT (blocking-evidence retention); they follow the constant.
- auth-context.ts:512 hardcoded "99%" message -> derive from constant.

## wp4 P (executable)
Semantics: codexMainAccountHardLock absent or true = on; explicit false = off (persisted). Threshold 98 (MAIN_ACCOUNT_HARD_LOCK_PERCENT). Same convention as fastRows in config-routes.ts.
Writer A (core, write scope: src/**, tests/**, structure/**, scripts/test-layout/layout.json):
- src/codex/quota-types.ts: MAIN_ACCOUNT_HARD_LOCK_PERCENT = 98 (#5694).
- src/codex/main-account-hard-lock.ts: export isMainAccountHardLockEnabled(config) = config.codexMainAccountHardLock !== false; getMainAccountHardLockStatus uses it.
- Replace every === true gate: auth-context.ts 960/973/1017/1545/1623, native-profile-startup.ts 191/228/239/389/708, config-routes.ts projections 351/706.
- config-routes.ts PUT: true deletes key, false stores false (mirror fastRows); rollback path unchanged.
- config-schema.ts: .catch(undefined) so malformed values mean default-on.
- types/config.ts doc comment; auth-context.ts:512 message uses the constant.
- Tests: update existing hard-lock tests; add tests/codex-integration/main-account-hard-lock-default.test.ts (absent=on, false=off, malformed=on, 97.9 ready, 98 blocked, settings GET/PUT round trip) registered in layout.json explicit + test-layout-expected.json. codex-auth-api.test.ts cap 6549 (6514 now): no net growth beyond cap.
- structure/providers/openai-tiers.md:291-315 rewrite (on by default, 98%, opt-out persists false, Reserve trade-off).
Writer B (gui/src/i18n/*.ts only): 99 -> 98 in mainHardLock* strings in all locales; desc adds "On by default."
Writer C (docs-site/** only): providers-accounts.md en + ko (and other locales mentioning it) -> 98%, on by default, opt-out; check configuration/providers.md:71 and guides/providers.md:377.
Previous opt-outs deleted the key, so they cannot be distinguished; PR notes it.
Focused: main-account-hard-lock-*.test.ts, settings-main-account-hard-lock, main-quota-*, reserve-*, reserve-claude-policy, codex-quota-auto-refresh-main-admission, codex-auth-api, codex-account-threshold-api; bun run lint:gui; GUI i18n tests.

9 changes: 9 additions & 0 deletions devlog/_plan/260924_l4_codex_cli_service/050_publish.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# 050 — publish
Rebase on origin/dev; bun run typecheck; focused tests for every item; bun run test:changed; bun run privacy:scan; bun run structure:check; bun run lint:gui; push branch; gh pr create --base dev with template + Security review + Carries/Closes; watch automatic checks; fix failures on head.

## wp5 P (executable)
- origin/dev moved to df61bcecd5 (#5737, #5738). Overlapping files: docs-site reference/configuration/providers.md, scripts/test-layout/layout.json, structure/config.md, structure/subagents.md, tests/fixtures/test-layout-expected.json. Resolve by keeping both sides' entries.
- Before rebase: git mv devlog/_plan/260924_l4_codex_cli_service -> devlog/_fin/ is deferred until after merge (unit stays open while the PR is open).
- Validation after rebase: bun run typecheck; focused union of all item tests; bun run test:changed (worktree under /Users/jun/.codex trips the test-home guard for some temp-dir tests — compare any failure with a pristine git archive copy); bun run privacy:scan; bun run structure:check; bun run lint:gui.
- GUI screenshot: run the dashboard (bun run src/cli/index.ts start on a spare port with a throwaway OPENCODEX_HOME), open Codex settings > Multi-auth > Advanced, capture the 98% card to .tmp/. Hosting: pr-assets push only if the user authorizes; otherwise the coordinator uploads it.
- PR body: Summary per item with Carries/Closes lines, Security review for #5713, Verification with commands, Checklist, coordinator decisions (Reserve trade-off, previous opt-outs re-enabled, stale connect marker retention, 64 MiB indeterminate).
1 change: 1 addition & 0 deletions docs-site/src/content/docs/fr/guides/remote-hub.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ ocx sync
Les diagnostics de disponibilité lisibles par un humain affichent les caractères de contrôle des valeurs du catalogue sous forme d’échappements hexadécimaux visibles, aussi bien à la première connexion que lorsque `ocx sync` refuse un catalogue de hub actualisé. Le statut JSON conserve la valeur de diagnostic d’origine.

La clé client est écrite dans le fichier privé `service-api-token`, jamais dans `config.json`. En mode connecté, l’usage provient du hub et est filtré par `apiKeyId`; après déconnexion, il provient du stockage local. Il n’existe aucune réplication entre les deux.
`ocx service uninstall` supprime le service local mais conserve une clé existante lorsque le client est connecté, que ses métadonnées de connexion sont invalides ou non concordantes, ou qu’un marqueur de connexion en attente correspond à la clé actuelle. Un marqueur valide pour une clé plus ancienne ne conserve pas une clé de service sans rapport. Si un marqueur est peu sûr, malformé ou illisible, le nettoyage du jeton ne peut pas être vérifié ; la commande avertit au lieu d’affirmer que la clé a été conservée. Utilisez `ocx disconnect` pour supprimer la clé locale et l’état d’un client connecté.

Le jeton admin permet la gestion ordinaire mais ne peut jamais créer une session de consentement. Les actions de consentement exigent une `gui-session`, une Origin correspondante et un jeton CSRF. `Tailscale-User-Login` n’est fiable que sur l’entrée de gestion dédiée; renseignez les identités exactes dans `remoteGui.allowedTailscaleUsers`.

Expand Down
9 changes: 5 additions & 4 deletions docs-site/src/content/docs/fr/guides/subagent-v1-default.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,11 @@ devraient les essayer :
de l'erreur 400. Réservez ce réglage aux destinations dont vous savez
qu'elles peuvent consommer cette charge.
4. **Enable `agentTaskRecovery`.** Fonction expérimentale désactivée par
défaut. Elle récupère la plupart des créations récentes via le backend
ChatGPT, au prix de quota, de latence et d'une dépendance à un comportement
non documenté. Elle perd encore les suivis de type message et les
enveloppes en plusieurs parties.
défaut. Elle récupère via le backend ChatGPT les éléments chiffrés
illisibles `NEW_TASK`, `MESSAGE`, `FOLLOWUP_TASK` et `FINAL_ANSWER`, au
prix de quota, de latence et d'une dépendance à un comportement non
documenté ; la récupération combo reste limitée aux tours des enfants
lancés, et les fragments de jetons découpés restent non pris en charge.

Consultez [Surface des sous-agents](/fr/guides/sub-agent-surface/) pour le
fonctionnement détaillé de chaque option et
Expand Down
6 changes: 6 additions & 0 deletions docs-site/src/content/docs/guides/remote-hub.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ The hub automatically issues a per-client key. The client writes it to the exist
`service-api-token` file, never `config.json`. While connected, usage comes from the hub usage store
filtered to that client's stable `apiKeyId`. After disconnect, usage comes from the local store.
OpenCodex does not mirror usage between the two stores.
`ocx service uninstall` removes the local service but preserves an existing key when the client is
connected, its connection metadata is invalid or mismatched, or a pending connection marker matches
the current key. A valid marker for an older key does not retain an unrelated service key.
If a marker is unsafe, malformed, or unreadable, token cleanup cannot be verified;
the command warns instead of claiming the key was kept. Use `ocx disconnect` to remove a connected
client's local key and state.

If a client saved a remote `http://` Hub URL before the secure transport rule, its Hub
operations now return `insecure_http_refused`. Run `ocx disconnect` locally, then reconnect
Expand Down
7 changes: 4 additions & 3 deletions docs-site/src/content/docs/guides/subagent-v1-default.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,10 @@ Four routes, in the order most people should try them:
3. **Trust a direct key-auth Responses relay.** A provider you explicitly mark with
`allowEncryptedV2AgentTasks: true` receives the opaque payload instead of the 400. Only do this
for a destination you know can consume it.
4. **Enable `agentTaskRecovery`.** Experimental and off by default. It recovers most fresh spawns
through the ChatGPT backend, at the cost of quota, latency and a dependency on undocumented
behavior, and it still loses message-type follow-ups and multipart envelopes.
4. **Enable `agentTaskRecovery`.** Experimental and off by default. It recovers unreadable encrypted
`NEW_TASK`, `MESSAGE`, `FOLLOWUP_TASK`, and `FINAL_ANSWER` items through the ChatGPT backend, at
the cost of quota, latency and a dependency on undocumented behavior; combo recovery remains
limited to spawned-child turns, and split-token fragments stay unsupported.

See [Sub-agent Surface](/guides/sub-agent-surface/) for the full mechanics of each, and
[Agent configuration](/reference/configuration/agents/) for the settings themselves.
Expand Down
1 change: 1 addition & 0 deletions docs-site/src/content/docs/ja/guides/remote-hub.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ ocx sync
準備状況を人が読む出力では、カタログ値に含まれる C0/C1 制御文字、DEL、Unicode の行・段落区切り文字(U+2028、U+2029)を目に見える 16 進エスケープとして表示します。初回の接続だけでなく、`ocx sync` が取得し直したハブのカタログを拒否したときも同じです。JSON 形式の状態には元の診断値をそのまま残します。

発行されたキーは所有者だけが読める `service-api-token` に保存され、`config.json` には入りません。接続中の使用量は hub 側で同じ `apiKeyId` に絞り込まれ、切断後はローカル保存分を表示します。両者はミラーリングされません。
`ocx service uninstall` はローカルサービスを削除しますが、クライアントが接続中である場合、接続メタデータが無効または不一致である場合、または保留中の接続マーカーが現在のキーと一致する場合は、既存のキーを保持します。古いキーに対する有効なマーカーがあっても、無関係なサービスキーは保持されません。マーカーが安全でない、不正な形式、または読み取れない場合、トークンのクリーンアップを確認できないため、キーを保持したと断定せずに警告します。接続中のクライアントのローカルキーと状態を削除するには `ocx disconnect` を使用します。

管理トークンは通常の管理だけに使え、同意セッションを作ることは永久にできません。同意操作にはサーバー発行の `gui-session`、一致する Origin、CSRF が必要です。`Tailscale-User-Login` は専用管理リスナーでのみ信頼し、許可する ID を `remoteGui.allowedTailscaleUsers` に正確に設定します。

Expand Down
Loading
Loading