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
294 changes: 294 additions & 0 deletions devlog/_plan/260912_kiro_native_boundaries/000_plan.md

Large diffs are not rendered by default.

99 changes: 99 additions & 0 deletions devlog/_plan/260912_kiro_task_continuity/000_findings.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# Kiro task repetition: continuity gaps

Date: 2026-09-12 (Asia/Seoul).

## Scope and baseline

Work is against the user fork `coseung2/opencodex`, based on `main` at `6aec2590b`
(`2.8.0-cs.20`). Its actual GitHub parent is `lidge-jun/opencodex`; upstream `dev` was
inspected at `7a0513c2f`. This is a scoped adaptation, not an upstream merge. Existing fork
image retirement, reasoning replay, and terminal behavior must survive.

## Upstream comparison

| Evidence | Existing fork status | Decision |
| --- | --- | --- |
| Upstream #2819, merged 2026-08-28, `d7a82a8fc42632760750a160c9811543b18bd76d` | Delivered-final local terminal and phase-absent hash record were present (`03c87a698`); empty exec repair and proactive echo contract were absent. | Adapt only the missing code-mode behavior. |
| #2475, merged 2026-08-25, `09062014ed4ff9ff2e200b8ce8970a4e22a4f4a1` | Catalog retained a declaration-order prefix, even when discovered tools arrived later. | Prioritize loaded search results when over budget. |
| #2750, merged 2026-08-27, `eeb774026d077cec6c91217c1f097afa92856ead` | No code-mode discovery contract or execution-path reservation. | Reserve bare freeform exec and derive the contract from the emitted catalog. |
| Host-error follow-up `163378050d75bda4bc6eb0821da9382e5a80c67a` | No host-specific recovery hint. | Add one idempotent hint for leading error context, preserving original output and status. |
| #2835 / #3012 / #3031 | Superseded prose, terminal completion, and blocking-question completion already present (`e2b2d453c`, `4ca112156`, `0055bdb7a`). | Preserve; do not reapply or weaken. |
| #3750 / issues #3734 and #3731 | Original-id adjacent result grouping already present (`7445490e2`). | Normalize after that grouping; never merge across a user/assistant barrier. |
| #543 / reasoning round-trip | Mid-turn user steering and redacted reasoning pairing already covered. | Preserve existing tests and ownership. |
| Fork-only `037a30984` (`fix(kiro): stop replaying progress commentary`) | The fork blanked every assistant `phase: "commentary"` before rebuilding Kiro history. Current upstream preserves assistant text. The same fork commit already added an explicit instruction not to repeat/paraphrase old progress. | Reverse only the commentary deletion; retain the anti-repeat instruction and stream phasing. |

## Findings and confidence

The fork sent `The tool completed without textual output.` for a successful freeform exec
cell that omitted `text()`/`notify()`. It also passed nonblank-but-empty wrapper text through.
No pre-call instruction explained why a bare await produces no visible result. Upstream #2819
reports models interpreting this as lost context and restarting completed work. The missing
wire contract is reproduced here, but the reported live session was not captured, so this is
not proof that every instance of the user's repetition has that cause.

A second deterministic failure was independent of generation: with 48 filler declarations,
exec or tools loaded by search disappeared from the outbound catalog. A model could repeatedly
search for, or avoid, the execution path it actually needed. Under the new policy, the original
order is preserved below budget; over budget, discoveries outrank filler and exec has a reserved
slot and bytes. Unlike a blind reservation, a single oversized exec fails rather than bypassing
the 96,000-byte limit.

A third deterministic continuity failure was fork-specific. Commit `037a30984` classified Responses
`phase: "commentary"` as disposable UI prose and blanked it before rebuilding Kiro history. That
also removed substantive progress such as decisions, completed steps, rejected hypotheses, and next
actions. Tool calls/results survived, but the model could see what happened without the explanation
of why it happened or what remained. Current upstream preserves this assistant text. The deletion
was especially damaging at compaction boundaries: routed compaction summarizes the same rebuilt
provider history, so omitted commentary could not enter the checkpoint summary and was then lost
from replacement history. The fix preserves commentary as provider input memory while retaining the
existing instruction that forbids repeating/paraphrasing earlier progress; historical input is not
emitted by the response stream parser.

Known host errors can similarly encourage repeated invalid calls. Only verified code-mode calls
receive a recovery hint. Structured tools named exec, unrelated MCP namespaces, successful output
quoting a diagnostic, error status, images (including retired replay images), and nonempty
notification order remain protected by tests. The proxy does not execute or retry any command.

## Validation

