Skip to content
Closed
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
41 changes: 41 additions & 0 deletions docs/evidence/retired-surface-copy-2026-08-10.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Retired surfaces claimed a live Agent Desk — copy corrected to the current offer

Date: 2026-08-10
Scope: `src/worker.js` (retired app/api responses, health surface label) and `public/index.html` (developer REPLACE comments in the "Who signs it" section).

## Observed (live)

`https://app.tinystudio.io/` returned, alongside its intentional 410:

> The old TinyStudio app has been retired. TinyStudio.io now runs the **self-serve Agent Desk** from the main domain.

`https://api.tinystudio.io/` returned the same claim in its retired JSON message, and `https://tinystudio.io/health` reported `"surface":"agent-desk"`.

The Agent Desk is not the current offer. The legacy surface's own page frames itself as retired ("TinyStudio — the retired Agent Desk"), offer.md states "The earlier self-serve Agent Desk (one-shot Pipeline Brief) is demoted and is not the current offer," and the current offer is the Website Appraisal — the free leak audit of high-ticket service homepages. Two public surfaces and the health endpoint were therefore publishing product truth that contradicted the rest of the site, and both a human visiting the retired domain and an AI reading the retired JSON would walk away believing the Agent Desk is live.

Separately, the served homepage source (`public/index.html`, live since the leak-audit launch, commit 50d64c7) shipped two developer REPLACE comments inside the "Who signs it" section — the site's strongest credibility claim — including an empty `<p class="sig-note">` meant to carry "one true credential line". The paragraph was hidden by CSS (`display:none`) but the unfinished instruction was visible in the money page's source to any viewer.

## Fix

- Retired app page and retired API message now name the current offer: "TinyStudio.io now runs the Website Appraisal — the free leak audit of high-ticket service homepages." The retired framing and the 410s are unchanged.
- `/health` reports `"surface":"website-appraisal"`.
- The two REPLACE comments and the empty `sig-note` paragraph are removed from the homepage; the dead `.sig-note:empty` CSS rule is removed with them. No credential was invented — the removal only deletes placeholders.

## Guard (so it cannot return)

- `scripts/check-site.mjs`: every served marketing page (homepage, audit, agents, pricing, specimen, brief-requested) is rejected if it ships a `<!-- REPLACE:` comment.
- `scripts/test-agent-worker.mjs`: the retired app surface (410 HTML), the retired api surface (410 JSON), and `/health` are each asserted to name the Website Appraisal and never contain "Agent Desk", and the health `surface` field is pinned to `website-appraisal`.

## Verify

```bash
npm test # check + headings + sitemap + worker + ui, all suites green
```

Live re-check after deploy:

```bash
curl -s https://app.tinystudio.io/ | grep -c "Agent Desk" # 0
curl -s https://api.tinystudio.io/ | grep -c "Agent Desk" # 0
curl -s https://tinystudio.io/health # "surface":"website-appraisal"
Comment on lines +35 to +40

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Assert HTTP status codes in the live re-check.

The grep commands only inspect response bodies. A 404, 500, or proxy error page without Agent Desk can produce the same 0 result. Require 410 for the retired app and API, and 200 for /health.

Proposed verification update
- curl -s https://app.tinystudio.io/ | grep -c "Agent Desk"   # 0
- curl -s https://api.tinystudio.io/ | grep -c "Agent Desk"   # 0
- curl -s https://tinystudio.io/health                        # "surface":"website-appraisal"
+ app_status="$(curl -sS -o /tmp/tinystudio-app.html -w '%{http_code}' https://app.tinystudio.io/)"
+ test "$app_status" = "410" && ! grep -Fiq "Agent Desk" /tmp/tinystudio-app.html
+ api_status="$(curl -sS -o /tmp/tinystudio-api.json -w '%{http_code}' https://api.tinystudio.io/)"
+ test "$api_status" = "410" && ! grep -Fiq "Agent Desk" /tmp/tinystudio-api.json
+ health_status="$(curl -sS -o /tmp/tinystudio-health.json -w '%{http_code}' https://tinystudio.io/health)"
+ test "$health_status" = "200" && grep -Eq '"surface"[[:space:]]*:[[:space:]]*"website-appraisal"' /tmp/tinystudio-health.json
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Live re-check after deploy:
```bash
curl -s https://app.tinystudio.io/ | grep -c "Agent Desk" # 0
curl -s https://api.tinystudio.io/ | grep -c "Agent Desk" # 0
curl -s https://tinystudio.io/health # "surface":"website-appraisal"
Live re-check after deploy:
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/evidence/retired-surface-copy-2026-08-10.md` around lines 35 - 40,
Update the “Live re-check after deploy” verification commands to assert HTTP
status codes as well as checking response bodies: require 410 responses from the
retired app and API endpoints, and require a 200 response from the /health
endpoint while preserving the existing surface check.

```
1 change: 0 additions & 1 deletion public/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,6 @@
.sig-body h2{font-family:'Fraunces',serif;font-weight:200;font-size:40px;letter-spacing:-.028em;
line-height:1.1;margin-top:14px}
.sig-body p{margin-top:20px;font-size:16.5px;line-height:1.75;color:var(--soft);max-width:58ch}
.sig-note:empty{display:none}
@media (max-width:760px){.signer{grid-template-columns:1fr;gap:26px}}

/* extracted from inline style attributes — CSP style-src 'self' blocks those */
Expand Down
3 changes: 0 additions & 3 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -200,15 +200,12 @@ <h3>Does TinyStudio publish client work</h3>

