Skip to content
Merged
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
2 changes: 2 additions & 0 deletions .claude/rules/delegation-ladder.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ Pick the lead by how often the session needs Fable-grade judgment — then never
## Principles (all surfaces)

- **Review invariant.** Reviewer ≠ author, and reviewer tier ≥ author tier. When the lead authors an artifact itself, the reviewer is a *parallel* agent at the lead's own tier — a Fable lead gets a parallel Fable reviewer, an Opus lead a parallel Opus reviewer — so the review is independent of the author's context.
- **Finding vs. sign-off.** The reviewer *generates adversarial findings*; the lead *adjudicates* them — judges which are real, directs the fixes, spot-checks the result. Adjudication is the sign-off, and it always happens at the lead's tier by construction. "Who reviews" is therefore a question about defect-hunting, never about who approves.
- **Tiered review escalation (TJ, 2026-07-19).** Default reviewer for contained implementation is one tier above the author (Opus for Sonnet work under a Fable lead). Work touching a repo's **sacred invariants** (e.g. mail semantics, auth/security-critical paths, the licensing boundary) escalates to a reviewer at the lead's own tier **plus** an independent different-vendor pass (e.g. Codex). Rationale, earned empirically (Helpthread substrate run, 2026-07-19): every reviewer tier caught real defects, but *different* models caught disjoint ones — a Codex pass found a TOCTOU that both a Sonnet author and an Opus review missed, and a Sonnet author found a spec bug a Fable-tier review had passed. Diversity catches what tier alone doesn't; spend tier where invariants are sacred, spend diversity everywhere it's cheap.
Comment on lines +34 to +35

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

Require durable evidence of human review and sign-off.

These bullets define model-review roles but do not require human approval or preservation of the reviewer findings in git history. For sacred-invariant work such as licensing-boundary changes, add an explicit PR checklist/artifact recording the lead adjudication, different-vendor pass, and human approval.

🤖 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 @.claude/rules/delegation-ladder.md around lines 34 - 35, Add an explicit
requirement to the review process documentation for durable evidence of human
review and sign-off. For sacred-invariant changes, require a preserved PR
checklist or artifact recording the lead’s adjudication, the independent
different-vendor review findings, and human approval, alongside the existing
bullets on reviewer roles and tiered escalation.

Source: Learnings

@coderabbitai coderabbitai Bot Jul 19, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Clarify the lead-authored exception.

“Reviewer one tier above the author” is impossible when the lead authors the artifact and already occupies the highest tier. Explicitly reference the same-tier parallel-review rule from Line 33 to prevent conflicting reviewer assignments.

Proposed clarification
-- Default reviewer for contained implementation is one tier above the author
+- Default reviewer for contained implementation is one tier above the author;
+  when the lead authors the artifact, use the same-tier parallel reviewer
+  defined by the review invariant above.
📝 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
- **Tiered review escalation (TJ, 2026-07-19).** Default reviewer for contained implementation is one tier above the author (Opus for Sonnet work under a Fable lead). Work touching a repo's **sacred invariants** (e.g. mail semantics, auth/security-critical paths, the licensing boundary) escalates to a reviewer at the lead's own tier **plus** an independent different-vendor pass (e.g. Codex). Rationale, earned empirically (Helpthread substrate run, 2026-07-19): every reviewer tier caught real defects, but *different* models caught disjoint ones — a Codex pass found a TOCTOU that both a Sonnet author and an Opus review missed, and a Sonnet author found a spec bug a Fable-tier review had passed. Diversity catches what tier alone doesn't; spend tier where invariants are sacred, spend diversity everywhere it's cheap.
- **Tiered review escalation (maintainer, 2026-07-19).** Default reviewer for contained implementation is one tier above the author; when the lead authors the artifact, use the same-tier parallel reviewer defined by the review invariant above. Work touching a repo's **sacred invariants** (e.g. mail semantics, auth/security-critical paths, the licensing boundary) escalates to a reviewer at the lead's own tier **plus** an independent different-vendor pass (e.g. Codex). Rationale, earned empirically (Helpthread substrate run, 2026-07-19): every reviewer tier caught real defects, but *different* models caught disjoint ones — a Codex pass found a TOCTOU that both a Sonnet author and an Opus review missed, and a Sonnet author found a spec bug a Fable-tier review had passed. Diversity catches what tier alone doesn't; spend tier where invariants are sacred, spend diversity everywhere it's cheap.
🤖 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 @.claude/rules/delegation-ladder.md at line 35, Update the “Tiered review
escalation” guidance to explicitly handle lead-authored artifacts: when the lead
is the author and already occupies the highest tier, apply the same-tier
parallel-review rule defined on Line 33 instead of assigning a higher-tier
reviewer. Preserve the existing one-tier-above-author rule for non-lead authors
and the sacred-invariant escalation requirements.