- Wrote failing payload regressions before implementation. Empty-output guidance and catalog
preservation failed against the baseline; fixtures for optional tools/images were corrected
before the final run. Commentary-preservation regressions were then written against the PR branch:
four tests failed exactly on blanked tool-round commentary, dropped commentary-only turns, and
missing compaction-summary context before the deletion logic was reversed.
- Focused Kiro adapter, stream, reasoning round-trip, public-server completion, catalog-nudge,
Responses parser/compaction, and continuity coverage after the commentary fix: **264 pass, 0 fail,
883 assertions** across eight files. The narrower commentary/tool-round/compaction regressions are
**138 pass, 0 fail, 391 assertions** across two files.
- `bun run typecheck`: passed with the pinned Bun 1.4.0 installation.
- Frozen root dependency installation: passed without lockfile changes.
- Documentation frozen install/build: passed, 231 pages. English and Korean troubleshooting
pages explain the behavior and its limits.
- Initial repository-wide run: **7,309 pass, 11 skip, 8 fail (including 5 module-load errors)**
across 508 files. This was not a green full-suite run.
- A module-load-only pass isolated all five loading errors to missing React dependencies in the
new worktree's GUI package. Frozen GUI dependency installation changed no lockfile. The five
affected suites plus repository hygiene then passed: **96 pass, 0 fail, 366 assertions**.
- The remaining three `shutdown-launcher` cases (SIGINT/SIGTERM/SIGHUP) were rerun on a separate,
unmodified worktree at baseline `6aec2590b`: **0 pass, 3 fail**, all at the startup health check
(`tests/shutdown-launcher.test.ts:94`), before signal handling. No unrelated launcher source fix
is included. The full suite was not repeated after dependency installation.
- A repository-wide rerun after the commentary change was started but did not produce an aggregate:
the Bun test process remained CPU-bound for 576 seconds and was interrupted rather than reported
as green. The earlier baseline full-suite limitations and clean-main launcher reproduction above
remain the only completed repository-wide comparison. No claim of a green full suite is made.
- Staged `bun run privacy:scan` and `git diff --check`: passed. No dependency/lockfile changes.

No real Kiro account request, credential mutation, automatic deployment, or operational restart
was performed. A read-only health check reported the operational service as `2.8.0-cs.18`;
that version string alone does not establish which selectively copied modules are loaded.
The source correction and deployment status are deliberately separate.

## Structural follow-up

The continuity findings above exposed a layering problem as well as individual bugs: one monolithic
Kiro adapter owned task policy, wire mapping, auth/transport and event decoding. The follow-up plan
and implementation are documented in `devlog/_plan/260912_kiro_native_boundaries/000_plan.md`.
That refactor keeps this unit's behavior while separating continuity policy, bidirectional Kiro codec,
native transport, and the stable ProviderAdapter facade. Post-refactor focused coverage expands to
**357 pass, 0 fail, 1,206 assertions across 12 files**, including explicit architecture-boundary tests.
2 changes: 2 additions & 0 deletions docs-site/src/content/docs/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@ and WARN rows that include a recovery Action. When an OAuth provider account nee

### Kiro credential import

For repeated work or apparently missing tool output, see [Kiro repeats completed work](/troubleshooting/kiro-task-repetition/). This is separate from account login.

Kiro login expects the Kiro CLI: on Unix, install it with `curl -fsSL https://cli.kiro.dev/install | bash`;
on Windows PowerShell, use `irm 'https://cli.kiro.dev/install.ps1' | iex`; then sign in with `kiro-cli login`.
Without a `kiro-cli` session, `ocx login kiro` falls
Expand Down
2 changes: 2 additions & 0 deletions docs-site/src/content/docs/ko/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ Providers 페이지에서 계정을 추가하고, 다른 계정을 로그아웃

### Kiro 자격 증명 가져오기

작업을 반복하거나 도구 출력이 사라진 것처럼 보이면 [Kiro가 완료한 작업을 반복할 때](/ko/troubleshooting/kiro-task-repetition/)를 참고하세요. 계정 로그인과는 별도의 문제입니다.

Kiro 로그인에는 Kiro CLI가 필요합니다. Unix에서는 `curl -fsSL https://cli.kiro.dev/install | bash`, Windows PowerShell에서는 `irm 'https://cli.kiro.dev/install.ps1' | iex`로 설치한 뒤 먼저 `kiro-cli login`으로 로그인하세요. `kiro-cli` 세션이 없으면 `ocx login kiro`는 붙여 넣은 액세스 토큰이나 `KIRO_ACCESS_TOKEN` 환경 변수로 폴백합니다.

일반 `ocx login kiro` 가져오기는 CLI SQLite 데이터베이스를 읽기 전용으로 열며 데이터베이스, WAL, SHM을 수정하지 않습니다.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
title: Kiro가 완료한 작업을 반복할 때
description: 코드 모드의 출력 누락과 실제 대화 상태 손실을 구분하고 반복 도구 호출을 진단합니다.
---

