forked from Mike/freno-dev
Merge branch 'NOOK-336' — NOOK-336 Muse on the agents page
This commit is contained in:
@@ -9,7 +9,7 @@ Primary source: `~/Code/the-nook/docs/marketing-strategy.md`.
|
|||||||
## The sentence
|
## The sentence
|
||||||
|
|
||||||
> **Your Mac and your agents, under control.** The Nook puts your whole coding-agent
|
> **Your Mac and your agents, under control.** The Nook puts your whole coding-agent
|
||||||
> fleet in the notch — twelve agents, local or over SSH — so you see what is running,
|
> fleet in the notch — thirteen agents, local or over SSH — so you see what is running,
|
||||||
> unblock it in one tap, and keep the machine from overheating while it works.
|
> unblock it in one tap, and keep the machine from overheating while it works.
|
||||||
|
|
||||||
## The wedge
|
## The wedge
|
||||||
@@ -50,7 +50,7 @@ pages, marketing copy, comparison tables, meta descriptions, emails, FAQs, all o
|
|||||||
|
|
||||||
### 2. A claim requires a test to exist
|
### 2. A claim requires a test to exist
|
||||||
|
|
||||||
Copy that says "12 agents" or "no data leaves the device" must have a test backing it.
|
Copy that says "13 agents" or "no data leaves the device" must have a test backing it.
|
||||||
If a claim cannot be pointed at code or a test, it does not go in copy.
|
If a claim cannot be pointed at code or a test, it does not go in copy.
|
||||||
|
|
||||||
### 3. Honest privacy scoping
|
### 3. Honest privacy scoping
|
||||||
@@ -77,7 +77,7 @@ nothing posts itself.
|
|||||||
|
|
||||||
| Claim | Backing |
|
| Claim | Backing |
|
||||||
|---|---|
|
|---|---|
|
||||||
| Twelve hooked agents, one glance | `AgentSpec.all` — claude, codex, opencode, pi, omp, hermes, openclaw, zai, gemini, cline, qwen, deepseek |
|
| Thirteen hooked agents, one glance | `AgentSpec.all` — claude, codex, opencode, pi, omp, muse, hermes, openclaw, zai, gemini, cline, qwen, deepseek |
|
||||||
| Remote agents over SSH | `hook/setup.go` remote install path; `NOOK_HOST` TCP transport |
|
| Remote agents over SSH | `hook/setup.go` remote install path; `NOOK_HOST` TCP transport |
|
||||||
| Permission gate answered from a card | awaitPolicyTable + bridge directive path (`hook/normalize.go`, `serialize.go`) |
|
| Permission gate answered from a card | awaitPolicyTable + bridge directive path (`hook/normalize.go`, `serialize.go`) |
|
||||||
| Fan / thermal / charge control | `helper/` (privileged helper, SMC, no kext) |
|
| Fan / thermal / charge control | `helper/` (privileged helper, SMC, no kext) |
|
||||||
@@ -87,7 +87,7 @@ nothing posts itself.
|
|||||||
|
|
||||||
## Voice
|
## Voice
|
||||||
|
|
||||||
- Short, concrete, no hype adjectives. Numbers over adjectives ("twelve agents",
|
- Short, concrete, no hype adjectives. Numbers over adjectives ("thirteen agents",
|
||||||
"one tap", "$10 once").
|
"one tap", "$10 once").
|
||||||
- The notch/island is the product's home; agents are the product's point.
|
- The notch/island is the product's home; agents are the product's point.
|
||||||
- Never apologize for being a utility. The utility is the point.
|
- Never apologize for being a utility. The utility is the point.
|
||||||
|
|||||||
54
src/routes/nook/agents.test.ts
Normal file
54
src/routes/nook/agents.test.ts
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
/**
|
||||||
|
* Regression test for the /agents roster (NOOK-336).
|
||||||
|
*
|
||||||
|
* The page mirrors the app's registry, `AgentSpec.all` in
|
||||||
|
* the-nook/Sources/NookCore/Agents/AgentRegistry.swift. When Muse joined
|
||||||
|
* the registry in 0.10.0 the page kept twelve entries and kept saying
|
||||||
|
* "twelve", so a shipped agent was missing from the one page that lists
|
||||||
|
* them. The registry lives in another repo, so the expected roster is
|
||||||
|
* restated here; when an agent is added there, add it here and on the page.
|
||||||
|
*
|
||||||
|
* STATIC SOURCE AUDIT, the same pattern as the downloads regressions.
|
||||||
|
*/
|
||||||
|
import { describe, it, expect } from "bun:test";
|
||||||
|
import { readFileSync } from "node:fs";
|
||||||
|
import { join } from "node:path";
|
||||||
|
|
||||||
|
const SOURCE = readFileSync(join(import.meta.dir, "agents.tsx"), "utf8");
|
||||||
|
|
||||||
|
/** AgentSpec.all display names, in registry order. */
|
||||||
|
const REGISTRY = [
|
||||||
|
"Claude Code",
|
||||||
|
"Codex",
|
||||||
|
"OpenCode",
|
||||||
|
"Pi",
|
||||||
|
"Oh My Pi",
|
||||||
|
"Muse",
|
||||||
|
"Hermes",
|
||||||
|
"OpenClaw",
|
||||||
|
"Z.ai (ZCode)",
|
||||||
|
"Gemini CLI",
|
||||||
|
"Cline",
|
||||||
|
"Qwen Code",
|
||||||
|
"DeepSeek"
|
||||||
|
];
|
||||||
|
|
||||||
|
const NUMBER_WORDS = ["twelve", "thirteen", "fourteen", "fifteen"];
|
||||||
|
|
||||||
|
const entries = [...SOURCE.matchAll(/^\s{4}name: "([^"]+)",$/gm)].map((m) => m[1]);
|
||||||
|
|
||||||
|
describe("Nook /agents roster (NOOK-336)", () => {
|
||||||
|
it("lists every registry agent, in registry order", () => {
|
||||||
|
expect(entries).toEqual(REGISTRY);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("states the same count everywhere it names one", () => {
|
||||||
|
const word = NUMBER_WORDS[entries.length - 12];
|
||||||
|
for (const other of NUMBER_WORDS.filter((w) => w !== word)) {
|
||||||
|
expect(SOURCE.toLowerCase()).not.toContain(other);
|
||||||
|
}
|
||||||
|
expect(SOURCE).toContain(`all ${word}`);
|
||||||
|
expect(SOURCE).toContain(`The ${entries.length} agents`);
|
||||||
|
expect(SOURCE).toContain(`watches ${word} coding agents`);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -105,6 +105,29 @@ const AGENTS: AgentEntry[] = [
|
|||||||
gating:
|
gating:
|
||||||
"Full — honors the agent's own approval tiers, per-tool policies included"
|
"Full — honors the agent's own approval tiers, per-tool policies included"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Muse",
|
||||||
|
wiring:
|
||||||
|
"Plugin at ~/.nook/plugins/muse, installed, approved and enabled through Muse's own plugins CLI; each hook calls the shared hook binary. This Mac only — remote hosts skip it",
|
||||||
|
events: [
|
||||||
|
"SessionStart",
|
||||||
|
"SessionEnd",
|
||||||
|
"UserPromptSubmit",
|
||||||
|
"PreToolUse",
|
||||||
|
"PermissionRequest",
|
||||||
|
"PostToolUse",
|
||||||
|
"PostToolUseFailure",
|
||||||
|
"Stop",
|
||||||
|
"StopFailure",
|
||||||
|
"Notification",
|
||||||
|
"PreCompact",
|
||||||
|
"PostCompact",
|
||||||
|
"SubagentStart",
|
||||||
|
"SubagentStop"
|
||||||
|
],
|
||||||
|
gating:
|
||||||
|
"Full — permission prompts can be allowed or denied from a card, and every tool call under Verify"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "Hermes",
|
name: "Hermes",
|
||||||
wiring:
|
wiring:
|
||||||
@@ -240,8 +263,8 @@ export default function NookAgentsPage() {
|
|||||||
<EdgeCacheHeaders maxAge={300} />
|
<EdgeCacheHeaders maxAge={300} />
|
||||||
<PageHead
|
<PageHead
|
||||||
title="Supported agents"
|
title="Supported agents"
|
||||||
description="Every coding agent The Nook supports — all twelve, with each hook's exact event coverage and what you can do from a card: watch sessions live, answer permission prompts, unblock work."
|
description="Every coding agent The Nook supports — all thirteen, with each hook's exact event coverage and what you can do from a card: watch sessions live, answer permission prompts, unblock work."
|
||||||
ogTitle="The 12 agents The Nook supports, and what each hook sees"
|
ogTitle="The 13 agents The Nook supports, and what each hook sees"
|
||||||
/>
|
/>
|
||||||
<SubdomainHeader />
|
<SubdomainHeader />
|
||||||
<main class="min-h-screen px-[8vw] py-[8vh]">
|
<main class="min-h-screen px-[8vw] py-[8vh]">
|
||||||
@@ -249,7 +272,7 @@ export default function NookAgentsPage() {
|
|||||||
Supported agents
|
Supported agents
|
||||||
</h1>
|
</h1>
|
||||||
<p class="text-subtext0 mb-2 max-w-2xl text-lg">
|
<p class="text-subtext0 mb-2 max-w-2xl text-lg">
|
||||||
The Nook watches twelve coding agents in one place — your menu bar and
|
The Nook watches thirteen coding agents in one place — your menu bar and
|
||||||
notch show every session that is running, thinking, or blocked, and a
|
notch show every session that is running, thinking, or blocked, and a
|
||||||
card answers permission prompts without leaving your keyboard.
|
card answers permission prompts without leaving your keyboard.
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
Reference in New Issue
Block a user