diff --git a/ops/hub/__pycache__/hub-frontdoor.cpython-310.pyc b/ops/hub/__pycache__/hub-frontdoor.cpython-310.pyc index ec2460759..257508321 100644 Binary files a/ops/hub/__pycache__/hub-frontdoor.cpython-310.pyc and b/ops/hub/__pycache__/hub-frontdoor.cpython-310.pyc differ diff --git a/ops/hub/__pycache__/jev_placement.cpython-310.pyc b/ops/hub/__pycache__/jev_placement.cpython-310.pyc index abfaa70fd..aabdac10f 100644 Binary files a/ops/hub/__pycache__/jev_placement.cpython-310.pyc and b/ops/hub/__pycache__/jev_placement.cpython-310.pyc differ diff --git a/ops/hub/hub-frontdoor.py b/ops/hub/hub-frontdoor.py index 7fb01512c..440a00ea4 100644 --- a/ops/hub/hub-frontdoor.py +++ b/ops/hub/hub-frontdoor.py @@ -1606,10 +1606,17 @@ def _dechunk(buf, state): buf = buf[take:] state["size"] -= take if state["size"] == 0: - state["mode"] = "size" - if buf.startswith(b"\r\n"): buf = buf[2:] + # the CRLF closing a chunk can straddle reads: consume it + # in its own state, never as an (empty → unparseable) + # size line — that wedged the stream for good + state["mode"] = "crlf" continue break + if state["mode"] == "crlf": + if len(buf) < 2: break + if buf.startswith(b"\r\n"): buf = buf[2:] + state["mode"] = "size" + continue if state["mode"] == "done": break return out, buf @@ -1649,8 +1656,18 @@ def _resume_loop(self, c, shard_id, addr, cursor): # Byte-level edits (gap frames, synthetic heartbeats, swallowed # frames) are only valid on a stream we fully own. _head, _, _body = pre.partition(b"\r\n\r\n") - _dcst = {"mode": "size", "size": 0} - _clean, _rest = self._dechunk(_body, _dcst) + # de-chunk ONLY a chunked body (an identity-encoded engine body — + # HTTP/1.0, or a future non-chunked transport — parses as-is; the + # unconditional de-chunk dropped every frame of such a body). The + # unconsumed tail (a chunk-size line split across reads) carries + # into the next read instead of being discarded. + _dcst = {"mode": "size", "size": 0, + "chunked": b"transfer-encoding: chunked" in _head.lower()} + _pend = b"" + if _dcst["chunked"]: + _clean, _pend = self._dechunk(_body, _dcst) + else: + _clean = _body reasm += _clean frames, reasm = _parse_frames(reasm) with self.lock: @@ -1725,7 +1742,10 @@ def _resume_loop(self, c, shard_id, addr, cursor): if chunk is None: continue _hb_ticks = 0 - _dc_out, _rest = self._dechunk(chunk, _dcst) + if _dcst["chunked"]: + _dc_out, _pend = self._dechunk(_pend + chunk, _dcst) + else: + _dc_out = chunk reasm += _dc_out frames, reasm = _parse_frames(reasm) if b"server.cursor.unservable" in reasm or any(b"server.cursor.unservable" in f for f in frames): diff --git a/ops/hub/test_frontdoor.py b/ops/hub/test_frontdoor.py index 2b32b95f7..be4a6cdd2 100644 --- a/ops/hub/test_frontdoor.py +++ b/ops/hub/test_frontdoor.py @@ -2345,5 +2345,52 @@ def test_stalled_member_drop_does_not_wedge_the_group(self): "the surviving member must keep receiving (no wedged lock)") + +class TestResumeDechunk(unittest.TestCase): + """The resume path de-chunks the engine's chunked SSE body across + arbitrary read boundaries (83cd8afc follow-up). Group._dechunk is pulled + from the module source by AST — importing the module starts a server.""" + + @classmethod + def setUpClass(cls): + import ast, textwrap + src = open(os.path.join(os.path.dirname(os.path.abspath(__file__)), "hub-frontdoor.py")).read() + for node in ast.walk(ast.parse(src)): + if isinstance(node, ast.FunctionDef) and node.name == "_dechunk" and node.args.args and node.args.args[0].arg == "buf": + ns = {} + exec(textwrap.dedent(ast.get_source_segment(src, node)), ns) + cls.dechunk = staticmethod(ns["_dechunk"]) + return + raise AssertionError("Group._dechunk not found") + + @staticmethod + def chunked(*payloads): + return b"".join(b"%x\r\n%s\r\n" % (len(p), p) for p in payloads) + + def feed(self, wire, cut): + st = {"mode": "size", "size": 0} + out, pend = b"", b"" + for i in range(0, len(wire), cut): + o, pend = self.dechunk(pend + wire[i:i + cut], st) + out += o + return out, pend + + def test_every_read_boundary_yields_the_exact_body(self): + frames = [b"id: 1\ndata: {\"a\":1}\n\n", b"id: 2\ndata: " + b"x" * 300 + b"\n\n", b": hb\n\n"] + wire = self.chunked(*frames) + for cut in range(1, len(wire) + 1): + out, _ = self.feed(wire, cut) + self.assertEqual(out, b"".join(frames), "read size %d" % cut) + + def test_a_split_size_line_is_carried_not_dropped(self): + wire = self.chunked(b"data: one\n\n", b"data: two\n\n") + cut = wire.index(b"\r\n", 5) + 3 # inside the second chunk's size line + st = {"mode": "size", "size": 0} + a, pend = self.dechunk(wire[:cut], st) + self.assertEqual(a, b"data: one\n\n") + self.assertTrue(pend, "the partial size line must come back as the pending tail") + b, _ = self.dechunk(pend + wire[cut:], st) + self.assertEqual(b, b"data: two\n\n") + if __name__ == "__main__": unittest.main(verbosity=2) diff --git a/packages/app-bundle/manifest.json b/packages/app-bundle/manifest.json index 542167f12..1900d95d6 100644 --- a/packages/app-bundle/manifest.json +++ b/packages/app-bundle/manifest.json @@ -8,7 +8,7 @@ "upstream_base_sha": "3104c1428ec91f809e5ab86631300de41eb6952e", "promoted_at": "2026-09-13T22:15:25.839Z", "files": { - "packages/app/CONTEXT.md": "69e73ecec62f730398e8f25071e736a58b2f7a1d9059b60788e9936051051f14", + "packages/app/CONTEXT.md": "ce2c2fa79b95f053055fa92889dfa4e5ad583416d5008dd7203fe160ab155ade", "packages/app/index.html": "fa38026be3b7e7ec38958a558d7b4d059140b2aff998c3ac862601543702584d", "packages/app/package.json": "3c9bf3d487052d4834b7fd3ce93fcf6b7fc358de92b8be4b0e84fc424a971f74", "packages/app/playwright.config.ts": "b7dae0b39248b4ddf7cba829af96ac7fe3cc919add9711ecb5292d9bd52e1805", @@ -25,7 +25,7 @@ "packages/app/public/oc-theme-preload.js": "27227e802b3494e7c545da903e679efdb30ccc754cd4eb5cdf08005a40d560b6", "packages/app/src/app-desktop-commands.test.ts": "1d2057f238dc14e4407ff5c4e53afe091784790bc0fd0dbfde0eacd91e2bd968", "packages/app/src/app.tsx": "6fe2c1136330b0b76beb10b15c0ca9df2c62877c98ba3eb4cb91844125916a82", - "packages/app/src/design-polish.css": "6dceafb232f7132be588debc33c913fa6773966d54d6bbf6a1496b7622adeacc", + "packages/app/src/design-polish.css": "e84c1bf92265a91daa573069422a7491bbc2175bda28be66eba90ae26963bfc2", "packages/app/src/desktop-menu.ts": "350e0e9f2e4294bfe1b1f357b3cd2ea0908b14d20ca1e79fda2305db1958fb24", "packages/app/src/entry.tsx": "f35e1017f4c9d478d254b2a38043e5750064b6bef25169c3e07ae9f72ff1049c", "packages/app/src/index.css": "2c11df3dcebb381358e06626094b5dda3c35688ad7940d643b2cbb6cff1ea9e9", @@ -52,7 +52,9 @@ "packages/core/test/session-runner.test.ts": "4cf0d4e3989a32b0c693473d4f94bf787bd964e79b312a7ee0032305503edb20", "packages/core/test/tool-question.test.ts": "4df41393f15104a1d3a9c3d06e30cef515108490b41fcf4d9a7d9399fd4ed945", "packages/llm/src/cache-policy.ts": "04c1fb5d3d061cfa95d04e54df0a1c2cdaafac921224242446eaa2968bff7857", + "packages/llm/src/provider-error.ts": "65b9124905f0755c1e368df5150aa211bea3cc29afb66845b5ceaccba10042dd", "packages/llm/test/cache-policy.test.ts": "e921095c4301440c786105063439e49b2fedbaf6d46f30457e0a96388d268f4b", + "packages/llm/test/provider-error.test.ts": "ac3bf099319acdc27ff47ea79fd74357d55e12ab95131a07a72a5a2a9bc0c08f", "packages/opencode/script/build.ts": "876e7d569aa71ce060c1d4b24c96e9bf13245cbf4ca743828d645560a95aa641", "packages/opencode/script/httpapi-exercise.ts": "772bd2cf5748ca90c5d5790c2d044237518cc8ede0411fc4ba28b9d7440ba28c", "packages/opencode/test/amicode-release-workflow.test.ts": "f6dfcb3ed9c572ca8e8b21ff82e038872b635b25c68f9580f6d6f51ee2813189", @@ -107,7 +109,7 @@ "packages/app/src/components/amicode-default-model.tsx": "16a2de1feb12e07416fe5fbb25879391f912ee0909b553c868c1b531f2ed1f2d", "packages/app/src/components/amicode-defaults-capsule.tsx": "94dc081bc47abb7e50566fcd8e9e53124f9d7632d61f93eff4f1627e0c2efb2d", "packages/app/src/components/amicode-file-ref-bridge.tsx": "11c17d7fdb29d16530e188b13ee8af728f37d9adfbb518084106ce50cc0c527a", - "packages/app/src/components/connection-banner.tsx": "c793966e1f9d6f307af697032b235c2ff65afaa04f6cc232e40ce45e5745ded4", + "packages/app/src/components/connection-banner.tsx": "82194291181165ed7b1b1b3a6801a1bdcd2c2b7cdd733c28486bd69f86477a24", "packages/app/src/components/dialog-command-palette-v2.css": "85984957adaf15efcc0828310f3a0b438cedaaba776a9fec2eddb3ad83487fa2", "packages/app/src/components/dialog-command-palette-v2.tsx": "e12da3e5e9e503089dd9139b20e04f6b566cf74fa445f23a2e193f5883f7c5f3", "packages/app/src/components/dialog-connect-provider-harmoniqs.test.ts": "7c16914afe3e77ad09691bbfa8223981eda0c2faf3616ed6db2e4e5fa9ce9fdd", @@ -115,7 +117,7 @@ "packages/app/src/components/dialog-connect-provider.tsx": "6eb784f06171e3c22d934fd170199b6b1020295a365b669aa8581c86b464b77d", "packages/app/src/components/dialog-edit-project-v2.tsx": "f34aaed28604facd9d8a46a4934e2b331421d5f60902a2b160ddcec11af03bd9", "packages/app/src/components/dialog-edit-project.tsx": "5371da3de3a643d4347629af55c0adc2476bffe7b2f061535a92fd67e756e562", - "packages/app/src/components/dialog-new-project.tsx": "102fc33e8eeaf3c76ddd1b953b7b97995d30c02a3579f8b7036e47448a1582a8", + "packages/app/src/components/dialog-new-project.tsx": "acc359b435e1bec55b9bb0c4926551b9aabf1ab3150c6b018ddd1d3ba6465f34", "packages/app/src/components/dialog-release-notes.tsx": "0ea5b049786787643a7f6b54d4ccf84c4f8ffa4e8272426c0d32f60d445b6890", "packages/app/src/components/dialog-select-directory-v2.css": "2e2f18abdca77f9fe85da157c40f288f3b1641ca92845208749e16455fd58637", "packages/app/src/components/dialog-select-file.tsx": "e6278ee35dd27d203e00ad73f70c709c44a6c06f81ffbd931edfaa0c986b9e03", @@ -149,12 +151,12 @@ "packages/app/src/components/settings-providers.tsx": "c86c9bf4a6f6e198dc7b0995a69d5b76e851144987bbe601802b1b0120ee4ac4", "packages/app/src/components/solver-switch-banner.tsx": "ec7edeec6dc05a4a06b39241b4f3a8e7534da97722dd8ec6f26ff782025802e9", "packages/app/src/components/split-frame.tsx": "44c53737f72027b461097c03df48a4f411d04a82d02b1fce4901813c73dfcc72", - "packages/app/src/components/status-popover-body.tsx": "c7f5cce9066a6388de8531156a300503ead6f596cad2ea4269d64c421a97d0c5", - "packages/app/src/components/status-popover-indicator.test.ts": "9afc7b49d9021a94d74f3f777178230ae13bd26e5749da0cee4d3378eacacacd", - "packages/app/src/components/status-popover-indicator.ts": "887b3e659ff49fd0d2a8715fad6562dc7e9402b80d06442058502306bdb108f5", + "packages/app/src/components/status-popover-body.tsx": "2b6aa39a4358bbce7b6836b6a719be8eb24db96cd603bc0b4fb9fb0365413fed", + "packages/app/src/components/status-popover-indicator.test.ts": "e3530caa3a46b822603a8d0a753550605951c2cc5e95c60c46636935f2398a7a", + "packages/app/src/components/status-popover-indicator.ts": "d705c258e3404567fa5ae6d8ce9c27010832f12fdd614cef21f0297154e7faae", "packages/app/src/components/status-popover-model.test.ts": "10634035bab0f31de24564e0d6c8413a0f7434fb2c08ac3ef722981a69dd08e7", "packages/app/src/components/status-popover-model.ts": "ec5a5a3caf9344fe617c7bc668af81d96ad4290378c34186cd4cd959821f1c85", - "packages/app/src/components/status-popover.tsx": "520c9e33b072cca1470508531eba194c690f0be86028f1b5abcbad0fe591bd5e", + "packages/app/src/components/status-popover.tsx": "f712c9b54b0ce63e2020a22bdb55bcc104e49ef41d4d5aea216b22900a3392ef", "packages/app/src/components/terminal.tsx": "2ce242034ae129c1f475c7a24fdec3facdd9bb1f49ba8c6b503643b07ae241e5", "packages/app/src/components/titlebar-channel.test.ts": "184238871c46f586dcc21081f710e37a77914c983fccf250665c7317212e41d8", "packages/app/src/components/titlebar-channel.ts": "385ace91d3c69c92f5b442bf15d2040e35df855f1d4ece47312c1ff8e1b01780", @@ -200,8 +202,8 @@ "packages/app/src/context/server-sdk.tsx": "9dc721c54074a323fb879aedf76cf29c1888088ab6b9b0c68aae683ca4f563f1", "packages/app/src/context/server-session-child-active.test.ts": "de8c467f67f88b6cce351c1805ec90728cf238eb1ef32f39ffdbbf3de4dcec22", "packages/app/src/context/server-session-orphan-part.test.ts": "1d635374c0bfff25a01825061aabac7334e5cdaedca2dab9f3d9467ff543caea", - "packages/app/src/context/server-session.test.ts": "31b14c85a843eb172899f456566ad7ab7d07a22eaf8b31d29a22e255e95cb96b", - "packages/app/src/context/server-session.ts": "9fbb312e7183ca0f1266ee13b59fb8545a64a8e9539645790c8969e7bdf4053b", + "packages/app/src/context/server-session.test.ts": "b332098635885211bccaec0d7da8ca6b60696b04bd3f89ba3fcd97cd4c881856", + "packages/app/src/context/server-session.ts": "ad486fc5d36f93f5f53d51b70fdf191a3008b67f2b280dfc58b64e6d8d20982d", "packages/app/src/context/server-sync.tsx": "55ac830560ddd947b5d58a9c496a4e94ffc63fd7241c74ba9b843aea724b74ce", "packages/app/src/context/server.tsx": "08e978e4b4b3094221a2a0b92e069f39cbedb6d6cf95935881e21cde52265ee2", "packages/app/src/context/session-mirror.test.ts": "65e6d6474e4e67f2da194047140c8c8aac04fe0cc9926441468e53fabc48db96", @@ -355,7 +357,7 @@ "packages/opencode/src/project/instance-context.ts": "65a35792e50e96a50ea14cd9f928045c0e2fc15eb49506f5bbceee38c4af1457", "packages/opencode/src/project/instance-store.ts": "c22d3e2499e63dd8d9395d58189df75444d306774df833e746f22e327edcf2ab", "packages/opencode/src/provider/auth.ts": "b0ab1322c1039e27176bf9e3500603eae27506065ac141a69710220f3361f6b8", - "packages/opencode/src/provider/error.ts": "7f3c8210c775e2ce98140bf015dc97e61192912af062c75e18ecb09ee2736a0f", + "packages/opencode/src/provider/error.ts": "d72310be26cfae5c2943f9939a6461e848532a5646ff405d628e9a50fc1ebe91", "packages/opencode/src/provider/provider.ts": "b89bc0ca0a12ea0cfaf5c956a4b731a0397d4c407e787a16cdd66fb7f54ee476", "packages/opencode/src/provider/transform.ts": "70c7492d4a23a30ebc340a5605702b1602960f4b412e18557534e02962c137b8", "packages/opencode/src/question/index.ts": "8317348c2ca27dd9e4f7d18fdc126a4d355c20495c1b86668430ad477a68e9b3", @@ -423,7 +425,7 @@ "packages/opencode/test/server/amicode-vault-browser.test.ts": "03347a6a9b6ba250b7a1150449cbe44b8817dbc0ebc433c89a703f4818492a5a", "packages/opencode/test/server/amicode-vaults.test.ts": "3f7c8ecfdc250ff360c0ed66d9cc6354d9069e66001281b3f6e30981b9f71c35", "packages/opencode/test/server/amicode-warrants.test.ts": "a7ad74da87f77f4488f334debf8c126671d563839891eb3a19b3d1a134dbc504", - "packages/opencode/test/server/amicode-widget-frame.test.ts": "5246d63240eae3390c8ba7f14950c41d546d6936cbe64df35da503febec72a1f", + "packages/opencode/test/server/amicode-widget-frame.test.ts": "a0374ab77ea5b39d8a7cbe9985537045506fd233299cfae081920714ca184e5f", "packages/opencode/test/server/amicode-widget-manifest.test.ts": "ac404d1737bdde8ea3464cf0b5fa12f0a6f9e630a0698ca5fdec38449cb66d0f", "packages/opencode/test/server/amicode-widgets.test.ts": "9e7ad16922e59583c337ff9383e57988b8abdfc0836ec3280655196cd192e8e4", "packages/opencode/test/server/auth-accept-set.test.ts": "8fe698812ed9a809d21ace1a9751bd3f1976ab1e58ad5bda65dbfff58df8e3bc", @@ -448,6 +450,7 @@ "packages/opencode/test/server/session-diff-missing-patch.test.ts": "70526ca7fb86741843fd167f8f2f9c6f6d7e5e415a20a5448d17d24229bdd65b", "packages/opencode/test/server/session-diff-scoped.test.ts": "20ef80b92ad872573b371540575f028be8f1ad3c9f34d72f814b621e14e7a59e", "packages/opencode/test/server/sse-tick-telemetry.test.ts": "95738379df27d2da236f968a3d197cf27bcce17e8ec8ce1d288d4d2c1184d8ee", + "packages/opencode/test/server/stdout-channel.test.ts": "812080bb29d09008dacf29741e8f6f06b4ac9fe4623e6992a046313597c3dd1c", "packages/opencode/test/server/summary-diff-wire.test.ts": "080236ce0a7985195a8f385ae65311d63dc18826439a9729c7c87ce4f55efd55", "packages/opencode/test/server/tcp-keepalive.test.ts": "e5c26de10fe44fd6485e0f75f667b2662f69896135f014b0b86772a6ca48fff5", "packages/opencode/test/server/workspace-routing.test.ts": "2574731ac379c540f450edc15f8750ac5360e8c33b4a0dad7c61e8eb686137bb", @@ -455,7 +458,7 @@ "packages/opencode/test/session/business-record.test.ts": "7857094479408bcfd6ea8d9f5b425c6384bcf8490f930674bc1c203e82782d75", "packages/opencode/test/session/instruction.test.ts": "06e1b371a08c7d07ed7688b997eb43ca9957ccd07936f601797d7f04a2bf0ab7", "packages/opencode/test/session/llm-native-recorded.test.ts": "7139b58569af0172862af521e8f8d7a78132f40f06dcceb4baf8ca3a2f07d3bd", - "packages/opencode/test/session/message-v2.test.ts": "3a45b7b884a33ee48daf533ac84bf5c0b34d01845b8c1c4cc7e68de88b063ed1", + "packages/opencode/test/session/message-v2.test.ts": "90fbd916cea08ddb1de066dccf2677490b547afc5805aa36e55683b28fbb079f", "packages/opencode/test/session/mutation.test.ts": "ccb82b6858ac097d2af09a94497d05f6a0ff843b928a69e763fdb510905a10cd", "packages/opencode/test/session/processor-effect.test.ts": "51ebe1cb9b7b0e1d249472367491a1306b5add24ca8b04d5dc15b2b2fa1f1b56", "packages/opencode/test/session/prompt.test.ts": "e3d0748edb833640ef284857ae725e4b974843480d4128f56239e3fd1e6d481f", @@ -521,13 +524,16 @@ "packages/session-ui/src/context/data.tsx": "7b840b5bf6929445d21da2cbd8e8006316c6950a09d559ea77e8c397e728cd99", "packages/session-ui/src/pierre/worker.ts": "7f210f931777956567eaeea15f2f5478befc7874a64a4b685504c59c66503fee", "packages/session-ui/src/util/clipboard.ts": "c37ba53914714ed04135e5a254e8ea90186f097d7470fa0873a83de82f3fef2d", - "packages/ui/src/amicode/amico-presence.css": "b3f345b607e318dcfbefcdc677fe21cc7d387b9946b0f9d625b0a842fe7e31b9", - "packages/ui/src/amicode/amico-presence.stories.tsx": "6012506c946a18460f8a6105c5860a050e47e7708818b0408b516370f50b7094", + "packages/ui/src/amicode/activity-dot.tsx": "fc3c9e620cdd204e930f0d53a0a44456e0c886679174c91f0efbf9707daa7bc6", + "packages/ui/src/amicode/activity.test.ts": "1674ca5138780242767b0eb42fc444a9b8ce7868ac119117dd1487b7209180b2", + "packages/ui/src/amicode/activity.ts": "a2c9b4fe27175a400ea0bcfeb433dfcb572cd793766bf0fd232c741feef5cfbf", + "packages/ui/src/amicode/amico-presence.css": "1effe22b91a512c46ba0b4f4231da4b7665fc00c2f3bd8e1e9e76c6b7532e44c", + "packages/ui/src/amicode/amico-presence.stories.tsx": "e5d95248b32f2aa2a3879c3695721d6bdca77d90f3229ce83d42e030631763bb", "packages/ui/src/amicode/amico-presence.test.ts": "c7ea8c840004d06e231a7368b3c10e11b7dd7efcbcaca4867b0f30167bd2e2bb", "packages/ui/src/amicode/amico-presence.ts": "b4708117445d3fa5cf9be8c9b2f51bfb1f6b01a76e2fac114cde93107a075e26", "packages/ui/src/amicode/amico-wave.stories.tsx": "fed064c5202bd772308e2c6165c9d63182661fe6ce590c75cac1fd0e9deadf94", "packages/ui/src/amicode/amico-wave.tsx": "478cd8b19a87679016d9dbb0aa494ba7d1f1ef67b3da1d09fb35d28e33de9017", - "packages/ui/src/amicode/amicode.css": "a7b8e410dad9ee66190cc31d4a4782efa44e8f759d89d701c7525e67002b98c8", + "packages/ui/src/amicode/amicode.css": "5ac35d2f3dd9d64f904e5da89ee361bc8f81a319308bd2686fcc71f2d175a561", "packages/ui/src/amicode/approval-bridge.test.ts": "5b5e5a41c827b7a3cdaf455dbf488cfa7b8d339f46e64f5a35a0ba9226eb0ebf", "packages/ui/src/amicode/approval-bridge.ts": "ceaa6024916794ece1bc80a004b79c36406d2bc512f82e003c25d919c9050e48", "packages/ui/src/amicode/approval-card.tsx": "f55bd13bfded569020ad0ce0d385da3018aee8e833ec573cb45447114658a11b", @@ -544,10 +550,10 @@ "packages/ui/src/amicode/bridge.ts": "e7b93a15060a0cb1ab0be2b367f73e926d74b990a8af917a9966b451ee303b5b", "packages/ui/src/amicode/card.stories.tsx": "b1591abb4af426b0eb08588ea1585336a392d755b5d308cb31f17cb65acf5a3e", "packages/ui/src/amicode/card.tsx": "1f462017d9113082bb2e802e3d812b25cf5ee9b1bd848559e0533de4d382517f", - "packages/ui/src/amicode/connection-icon.tsx": "2b36c05209a3b5091c6407d59add58fb51ec34724ae6411af85c3dcc797a9987", + "packages/ui/src/amicode/connection-icon.tsx": "f0ffda2ebae57a2945a60cd278b5aa3986273b0cabe97ed46f417c037d167879", "packages/ui/src/amicode/connection-picker.tsx": "73293d1e159dab94a6d1600844fa1e47810ce0558bda6ba4e4209f7e368e3aff", "packages/ui/src/amicode/connections-paths.test.ts": "07c86e8e04700cdbd55bff8db342a8400d85114d76bc73fee8205e9162953f2a", - "packages/ui/src/amicode/connections-tab.tsx": "06489a47bbd6d482ba4d2dc2cf4e9e8e9c648be774f78cd76e2abc87451116e5", + "packages/ui/src/amicode/connections-tab.tsx": "da11957bee28ff988427f9001be81716254bea218057d6f1ff5e7a2fce374446", "packages/ui/src/amicode/connections.stories.tsx": "fda54a41c4b46f5cab5278278f92c01d1fea70610f7b8641fa5855be6bd9d486", "packages/ui/src/amicode/connections.test.ts": "a718b1b698178087fdac5294c1661ca2eb200491e2a076465a09ab52c70b8910", "packages/ui/src/amicode/connections.ts": "89b6c99e991e1aa594768a6555f7f555782dd615c21132e6a688155431cc0dfd", @@ -590,7 +596,7 @@ "packages/ui/src/amicode/run-plot.ts": "b4bc50f279cb864f7720e56ba69b993c7a4e599a71047162173b1b93a63598ac", "packages/ui/src/amicode/run-series.test.ts": "2e7aec7cdf7eb056efbe52d180ff316482e3010e2442611daaf4bda444c82705", "packages/ui/src/amicode/run-series.ts": "c94496068ae05f4600b9dd9fab4247b678dae7aaba31ef48e4389b0e7fefc52c", - "packages/ui/src/amicode/run-window.tsx": "e8343faa72bf6e7545f48e47d2576cd781f038b3ccb448e25130a52df17df5f0", + "packages/ui/src/amicode/run-window.tsx": "60c71ddaf9161ceaeeba10c1838003731a288dc6d85473d2f8d17e34c771c289", "packages/ui/src/amicode/shell-row.test.ts": "48ec6f0786edf81f163e350904bc2a93b1a55375b8115e688237ce8c2f1a7e64", "packages/ui/src/amicode/shell-row.ts": "b39dc05d2b77ba6d44456248782b31f6219c891d56700203186a65ccb48319ad", "packages/ui/src/amicode/solver-switch.test.ts": "c9cc10d657d7adf0c388e56cb6058affed5a255bdeb9b8f2fea5c02f4daff1fe", @@ -608,7 +614,7 @@ "packages/ui/src/amicode/thinking.ts": "ce2529285621620df168eaaa845cd2957b4fe5e61729fdfa736a8702ccf059b7", "packages/ui/src/amicode/ui-bridge.ts": "352f862a7a29245b635257485c377e6ac240e32a9def21173365177fb544a93f", "packages/ui/src/amicode/upload.ts": "9a3a59541ba056a5069f5145cc10bbcc8d44caeb7cfce7a59d97415de2e4a149", - "packages/ui/src/amicode/vaults-tab.tsx": "9e93b7424f0d885250cf999a115b1801d5973f3fdb9095a5c29d74e7093af7e6", + "packages/ui/src/amicode/vaults-tab.tsx": "28be62b5776501c6ef283f2905913ab033977c1661b479339877869dea8cad46", "packages/ui/src/amicode/vaults.test.ts": "24826e6b8b083b0a7478e469f3d4fd7319c973da281cb569e3d885d83d3d46d4", "packages/ui/src/amicode/vaults.ts": "6250b08a8d6493bd42c5407bfcb581a300757b273a587247e3666ddbe25c00af", "packages/ui/src/amicode/wave-geometry.test.ts": "3a89a89310b8c9ce15b402ced6dec83d691bc4ccf50448f2a89e4c0ff1c80cc7", @@ -627,6 +633,7 @@ "packages/ui/src/amicode/widget-tokens.test.ts": "426064638b322a421f794bedf5dbf41ad75fc30b3da6e2d02dcf6ed2f85d5f45", "packages/ui/src/amicode/widget-tokens.ts": "397edcfa18882b2b6b6abef0a8783d72323f793e974d0bd440ca240a10b2f737", "packages/ui/src/components/amico-spinner.tsx": "75114d38aac924a37fee563e35375ebfd5e96cf3771690d01ad484f91df1c563", + "packages/ui/src/components/amicode-activity.tsx": "2924852f0dc23fe3c9b0c5962fbbd6218532d7f5d8bfd4f4ef1e4aa31b6d07dc", "packages/ui/src/components/amicode-approval-bridge.tsx": "ec853afaf3f7bad097532e4887d9d125e88326945a47229fbb0831670c7b2fad", "packages/ui/src/components/amicode-ask-bridge.tsx": "2ddd8ad2663d965e6c42f11cde28bc516e9e881c60dcc7e85443f8bea6de92ef", "packages/ui/src/components/amicode-ask.tsx": "096496c187b7e4def0230c59df2e83757d1e3ebf567d946095c3e81f6ce341f0", @@ -656,6 +663,8 @@ "packages/ui/src/components/amicode-widget-grid.tsx": "df589de093bca703e9fdbbffc6a13020e96ee0ef43e545718f91277ec0b7cd24", "packages/ui/src/components/brain-engine.tsx": "955723ad42c6abfb785313f62277143142f1248987c45da30eadaf28d5137072", "packages/ui/src/components/brain-ref.tsx": "c97a0ac0dad470c9b9e194d6ba94d1f1cfbb774bdbea3f798bece4a2a9968a60", + "packages/ui/src/components/card.css": "0f87ac777181fb1eebbdc9d4f4c658aeff83eb0bd1171b9ef909c64504b11332", + "packages/ui/src/components/card.tsx": "f7cc63c3a3ba8a2f31e06584fedcf42b9f2bf69c04aa1c830ed2d6a7dc6ef837", "packages/ui/src/components/context-menu.css": "7c701902c852f205a178ded4fe8c6181ba43cb4d1c42c6ad9a39ae368738aa1a", "packages/ui/src/components/context-menu.stories.tsx": "0542961bd9db8e191e122b901519452217a410ea5339e8d3ee09a73258ba59a9", "packages/ui/src/components/context-tree-data.tsx": "ca261e7a5eeed09130af14bb755fc2258833d2ac9efd995418cb32927de05d86", @@ -725,7 +734,8 @@ "packages/app/src/components/prompt-input/slash-popover.tsx": "a1800173edebcd419802796470f7270acaf0ef689a72f1b81a1cedfd8968337d", "packages/app/src/components/prompt-input/submit-stream-gap.test.ts": "351f0f5a8cf7aff55c859cb82fbca388ef848831256b80f74ee52ab9cf5d07c6", "packages/app/src/components/prompt-input/submit.ts": "cdb01cf2f2485fbbdb7ddc77dcdea99197d8c03bd302b8fe032bee8c15f525c3", - "packages/app/src/components/session/context-warning-banner.tsx": "f5fab4d7a9536238b70d64488fc30d44f6a4948fdcffd910a9666f4b6c296019", + "packages/app/src/components/server/server-row.tsx": "caf3179cf0b34b00fcab6ed57a324ff1f90f571f604216c49164dc54bd9f12ab", + "packages/app/src/components/session/context-warning-banner.tsx": "c4ceb3f9589ebd21cc66e21cef209552fc5fcff6cd825da5069c2259c8d33e50", "packages/app/src/components/session/index.ts": "f0d58fa3a336639566ec51a10b692649707f91a7b780c0b5c4dcf18642d030e8", "packages/app/src/components/session/panel-menu.tsx": "42f323046b7375ae158023a51506038eb15f2e1545c407f45acd47446a8ef3e0", "packages/app/src/components/session/pdf-canvas-view.tsx": "591bac93a2e1e10a1b42404a29bcc5222ebbc5faf734c80556fbca35c90551dd", @@ -761,7 +771,7 @@ "packages/app/src/components/settings-v2/developer-tools-rebuild-flags.ts": "561a75fa456b832d4af6f782c7ecf5269ce768fc2adc59c15a79197a2dde84c0", "packages/app/src/components/settings-v2/developer-tools-request-state.test.ts": "29711b3bc17fddbb8d046e104bc78e775a9ec7c5aa0ee2e181fbcd8b2b5e2135", "packages/app/src/components/settings-v2/developer-tools-request-state.ts": "e9678ed32e7c2562b18143f39a51c0a94dbf0a0884d056653c6c77e4cd07a9bd", - "packages/app/src/components/settings-v2/developer-tools.tsx": "0e3a739a1ed3cb6311f93174080a3bce71219cee9bcaccd0719d3bf9e6932988", + "packages/app/src/components/settings-v2/developer-tools.tsx": "351b2696211fc67e31e1b7265c809de01c54312fb90c0eef50f95896a07684b2", "packages/app/src/components/settings-v2/dialog-settings-v2.tsx": "a1e1fb7eea7bbad7708b97a721b54a4897c8cb6f582b71d6bb7c8ca7f44930db", "packages/app/src/components/settings-v2/general.tsx": "2abf6c9c7b4b9bf020ed224dbc7fff4574db47711956fc08e1b8e84e781d395a", "packages/app/src/components/settings-v2/permission-scope-relocation.test.ts": "39539c4fc4b7433f08b913100f48a7fa75d6ab47615ba697aa9ae8eee09d316b", @@ -780,6 +790,7 @@ "packages/app/src/context/global-sync/types.ts": "da1408b5665534588a0f437972730b810b0d1271a98bb8d0c442f3d4625bbf7f", "packages/app/src/pages/home/home-projects-view.tsx": "074f1cdd7926db9574164824666cd63f1f5bd0f8e8dfb65453f6fe8f2dca0ec8", "packages/app/src/pages/home/home-sessions-view.tsx": "5b73b18e4349a628a15e09a3810ecf2319bde222e18fe8de5d08373ac91fb37c", + "packages/app/src/pages/home/legacy-home.tsx": "43c48bfadf63c56660c8ae4dce15ef2526e87aca36b375f863510dd76e64000e", "packages/app/src/pages/layout/helpers.test.ts": "3a77cfe018ce2867cccded2c726f556e53a9895a77baa944a4878714b9b2b59e", "packages/app/src/pages/layout/helpers.ts": "b9b9bd551833390d9dcb7e2bc56de77abdef770d7d786f732930ed2bb6b8f4d6", "packages/app/src/pages/layout/notification-toasts.test.ts": "6a95bd3dccb03be894b5d2adb4bc1f7531a9ec704e4d0eae1eba4ec89bbc9846", @@ -789,10 +800,10 @@ "packages/app/src/pages/layout/session-list-chip.tsx": "62373670362fd78e944753b2839820411b5c67dea369dec6a39c5d03df827b16", "packages/app/src/pages/layout/session-list-chip.wiring.test.tsx": "3f19399ea11aabbd6c11624ebc0597301e05cfc033da543c8231a21839880997", "packages/app/src/pages/layout/session-tab-avatar.tsx": "89e83e239d513f91b31f16473be531eaf82768cefe637ea5f10d752cea4ef887", - "packages/app/src/pages/layout/session-tab-status.test.ts": "d6e62365948450c0acda628bc5d03233e5e6ead69649c2d2fb7e20c906007e74", - "packages/app/src/pages/layout/session-tab-status.tsx": "0960d24e581e5cdd38d1bea5e745039542e5ab5268f5540cf8fa87d84717922b", - "packages/app/src/pages/layout/sidebar-items.tsx": "daf940fc66f34e5f83410a8580f7bb1790bedc599ab4d64fcda2301537b24865", - "packages/app/src/pages/layout/sidebar-workspace.tsx": "a0f8e3fbd16d09e783db2a7a09c686d3aa993436d882425d3436a59ec4adf94b", + "packages/app/src/pages/layout/session-tab-status.test.ts": "4f123d40f8cc817d82476daf0b79355783fc101ce8384efbed3896b9f8cbe3eb", + "packages/app/src/pages/layout/session-tab-status.tsx": "61bca75aee87050878a03a9455329478a380193afb52208d2f0000509a08b308", + "packages/app/src/pages/layout/sidebar-items.tsx": "a3e62d5b1fd9ee9f021d466c058c640cf43553a7ad9b69f810a4c12b6f9e46c4", + "packages/app/src/pages/layout/sidebar-workspace.tsx": "19a9daf1b8bf2a4d7b3ec1439a3cc4ce2472f71d93f8d0b0f9e27727397eca45", "packages/app/src/pages/layout/worktree-auto-rename.test.ts": "fb6fac363b8bee1225bbcff8098019c02f19b095b5cd96c29f7e673acb1e4e89", "packages/app/src/pages/layout/worktree-auto-rename.ts": "2ef3e506b96b972cb55799a89aa54ca6453fc31c80bc022aa16db6ecfe9cdced", "packages/app/src/pages/new-session/new-session-draft-controller.ts": "3607771a22b6855afd0b0d666de662c9070a2dcd56ae96ba51d89c9e11018e81", @@ -854,7 +865,7 @@ "packages/opencode/src/server/amicode/vault-browser.ts": "8a8252fb0b46583c75e9475d7c89e68c092f5255b21476f3c3d0b9d379ea2d48", "packages/opencode/src/server/amicode/vaults.ts": "e48c90c64de27abe24a510f188def6b56297d9bb1fa1ae08cbcc94888d42044a", "packages/opencode/src/server/amicode/warrants.ts": "13ef47a676245d577617f6e5af2c8a2beb3102346d2dbb43076159f3f43c01a7", - "packages/opencode/src/server/amicode/widget-frame-html.ts": "3df10eeeccbb81d2b163195ceaa1d5abc24e90506471ff6d6b2a5fc40e52db52", + "packages/opencode/src/server/amicode/widget-frame-html.ts": "c5395910b66c921a4b6f3f3fd214d19f98808dbe41754ecd541553494884acdf", "packages/opencode/src/server/amicode/widget-manifest.ts": "5753daf16ef4c1e74c97d4a515b30d123f7afbfee29bb07381c6f10ecc14cebf", "packages/opencode/src/server/amicode/widget-runtime.ts": "a5fe95eba46df87c4b4c54bc07bb91587b73e88eb90db889bc87358ece4b3f27", "packages/opencode/src/server/amicode/widgets.ts": "4315aa80eca9e0941d1198d253fd9ad37f57b7600ef3d7f116a6b8a9ee73095b", @@ -895,7 +906,7 @@ "packages/session-ui/src/v2/components/preview-nav-state.test.ts": "cec09a8b3c08ab16581d3d5b6ff704584b3c87d81c25e8af20f6f00272f3593f", "packages/session-ui/src/v2/components/preview-nav-state.ts": "ccaeb94d1ab39271f5dcd49c935c8fc7b54d4ffbd66e1352e4d797c9205553fc", "packages/session-ui/src/v2/components/preview-view-state.ts": "4ec961c7720417166dcccd45f0d4702afec664dfe7f4d0dd8668bb9b1d8af5e6", - "packages/session-ui/src/v2/components/session-review-file-preview-v2.tsx": "fc06f46ed3c92c8066744da1f6ac97db7d8b7d2aeec5ef776d743dd93b317936", + "packages/session-ui/src/v2/components/session-review-file-preview-v2.tsx": "d4936b1512a334468c48d3c0f496e9b266927af20bdfbc84172c14139f78fc4f", "packages/session-ui/src/v2/components/session-review-v2.css": "bb306f226fda8f8ba6cf0ae706843ba9f2b48f3a3446433515e8a8dd1f9dc626", "packages/session-ui/src/v2/components/session-review-v2.tsx": "4151286efb6e0e148246ee3eebae24a2e5d4eac2603fd5ea8546d0839a694161", "packages/session-ui/src/v2/components/shiki-highlight-decorations.test.ts": "f50e8156b708f3e0ddbc509abf71751778a74923dac9d7e65385b178f6346718", @@ -966,7 +977,7 @@ "packages/app/src/pages/session/v2/accumulate-diffs.test.ts": "289ef80e26c9e85d3121d3705cefd467d147d4872410fce7309d9b7a382020fa", "packages/app/src/pages/session/v2/accumulate-diffs.ts": "a4d5ee94b31db8def04d4b1e5efc909a8c5e0e14368af0e37414e98d4d819936", "packages/app/src/pages/session/v2/adversarial-ui-e2e.test.ts": "0767c40885b0dec6a55ec25600061b76ef06aeddc9f10b20ad256de407acb9f0", - "packages/app/src/pages/session/v2/lineage-ledger-panel.css": "d928c053a4da2aded4df8bd0d32e8133e46c17a3592b0ccdb4811a68e4a523e3", + "packages/app/src/pages/session/v2/lineage-ledger-panel.css": "04ec96e285912075ca83c412f2d699500c9756b8414b9c87a028546bb662fc8f", "packages/app/src/pages/session/v2/lineage-ledger-panel.test.tsx": "f621617f3ee0bb27923a0337049f54cbfc37cb2a7895a98ae79521a0b633e955", "packages/app/src/pages/session/v2/lineage-ledger-panel.tsx": "f572b8aca1e413d9b4a2394e6ba0ea63b2eecbd7f21b79907cede82ff2ae4d1b", "packages/app/src/pages/session/v2/lineage-ledger-view.test.ts": "0b3ac457706875994ff5abf94704201a1f8b45c63d8241d5ecaa5b21ca9bcc50", @@ -992,7 +1003,7 @@ "packages/opencode/src/server/routes/instance/httpapi/handlers/event.ts": "88c7bae32fa01ab213e95cb4e4891fd3ccb961782e80a416e321c5daf90fb487", "packages/opencode/src/server/routes/instance/httpapi/handlers/experimental.ts": "69ca3dd48d95157fc822e1f76eb42ac873df50f22616b85194619ca658613867", "packages/opencode/src/server/routes/instance/httpapi/handlers/file.ts": "10bcb79b117beebee04184fb48c1ad789e782e2f7ae4b0c68603edc00f03aee9", - "packages/opencode/src/server/routes/instance/httpapi/handlers/global.ts": "a31e4d0abe4f76e667167c5017aca5559b53938db63bdc1d656a154e1aaf5fea", + "packages/opencode/src/server/routes/instance/httpapi/handlers/global.ts": "040554475b6ba22ad666dfeaca2576658854c46cd18efe3b2d68959f9eaaed80", "packages/opencode/src/server/routes/instance/httpapi/handlers/mcp.ts": "7da08d58765cdf2b6ce4648fc70de371402949f5bb7b75696f674d43f2d5365b", "packages/opencode/src/server/routes/instance/httpapi/handlers/provider.ts": "8baf16cad0992c5351b61b0c0fb27903bb25b17e1b25fc7c5d77f807c24413a6", "packages/opencode/src/server/routes/instance/httpapi/handlers/session.ts": "b37ff4136c4aea85b23083bf441f03e09820e3e4cdd95e4118ca570d8435b94f", @@ -1013,11 +1024,11 @@ "packages/ui/src/v2/components/text-shimmer-v2.tsx" ], "exceptions": [], - "extracted_at": "2026-10-23T13:24:11.640Z", + "extracted_at": "2026-10-25T15:07:55.879Z", "per_package": { "packages/app": { "A": 254, - "M": 162, + "M": 164, "D": 0 }, "packages/core": { @@ -1027,11 +1038,11 @@ }, "packages/llm": { "A": 1, - "M": 5, + "M": 7, "D": 0 }, "packages/opencode": { - "A": 98, + "A": 99, "M": 100, "D": 0 }, @@ -1056,13 +1067,13 @@ "D": 0 }, "packages/ui": { - "A": 144, - "M": 64, + "A": 148, + "M": 66, "D": 0 } }, "counts": { - "overlay_total": 991, + "overlay_total": 1002, "deletions": 7, "server_coupled": 0 }, @@ -1111,7 +1122,9 @@ "packages/core/test/session-runner.test.ts": "M", "packages/core/test/tool-question.test.ts": "M", "packages/llm/src/cache-policy.ts": "M", + "packages/llm/src/provider-error.ts": "M", "packages/llm/test/cache-policy.test.ts": "M", + "packages/llm/test/provider-error.test.ts": "M", "packages/opencode/script/build.ts": "M", "packages/opencode/script/httpapi-exercise.ts": "M", "packages/opencode/test/amicode-release-workflow.test.ts": "A", @@ -1507,6 +1520,7 @@ "packages/opencode/test/server/session-diff-missing-patch.test.ts": "M", "packages/opencode/test/server/session-diff-scoped.test.ts": "A", "packages/opencode/test/server/sse-tick-telemetry.test.ts": "A", + "packages/opencode/test/server/stdout-channel.test.ts": "A", "packages/opencode/test/server/summary-diff-wire.test.ts": "A", "packages/opencode/test/server/tcp-keepalive.test.ts": "A", "packages/opencode/test/server/workspace-routing.test.ts": "M", @@ -1580,6 +1594,9 @@ "packages/session-ui/src/context/data.tsx": "M", "packages/session-ui/src/pierre/worker.ts": "M", "packages/session-ui/src/util/clipboard.ts": "A", + "packages/ui/src/amicode/activity-dot.tsx": "A", + "packages/ui/src/amicode/activity.test.ts": "A", + "packages/ui/src/amicode/activity.ts": "A", "packages/ui/src/amicode/amico-presence.css": "A", "packages/ui/src/amicode/amico-presence.stories.tsx": "A", "packages/ui/src/amicode/amico-presence.test.ts": "A", @@ -1686,6 +1703,7 @@ "packages/ui/src/amicode/widget-tokens.test.ts": "A", "packages/ui/src/amicode/widget-tokens.ts": "A", "packages/ui/src/components/amico-spinner.tsx": "A", + "packages/ui/src/components/amicode-activity.tsx": "A", "packages/ui/src/components/amicode-approval-bridge.tsx": "A", "packages/ui/src/components/amicode-ask-bridge.tsx": "A", "packages/ui/src/components/amicode-ask.tsx": "A", @@ -1715,6 +1733,8 @@ "packages/ui/src/components/amicode-widget-grid.tsx": "A", "packages/ui/src/components/brain-engine.tsx": "A", "packages/ui/src/components/brain-ref.tsx": "A", + "packages/ui/src/components/card.css": "M", + "packages/ui/src/components/card.tsx": "M", "packages/ui/src/components/context-menu.css": "M", "packages/ui/src/components/context-menu.stories.tsx": "M", "packages/ui/src/components/context-tree-data.tsx": "A", @@ -1784,6 +1804,7 @@ "packages/app/src/components/prompt-input/slash-popover.tsx": "M", "packages/app/src/components/prompt-input/submit-stream-gap.test.ts": "A", "packages/app/src/components/prompt-input/submit.ts": "M", + "packages/app/src/components/server/server-row.tsx": "M", "packages/app/src/components/session/context-warning-banner.tsx": "A", "packages/app/src/components/session/index.ts": "M", "packages/app/src/components/session/panel-menu.tsx": "A", @@ -1839,6 +1860,7 @@ "packages/app/src/context/global-sync/types.ts": "M", "packages/app/src/pages/home/home-projects-view.tsx": "M", "packages/app/src/pages/home/home-sessions-view.tsx": "M", + "packages/app/src/pages/home/legacy-home.tsx": "M", "packages/app/src/pages/layout/helpers.test.ts": "M", "packages/app/src/pages/layout/helpers.ts": "M", "packages/app/src/pages/layout/notification-toasts.test.ts": "A", diff --git a/packages/app-bundle/overlay/packages/app/CONTEXT.md b/packages/app-bundle/overlay/packages/app/CONTEXT.md index bd0ba7993..0afaa05c9 100644 --- a/packages/app-bundle/overlay/packages/app/CONTEXT.md +++ b/packages/app-bundle/overlay/packages/app/CONTEXT.md @@ -106,6 +106,34 @@ It persists until onboarding is complete and then disappears; it never gates the _Avoid_: Onboarding modal, wizard (the wizard is the conversational interview; the nudge only surfaces its state), setup wall +### Activity vocabulary + +**Activity**: +The one semantic state set every status surface speaks — session dots (tab strip, +sessions dropdown, sidebar, home), run status (run window, run view), health dots +(connection, MCP, LSP, server, vault), build status, and status banners. Five roles, +each a `--activity-*` token in `src/design-polish.css` (solid dot colour plus a `-soft` +fill) aliasing the theme's v2 state tokens so light and dark move together: + +| Role | Colour | Means | +| --- | --- | --- | +| `running` | blue | in progress — working, solving, pending, validating | +| `attention` | amber | waiting on you — permission, question, needs auth, expired, drift, stalled | +| `success` | green | done-unread, healthy, finished | +| `error` | red | failed, unreachable | +| `idle` | grey | done-seen, aborted, stopped, disabled | + +A session's tab status ranks **error > attention > running > done-unread > idle**. Running +dots share one reduced-motion-aware pulse (`.amc-activity-pulse`). Colour is never the +only signal: every status dot carries an accessible label or sits beside text that +names the state. + +**Yellow never encodes a state.** Yellow is brand and selection only (the `--accent` +family). Amico's presence — the thought-rail harmonic dot, the working lane, the +thinking wave, the mark — is brand, not status, and keeps the accent. +_Avoid_: yellow "running", gold/amber warning edges from the theme as an attention +colour, the agent identity tint on a status spinner, raw hex status colours + ## Relationships - The **Landing** is a **Chat**; the window never opens on anything else. diff --git a/packages/app-bundle/overlay/packages/app/src/components/connection-banner.tsx b/packages/app-bundle/overlay/packages/app/src/components/connection-banner.tsx index be54a988d..8be6b59fe 100644 --- a/packages/app-bundle/overlay/packages/app/src/components/connection-banner.tsx +++ b/packages/app-bundle/overlay/packages/app/src/components/connection-banner.tsx @@ -1,6 +1,7 @@ import { Show, createEffect, createSignal, onCleanup } from "solid-js" import { useLanguage } from "@/context/language" import { useServerSDK } from "@/context/server-sdk" +import { ActivityDot } from "@opencode-ai/ui/amicode-activity" // Amicode webview: a dead server (e.g. an opencode:build restart) used to read // as an endless "thinking" wave — the event loop retries silently every 250ms. @@ -64,12 +65,18 @@ export function ConnectionBanner() { "border-radius": "var(--radius-full)", "font-size": "12px", "font-weight": 600, - border: "1px solid var(--v2-border-border-base, #3c3c3c)", - background: "var(--v2-background-bg-layer-01, #1e1e1e)", - "box-shadow": "0 8px 24px rgba(0, 0, 0, 0.35)", - color: down() ? "var(--v2-state-fg-warning, #d29922)" : "var(--v2-state-fg-success, #3fb950)", + display: "flex", + "align-items": "center", + gap: "var(--space-2)", + border: "1px solid var(--v2-border-border-base)", + background: "var(--v2-background-bg-layer-01)", + "box-shadow": "var(--elev-float)", + color: "var(--v2-text-text-base)", }} > + {/* activity dot: attention while the link is down, success once back. + The words carry the state; the dot is the at-a-glance colour. */} + {down() ? language.t("app.server.connectionLost") : language.t("app.server.reconnected")} diff --git a/packages/app-bundle/overlay/packages/app/src/components/dialog-new-project.tsx b/packages/app-bundle/overlay/packages/app/src/components/dialog-new-project.tsx index e75364a8a..a7d761544 100644 --- a/packages/app-bundle/overlay/packages/app/src/components/dialog-new-project.tsx +++ b/packages/app-bundle/overlay/packages/app/src/components/dialog-new-project.tsx @@ -76,7 +76,7 @@ export function DialogNewProject(props: {