작업을 반복한다는 사실만으로 Kiro의 대화 문맥이 사라졌다고 판단할 수는 없습니다. Codex 코드 모드에서 바깥쪽 `exec` 도구는 JavaScript를 실행하며, 단순한 `await`나 마지막 식의 반환값은 자동으로 출력되지 않습니다. 명령이 실행됐어도 모델에는 빈 도구 결과가 보일 수 있습니다.

## 코드 모드의 빈 출력

다음 단계에서 필요한 반환값은 같은 셀에서 출력합니다.

```js
text(JSON.stringify(await tools.exec_command({ cmd: "ls" })));
```

출력이 비었다는 이유만으로 파일 수정·배포 등 부작용이 있는 작업을 다시 실행하지 말고 기존 상태를 먼저 확인해야 합니다. 명령이 `session_id`를 반환했다면 새로 실행하는 대신 해당 세션을 조회합니다.

OpenCodex는 실제 코드 모드 도구 목록을 확인한 뒤 실행 전 지침과 Kiro에 전달하는 빈 결과 설명을 제공합니다. 동일한 원래 호출의 인접 출력은 합친 뒤 설명을 한 번만 추가합니다. 실패 래퍼나 오류 결과는 실패로 유지하고, 이미지 결과는 출력 누락으로 취급하지 않습니다. 무관한 MCP 도구나 이름만 `exec`인 일반 구조화 도구에는 JavaScript 실행 환경 지침을 넣지 않습니다.

`tools.apply_patch`에 문자열 대신 객체를 전달하거나 모듈을 import하는 등 알려진 호스트 오류에는 짧은 복구 안내를 덧붙입니다. 원래 오류 내용과 상태는 유지하며, 정상 출력에서 오류 문구를 인용한 경우에는 변경하지 않습니다.

## 도구 목록이 큰 경우

Kiro에 보내는 클라이언트 도구 목록에는 48개·직렬화 크기 96,000바이트 한도가 있으며, 비공개 완료 도구를 위한 여유는 별도로 둡니다. 한도를 초과하면 도구 검색 결과를 일반 선언보다 우선하고, 중첩 도구를 실행하는 freeform `exec`의 공간을 예약합니다. 이후 검색 진입점과 나머지 도구를 가능한 범위에서 포함합니다. 생략 안내는 실제 전송 목록을 기준으로 작성합니다. `exec` 하나가 바이트 한도보다 크면 제한을 무시하지 않고 명시적으로 오류를 반환합니다.

한도 이내에서는 선언 순서를 유지합니다. 네임스페이스가 있는 MCP 셸 도구는 코드 모드를 비활성화하지 않습니다. 이 동작을 위한 추가 설정이나 계정 재인증은 필요하지 않습니다.

## 작업 종료와 대화 상태

기존 Kiro 비공개 완료 채널은 그대로 턴을 종료합니다. 진행 메시지는 최종 답변이 아니며, 이미 전달한 최종 답변 때문에 닫힌 작업을 다시 열어서는 안 됩니다. 실제 사용자 후속 질문은 정상적으로 처리합니다. 이 수정은 도구 이력을 버리거나, 추론 상태 재전송을 바꾸거나, 인자가 같다는 이유만으로 도구 호출을 삭제하거나, 명령을 자동 재실행하지 않습니다.

`phase: "commentary"`로 표시된 assistant 메시지도 Kiro 이력에 보존합니다. 진행 문구에는 결정 사항, 이미 끝낸 단계, 폐기한 가설, 다음 미완료 작업이 들어갈 수 있으므로 이를 삭제하면 다음 도구 결과 라운드에서 작업 상태를 잃은 것처럼 보일 수 있습니다. routed compaction이 체크포인트 요약을 만들 때도 같은 이력이 입력으로 사용되므로 commentary를 보존해야 압축 뒤에 이런 결정이 사라지지 않습니다. 과거 commentary는 입력 문맥일 뿐 UI에 자동으로 다시 출력되지 않으며, Kiro에는 이전 진행 문구를 반복하거나 바꿔 말하지 말라는 지침을 계속 제공합니다.

회귀 테스트는 빈 결과 설명 누락, 도구 목록 탈락, commentary 소실, 압축 입력 문맥 소실을 재현하지만 모든 모델 반복 현상의 원인이 같다는 뜻은 아닙니다. 수정 빌드 배포 후에도 반복된다면 직전 결과가 빈 출력인지, 오류인지, 정상 결과인지, 이미 전달한 최종 답변인지, 또는 compaction 경계를 지난 직후인지 구분해야 합니다. 실행 중인 버전과 민감 정보를 제거한 요청 식별자를 기록하되 자격 증명이나 원문 비공개 프롬프트를 공개하지 않습니다.