- **Verification vs. review litmus.** If the checklist can be written in advance, it's verification — Haiku runs it. If the reviewer has to generate the checklist, it's review — it goes up-ladder.
- **Don't-delegate floor.** If writing a self-contained spec costs more than doing the task, the lead does it directly.
- **On failure.** One retry with a corrected spec. On a second failure, escalate one tier or the lead absorbs the task. Never re-run a failing agent on an unchanged spec.
Expand Down
2 changes: 2 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ Adapted in our own words from Andrej Karpathy's observations on LLM coding pitfa

**Agents** are human support staff. **Assistants** are AI actors. Never conflate them — in schema, code, docs, or prose.

**Modules** are the extension artifacts operators install (free or paid; TJ, 2026-07-18). Never "plugins" — that word survives only inside the legal phrase *plugin exception* (the AGPL §7 additional permission) and charter quotations.

## UI fidelity (TJ, 2026-07-12)

The Agent Inbox UI's pixel source of truth is the Claude Design prototype — `Helpthread App.dc.html` in the "Helpthread Agent Inbox Design" project (the "Helpthread" design-system project carries the same components). **The dogfood site must match it exactly — the whole designed surface, not a subset.** Design-system files under `web/src/components/ds/` stay verbatim copies; improvements go upstream in the design project first. Any deviation — visual, copy, or interaction — requires TJ's explicit sign-off. Remaining gaps are tracked as the fidelity checklist on [HT-23](https://resonantiq.atlassian.net/browse/HT-23); the ticket is not done until the checklist is.
Expand Down
163 changes: 163 additions & 0 deletions specs/modules/catalog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
# Module Catalog & the Open-Core Line

Status: **accepted** (2026-07-18, TJ — HT-66). This is the canonical free-vs-paid line for
Helpthread functionality. CHARTER.md §3/§4 governs the legal/architectural mechanics;
`specs/ui/admin-ia.md` §2 carries the reference-instance observations this catalog resolves.
Where `admin-ia.md` deferred core-vs-module calls to "ticket grooming," this document is
that decision.

**Provenance.** The market inventory below derives from FreeScout's public module listing
(freescout.net/modules — 71 official modules, read 2026-07-18) and the black-box
observations already recorded in `admin-ia.md`. It is priced-demand data: a decade of what
self-hosted helpdesk operators actually pay for. No module source code was observed
(CHARTER provenance rules). FreeScout's third-party community marketplace has not yet been
inventoried; revisit at grooming if a gap appears.
Comment on lines +9 to +14

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

Do not describe the module listing as proof of what operators actually pay for.

The cited listing supports an inventory and market-signal claim, but it does not establish actual purchasing behavior. Please soften “priced-demand data” and “what ... operators actually pay for” unless payment evidence is available.

Suggested wording
- It is priced-demand data: a decade of what
- self-hosted helpdesk operators actually pay for.
+ It is market-signal data: a decade of modules offered to
+ self-hosted helpdesk operators.
📝 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
**Provenance.** The market inventory below derives from FreeScout's public module listing
(freescout.net/modules — 71 official modules, read 2026-07-18) and the black-box
observations already recorded in `admin-ia.md`. It is priced-demand data: a decade of what
self-hosted helpdesk operators actually pay for. No module source code was observed
(CHARTER provenance rules). FreeScout's third-party community marketplace has not yet been
inventoried; revisit at grooming if a gap appears.
**Provenance.** The market inventory below derives from FreeScout's public module listing
(freescout.net/modules — 71 official modules, read 2026-07-18) and the black-box
observations already recorded in `admin-ia.md`. It is market-signal data: a decade of modules offered to
self-hosted helpdesk operators. No module source code was observed
(CHARTER provenance rules). FreeScout's third-party community marketplace has not yet been
inventoried; revisit at grooming if a gap appears.
🤖 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 `@specs/plugins/catalog.md` around lines 9 - 14, Revise the provenance
paragraph to remove claims that the FreeScout module listing proves operators’
purchasing behavior. Replace “priced-demand data” and “what self-hosted helpdesk
operators actually pay for” with wording limited to module inventory and market
signals, while preserving the existing source, date, and provenance constraints.


## 1. The line, stated once

**Free core = parity and hygiene. Paid = intelligence, channels, and enterprise.**

- Everything a self-hosted helpdesk operator would call table stakes — including features
FreeScout paywalls — ships AGPL-free in core. Security hygiene is always free:
**passkey login (WebAuthn) is core**, deliberately, where the reference ecosystem sells
2FA. The conventionally accepted auth paywall is enterprise SSO, and that is where ours
sits (§3.3).
Comment on lines +20 to +24

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

Clarify “AGPL-free” to avoid a licensing contradiction.

The same document describes the core as “charter-core AGPL” at Line [48], so “AGPL-free” can be read as “not AGPL licensed.” State explicitly that the functionality is free of charge in the AGPL core, or that it is AGPL-licensed and free of charge.

🤖 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 `@specs/plugins/catalog.md` around lines 20 - 24, Clarify the “AGPL-free in
core” wording in the paragraph by explicitly stating that these features are
AGPL-licensed and available free of charge in the core. Preserve the existing
feature and paywall distinctions while removing any implication that the
functionality is not AGPL licensed.

- The charter floor applies verbatim: nothing free today gets paywalled retroactively;
monetization adds, never subtracts.
- The line is one-way asymmetric: free → paid never happens; paid → free stays possible.
When a future call is genuinely uncertain, born-proprietary is the reversible choice.
- **Born-proprietary discipline**: a paid module lives in a closed repo from its first
commit and touches core only through public extension points. Nothing intended for the
paid catalog is ever prototyped inside the AGPL tree.
- **Zero privileged first-party access**: any hook a paid module needs ships in the public
module API first (charter module boundary).
- **Preferred module shape is out-of-process** — typed events/webhooks plus the public
API — which needs no §7 exception at all. The in-process build-time module API is built
only when a module genuinely needs UI presence, and not before a real module hits that
wall.
- Positioning corollary, used deliberately in marketing: tags, the public API + webhooks,
the knowledge base, dark mode, keyboard shortcuts, and passkey-class security are paid
modules in the FreeScout ecosystem and free in Helpthread core.

## 2. Free core

### 2.1 Already shipped

Tags (HT-29) · internal notes (HT-28) · single-Agent assignee, now roster-wide (HT-31,
HT-54) · soft delete (HT-30) · four-state status incl. spam and pending (HT-26) · folder
semantics (open/closed/spam listing) · public API (charter-core, with the MCP server to
follow it) · per-Agent identity, login, team management, mailbox-access grants (HT-54) ·
theme/appearance preference (HT-54) · keyboard-shortcuts surface (admin-ia deviation
list) · open-tracking privacy default OFF (HT-32).

### 2.2 Committed core, built incrementally (priority at grooming)

Saved replies · custom folders · send & close · satisfaction ratings · basic reports ·
basic workflows/automations · global search · basic custom fields (conversations and
customers) · custom mailbox signatures · office hours / auto-reply windows · out of
office · followers · @mentions in notes · snooze-until-a-date (extends `pending`) ·
sender time zone · noreply-address warnings and external-image blocking · CSV export ·
GDPR-grade hard delete and export (extends soft delete) · extended editor · dark mode
(full surface) · **passkey login** (WebAuthn on the HT-54 session infrastructure) ·
knowledge base (charter-core) · notifications matrix (email/browser, per admin-ia).

The chat channel is core engine work when it arrives (charter §4: a second channel over
the same engine), distinct from any paid trappings layered on it.

### 2.3 Not ported — obsolete by architecture

Move/Remove IMAP Message (no IMAP polling) · Faster Search via Meilisearch (search is
Postgres-native) · Auto Login from notification emails · Custom Homepage · Ticket Number
in subject (threading never depends on it; display numbers shipped in HT-27) · Mailbox
Icons · Twitter/X DM integration (API effectively dead).

## 3. Paid modules — three clusters

Each entry is born proprietary (closed repo), integrates out-of-process unless noted, and
ships through the marketplace when that phase opens (charter §5). Order within clusters is
rough priority.

### 3.1 Intelligence (the differentiator; charter-named leading candidates)

- **Draft-reply assistant** — the first module (§4). Subscribes to inbound events, calls
the operator-configured model with the operator's keys, posts a draft as an assistant
actor; an Agent approves in core UI. Pure out-of-process.
- **Auto-triage** — tagging, routing, priority; same event-driven shape.
- **KB-grounded auto-answers** — depends on the KB and widget; later.
- AI subsumes rather than ports several reference modules: ticket translation,
learning spam filter, customer data enrichment, satisfaction/sentiment analysis become
facets of assistant modules, not standalone products.
Comment on lines +82 to +89

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use the canonical “Assistant” vocabulary for AI actors.

Terms such as “assistant actor,” “assistant modules,” and “assistant-actor API” are inconsistent with the required Agent/Assistant distinction. Use “Assistant” when referring to the AI actor, including the API terminology.

As per coding guidelines, human support staff must be referred to as “Agents” and AI actors as “Assistants.”

Also applies to: 121-128

🤖 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 `@specs/plugins/catalog.md` around lines 82 - 89, Update the AI terminology in
the catalog section: replace “assistant actor” and “assistant modules” with
“Assistant” vocabulary, and ensure any related API references use “Assistant” as
the AI actor term. Preserve “Agent” exclusively for human support staff and
apply the same terminology consistently in the referenced later section.

Source: Coding guidelines


### 3.2 Channels & integrations (the reference ecosystem's biggest paid cluster)

WhatsApp · Telegram (integration + notifications) · SMS (Twilio-class) · Facebook
Messenger · Slack notifications · Jira · commerce order-context panes
(Shopify/WooCommerce-class) · mobile push (paired with any future mobile surface).
All are out-of-process by nature: a channel adapter feeds the same channel-agnostic
conversation engine; an integration consumes events and the public API.

### 3.3 Enterprise & ops

- **Enterprise Auth** — SAML/OIDC SSO, SCIM/directory sync, 2FA *policy enforcement*,
login audit. (Passkeys themselves are core, per §1.)
- **PGP / S-MIME** signing and encryption.
- **Wallboards & advanced analytics** (basic reports stay core).
- **Kanban view** · **time tracking** · **CRM-grade customer management** (basic
customer records and fields stay core).
- **White-labeling** — see §3.4.
- *Possible, deliberately undecided*: an advanced-workflows module above core's basic
automations. Deciding it is deferred; the core/paid seam inside "workflows" gets drawn
when basic automations are specced, not retroactively.

### 3.4 The white-label pattern

The embeddable support widget and end-user portal ship **free with Helpthread branding**;
**branding removal is paid**. Every free install is distribution; the pattern is additive
monetization and thus charter-clean (Help Scout's Beacon and the reference ecosystem both
validate it).

## 4. Build sequence

1. **HT-67 — module substrate v1 spec**: typed event vocabulary, webhook delivery
(registration, signed payloads, retries), assistant-actor API (draft-post,
list-pending, approve/send with audit). Doubles as counsel raw material for the
§7-exception text (HT-5) — the exception gets drafted against a real API, before the
first external contribution.
2. **Core: event emission + webhook delivery** (AGPL — the substrate is always free).
3. **Core: assistant-actor API + draft-review inbox UI** (design-project-first per the
UI-fidelity rule; the schema has been AI-ready since day one).
4. **First module: draft-reply assistant** in a closed repo, dogfooded on the live
Resonant IQ desk. Dogfood installs are a private npm package in the Vercel build —
no marketplace plumbing required to use our own modules.
5. Marketplace plumbing (license keys, registry, update channel) stays deferred to its
charter phase.

## 5. Marketplace phase — additive by contract

The standing rule (TJ, 2026-07-18): **everything built for dogfood must be sellable
without rebuild — the marketplace only ever adds.** What that means concretely, recorded
now so the marketplace design inherits it:

- **Runtime credentials ≠ licenses.** Modules authenticate with security credentials
(assistant tokens, webhook signing secrets — substrate v1, free core, every module
uses them). A license key is a *distribution* credential: it authenticates registry
download and the update channel. No runtime license check exists in the substrate,
ever — a runtime phone-home inside a self-hosted product is both hostile to the
own-your-data posture and trivially strippable; enforcement in this market is
distribution + updates + support. Revoking a license stops updates; it never breaks a
running helpdesk.
- **Dogfooding needs no licensing** — we are the vendor; our installs are direct
deployments of product-shaped module repos (credentials/env config only, no
first-party special-casing). The dogfooded artifact IS the marketplace artifact.
- **Install bundles come later, attribution starts now**: assistants and webhook
endpoints carry a `module` slug from substrate v1, so marketplace-phase
install/uninstall/health tooling references existing rows rather than retrofitting
identity.
- Modules **we host** as convenience services are ordinary SaaS billing — no special
machinery in the product.

## 6. Changelog

- **2026-07-18**: initial version (HT-66). Free/paid line decided by TJ from the
FreeScout official-catalog inventory + charter constraints; passkeys-core,
Enterprise-Auth-paid, white-label pattern, and the three paid clusters locked.
9 changes: 6 additions & 3 deletions specs/ui/admin-ia.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,10 @@ What this classification means for Helpthread (charter §3 governs):
These are honest positioning differentiators: FreeScout charges for them, we don't.
- **Their paid list is market signal for OUR marketplace candidates** — Custom Folders,
Saved Replies, Send & Close, Satisfaction Ratings are proven willingness-to-pay
features. Core-vs-module for each is decided at ticket grooming; the charter's floor
("nothing free today gets paywalled retroactively; monetization adds, never subtracts")
applies, and AI-powered modules remain the leading paid candidates.
features. Core-vs-module is now decided: `specs/modules/catalog.md` (HT-66) is the
canonical line — all four land core-free there; the charter's floor ("nothing free
today gets paywalled retroactively; monetization adds, never subtracts") applies, and
AI-powered modules lead the paid catalog.

- **Dashboard (home)** — multi-mailbox card grid: one card per mailbox with folder counts
(Unassigned/Mine/Starred/Drafts/Assigned + last-activity dates) and quick actions
Expand Down Expand Up @@ -91,3 +92,5 @@ What this classification means for Helpthread (charter §3 governs):

- **2026-07-18**: initial version from TJ's HT-54 fidelity review (screenshot index +
three-scope rule + module caveat). Roadmap tickets for deferred surfaces filed under HT.
- **2026-07-18** (HT-66): §2's open core-vs-module calls resolved by
`specs/modules/catalog.md`; this doc keeps the observations, that one keeps the line.
Loading