|
| 1 | +# Close-out: the blocked-on-user state |
| 2 | + |
| 3 | +Merged. `afc1cc59c` (#3031) carries the contract change, the tests, and the |
| 4 | +public documentation. |
| 5 | + |
| 6 | +## What shipped |
| 7 | + |
| 8 | +The injected Kiro contract now describes three states instead of two. Alongside |
| 9 | +"still working" and "fully complete" there is "cannot continue until the user |
| 10 | +supplies a decision, information, or a clarification that only they can give" — |
| 11 | +and that question is delivered as the final answer, through the channel that |
| 12 | +already terminates the turn correctly. |
| 13 | + |
| 14 | +Four surfaces carry it, because a model that reads one of them and not the |
| 15 | +others gets a contradiction: |
| 16 | + |
| 17 | +- `KIRO_COMPLETION_INSTRUCTIONS` — the prose contract. |
| 18 | +- `KIRO_COMPLETION_RETRY_MESSAGE` — the one instruction the model sees at the |
| 19 | + exact moment it failed to complete. Its old tail, *"Do not ask the user for |
| 20 | + another task"*, was scoped to soliciting new work but read as a ban on asking |
| 21 | + anything. |
| 22 | +- The completion tool's schema description — what the model reads while |
| 23 | + *choosing* a tool. |
| 24 | +- The `answer` property description — what may go in the field. |
| 25 | + |
| 26 | +Round one changed the terminality half of that schema description and left the |
| 27 | +eligibility half saying only "fully complete". That asymmetry is part of why |
| 28 | +prose alone did not move the outcome. |
| 29 | + |
| 30 | +## Review changed the shape twice |
| 31 | + |
| 32 | +The review record is worth keeping, because both corrections were substantive. |
| 33 | + |
| 34 | +An independent design audit ran six rounds before the commit. It killed |
| 35 | +ask-tool isolation as unreachable (measured: 8 `request_user_input` calls |
| 36 | +across 644 rollouts, ask-then-another-tool **0** times), caught a test |
| 37 | +precondition that could not fail — `not.toContain("omitted")` against a notice |
| 38 | +that says capitalized `Omitted` — and caught the schema description still |
| 39 | +admitting only a completed answer. |
| 40 | + |
| 41 | +PR review then found the trigger was too narrow. "Blocked on a decision" does |
| 42 | +not cover "what is the account id" or "which of these paths did you mean", and a |
| 43 | +model stuck on a missing value is stuck exactly as hard as one stuck on a |
| 44 | +choice. The wording now names a decision, information, and clarification, and |
| 45 | +the doc comments say why, so a future reader does not narrow it back. |
| 46 | + |
| 47 | +Review also asked for ordering assertions on the non-regression test. Counts and |
| 48 | +payloads alone would have passed on a reordered stream, or on an early `done` |
| 49 | +followed by a second one. |
| 50 | + |
| 51 | +## What was deliberately not built |
| 52 | + |
| 53 | +No adapter gate. Across 644 rollouts the same-inference prose-plus-tool shape |
| 54 | +occurs 26 times: 4 question-tailed (1329-1938 chars) and 22 ordinary progress |
| 55 | +narration (608-3141). The ranges overlap completely, and at `flushOpen` the |
| 56 | +adapter knows only that a non-completion tool was emitted, its restored |
| 57 | +identity, and its arguments. `stopReason` cannot help, because Kiro sends |
| 58 | +`END_TURN` for progress prose too. Every gate is a coin flip on whether a user |
| 59 | +sees their agent's work. |
| 60 | + |
| 61 | +No reservation guard for the injection budget. Both charged inputs are |
| 62 | +structurally capped and the predecessor unit already proved that guard's test |
| 63 | +passes with the guard removed. Two hostile-catalog tests pin the property |
| 64 | +instead, each asserting its own precondition so neither can pass while charging |
| 65 | +less than it claims. |
| 66 | + |
| 67 | +## The limit, stated plainly |
| 68 | + |
| 69 | +This is influence, not enforcement, and it cannot promise non-recurrence. Kiro |
| 70 | +accepts only automatic or no tool choice, so no typed progress/pause/complete |
| 71 | +protocol can be forced upstream, and the good and bad event streams are |
| 72 | +observationally identical at the adapter. The tests prove the contract is |
| 73 | +delivered, not that the model obeys it. |
| 74 | + |
| 75 | +The goalplan criterion demanding a code-level mechanism was amended by recorded |
| 76 | +steering (`260831-c1-amend-prose-only-mechanism`) rather than reinterpreted to |
| 77 | +fit the diff. |
| 78 | + |
| 79 | +## Landed-state verification |
| 80 | + |
| 81 | +Read out of `origin/dev` after the merge, not the working tree: |
| 82 | + |
| 83 | +- `src/adapters/kiro-constants.ts` carries the widened trigger on both |
| 84 | + constants. |
| 85 | +- `src/adapters/kiro.ts` carries it on the schema description and the `answer` |
| 86 | + property. |
| 87 | +- `tests/kiro-adapter.test.ts` carries the two contract tests and the two |
| 88 | + hostile-catalog tests. |
| 89 | +- `tests/kiro-stream.test.ts` carries the parameterized non-regression test. |
| 90 | +- `docs-site/src/content/docs/reference/adapters.md` documents the pause |
| 91 | + semantics; seven translated locales carry the same statement. |
| 92 | + |
| 93 | +CI on the merged head: 23 checks green, the only non-pass being the |
| 94 | +intentionally skipped Windows matrix placeholder. One `macos` failure was |
| 95 | +investigated and is unrelated — |
| 96 | +`tests/shutdown-launcher.test.ts` spawns a real launcher and waits on POSIX |
| 97 | +signal delivery under a 20s bound, contains no Kiro reference, and passed on |
| 98 | +rerun of the identical commit. |
| 99 | + |
| 100 | +Focused evidence at the merged tree: `bun run typecheck` exit 0; 206 pass / 0 |
| 101 | +fail / 797 expect() calls across `kiro-adapter`, `kiro-stream`, and |
| 102 | +`tool-catalog-nudge`; `bun run privacy:scan` passed. The local full suite was |
| 103 | +excluded by instruction; CI covered it. |
| 104 | + |
| 105 | +## Merge trail |
| 106 | + |
| 107 | +- `f5a625cf3` (#3012) — round one, terminal completion contract. |
| 108 | +- `6f75616f0` (#3014) — round one close-out. |
| 109 | +- `1031b6fff` (#3016) — round one landed-state record. |
| 110 | +- `afc1cc59c` (#3031) — this unit. |
| 111 | + |
0 commit comments