## 원본 저장소 참고

이번 포크 적용은 [#2819: 빈 exec 출력과 완료 답변 재개 방지](https://github.com/lidge-jun/opencodex/pull/2819), [#2475: 도구 검색 결과 우선 보존](https://github.com/lidge-jun/opencodex/pull/2475), [#2750: 코드 모드 탐색 및 실행 경로 예약](https://github.com/lidge-jun/opencodex/pull/2750)을 참고했습니다. 이미 반영된 완료 관련 수정에는 [#3012](https://github.com/lidge-jun/opencodex/pull/3012), [#3031](https://github.com/lidge-jun/opencodex/pull/3031), 인접 출력의 소유권 보존 수정 [#3750](https://github.com/lidge-jun/opencodex/pull/3750)이 있습니다.
38 changes: 38 additions & 0 deletions docs-site/src/content/docs/troubleshooting/kiro-task-repetition.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
title: Kiro repeats completed work
description: Distinguish missing code-mode output from lost conversation state and diagnose repeated tool calls.
---

Repeated work is not by itself evidence that Kiro lost the conversation. In Codex code mode, the outer `exec` tool evaluates JavaScript, and a bare `await` or final expression does not print its result. The model can therefore see an empty tool response even though the command ran successfully.

## Empty code-mode output

When a value is needed for the next step, print it in the same cell:

```js
text(JSON.stringify(await tools.exec_command({ cmd: "ls" })));
```

Do not rerun an edit, deployment, or other side-effecting operation solely because the output was empty. Inspect existing state first. If a command returns a `session_id`, poll that session rather than start the command again.

OpenCodex supplies this contract before a verified code-mode call and explains empty output on its Kiro continuation. It combines adjacent outputs from the same original call before adding one explanation. A failed wrapper or an error result remains a failure; image output is not treated as a missing print. Unrelated MCP tools and structured tools merely named `exec` do not receive JavaScript-isolate instructions.

Known code-mode host errors, such as passing an object instead of a string to `tools.apply_patch` or importing a module, receive a short recovery hint. The original error text and status are retained. Successful output quoting an error message is left unchanged.

## Large tool catalogs

Kiro's client-tool catalog is bounded to 48 tools and 96,000 serialized bytes, with separate headroom for the private completion tool. When that budget is exceeded, tools returned by tool search take priority over ordinary declarations. OpenCodex reserves space for the freeform `exec` execution path, then the search gateway and remaining tools as space permits. The omission notice describes the actual emitted catalog. A single `exec` specification that cannot fit the byte budget fails explicitly instead of bypassing the limit.

Below the budget, declaration order is unchanged. Namespaced MCP shell tools do not disable the code-mode contract. No setting or account reauthentication is needed for this behavior.

## Completion and conversation state

Kiro's existing private completion channel still ends the turn. Progress text is not a final answer, and a delivered final answer must not reopen the task. Real user follow-ups continue normally. This correction does not discard tool history, change reasoning-blob replay, remove repeated calls solely because their arguments match, or introduce automatic command retries.

Assistant messages marked `phase: "commentary"` are preserved in the Kiro history. They can contain decisions, completed steps, rejected hypotheses, and the next unfinished action, so dropping them can make a later tool-result round look as if the task state was lost. The same history is used when a routed compaction turn creates its checkpoint summary, so preserving commentary also prevents those decisions from disappearing at compaction. Historical commentary is input context only; OpenCodex does not automatically stream it to the UI again, and Kiro is explicitly instructed not to repeat or paraphrase earlier progress updates.

The adapter tests reproduce missing-output guidance, catalog eviction, commentary loss, and compaction-context loss deterministically; they do not prove that every model-generated repetition has the same cause. If repetition persists after deploying the corrected build, distinguish whether the preceding output was empty, an error, a successful result, an already-delivered final answer, or a compaction boundary. Record the running version and sanitized request identifiers, not credentials or raw private prompts.

## Upstream references

The fork adaptation is based on [#2819: empty exec output and final-answer reopening](https://github.com/lidge-jun/opencodex/pull/2819), [#2475: tool-search result priority](https://github.com/lidge-jun/opencodex/pull/2475), and [#2750: code-mode discovery and execution-path reservation](https://github.com/lidge-jun/opencodex/pull/2750). The already-present completion fixes include [#3012](https://github.com/lidge-jun/opencodex/pull/3012), [#3031](https://github.com/lidge-jun/opencodex/pull/3031), and the adjacent-result ownership fix [#3750](https://github.com/lidge-jun/opencodex/pull/3750).
Loading
Loading