Repair stale port references in the code, chat, and icon surfaces.

54c2acc6a0ed · AtlantisPleb · · parent 9fae69f072ef

Repair stale port references in the code, chat, and icon surfaces.

Three test modules failed on references the Sarah -> OpenAgents port left
behind. Sorting them by who was actually wrong:

The router was wrong. TRANSPARENCY-001 binds the public forge web UI to the
GitHub-identical URLs (`/<owner>/<repo>`, `/<owner>/<repo>/commit/:sha`,
`/<owner>/<repo>/blob/:ref/*path`) with the owning account as a LITERAL scope
segment, so no other two-segment path on the domain is shadowed. The port had
regressed those to `/code/:owner/:repo` with a wildcard owner, and the blob
route dropped `:ref` entirely — `CodeBlobLive.mount/3` matches on `"ref"`, so
that route could not serve a single request. Restored the literal-owner scope
and the three routes the LiveViews and the invariant both expect.

The app was wrong about its icons. `priv/static/favicon.ico` was the blank
152-byte Phoenix placeholder, the PNG variants were missing, and the root
layout linked no icon at all. Shipped the real icon set and the four `<link>`
tags, and listed the new files in `static_paths/0`.

The dead Phoenix scaffold was wrong. `PageController`, `PageHTML`, and
`page_html/home.html.heex` were unrouted leftovers — `/` is `HomeLive` ("The
Agent Forge") — and the scaffold page carried nine hand-written `<svg>`
elements, exactly the second unmanaged icon set the sourcing test exists to
catch. Deleted.

The tests were wrong where they pointed at Sarah's tree: the chat template
path, and the icon-sourcing glob plus its exemption list. Sarah's landing-grid
exemption is dropped rather than repointed — the OpenAgents home renders no
background SVG, and Sarah's landing template is deliberately not this app's.
Each edit says why in place.

The test provider was over-renamed: `"You are Sarah."` is a quote from the
installed persona document, not a module name, and the mechanical rename
turned it into `"You are OpenAgents."` so the persona assertion could never
hold. Restored the quote.

21 of the 22 pass. The last one, `#client-error [aria-label="Dismiss notice"]`,
needs a one-line change to the flash component in
`lib/openagents_web/components/core_components.ex`, which is being rewritten
concurrently for the DaisyUI removal — left for that owner.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0149rBWy7br1Z7bbz9NrQhEr
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>

Deploy story

What this commit did to the running system — joined from the forge receipt chain, the part a commit page elsewhere cannot show.

Not deployed through the forge lane

No push, promotion, build, or deploy receipt references this commit (receipts are scanned over a bounded recent window). Changes shipped by full node replacement carry their proof in the release gate receipt instead.

Changed files

  • modified lib/openagents_web.ex
  • modified lib/openagents_web/components/layouts/root.html.heex
  • deleted lib/openagents_web/controllers/page_controller.ex
  • deleted lib/openagents_web/controllers/page_html.ex
  • deleted lib/openagents_web/controllers/page_html/home.html.heex
  • modified lib/openagents_web/router.ex
  • added priv/static/apple-touch-icon.png
  • added priv/static/favicon-16x16.png
  • added priv/static/favicon-32x32.png
  • modified priv/static/favicon.ico
  • modified test/openagents_web/icon_affordances_test.exs
  • modified test/openagents_web/live/chat_live_test.exs
  • modified test/support/providers/test.ex

Diff

13 files changed, +67 -232

lib/openagents_web.ex modified +3 -1

@@ -17,7 +17,9 @@ defmodule OpenAgentsWeb do

17 17
  those modules here.
18 18
  """
19 19
20
  def static_paths, do: ~w(assets fonts images favicon.ico robots.txt)
20
  def static_paths,
21
    do:
22
      ~w(assets fonts images favicon.ico favicon-32x32.png favicon-16x16.png apple-touch-icon.png robots.txt)
21 23
22 24
  def router do
23 25
    quote do
lib/openagents_web/components/layouts/root.html.heex modified +4

@@ -4,6 +4,10 @@

4 4
    <meta charset="utf-8" />
5 5
    <meta name="viewport" content="width=device-width, initial-scale=1" />
6 6
    <meta name="csrf-token" content={get_csrf_token()} />
7
    <link rel="icon" href={~p"/favicon.ico"} sizes="any" />
8
    <link rel="icon" href={~p"/favicon-32x32.png"} type="image/png" sizes="32x32" />
9
    <link rel="icon" href={~p"/favicon-16x16.png"} type="image/png" sizes="16x16" />
10
    <link rel="apple-touch-icon" href={~p"/apple-touch-icon.png"} sizes="180x180" />
7 11
    <.live_title default="OpenAgents" suffix=" · OpenAgents" phx-no-format>{assigns[:page_title]}</.live_title>
8 12
    <link phx-track-static rel="stylesheet" href={~p"/assets/css/app.css"} />
9 13
    <script defer phx-track-static type="text/javascript" src={~p"/assets/js/app.js"}>
lib/openagents_web/controllers/page_controller.ex deleted -7

@@ -1,7 +0,0 @@

1
defmodule OpenAgentsWeb.PageController do
2
  use OpenAgentsWeb, :controller
3
4
  def home(conn, _params) do
5
    render(conn, :home)
6
  end
7
end
lib/openagents_web/controllers/page_html.ex deleted -10

@@ -1,10 +0,0 @@

1
defmodule OpenAgentsWeb.PageHTML do
2
  @moduledoc """
3
  This module contains pages rendered by PageController.
4
5
  See the `page_html` directory for all templates available.
6
  """
7
  use OpenAgentsWeb, :html
8
9
  embed_templates "page_html/*"
10
end
lib/openagents_web/controllers/page_html/home.html.heex deleted -199

@@ -1,199 +0,0 @@

1
<Layouts.flash_group flash={@flash} />
2
<div class="left-[40rem] fixed inset-y-0 right-0 z-0 hidden lg:block xl:left-[50rem]">
3
  <svg
4
    viewBox="0 0 1480 957"
5
    fill="none"
6
    aria-hidden="true"
7
    class="absolute inset-0 h-full w-full"
8
    preserveAspectRatio="xMinYMid slice"
9
  >
10
    <path fill="#EE7868" d="M0 0h1480v957H0z" />
11
    <path
12
      d="M137.542 466.27c-582.851-48.41-988.806-82.127-1608.412 658.2l67.39 810 3083.15-256.51L1535.94-49.622l-98.36 8.183C1269.29 281.468 734.115 515.799 146.47 467.012l-8.928-.742Z"
13
      fill="#FF9F92"
14
    />
15
    <path
16
      d="M371.028 528.664C-169.369 304.988-545.754 149.198-1361.45 665.565l-182.58 792.025 3014.73 694.98 389.42-1689.25-96.18-22.171C1505.28 697.438 924.153 757.586 379.305 532.09l-8.277-3.426Z"
17
      fill="#FA8372"
18
    />
19
    <path
20
      d="M359.326 571.714C-104.765 215.795-428.003-32.102-1349.55 255.554l-282.3 1224.596 3047.04 722.01 312.24-1354.467C1411.25 1028.3 834.355 935.995 366.435 577.166l-7.109-5.452Z"
21
      fill="#E96856"
22
      fill-opacity=".6"
23
    />
24
    <path
25
      d="M1593.87 1236.88c-352.15 92.63-885.498-145.85-1244.602-613.557l-5.455-7.105C-12.347 152.31-260.41-170.8-1225-131.458l-368.63 1599.048 3057.19 704.76 130.31-935.47Z"
26
      fill="#C42652"
27
      fill-opacity=".2"
28
    />
29
    <path
30
      d="M1411.91 1526.93c-363.79 15.71-834.312-330.6-1085.883-863.909l-3.822-8.102C72.704 125.95-101.074-242.476-1052.01-408.907l-699.85 1484.267 2837.75 1338.01 326.02-886.44Z"
31
      fill="#A41C42"
32
      fill-opacity=".2"
33
    />
34
    <path
35
      d="M1116.26 1863.69c-355.457-78.98-720.318-535.27-825.287-1115.521l-1.594-8.816C185.286 163.833 112.786-237.016-762.678-643.898L-1822.83 608.665 571.922 2635.55l544.338-771.86Z"
36
      fill="#A41C42"
37
      fill-opacity=".2"
38
    />
39
  </svg>
40
</div>
41
<div class="px-4 py-10 sm:px-6 sm:py-28 lg:px-8 xl:px-28 xl:py-32">
42
  <div class="mx-auto max-w-xl lg:mx-0">
43
    <svg viewBox="0 0 71 48" class="h-12" aria-hidden="true">
44
      <path
45
        d="m26.371 33.477-.552-.1c-3.92-.729-6.397-3.1-7.57-6.829-.733-2.324.597-4.035 3.035-4.148 1.995-.092 3.362 1.055 4.57 2.39 1.557 1.72 2.984 3.558 4.514 5.305 2.202 2.515 4.797 4.134 8.347 3.634 3.183-.448 5.958-1.725 8.371-3.828.363-.316.761-.592 1.144-.886l-.241-.284c-2.027.63-4.093.841-6.205.735-3.195-.16-6.24-.828-8.964-2.582-2.486-1.601-4.319-3.746-5.19-6.611-.704-2.315.736-3.934 3.135-3.6.948.133 1.746.56 2.463 1.165.583.493 1.143 1.015 1.738 1.493 2.8 2.25 6.712 2.375 10.265-.068-5.842-.026-9.817-3.24-13.308-7.313-1.366-1.594-2.7-3.216-4.095-4.785-2.698-3.036-5.692-5.71-9.79-6.623C12.8-.623 7.745.14 2.893 2.361 1.926 2.804.997 3.319 0 4.149c.494 0 .763.006 1.032 0 2.446-.064 4.28 1.023 5.602 3.024.962 1.457 1.415 3.104 1.761 4.798.513 2.515.247 5.078.544 7.605.761 6.494 4.08 11.026 10.26 13.346 2.267.852 4.591 1.135 7.172.555ZM10.751 3.852c-.976.246-1.756-.148-2.56-.962 1.377-.343 2.592-.476 3.897-.528-.107.848-.607 1.306-1.336 1.49Zm32.002 37.924c-.085-.626-.62-.901-1.04-1.228-1.857-1.446-4.03-1.958-6.333-2-1.375-.026-2.735-.128-4.031-.61-.595-.22-1.26-.505-1.244-1.272.015-.78.693-1 1.31-1.184.505-.15 1.026-.247 1.6-.382-1.46-.936-2.886-1.065-4.787-.3-2.993 1.202-5.943 1.06-8.926-.017-1.684-.608-3.179-1.563-4.735-2.408l-.043.03a2.96 2.96 0 0 0 .04-.029c-.038-.117-.107-.12-.197-.054l.122.107c1.29 2.115 3.034 3.817 5.004 5.271 3.793 2.8 7.936 4.471 12.784 3.73A66.714 66.714 0 0 1 37 40.877c1.98-.16 3.866.398 5.753.899Zm-9.14-30.345c-.105-.076-.206-.266-.42-.069 1.745 2.36 3.985 4.098 6.683 5.193 4.354 1.767 8.773 2.07 13.293.51 3.51-1.21 6.033-.028 7.343 3.38.19-3.955-2.137-6.837-5.843-7.401-2.084-.318-4.01.373-5.962.94-5.434 1.575-10.485.798-15.094-2.553Zm27.085 15.425c.708.059 1.416.123 2.124.185-1.6-1.405-3.55-1.517-5.523-1.404-3.003.17-5.167 1.903-7.14 3.972-1.739 1.824-3.31 3.87-5.903 4.604.043.078.054.117.066.117.35.005.699.021 1.047.005 3.768-.17 7.317-.965 10.14-3.7.89-.86 1.685-1.817 2.544-2.71.716-.746 1.584-1.159 2.645-1.07Zm-8.753-4.67c-2.812.246-5.254 1.409-7.548 2.943-1.766 1.18-3.654 1.738-5.776 1.37-.374-.066-.75-.114-1.124-.17l-.013.156c.135.07.265.151.405.207.354.14.702.308 1.07.395 4.083.971 7.992.474 11.516-1.803 2.221-1.435 4.521-1.707 7.013-1.336.252.038.503.083.756.107.234.022.479.255.795.003-2.179-1.574-4.526-2.096-7.094-1.872Zm-10.049-9.544c1.475.051 2.943-.142 4.486-1.059-.452.04-.643.04-.827.076-2.126.424-4.033-.04-5.733-1.383-.623-.493-1.257-.974-1.889-1.457-2.503-1.914-5.374-2.555-8.514-2.5.05.154.054.26.108.315 3.417 3.455 7.371 5.836 12.369 6.008Zm24.727 17.731c-2.114-2.097-4.952-2.367-7.578-.537 1.738.078 3.043.632 4.101 1.728.374.388.763.768 1.182 1.106 1.6 1.29 4.311 1.352 5.896.155-1.861-.726-1.861-.726-3.601-2.452Zm-21.058 16.06c-1.858-3.46-4.981-4.24-8.59-4.008a9.667 9.667 0 0 1 2.977 1.39c.84.586 1.547 1.311 2.243 2.055 1.38 1.473 3.534 2.376 4.962 2.07-.656-.412-1.238-.848-1.592-1.507Zm17.29-19.32c0-.023.001-.045.003-.068l-.006.006.006-.006-.036-.004.021.018.012.053Zm-20 14.744a7.61 7.61 0 0 0-.072-.041.127.127 0 0 0 .015.043c.005.008.038 0 .058-.002Zm-.072-.041-.008-.034-.008.01.008-.01-.022-.006.005.026.024.014Z"
46
        fill="#FD4F00"
47
      />
48
    </svg>
49
    <div class="mt-10 flex justify-between items-center">
50
      <h1 class="flex items-center text-sm font-semibold leading-6">
51
        Phoenix Framework
52
        <small class="badge badge-warning badge-sm ml-3">
53
          v{Application.spec(:phoenix, :vsn)}
54
        </small>
55
      </h1>
56
      <Layouts.theme_toggle />
57
    </div>
58
59
    <p class="text-[2rem] mt-4 font-semibold leading-10 tracking-tighter text-balance">
60
      Peace of mind from prototype to production.
61
    </p>
62
    <p class="mt-4 leading-7 text-base-content/70">
63
      Build rich, interactive web applications quickly, with less code and fewer moving parts. Join our growing community of developers using Phoenix to craft APIs, HTML5 apps and more, for fun or at scale.
64
    </p>
65
    <div class="flex">
66
      <div class="w-full sm:w-auto">
67
        <div class="mt-10 grid grid-cols-1 gap-x-6 gap-y-4 sm:grid-cols-3">
68
          <a
69
            href="https://phoenix.hexdocs.pm/overview.html"
70
            class="group relative rounded-box px-6 py-4 text-sm font-semibold leading-6 sm:py-6"
71
          >
72
            <span class="absolute inset-0 rounded-box bg-base-200 transition group-hover:bg-base-300 sm:group-hover:scale-105"></span>
73
            <span class="relative flex items-center gap-4 sm:flex-col">
74
              <svg viewBox="0 0 24 24" fill="none" aria-hidden="true" class="h-6 w-6">
75
                <path d="m12 4 10-2v18l-10 2V4Z" fill="currentColor" fill-opacity=".15" />
76
                <path
77
                  d="M12 4 2 2v18l10 2m0-18v18m0-18 10-2v18l-10 2"
78
                  stroke="currentColor"
79
                  stroke-width="2"
80
                  stroke-linecap="round"
81
                  stroke-linejoin="round"
82
                />
83
              </svg>
84
              Guides &amp; Docs
85
            </span>
86
          </a>
87
          <a
88
            href="https://github.com/phoenixframework/phoenix"
89
            class="group relative rounded-box px-6 py-4 text-sm font-semibold leading-6 sm:py-6"
90
          >
91
            <span class="absolute inset-0 rounded-box bg-base-200 transition group-hover:bg-base-300 sm:group-hover:scale-105"></span>
92
            <span class="relative flex items-center gap-4 sm:flex-col">
93
              <svg viewBox="0 0 24 24" aria-hidden="true" class="h-6 w-6">
94
                <path
95
                  fill="currentColor"
96
                  fill-rule="evenodd"
97
                  clip-rule="evenodd"
98
                  d="M12 0C5.37 0 0 5.506 0 12.303c0 5.445 3.435 10.043 8.205 11.674.6.107.825-.262.825-.585 0-.292-.015-1.261-.015-2.291C6 21.67 5.22 20.346 4.98 19.654c-.135-.354-.72-1.446-1.23-1.738-.42-.23-1.02-.8-.015-.815.945-.015 1.62.892 1.845 1.261 1.08 1.86 2.805 1.338 3.495 1.015.105-.8.42-1.338.765-1.645-2.67-.308-5.46-1.37-5.46-6.075 0-1.338.465-2.446 1.23-3.307-.12-.308-.54-1.569.12-3.26 0 0 1.005-.323 3.3 1.26.96-.276 1.98-.415 3-.415s2.04.139 3 .416c2.295-1.6 3.3-1.261 3.3-1.261.66 1.691.24 2.952.12 3.26.765.861 1.23 1.953 1.23 3.307 0 4.721-2.805 5.767-5.475 6.075.435.384.81 1.122.81 2.276 0 1.645-.015 2.968-.015 3.383 0 .323.225.707.825.585a12.047 12.047 0 0 0 5.919-4.489A12.536 12.536 0 0 0 24 12.304C24 5.505 18.63 0 12 0Z"
99
                />
100
              </svg>
101
              Source Code
102
            </span>
103
          </a>
104
          <a
105
            href={"https://github.com/phoenixframework/phoenix/blob/v#{Application.spec(:phoenix, :vsn)}/CHANGELOG.md"}
106
            class="group relative rounded-box px-6 py-4 text-sm font-semibold leading-6 sm:py-6"
107
          >
108
            <span class="absolute inset-0 rounded-box bg-base-200 transition group-hover:bg-base-300 sm:group-hover:scale-105"></span>
109
            <span class="relative flex items-center gap-4 sm:flex-col">
110
              <svg viewBox="0 0 24 24" fill="none" aria-hidden="true" class="h-6 w-6">
111
                <path
112
                  d="M12 1v6M12 17v6"
113
                  stroke="currentColor"
114
                  stroke-width="2"
115
                  stroke-linecap="round"
116
                  stroke-linejoin="round"
117
                />
118
                <circle
119
                  cx="12"
120
                  cy="12"
121
                  r="4"
122
                  fill="currentColor"
123
                  fill-opacity=".15"
124
                  stroke="currentColor"
125
                  stroke-width="2"
126
                  stroke-linecap="round"
127
                  stroke-linejoin="round"
128
                />
129
              </svg>
130
              Changelog
131
            </span>
132
          </a>
133
        </div>
134
        <div class="mt-10 grid grid-cols-1 gap-y-4 text-sm leading-6 text-base-content/80 sm:grid-cols-2">
135
          <div>
136
            <a
137
              href="https://elixirforum.com"
138
              class="group -mx-2 -my-0.5 inline-flex items-center gap-3 rounded-lg px-2 py-0.5 hover:bg-base-200 hover:text-base-content"
139
            >
140
              <svg
141
                viewBox="0 0 16 16"
142
                aria-hidden="true"
143
                class="h-4 w-4 fill-base-content/40 group-hover:fill-base-content"
144
              >
145
                <path d="M8 13.833c3.866 0 7-2.873 7-6.416C15 3.873 11.866 1 8 1S1 3.873 1 7.417c0 1.081.292 2.1.808 2.995.606 1.05.806 2.399.086 3.375l-.208.283c-.285.386-.01.905.465.85.852-.098 2.048-.318 3.137-.81a3.717 3.717 0 0 1 1.91-.318c.263.027.53.041.802.041Z" />
146
              </svg>
147
              Discuss on the Elixir Forum
148
            </a>
149
          </div>
150
          <div>
151
            <a
152
              href="https://discord.gg/elixir"
153
              class="group -mx-2 -my-0.5 inline-flex items-center gap-3 rounded-lg px-2 py-0.5 hover:bg-base-200 hover:text-base-content"
154
            >
155
              <svg
156
                viewBox="0 0 16 16"
157
                aria-hidden="true"
158
                class="h-4 w-4 fill-base-content/40 group-hover:fill-base-content"
159
              >
160
                <path d="M13.545 2.995c-1.02-.46-2.114-.8-3.257-.994a.05.05 0 0 0-.052.024c-.141.246-.297.567-.406.82a12.377 12.377 0 0 0-3.658 0 8.238 8.238 0 0 0-.412-.82.052.052 0 0 0-.052-.024 13.315 13.315 0 0 0-3.257.994.046.046 0 0 0-.021.018C.356 6.063-.213 9.036.066 11.973c.001.015.01.029.02.038a13.353 13.353 0 0 0 3.996 1.987.052.052 0 0 0 .056-.018c.308-.414.582-.85.818-1.309a.05.05 0 0 0-.028-.069 8.808 8.808 0 0 1-1.248-.585.05.05 0 0 1-.005-.084c.084-.062.168-.126.248-.191a.05.05 0 0 1 .051-.007c2.619 1.176 5.454 1.176 8.041 0a.05.05 0 0 1 .053.006c.08.065.164.13.248.192a.05.05 0 0 1-.004.084c-.399.23-.813.423-1.249.585a.05.05 0 0 0-.027.07c.24.457.514.893.817 1.307a.051.051 0 0 0 .056.019 13.31 13.31 0 0 0 4.001-1.987.05.05 0 0 0 .021-.037c.334-3.396-.559-6.345-2.365-8.96a.04.04 0 0 0-.021-.02Zm-8.198 7.19c-.789 0-1.438-.712-1.438-1.587 0-.874.637-1.586 1.438-1.586.807 0 1.45.718 1.438 1.586 0 .875-.637 1.587-1.438 1.587Zm5.316 0c-.788 0-1.438-.712-1.438-1.587 0-.874.637-1.586 1.438-1.586.807 0 1.45.718 1.438 1.586 0 .875-.63 1.587-1.438 1.587Z" />
161
              </svg>
162
              Join our Discord server
163
            </a>
164
          </div>
165
          <div>
166
            <a
167
              href="https://elixir-slack.community/"
168
              class="group -mx-2 -my-0.5 inline-flex items-center gap-3 rounded-lg px-2 py-0.5 hover:bg-base-200 hover:text-base-content"
169
            >
170
              <svg
171
                viewBox="0 0 16 16"
172
                aria-hidden="true"
173
                class="h-4 w-4 fill-base-content/40 group-hover:fill-base-content"
174
              >
175
                <path d="M3.361 10.11a1.68 1.68 0 1 1-1.68-1.681h1.68v1.682ZM4.209 10.11a1.68 1.68 0 1 1 3.361 0v4.21a1.68 1.68 0 1 1-3.361 0v-4.21ZM5.89 3.361a1.68 1.68 0 1 1 1.681-1.68v1.68H5.89ZM5.89 4.209a1.68 1.68 0 1 1 0 3.361H1.68a1.68 1.68 0 1 1 0-3.361h4.21ZM12.639 5.89a1.68 1.68 0 1 1 1.68 1.681h-1.68V5.89ZM11.791 5.89a1.68 1.68 0 1 1-3.361 0V1.68a1.68 1.68 0 0 1 3.361 0v4.21ZM10.11 12.639a1.68 1.68 0 1 1-1.681 1.68v-1.68h1.682ZM10.11 11.791a1.68 1.68 0 1 1 0-3.361h4.21a1.68 1.68 0 1 1 0 3.361h-4.21Z" />
176
              </svg>
177
              Join us on Slack
178
            </a>
179
          </div>
180
          <div>
181
            <a
182
              href="https://fly.io/docs/elixir/getting-started/"
183
              class="group -mx-2 -my-0.5 inline-flex items-center gap-3 rounded-lg px-2 py-0.5 hover:bg-base-200 hover:text-base-content"
184
            >
185
              <svg
186
                viewBox="0 0 20 20"
187
                aria-hidden="true"
188
                class="h-4 w-4 fill-base-content/40 group-hover:fill-base-content"
189
              >
190
                <path d="M1 12.5A4.5 4.5 0 005.5 17H15a4 4 0 001.866-7.539 3.504 3.504 0 00-4.504-4.272A4.5 4.5 0 004.06 8.235 4.502 4.502 0 001 12.5z" />
191
              </svg>
192
              Deploy your application
193
            </a>
194
          </div>
195
        </div>
196
      </div>
197
    </div>
198
  </div>
199
</div>
lib/openagents_web/router.ex modified +26 -4

@@ -3,6 +3,9 @@ defmodule OpenAgentsWeb.Router do

3 3
4 4
  import OpenAgentsWeb.UserAuth
5 5
6
  # The account segment public forge URLs live under, mirroring GitHub.
7
  @forge_url_owner Application.compile_env(:openagents, :forge_url_owner, "OpenAgentsInc")
8
6 9
  pipeline :browser do
7 10
    plug :accepts, ["html"]
8 11
    plug :fetch_session

@@ -48,9 +51,6 @@ defmodule OpenAgentsWeb.Router do

48 51
      live "/status", NetworkStatusLive, :index
49 52
      live "/changelog", ChangelogLive, :index
50 53
      live "/leaderboard", LeaderboardLive, :index
51
      live "/code/:owner/:repo", CodeRepoLive, :index
52
      live "/code/:owner/:repo/blob/*path", CodeBlobLive, :index
53
      live "/code/:owner/:repo/commit/:sha", CodeCommitLive, :index
54 54
    end
55 55
56 56
    # `/components/icons` must stay ahead of `/components/:slug` so the literal

@@ -75,6 +75,25 @@ defmodule OpenAgentsWeb.Router do

75 75
    get "/healthz", HealthController, :show
76 76
  end
77 77
78
  # The public forge web UI (TRANSPARENCY-001), addressed exactly the way the
79
  # GitHub URL it replaces is:
80
  # openagents.com/OpenAgentsInc/sarah/blob/main/README.md.
81
  #
82
  # The owner is a LITERAL scope segment, not a `:owner` pattern: a wildcard
83
  # first segment would match every two-segment path on the domain (/dev/ui,
84
  # a future /foo/bar) and shadow it. Scoping to the owning account keeps the
85
  # GitHub-identical URL while touching nothing else.
86
  scope "/#{@forge_url_owner}", OpenAgentsWeb do
87
    pipe_through :browser
88
89
    live_session :public_code,
90
      on_mount: [{OpenAgentsWeb.UserAuth, :mount_current_user}] do
91
      live "/:repo", CodeRepoLive, :index
92
      live "/:repo/commit/:sha", CodeCommitLive, :index
93
      live "/:repo/blob/:ref/*path", CodeBlobLive, :index
94
    end
95
  end
96
78 97
  scope "/", OpenAgentsWeb do
79 98
    pipe_through [:browser, :authenticated]
80 99

@@ -109,7 +128,10 @@ defmodule OpenAgentsWeb.Router do

109 128
    delete "/data", DataController, :delete
110 129
    delete "/data/reset", DataController, :reset
111 130
112
    get "/machines", ComputersController, :index
131
    # The legacy Computers path is a permanent-ish redirect, not a second
132
    # render of the surface: it must drop its query (an OAuth `code=` must
133
    # never survive into the canonical URL).
134
    get "/machines", LegacyMachinesController, :show
113 135
114 136
    get "/memory/export", MemoryExportController, :show
115 137
  end
priv/static/apple-touch-icon.png added

Binary file. Nothing to show as text.

priv/static/favicon-16x16.png added

Binary file. Nothing to show as text.

priv/static/favicon-32x32.png added

Binary file. Nothing to show as text.

priv/static/favicon.ico modified

Binary file. Nothing to show as text.

test/openagents_web/icon_affordances_test.exs modified +24 -9

@@ -67,19 +67,34 @@ defmodule OpenAgentsWeb.IconAffordancesTest do

67 67
    test "no surface hand-writes an svg outside the vendored set" do
68 68
      # Every glyph must come from `priv/icons` through `icon/1`. A pasted
69 69
      # `<svg>` in a template is how a second, unmanaged icon set starts.
70
      # The landing grid is a documented exception: it is a background pattern,
71
      # not an icon, and it has to be a DOM SVG so its stroke can read `--line`
72
      # rather than being baked into an opaque data URI. See DESIGN.md.
73
      grid = "lib/sarah_web/controllers/home_html/show.html.heex"
74
75
      assert File.read!(grid) =~ "landing-grid",
76
             "the inline-SVG exemption for #{grid} is stale; it no longer holds the grid"
70
      #
71
      # Ported from Sarah, where this globbed `lib/sarah_web/**` and carried a
72
      # documented exemption for Sarah's landing template
73
      # (`lib/sarah_web/controllers/home_html/show.html.heex`), whose
74
      # `landing-grid` is a background pattern rather than an icon. That
75
      # exemption is dropped rather than repointed: the OpenAgents home is
76
      # `OpenAgentsWeb.HomeLive` ("The Agent Forge"), it renders no background
77
      # SVG, and Sarah's landing template is deliberately not part of this app.
78
      # If a background pattern is ever added here, re-add the exemption WITH
79
      # the staleness assertion that guarded it.
80
      #
81
      # The exempt files are the ones that IMPLEMENT the vendored set:
82
      # `icons.ex` holds it, and `icon/1` is defined in both `sarah_ui.ex` (which
83
      # matches the `ui.ex` suffix Sarah used) and `core_components.ex`. The
84
      # assertions below fail loudly if either stops being icon plumbing, so the
85
      # exemption cannot silently become a hole.
86
      renderers = ["lib/openagents_web/components/core_components.ex"]
87
88
      for renderer <- renderers do
89
        assert File.read!(renderer) =~ "OpenAgentsWeb.Icons.fetch!",
90
               "the inline-SVG exemption for #{renderer} is stale; it no longer renders the vendored set"
91
      end
77 92
78 93
      offenders =
79
        "lib/sarah_web/**/*.{ex,heex}"
94
        "lib/openagents_web/**/*.{ex,heex}"
80 95
        |> Path.wildcard()
81 96
        |> Enum.reject(&String.ends_with?(&1, ["ui.ex", "icons.ex"]))
82
        |> Enum.reject(&(&1 == grid))
97
        |> Enum.reject(&(&1 in renderers))
83 98
        |> Enum.filter(fn path -> path |> File.read!() |> String.contains?("<svg") end)
84 99
85 100
      assert offenders == [],
test/openagents_web/live/chat_live_test.exs modified +4 -1

@@ -117,7 +117,10 @@ defmodule OpenAgentsWeb.ChatLiveTest do

117 117
  end
118 118
119 119
  test "plain message text is flush with its tags so pre-wrap renders nothing extra" do
120
    template = File.read!("lib/sarah_web/live/chat_live.ex")
120
    # Ported from Sarah: the file this reads was `lib/sarah_web/live/chat_live.ex`
121
    # there. Only the path changed with the re-namespacing — the assertion below
122
    # is unchanged and still guards the same markup.
123
    template = File.read!("lib/openagents_web/live/chat_live.ex")
121 124
122 125
    # `.message-content` is `white-space: pre-wrap`, which is what preserves the
123 126
    # line breaks a person actually typed. Any newline or indentation the
test/support/providers/test.ex modified +6 -1

@@ -54,7 +54,12 @@ defmodule OpenAgents.Providers.Test do

54 54
55 55
      "[inspect-persona]" ->
56 56
        result =
57
          if String.contains?(request.instructions, "You are OpenAgents.") and
57
          # The re-namespacing port rewrote this literal to "You are OpenAgents.",
58
          # but it is not a module name — it is a quote from the installed
59
          # persona document (`priv/sarah/persona/sarah.v1.md`, which still reads
60
          # "You are Sarah. You are an OpenAgent built by OpenAgents."). Asserting
61
          # the shipped persona text is the whole point of this branch.
62
          if String.contains?(request.instructions, "You are Sarah.") and
58 63
               String.contains?(request.instructions, "You are an OpenAgent") and
59 64
               String.contains?(request.instructions, "sarah.role.general_collaborator.v1") do
60 65
            "Sarah persona and role received."

This page updates live while a promote is in flight · changelog