<section class="signer" id="who-signs">
<div class="sig-portrait" aria-hidden="true">
<!-- REPLACE: 480x480 photo at public/nish.jpg, then swap this div for:
<img src="nish.jpg" alt="Nish, who runs the desk" width="120" height="120"> -->
<span>NISH</span>
</div>
<div class="sig-body">
<span class="sc xi19">Who signs it</span>
<h2 class="xi20">One name goes on every audit. That is the ceiling, and it is deliberate.</h2>
<p>A department of specialists does the reading. Seven of them, each with a single job, a fixed set of inputs and a checklist it must satisfy — working from your own pages and numbers and the competitors you actually have, never a template for your sector. It could run a hundred audits at once.<br><br>It will not. Nothing leaves this desk without my name on it, and I do not sign what I have not read line by line. That is the whole reason the number is six a month, and the reason it will not move.</p>
<p class="sig-note"><!-- REPLACE: one true credential line — years in the work, or a background line you are happy to stand behind. Delete this comment when done. --></p>
</div>
</section>

Expand Down
20 changes: 20 additions & 0 deletions scripts/check-site.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -1083,6 +1083,26 @@ for (const [pageName, pageHtml] of ownedPages) {
}
}

// ---- Developer REPLACE comments (dogfood: public/index.html shipped two of
// them inside the "Who signs it" section — an empty sig-note paragraph and a
// photo swap note — so the live homepage source carried an unfinished
// credential line next to its strongest credibility claim). A served marketing
// page must never ship a "REPLACE:" instruction meant for the editor's eye.
const placeholderScanPages = [
["homepage", siteHome],
["audit page", siteAudit],
["desk page", read("public/agents.html")],
["pricing page", read("public/pricing.html")],
["specimen page", read("public/specimen.html")],
["brief-requested page", read("public/brief-requested.html")]
];

for (const [pageName, pageHtml] of placeholderScanPages) {
if (pageHtml.includes("<!-- REPLACE:")) {
failures.push(`Owned page must not ship a developer REPLACE comment: ${pageName}`);
}
}

// ---- Retired Agent Desk index guard (dogfood: Google still presents the
// retired self-serve "TinyStudio Agent Desk" title/snippet for tinystudio.io)
// ----------------------------------------------------------------------------
Expand Down
31 changes: 30 additions & 1 deletion scripts/test-agent-worker.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class FakeStatement {

async all() {
this.db.calls.push({ method: "all", sql: this.sql, values: this.values });
return { results: [] };
return { results: [{ name: "agent_runs" }, { name: "agent_usage_limits" }] };
}
}

Expand Down Expand Up @@ -1045,3 +1045,32 @@ test("worker does not serve unlisted asset-like paths outside the public allow-l
const res = await worker.fetch(new Request("https://tinystudio.io/not-listed.js"), env);
assert.equal(res.status, 404);
});

test("retired app surface names the current offer, not a live Agent Desk", async () => {
const env = {};
const res = await worker.fetch(new Request("https://app.tinystudio.io/"), env);
assert.equal(res.status, 410);
const html = await res.text();
assert.match(html, /retired/i, "app surface must keep its retired framing");
assert.match(html, /Website Appraisal/, "app surface must name the current offer");
assert.doesNotMatch(html, /Agent Desk/i, "app surface must not revive the retired product name");
});

test("retired api surface names the current offer, not a live Agent Desk", async () => {
const env = {};
const res = await worker.fetch(new Request("https://api.tinystudio.io/"), env);
assert.equal(res.status, 410);
const body = await res.json();
assert.equal(body.status, "retired");
assert.match(body.message, /Website Appraisal/, "api surface must name the current offer");
assert.doesNotMatch(body.message, /Agent Desk/i, "api surface must not revive the retired product name");
});

test("worker health endpoint reports the current offer surface, not the retired Agent Desk", async () => {
const env = { DB: new FakeDB(), AI: {} };
const res = await worker.fetch(new Request("https://tinystudio.io/health"), env);
assert.equal(res.status, 200);
const body = await res.json();
assert.equal(body.surface, "website-appraisal");
assert.ok(body.ok, "health endpoint must report healthy with configured AI and DB");
});
6 changes: 3 additions & 3 deletions src/worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -1228,7 +1228,7 @@ async function healthResponse(env) {
{
ok,
service: "tinystudio-io-public",
surface: "agent-desk",
surface: "website-appraisal",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Align the health label with the checks it performs

When the legacy Agent Desk AI binding or either agent_* table is unavailable while the Website Appraisal homepage and signup flow remain functional, this endpoint now identifies the affected surface as website-appraisal and returns 503 because ok is still gated on those Agent Desk dependencies. Monitoring keyed by surface will therefore report the current appraisal as unhealthy for an unrelated legacy failure; either retain an Agent Desk-specific label or revise the checks to cover the Website Appraisal's actual assets and signup dependencies.

Useful? React with 👍 / 👎.

ai: checks.ai ? "configured" : "missing",
db: checks.db ? "configured" : "missing",
checks,
Expand Down Expand Up @@ -1266,7 +1266,7 @@ function retiredAppResponse() {
<body>
<main>
<h1>TinyStudio app retired.</h1>
<p>The old TinyStudio app has been retired. TinyStudio.io now runs the self-serve Agent Desk from the main domain.</p>
<p>The old TinyStudio app has been retired. TinyStudio.io now runs the Website Appraisal — the free leak audit of high-ticket service homepages.</p>
<a href="https://tinystudio.io/">Go to TinyStudio.io</a>
</main>
</body>
Expand All @@ -1288,7 +1288,7 @@ function retiredApiResponse() {
{
ok: false,
status: "retired",
message: "The old TinyStudio API has been retired. TinyStudio.io now runs the self-serve Agent Desk from the main domain.",
message: "The old TinyStudio API has been retired. TinyStudio.io now runs the Website Appraisal — the free leak audit of high-ticket service homepages.",
publicSite: "https://tinystudio.io/"
},
{
Expand Down
Loading