70 Commits
Author SHA1 Message Date
Aron PrinsandClaude Opus 5.5 ee9de7fb26 Screenshots: recapture all for v2026.1106.0 (#174)
Recaptures every docs screenshot against `v2026.1106.0` (`d69631b0`).
196 of 278 were stale, and some contradicted the text, such as the
removed **Run with provider trace** button and the old roster tabs.

## What changed

- **Images:** 276 of 276 captured in both themes; 271 PNGs changed.
Every registry entry is stamped `v2026.1106.0`.
- **Pipeline:** `seed.mjs`, `capture.mjs`, `routes.mjs`, `config.mjs`
and `github-review-fixture.mjs` now match this release's UI. No targets
were dropped.
- **Caption:** `experimental/file-viewer.md` now describes what its
image shows.

## Check these

- **Staged state:** the budget banner is removed in the browser on
`dashboard/dashboard-overview`, `experimental/server-info` and
`onboarding/sidebar-new-company-button`. The budget pages keep their
real incidents. The seed also turns off hard stops outside the Budget
Demo agents, and marks agents stuck in `verifying` as ready, so demo
pages aren't paused.
- **`experimental/file-viewer-browse`:** opening the task **Files** tab
crashed the app at the tag on the seeded instance (`Maximum update depth
exceeded` in `SidePanelTabs`), so the image shows a file open in its
side panel instead. `file-viewer.md` still lists `g f` as an entry
point.

## Review coverage

All 140 light images were checked at contact-sheet size, so fine text
wasn't readable that way. 44 images from the final run, 24 light and 20
dark, were opened at full size. The remaining dark images weren't
viewed.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-11-07 16:41:26 +01:00
d627632874 Release docs for paperclip v2026.1106.0 (#172)
Docs for parent release `v2026.1106.0` (`d69631b0`), up from
`v2026.1023.0` (`1b4c8038`): 515 parent commits.

## How this branch was built

The tag is 914 commits behind what `nightly` has drafted, so this branch
isn't cut from `nightly` HEAD. It starts at nightly commit `1952052`
(parent `043f2514`), 19 commits before the tag, then adds:

- the `main` hotfix (#160)
- the sync tooling from `nightly`
- docs for those 19 commits

Later nightly drafts stay on `nightly`, so no pages had to be removed.
No `nightly-draft/*` PRs are open.

## What changed

- **Runner by default:** new Claude, Codex, OpenCode and Pi agents start
on Paperclip Runner on supported hosts, with **Legacy runner** and
**Upgrade runner**.
- **Workspaces:** cleanup of finished workspaces, optional Git
expiration, and restore points for unsaved work. Restore points are off
by default.
- **New pages:** Prompt injection prevention, Google Workspace, GitHub
Copilot, Speko, Braintrust, Daytona, Ditto and Unikraft.
- **Breaking and upgrade notes:** the run history limit, Sentry run
failures off by default and the DSN variables, the Docker start command
for custom images, `--yes` on `instructions-file:delete`, and slower
migrations on large instances.
- **Also covered:** project repositories as skill sources, roster bulk
edit, Artifacts V1 (experimental, off by default), composer dismissal,
`expectedStatusVersion`, `unexecuted_review_stage`, and plugin workspace
providers.
- **Changelog:** a v2026.1106.0 entry in `reference/changelog.md`.

## Older text corrected

These were wrong at the tag, and most are also wrong on the live site:

- which permissions let an agent read a peer's configuration or change
instructions (`api/agents.md`)
- `decideNowCount`, which doesn't exist; the field is `deskBadgeCount`
- `file-resources` routes, which are board-only
- the **Create project** dialog fields, a CEO rule the code doesn't
enforce, and where a terminated agent's reports appear
- `instructions-file:put` and `:delete` examples that always failed
(`cli/agent.md`)
- a curl example that returned `422` (`api/cases.md`)
- Google Workspace **Reconnect** instructions, which claimed it reopens
the service picker
- the `permissionKey` table, which listed 8 of 21 keys
- drafting text at the end of `api/agents.md`

## ⚠ Please check these

- **Product behaviour that may be a parent bug.** The docs now describe
the tag's code, which you may prefer to fix upstream:
- The project **Environment** dropdown saves a choice, but runs ignore
it (`experimental/environments.md`).
- `environments:manage` is granted by roles but no environment route
checks it.
- `suggest-changes` is documented as agent-only, because only agents
have a consent path. Company skill policy decides skill edits.
- **Reader-visible mismatches in the parent UI.** The docs follow the
code. Upstream copy still mentions a "Built-in agents tab", says Copilot
"awaits qualification", and tells people to "Reconnect Google Workspace
to change access".

## ⚠ Post-tag leaks removed

Nothing to remove from an already-drafted page: post-tag surfaces such
as 1Password, Vercel, Supabase deploy, custom gateway onboarding and
Artifacts V1 as default never came onto this branch. Authors left out
post-tag hunks of the next nightly draft, and the reasons are in the run
notes.

## ⚠ Drift

None. Zero findings at the tag, from a full parent snapshot.

## ⚠ Verification Failures

The tag-accuracy gate reports one leak and nine review entries. None is
a real failure:

- **Leak:** `reference/cli/service.md`, `paperclipai payload and`. This
is a false positive; it's prose from a real message at
`cli/src/commands/service.ts:184`.
- **Review, 8 new connector pages:** the gate can't confirm new pages.
Reviewers confirmed each surface exists at the tag.
- **Review, `local_tools`:** an example value from the tag's Runner
README.

Not provable from code, and kept deliberately:

- `sandbox-providers.md` uses `sandbox.yaml`. The tag's README says
`install.yaml`, which returned 404 when checked. The upstream fix is
post-tag.
- The Google Workspace row about older OAuth brokers rests on release
notes and a design doc. The broker isn't in this repo.
- External claims about provider behaviour (for example Braintrust,
Daytona, Unikraft and Google scopes).

## ↻ Renames detected

None. The rename helper wasn't run: the 19-commit delta adds no new
adapter, skill, or plugin directories that it would check.

## Verification

All checks read a checkout pinned to the tag.

- **First round:** authors, a release-notes audit, an audit of
corrections stranded on `nightly`, an audit of 321 lines the last
realign dropped from `main` (about 130 checked directly in code), and
six fresh verifiers.
- **Second round:** seven new verifiers re-checked every changed area,
tracing behaviour rather than matching labels, and fixed about 50 more
defects. That volume means more may remain.
- **Limits of that second round:**
- Each verifier reported what it only string-matched. That includes
parts of Artifacts V1, the **Upgrade runner** notice, Copilot run
behaviour, and some Plugin SDK contract text.
  - The second-round fixes themselves weren't reviewed by a third round.
- **Gates:** `docs:build`, `docs:test` and `sync:check` pass.
- **Nothing was run against a live instance.** All of this comes from
reading code.

## Screenshots

**196 of 278 screenshots are stale and none were recaptured.** The list
is in `SCREENSHOTS_PENDING.md`. Some visibly differ from the text, such
as the removed **Run with provider trace** button and the old roster
tabs.

## After merge

1. Keep the PR title as is: `tag-docs-release.yml` reads the version
from it.
2. Confirm the `docs/v2026.1106.0` tag exists.
3. Run `node scripts/sync/realign-nightly.mjs release/v2026.1106.0
--push`, then audit for dropped lines and duplicated paragraphs, and set
`nightly` state back to `branch_mode: nightly`.
4. Check that `docs.paperclip.ing` serves the release: a new page, a new
claim, and the changelog's top entry.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
Co-authored-by: DevRel Gemini <[email protected]>
Co-authored-by: Paperclip <[email protected]>
Co-authored-by: Dotta <[email protected]>
Co-authored-by: ClaudeCoder <[email protected]>
2026-11-07 13:02:42 +01:00
0ea1994fa7 Release docs for paperclip v2026.1023.0 (#156)
## Summary

Release docs for Paperclip **v2026.1023.0** (parent tag commit
`1b4c8038`).

- **Window:** `v2026.1012.0` → `v2026.1023.0`. The tag was cut from
parent `master` at 2026-10-12, so the cumulative window is the
merge-base `22a3ea34` → `1b4c8038`. That's 200 commits and 2,501 files,
with no compare truncation.
- **Branch:** cut from `nightly` (`1b81e21`). Nightly had drafted
against parent master up to `043f2514` (Oct 22), which is 496 commits
past the tag. Most of nightly's #151–#155 work is post-tag.
- **Review:** six reviewers checked all 161 changed pages hunk by hunk
against a local checkout of the tag, using post-tag history
(`1b4c8038..043f2514`) to date each claim. The tag-accuracy gate was
then re-run on the result.

**Headline doc changes:**
- **New pages (21):**
  - [Custom model providers](docs/connectors/custom-model-providers.md)
  - [Decision Models API](docs/reference/api/decision-models.md)
  - [Cases](docs/experimental/cases.md)
  - [External agents: OpenAI Dot](docs/experimental/external-agents.md)
  - [Agent cryptographic identity](docs/guides/org/agent-identity.md)
- [Agent complaints and
suggestions](docs/administration/agent-commentary.md)
  - [Runtime Commands](docs/reference/cli/runtime.md)
- 14 connector guides: Bitly, Calendly, Context7, Enterpret, Exa,
Firecrawl, Gauge, GSC Wizard, Make, Parallel Search, Superagent, Tavily,
Telem.AI and Windsor.ai
- **Updated pages:**
  - Private tasks and projects, with sharing and inherited privacy.
- Costs: estimated, unpriced and subscription spend, the Overview
breakdowns, provider cost reports, and the Decisions view.
  - Operators get default company editing permissions (#15377).
  - Agent setup checks and your primary agent.
  - Slack: automatic setup and **Require at-mention**.
  - The simplified dedicated GitHub App setup.
  - Cursor and Pi on Paperclip Runner, and the **Harness** label.
  - Expanded assistant MCP tools and the `paperclip:configure` scope.
  - CSV and HTML artifact previews.
  - The plugin agent lifecycle contract.
- Server-host AI sign-in, and new Linear, Airtable and Hugging Face
methods.
- A changelog entry, and 102 pages stamped `paperclip_version:
v2026.1023.0`.

### ⚠ Post-tag leaks removed

These document parent `master` features that are **not in
v2026.1023.0**. They stay on `nightly` for a later release.

- **Pages removed (7):**
  - `connectors/github-copilot.md` (92b23813)
  - `connectors/google-workspace.md` (23b2ceb0)
  - `connectors/braintrust.md` (92cfd701)
  - `connectors/daytona.md` (0b62c736)
  - `connectors/ditto.md` (a1e2173c)
  - `connectors/speko.md` (22d05644)
  - `connectors/prompt-injection-prevention.md` (2c96f767)

Their nav entries and catalog rows are already removed, and no page
links to them.
- **Reverted to `main`:**
  - 54 pages whose nightly changes were all post-tag. That includes:
- The Google per-app "no longer listed" notes and Gmail archive
(23b2ceb0, e4ce9890).
- The skills guide and the company-skill-policy API (repository packages
and auto-updates: a9830414, 473c80d1, df4ee06e).
    - The Cases API (handoffs and workflows: 505e1a55, 0a5f1546).
- The companies API (observability and prompt injection: ac9459ba,
2c96f767).
- `deploy/docker.md`, the claude-code and hermes adapters, and
`cli/agent.md` / `cli/service.md` (`--runner`, managed-shim guard).
  - The rest only changed Sources-link SHAs or had nightly-only wording.
- **Sections trimmed:**
- The Runner-default rollout, its upgrade notice and `runner` fields
(adb69e8f, 8193abb9, 39e44a9d, 734c2653).
  - Grok Bot and Muse (b8ffeb97, e6dcc6b0).
  - Task workspaces and plugin project storage (f329b24e, 8b4ab65b).
  - Task Retry and recovery status lines (d33b40a5).
- The commentary read API, `commentary:view`, and Pipelines removal
(e6dcd1e8, e5927e1d, 90777488).
  - Scoped and async budget enforcement (30b753f6).
- Plugin WebSocket routes, agent detail tabs, resource-lifecycle
delivery and Runner tasks (42715d45, db65a086, 33cc567f).
- Slack managed Cloud setup and DM at-mention changes (f0e12c85,
df06df23).
- Review-bot queued-comment, reconnect and naming changes (3b8324a2,
52459590, 7eea9d82).
  - OpenRouter attribution headers (9179d8dc).
  - Agent, project and routine search (7b9334cd).
  - Artifacts upload (762d680d).
- Env-var rows: `NATIVE_HARNESS_BACKUP_*`, `WORKSPACE_COMPACTION_*`,
`GIT_CACHE_*`/`GIT_BASE_*`, `SKILL_VERSION_RETENTION_*`, `NATIVE_MCP_*`
and `SENTRY_RUN_FAILURES`.
  - `/api/liveness` (a0651c96).
- Source links pinned to post-tag commits now point at the tag commit.

### ⚠ Drift

Checked against the tag (`check-drift --against 1b4c8038`). There are 33
candidates, the same set as the last nightly runs:
- **High:** `PAPERCLIP_WORKSPACE_GIT_SCAN_*`,
`PAPERCLIP_WORKSPACE_GIT_SNAPSHOT_TIMEOUT_MS`, `PAPERCLIP_RUNNER_API_*`,
`PAPERCLIP_MCP_AUTHORIZATION_ORIGIN` and `PAPERCLIP_CLOUD_CONNECTOR_*`
are known false positives. They're read through helpers or `env.`
receivers the checker doesn't scan.
- **High:** `PAPERCLIP_ID_CONNECTOR_*` is documented as retired, which
is intentional.
- Verify: `agent-avatars` (`:file` param), `companies/import/transfers*`
(constant route path), `chats/{agentRef}` (`router[method]` loop), and
`mcp/requests/{id}` plus the Dot pairing routes (array registration in
`public-mcp.ts`). These are known false positives.

### ⚠ Verification Failures / review notes

- **Tag-accuracy gate false positives:**
- `cli/runtime.md`: `--sha256` is a `.requiredOption` in
`cli/src/commands/runtime.ts`. `SSL_CERT_FILE`, `SSL_CERT_DIR` and
`NODE_EXTRA_CA_CERTS` are passed through by key list in
`buildPiSetupEnvironment`.
- `plugins/sdk.md`: `ENVIRONMENT_ACQUISITION_PROVIDER_STATES` is an SDK
export.
- `skills.md`: `PAPERCLIP_HELPER_STATE_DIR` is read in the skill's
upload script.
- `adapters/cursor-local.md`: the `acpx*` fields are validated in
`paperclip-runner-permissions.ts`.
- **New pages the gate can't auto-confirm:** each was confirmed by hand
at the tag, against the app definitions, routes and UI.
- **Claims kept on weaker evidence (commit message or UI string, not
code) — please eyeball:**
  - "a new bot starts in mentions-only mode" (github-setup).
  - "Mentions work in issue and PR descriptions" (review-bot setup).
  - Airtable's "HTTPS or localhost" sign-in note.
  - The "37 tools" figure on assistant-connections.
  - Reservation semantics on the costs guide.

### Screenshots

142 of 278 screenshots depend on UI files changed in this window (see
`SCREENSHOTS_PENDING.md`). They were last captured against v2026.1012.0
(#150), and a recapture is still pending.

### Checks

`docs:build` and `sync:check` pass: no broken links, and the only
orphans are the four pre-existing ones (`you-com`, `hosted-beta` and the
two intentional CLI redirect pages). All eight `docs:test` suites pass.

### After merge

1. Confirm the `docs/v2026.1023.0` tag was created.
2. Run `node scripts/sync/realign-nightly.mjs release/v2026.1023.0
--push`.
3. Re-apply this branch's decisions on `nightly`.
4. Flip `nightly`'s state back to `branch_mode: nightly`.
5. Verify docs.paperclip.ing serves the changelog entry and new pages.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
Co-authored-by: DevRel Gemini <[email protected]>
Co-authored-by: Paperclip <[email protected]>
Co-authored-by: Dotta <[email protected]>
Co-authored-by: ClaudeCoder <[email protected]>
2026-10-24 13:01:34 +02:00
Aron PrinsandClaude Opus 5.5 d811a89622 Screenshots: recapture all for v2026.1012.0 and align guides with the release UI (#150)
## Summary

Every docs screenshot is retaken from Paperclip **v2026.1012.0**, in
light and dark. Verifying them showed that about 50 guides described UI
the release had moved or renamed, so those guides are updated too.

**Screenshots**
- 138 automated captures (276 PNGs), all stamped `v2026.1012.0`
(`bba6a45`). The final run had no failed steps or skipped captures, and
the luminance and theme check passes on all 278 files.
- Four independent reviewers checked every light shot against its
caption, then a fix round cleared the findings.
- 37 captures (74 PNGs) are retired: none is embedded on any page, or
the screen no longer exists in the release.
- The capture pipeline (`scripts/screenshots/*`) is fixed for the
release UI:
- turns off the remote "Introducing Connectors" announcement that
covered most shots;
  - masks local temp paths as `~/acme/…`;
- keeps the demo company quiet during capture (no recovery loops, no
capture-created activity rows);
- seeds the states the guides describe: status cards, 50/80/100%
budgets, a blocked inbox, schedule triggers, a checkbox confirmation,
skills-capable agents and more;
- uses updated routes and steps for the moved UI, and gains
`scrollToTop`, `readyText`, per-target `experimental` flags, and comma
lists for `--only`.
- **The budget shots show a fixed incident card.** In v2026.1012.0 a
warning-threshold incident is labelled "hard stop · This scope is
paused", which is wrong. The fix is
[paperclipai/paperclip#16201](https://github.com/paperclipai/paperclip/pull/16201).
The costs and budget shots were captured from v2026.1012.0 with that
patch applied, and the budget guides say so and explain what
v2026.1012.0 itself shows.

**Docs aligned with the release UI**
- **Audit:** costs, budgets, runs and the timeline moved under Audit.
That covers Costs and Budgets, Activity Log, Work Timeline, Set a
monthly budget, and Dashboard.
- **Agents:** the agent page's side menu (**Overview**, **Harness /
Runtime**), the two-step **New agent** dialog, **Run now**, and the org
chart as a view toggle. That covers Agents, Your first agent, Watching
agents work, Key concepts, Org structure, Agent adapters and Adapters.
- **Projects, routines, tasks, approvals:** current tabs, buttons and
flows.
- **Skills, plugins, company, settings:** current labels, including
instant-join invites, the Experimental settings list, and **Settings →
Experimental** paths on 21 pages.
- **Removed features:** Auto-Create Recovery Tasks and Cloud Sync are
marked as removed in this release.
- Every rewrite was checked against the v2026.1012.0 UI source, then by
two independent verifiers. A changelog entry is added under
v2026.1012.0.

## Checks
- [x] `npm run docs:build`
- [x] `npm run docs:test` (all suites)
- [x] `sync:lint-links` and `sync:verify-nav`: only the 4 intentional
orphans remain
- [x] SEO metadata and crawlable links

## Known, accepted
- The activity feeds lead with agent setup events rather than task
events.
- The dashboard agent strip shows two cards for Ada.
- Agent budgets can only be created from the CLI or API in this release,
and the guides say so.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-13 18:44:53 +02:00
DottaandPaperclip 29a78936e5 docs: explain and set up experimental GitHub review bots (#130)
## Thinking Path

> - Paperclip runs agent work as tasks and runs.
> - The experimental GitHub chat connector lets GitHub conversations and
PR events enter those tasks.
> - Installing an App, scheduling reviews, and requiring a passing check
are independent choices.
> - Readers need both that explanation and a concrete setup tutorial.
> - These guides pair the mental model with a Storybook reviewer that
can be tested from failure to success.

## What Changed

- Group all four GitHub pages under an expandable GitHub sidebar
section, with matching breadcrumbs.
- Add **Understanding GitHub PR review bots**, preserving the
conversational explanation of installation, triggers, scores, checks,
and formal reviews.
- Add a separate **Set up a GitHub review bot** tutorial with a copyable
Storybook instruction, agent/runtime prerequisites, App registration and
installation, repository selection, identity linking, and required-check
configuration.
- Mark both pages as experimental chat documentation and cross-link
them. Update the older GitHub pages to remove conflicting legacy setup
advice.
- Include four real setup UI screenshots in both themes, using
explicitly labeled demo responses. Register all eight images for
reproducible capture and source-change tracking.
- Add a screenshot-only fixture and small capture helpers for native
selects, required content, and a configurable local port.

## Verification

- Latest-head GitHub `docs-test` and Cloudflare Pages checks passed at
`b4e7943f8e77bc3320ea6eb0379dd1ff65f87a98`.
- Deployed preview browser-checked: [understanding review
bots](https://5e364a56.paperclip-docs-74t.pages.dev/connectors/understanding-github-review-bots/)
and [setup
tutorial](https://5e364a56.paperclip-docs-74t.pages.dev/connectors/github-review-bot-setup/).

- GitHub sidebar collapse/expand and navigation between nested pages
checked in the embedded browser.
- Both pages checked in the embedded browser. Followed the cross-links
in both directions and verified all four images load in light and dark
themes.
- All eight screenshots captured from the actual UI at Paperclip
revision `7ba761fe007bb798400d3e62346fa964f607f0f8`. No live GitHub
credentials or agent runs are represented by these fixtures.
- `npm run sync:lint-links`, `npm run sync:verify-nav`, and `npm run
sync:verify-screenshots` passed. Navigation reports only the three
pre-existing unlisted/orphan pages.
- `npm run docs:build` and the complete `npm run docs:test` suite
passed, including static routes, sitemap history, asset fingerprints,
navigation, crawlable links, source blocks, 1,945 link-resolution
checks, and SEO metadata.
- Reviewed the current GitHub documentation for required checks,
expected App sources, and neutral results.

## Risks

The chat feature is experimental and the UI may change. Screenshot
dependencies and capture commands are recorded for refreshes. The
tutorial distinguishes illustrative UI captures from the live acceptance
tests readers must perform. This changes documentation and its
screenshot pipeline only.

## Model Used

OpenAI GPT-6 through Codex, using repository tools and the embedded
browser. The precise serving model variant and context-window size were
not exposed.

## Checklist

- [x] Both requested pages exist and cross-reference each other.
- [x] Both identify the experimental chat feature.
- [x] Screenshots include light and dark themes with capture provenance.
- [x] Documentation build and targeted verification passed.
- [x] Complete docs test suite and PR checks passed.

---------

Co-authored-by: Paperclip <[email protected]>
2026-09-22 09:07:35 -05:00
39633c2217 docs: connectors catalog, operator-first third revision (#124)
Connector catalog, setup guides, and shared access documentation,
followed by a final code-accuracy repair pass. This PR does not change
application behavior.

## Final accuracy pass

Checked against shipped Paperclip `v2026.916.0`, commit
`dffc2b3ca1b9e88fa21cb17493083e682dffd1ca`, rather than the dirty local
checkout or the earlier canary baseline.

- Corrects connector/method-specific identity choices, human audiences,
and managed GitHub versus PAT scope and verification.
- Explains that **Always allow** covers different arguments for the same
agent/action/connection, with project scope when present; uses actual
button labels and removes the test-panel control from review
instructions.
- Qualifies new-action quarantine, including safe-default read
exceptions. Removes unconditional approval guarantees.
- Separates provider channel/repository reach from Paperclip sender
authorization.
- Completes sandbox sign-in and model credential-selection instructions
from the current UI implementation.
- Repairs Notion's hub summary, removes incomplete optional
Notion/Sentry client-registration procedures, and corrects Linear's
provider-versus-Paperclip attribution.
- Removes unsupported Postman tier claims, contradictory Cloudinary/Mem0
verification assertions, API-equivalence claims, and overbroad
successful-test assurances.
- Retains Supabase's required project reference: both released method
definitions explicitly require it. An earlier review suggested
otherwise; release code is authoritative here.
- Updates the release baseline and removes draft commit chronology from
the public introduction.

## Availability and remaining runtime gates

- **Google:** Verification is pending. Per the product-owner
clarification, authorization can continue where Google offers an
Advanced option; this is not available for every account and does not
override Workspace policy or other Google prerequisites. Notices on the
hub and all Google guides now distinguish an unverified-app warning from
blocked authorization.
- **Slack is available but not yet fully functional; follow-up fixes are
planned.** For agent tools, the released OAuth endpoint/scope defaults
differ from Slack's documented MCP contract. The page now warns against
treating that route as production-ready and removes the misleading
bot-scope walkthrough. Chat-channel bot setup remains separate.
Engineering must reconcile the integration and run OAuth plus one read
before removing this warning. Source:
https://docs.slack.dev/ai/slack-mcp-server/
- No credentialed connector run was performed in this pass. Code
consistency, provider documentation, UI rendering, and successful live
execution are separate evidence levels. No claim of runtime
certification for all connectors.

## Validation

- Root build: 253 crawlable documentation pages.
- Full `docs:test`: all eight suites passed locally, including
root/subpath routes, sitemap history, fingerprints, navigation, skill
source blocks, crawlable links, doc-link resolution, and SEO metadata.
- Internal-link lint: 258 Markdown files; no broken internal links.
- Latest cleanup: full build, all eight docs:test suites, internal-link
lint and diff whitespace checks passed; 1,878 link-resolution checks.
- Fixed the Calendar MCP reference URL; browser-checked the five
inconclusive external destinations (Miro article loads; Asana, Google
Cloud, OpenAI and xAI reach sign-in/console screens). Authenticated
destinations were not tested beyond those screens.
- Replaced the Sandbox providers editorial TODO with a scope note and
removed the CLI overview's unfinished-guide announcement.
- Browser client navigation: 687 checks passed using installed Chrome.
Initial launch lacked the downloaded Playwright browser; rerun used
`DOCS_CHROMIUM_PATH` without changing the tests.
- Nine representative connector/shared pages at 1440px and 390px: HTTP
200, one article H1, no page-level horizontal overflow. Mobile
screenshot inspected; approval page opened in the Codex browser.
- Navigation audit reports three existing non-connector orphan files;
this patch does not alter those files or their navigation.

The previous revision's provider-page expansion, Google shared setup
guide, navigation additions, and accidental node_modules-symlink cleanup
remain in this PR. Internal review ledgers remain outside the
publication branch. No merge or production deployment authorized.

---------

Co-authored-by: DevRel Gemini <[email protected]>
Co-authored-by: Paperclip <[email protected]>
Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
Co-authored-by: Michael Nguyen <[email protected]>
2026-09-16 22:19:14 -10:00
Michael Nguyen 9f46125a8d Add unlisted hosted beta guide and FAQ (#122)
## Summary
Adds the hosted beta getting-started guide and FAQ at `/hosted-beta/`,
using the existing docs header, sidebar, article layout, theme controls,
and table of contents.

The page remains outside the navigation/search manifest, homepage
listings, previous/next links, and sitemap, with a `noindex` directive.
Direct-link visitors can navigate into the regular docs. This is a
public, unlisted page rather than access-controlled content.

## Validation
- Root and subpath builds and unlisted discovery checks pass.
- Existing static route verification passes.
- Desktop and mobile browser checks show no overflow or runtime errors.
- Table-of-contents anchors and navigation into regular docs verified.

Local preview: http://127.0.0.1:4337/hosted-beta/
Hosted preview:
https://aa3d8178.paperclip-docs-74t.pages.dev/hosted-beta/

Cloudflare deployment succeeded for commit 4b94d17.
2026-09-11 00:43:36 -07:00
Aron PrinsandClaude Opus 4.8 27d7a5ab4c Release docs for paperclip v2026.831.1 (#120)
Syncs docs to parent release **v2026.831.1** (cumulative from
`v2026.824.1`, via merge-base `664052f`). Authored fresh against the
release tag; every claim verified at the tag.

## What changed

**New**
- **Kimi Code adapter** (`kimi_local`) — new reference page, wired into
the adapters overview, nav, and anchor-map source mapping.

**Reference**
- **Env vars** — `PAPERCLIP_WORKSPACE_REAPER_COOLDOWN_DAYS`, opt-in
`SENTRY_DSN`, and the operator controls `PAPERCLIP_HIDDEN_SETTINGS` /
`PAPERCLIP_SETTING_DEFAULTS`.
- **Instance Settings** — new "operator controls for hosted deployments"
section (hide surfaces / override defaults).
- **Node.js floor → 24.11.0** across installation, setup,
local-development, plugin dev, Modal, and the getting-started/terminal
guides.
- **Grok adapter** — `permissionMode` no longer defaults to `dontAsk`;
when unset no flag is passed, and `--always-approve` is the unattended
policy.
- **CLI `agent`** — Kimi skills install path (`~/.kimi-code/skills`) +
`KIMI_CODE_HOME`.

**Guides**
- **Onboarding** — rebuilt around a single-card wizard that opens on
creating your agent; the mission step is gone, the goal is set
afterward.
- **Settings unification** — Invites folded into a Members tab, one
shared settings nav, and the company brand color + per-company
attachment size limit removed (also reflected in the Companies and Cases
APIs).
- **Governance behavior** — silent-run detection and stranded-task
recovery no longer act on their own; agent thought text is excluded from
automatic comments; invalid agent credentials now return `401`.

**Changelog** — entry added for v2026.831.1.

## Gates

- `docs:build`, SEO metadata, crawlable-links, sitemap-lastmod
(194/194), lint-links, verify-nav — all pass.
- **Edit verification:** every new high-confidence claim verified at the
tag.
- **Tag-accuracy gate:** 31 files checked, **0 post-tag leaks**, 30
clean, 1 review (below).

## ⚠ Drift (Verify before acting — not auto-resolved)

Medium-confidence REST-route drift in `docs/reference/api/companies.md`
— the import-transfer routes may no longer exist at these paths (likely
a false negative from prefix/dynamic registration; confirm before
editing):

- `POST /api/companies/import/transfers`
- `PUT /api/companies/import/transfers/{transferId}/parts/{partIndex}`
- `GET /api/companies/import/transfers/{transferId}`
- `POST /api/companies/import/transfers/{transferId}/preview`
- `POST /api/companies/import/transfers/{transferId}/apply`

## ⚠ Review

- `docs/reference/adapters/kimi-local.md` — new page; the only flagged
claim is the `secret-id` JSON **example placeholder** (not a real
identifier). Authored directly from the adapter's config surface at the
tag.

## Screenshots (deferred)

288 of 342 registered screenshots are stale (org-wide rename +
settings/onboarding rewrites), tracked in `SCREENSHOTS_PENDING.md`.
Recapture is a follow-up pass — **the merged pages describe the new
onboarding/settings UI while screenshots still show the old flow until
then.**

---------

Co-authored-by: Claude Opus 4.8 <[email protected]>
2026-09-02 13:06:00 +02:00
Aron PrinsandClaude Opus 5 4644dda3a3 test: guard sitemap lastmod against shallow clones and metadata sweeps (#119)
Picks up the regression test from #104 (@cryppadotta) — closed as
superseded, but its fixture design was the best part of it and worth
landing on its own.

## Why this gap mattered

The sitemap `lastmod` bug shipped twice, and **neither failure was
detectable by any check in `docs:test`**:

| | Symptom | Why nothing caught it |
|---|---|---|
| #117 | 0 dates in production for weeks | Shallow checkout doesn't make
`git log` *fail* — it succeeds, returning one date per file |
| #118 | 192 concurrent `git fetch --unshallow` fighting over
`.git/shallow.lock`, dateless sitemap | Reproduces only on a shallow
clone — never locally, never in CI |

Both are Cloudflare-only failure modes. The only detector we had was
reading the live sitemap, which is how this whole thread started.

## What landed

`scripts/verify-sitemap-lastmod-history.mjs`, wired into `docs:test`.
Three cases against **real depth-1 clones** — the fixture design and
`--no-local` insight are @cryppadotta's:

1. Full history publishes real per-document dates
2. Shallow clone that can reach origin recovers history
3. Shallow clone with unreachable origin omits dates rather than lying

Two changes on top of the original:

**Overlay the working-tree builder into the clone.** The clone carries
committed HEAD, so without this the shallow cases silently test the last
commit instead of the change being made. No-op in CI; the difference is
real locally, and it is what makes the check usable while iterating.

**Assert no single date covers >75% of pages.** The existing "more than
one distinct date" assertion passes at *2* distinct dates — precisely
the state #118 fixed, where 190 of 193 pages carried the date of a
frontmatter-only sweep. Bounding the largest cluster catches that class
without pinning a date that legitimate edits will move.

## Verified by breaking it

A check that has never failed proves nothing, so I reverted each fix in
turn:

**Revert body-aware dating (#118):**
```
  ok  lastmod values vary across documents (2 distinct) rather than one build date
FAIL  full history: no single date dominates (2026-08-25 covers 190/193, 98% <= 75%)
```
Note the pre-existing assertion passing right above the failure — that
is the gap this closes.

**Revert the single-flight memo (#118):**
```
FAIL  unshallowed build dates every route (2/193)
FAIL  unshallowed build produces varied dates (1 distinct)
```
The `.git/shallow.lock` race, caught by Case 2 and nothing else.

Restored, clean run is green: 193/193 dated, 31 distinct, largest
cluster 28%.

## Cost

**~55s** added to `docs:test` for three builds (`docs-test` was 32s).
Steep for a test suite, and worth flagging rather than burying — but the
alternative detector for this failure class is noticing the live sitemap
is wrong.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
2026-08-29 11:10:35 +02:00
Aron PrinsandClaude Opus 5 c593c23233 seo: date sitemap entries by body changes, not frontmatter sweeps (#118)
Follow-up to #117. That PR got `<lastmod>` publishing at all; this one
makes the dates worth resubmitting.

## The problem

**190 of 193 pages read `2026-08-25`** — the date of #115, which added
`seo_title`/`seo_description` to all 192 pages. Here is everything it
changed in a representative file:

```diff
+---
+seo_title: "Key Concepts: Companies, Agents, Tasks"
+seo_description: The seven ideas behind Paperclip — company, agent, task...
+---
+
 # Key Concepts
```

Not a word of prose. `lastmod` is meant to carry the date a page's
**content** last changed, so resubmitting this hands Search Console the
"whole site changed at once" signal that `dropUniformLastmod` and the
shallow-checkout guard both exist to prevent. It cleared
`dropUniformLastmod` only because 3 pages happened to differ.

## The fix

Walk each file's history and report the newest commit that changed the
**rendered body** — comparing `parseFrontmatter().body` across
consecutive commits, so frontmatter-only commits are skipped. Reusing
the build's own parser means the body compared is exactly the body the
site renders.

| | Before | After |
|---|---|---|
| Distinct dates | **2** | **31** |
| Largest single-date cluster | 190 pages | 54 pages |
| Range | 2 days | 2026-04-17 → 2026-08-27 |

Top of the new distribution:

| Date | Pages |
|---|---|
| 2026-08-18 | 54 |
| 2026-06-04 | 21 |
| 2026-08-25 | 17 |
| 2026-07-08 | 16 |
| 2026-07-20 | 15 |
| 2026-04-22 | 12 |

Spot-checked both directions:

- `key-concepts.md` — last touched by the frontmatter sweep, now dates
to **2026-07-08**, the commit that changed "Claude Local" to "Claude
Code" in the body.
- `day-to-day/issues.md` — **keeps 2026-08-25**, because release commit
`6c4519a` that day added a real "Who may resolve a card" section. Its
frontmatter-only `paperclip_version` bump in the same release was
correctly skipped.

## Two supporting fixes

**Concurrency.** ~600 git round-trips in series cost 40s. Resolving them
in parallel: **11s**.

**A race the concurrency exposed** — and the reason this is worth
reading closely. `hasTrustworthyGitHistory()` memoised its *resolved
value*, so once all 192 pages asked at once, every one of them passed
the guard before the first resolved:

```
Could not deepen the shallow checkout: fatal: Unable to create '.git/shallow.lock': File exists.
Still shallow: omitting sitemap <lastmod> rather than dating every page alike.
   × 192
```

192 concurrent `git fetch --unshallow` calls fighting over the lock, and
**a sitemap with no dates at all**. This only reproduces on a shallow
clone — which is to say only on Cloudflare Pages, never locally or in
`docs-test`. Fixed by memoising the promise (single-flight).

## Verification

| Scenario | Result |
|---|---|
| Full clone | 193 dates, 31 distinct, 11s |
| `git clone --depth 1` (reproduces CF) | one unshallow, **193 dates, 31
distinct** |
| Shallow + unreachable remote | no dates, exit 0 |
| `npm run docs:test` (6 suites) | pass |
| `npm run sync:test` | 39 pass, 0 fail (+1 new) |

New unit test covers the `--follow --name-status` rename parsing — 55
docs files have been renamed, and reading the wrong field silently drops
their pre-rename history.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
2026-08-29 10:55:32 +02:00
Aron PrinsandClaude Opus 4.8 5457a4ff38 Release docs for paperclip v2026.824.1 (#116)
Release docs sync for **paperclip v2026.824.1** (cumulative window
`v2026.824.0 → v2026.824.1`, 4 commits / 12 files). This patch release
repairs the onboarding background-service flow end to end.

## Change manifest

| Watcher | Parent files | Kind | Docs target |
|---|---|---|---|
| cli-commands | `cli/src/commands/onboard.ts`,
`cli/src/onboard-service.ts` | modified |
`docs/reference/cli/setup-commands.md` |

**`docs/reference/cli/setup-commands.md`** (`onboard` section) — once
the background service is installed, onboarding now hands you off to the
running instance: it waits for the port the service actually bound
(fallback port if the configured one is busy), prints the dashboard URL,
and opens it in your browser on interactive terminals. Headless runs
print the URL; the new **`PAPERCLIP_NO_BROWSER=1`** opts out of the
browser launch. If the service doesn't come up, onboarding points at
`paperclipai service logs` instead of claiming success.
`paperclip_version` bumped to `v2026.824.1`.

**`docs/reference/changelog.md`** — new `v2026.824.1` docs-changelog
entry.

Not doc-worthy this window: `run.ts` runtime-info plumbing, the
`paperclipai doctor` diagnostic-message refinements, and the test files
— no new or now-wrong surface in our docs.

## Verification

- `docs:build` ✓ · `sync:check` ✓ · full `docs:test` (6/6) ✓
- **verify-edit** against `v2026.824.1`: **47 claims verified, 0
unverified, 0 suspicious**. `PAPERCLIP_NO_BROWSER` and `paperclipai
service logs` both confirmed in parent code at the tag.
- **Tag-accuracy (Phase 5.7):** self-contained release — `nightly`
carries no doc drafts (only `.sync-state.json` differs from `main`), so
there are no post-tag leaks to quarantine.
- **Screenshots:** window touched only `cli/**`, no `ui/src/**` —
nothing stale.

## ⚠ Drift

Investigated against `v2026.824.1`. The two previously high-confidence
CLI findings (`paperclipai binary`, `paperclipai into`) were **scanner
false positives** — the drift scanner was reading `paperclipai <word>`
out of `seo_description` frontmatter prose. Fixed in this PR
(`scripts/sync/check-drift.mjs` now skips the YAML frontmatter block);
both disappear.

Remaining (5, medium, `Verify:` — **confirmed correct, no action
needed**):

- `POST /api/companies/import/transfers` ·
`docs/reference/api/companies.md:433`
- `PUT /api/companies/import/transfers/{transferId}/parts/{partIndex}` ·
:434
- `GET /api/companies/import/transfers/{transferId}` · :435
- `POST /api/companies/import/transfers/{transferId}/preview` · :436
- `POST /api/companies/import/transfers/{transferId}/apply` · :437

These routes **exist** at `v2026.824.1`
(`server/src/routes/companies.ts` lines 696/762/825/944/958), registered
via the `COMPANY_IMPORT_TRANSFERS_ROUTE_PATH` constant from
`@paperclipai/shared`. The scanner only matches string-literal paths, so
constant/template-literal registration reads as a false negative — a
known medium-tier limitation. The docs are accurate; nothing to change.
(A follow-up could teach the resolver to follow cross-package path
constants.)

## Checklist

- [x] Cumulative diff from last release tag
- [x] Edits verified against the release tag
- [x] Build + link + SEO + crawlable gates pass
- [x] Drift investigated; false positives fixed at the scanner, false
negatives confirmed correct
- [x] Docs-changelog entry added
- [ ] After merge: tag `docs/v2026.824.1`, realign `nightly`, verify
`docs.paperclip.ing` serves the release

---------

Co-authored-by: Claude Opus 4.8 <[email protected]>
2026-08-27 12:55:02 +02:00
Aron PrinsandClaude Opus 5 325c9eb819 seo: hand-write titles and descriptions for all 192 pages (#115)
## Why

The build derived `<title>` from the **sidebar label** and the
description from the **first paragraph clipped to 220 characters**. Both
are the wrong source. A sidebar label is written for a 240px-wide nav
that supplies its own context; a search result has none.

On production that produced:

- **7 pages titled "Overview"**, and 32 pages sharing a title with
another page
- **109 of 193 descriptions cut off mid-word**, and 174 over 160
characters (where Google truncates)

```
/guides/welcome/key-concepts/
  BEFORE (220):  ...and if you misunderstand them early, the product wi
```

Near-identical titles are the weak-differentiation signal behind
"crawled — currently not indexed", which is the exact symptom on this
property.

## What changed

`seo_title` and `seo_description` frontmatter on **every one of the 192
pages**, written by hand against each page's real content and optimised
for the click — lead with what the reader can do, name the concrete
things covered, no keyword stuffing, no repeating the title.

| | Before | After |
|---|---|---|
| Duplicate titles | 32 pages | **0** |
| Duplicate descriptions | — | **0** |
| Descriptions cut mid-word | 109 | **0** |
| Descriptions over 160 chars | 174 | **0** |
| Title length (incl. suffix) | up to "Overview" | **26–60** |
| Description length | 31–240 | **122–158** |

**No prose was rewritten.** I measured content overlap between the
colliding pairs first — only 17–23%, so these were always distinct pages
wearing the same label, not duplicate content. The `docs/` diff is **564
insertions, zero deletions**.

### Examples

```
BEFORE — all seven identical:  "Overview | Paperclip Docs"
AFTER:  "Adapters Overview"      "API Overview"        "CLI Overview"
        "Deployment Overview"    "Bundled Skills"      "Optional Skills"
        "Experimental Features"

BEFORE — both identical:  "Issues | Paperclip Docs"
AFTER:  "Issues: Creating and Tracking Work"   /guides/day-to-day/issues/
        "Issues API"                           /reference/api/issues/
```

```
/guides/getting-started/five-minute-path/
BEFORE (220):  The shortest route from a running Paperclip instance to an agent that has
               just completed work for you. After Paperclip is installed, the path takes
               about 5 minutes: create a company, hire a CEO agent, approve its first s
AFTER  (131):  Install Paperclip, create a company, hire a CEO agent, and approve its
               first strategy — a working AI company in about five minutes.
```

## Plumbing

- **`site/build-release.mjs`** prefers the authored fields; the derived
path stays only as a fallback the CI gate prevents ever reaching.
`<title>`, `<meta name="description">`, and the `TechArticle` JSON-LD
all read from the same source.
- **`site/app.js`** uses the same fields, so a client-side transition
cannot leave a different title on screen than the crawler was served.
Verified in-browser: navigating `/guides/day-to-day/issues/` →
`/reference/api/issues/` swaps to exactly the server-rendered values, no
JS errors.
- **`scripts/verify-seo-metadata.mjs`** (new) enforces presence,
uniqueness, length, complete-sentence endings, and the
frontmatter-safety rules. Wired into `docs:test` and CI as its own step.

I negative-tested the gate rather than assuming it works — it correctly
fails on a duplicate title, a mid-word description, and a missing field,
and passes again once restored.

## Automating it going forward

`skills/sync-docs/SKILL.md` now:

- gains an **"Authored SEO metadata"** section: why the fields exist,
the enforced rules as a table, and how to actually write them (title
names the subject not the nav position; description writes for the
click; never generate mechanically from the first paragraph — *that is
the fallback the gate exists to prevent*).
- requires both fields in the **page-authoring instruction** given to
every subagent, with guidance on when to update an existing description
versus leave it.
- runs `docs:test:seo-metadata` and `docs:test:crawlable-links` as
**fail-loud gates in Phase 7** before commit.
- documents all six build gates in the files/gates section.

So once this lands, a new page cannot ship without hand-written
metadata, and a title collision cannot reach production.

## Verified

All six verifiers pass:

```
Static route verification passed
Asset fingerprint verification passed
Hierarchical Skills nav verification passed
Skill source block verification passed (11 skill pages, 1 control page)
Crawlable-link contract passed: 40886 internal links across 194 pages resolve in one hop
Authored-SEO contract passed: 192 pages carry a unique, hand-written seo_title and seo_description
```

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
2026-08-25 22:51:42 +02:00
Aron PrinsandClaude Opus 5 29beedeb6a seo: make the docs link graph crawlable (#113)
## Why

Google has indexed effectively nothing on `docs.paperclip.ing`. Search
Console over 3 months: **8 of 192 URLs** have ever drawn an impression,
**681 of 975 impressions (70%) go to
`/guides/agent-developer/comments-and-communication`** — a legacy URL
that 301s and isn't in the sitemap. Strip that, the homepage, and the
team's own `site:` queries, and the canonical docs corpus earned **~7
organic impressions in 90 days**.

It isn't an eligibility problem. Pages are fetchable, self-canonical,
`index, follow`, and identical under a Googlebot UA. It's the internal
link graph.

## What was actually broken

**1. Every relative markdown link 404'd.** Authors write
`./glossary.md`, but pages are served from trailing-slash route
directories, so links resolved one level too deep:

```
page: /guides/welcome/key-concepts/   href: ./glossary.md
  → /guides/welcome/key-concepts/glossary.md   404
  ( /guides/welcome/glossary.md would be 200 )
```

Crawled all 192 live pages: **all 742 unique `.md` targets return 404**.
That's **1,283 of 1,306 in-body internal links — 98% — broken**, leaving
**0.1 working in-body links per page**.

It went unnoticed because `app.js:postProcessInternalLinks` repairs
these at runtime. Crawlers index the pre-render.

**2. The sidebar wasn't server-rendered.** Interior pages shipped `<div
id="sb-sections"></div>`, filled by JS. So the raw HTML offered the
logo, prev, next — and ~7 dead links. No link equity reached deep pages.
Search Console classified 98% of crawling as refresh, 2% as discovery.

Net effect: a crawler saw every page as a dead end that was 98% broken
links. Crawl demand collapsed — 14 crawled of 184, 15% of crawl
responses 404.

## Changes

- **Rewrite markdown links to canonical routes at build time**, and fail
the build on any link no nav page publishes. (Passed first run with zero
unresolved — every link had a valid destination, just emitted in a
404ing form.)
- **Server-render the sidebar and breadcrumb** into every interior route
from the manifest `app.js` already uses. `app.js` detects
`data-server-rendered` and keeps the DOM rather than re-rendering
identical markup. The mobile drawer stays client-built — it's
`inert`/`aria-hidden` until a JS toggle opens it, so rendering it
duplicated 192 links/page (~41KB) for no crawl benefit.
- **Intercept canonical route links in articles** so in-page navigation
stays a soft transition instead of a full reload.
- **Omit sitemap `<lastmod>` when git history is untrustworthy.**
Reproduced the real mechanism: in a `--depth=1` clone, `git log -1`
returns the single fetched commit's date for *every* file. Two files
that differ locally (`2026-08-18` / `2026-07-08`) both come back
`2026-08-25` shallow. That is exactly the live `192 × 2026-08-20`.
Cloudflare Pages shallow-clones by default.
- **Ship `redirects.json`** — `app.js` fetches it at boot and it 404'd.
- **Canonicalise the footer's `/reference/api/overview`** link, which
spent a 301 on all 193 pages.
- **Add `scripts/verify-crawlable-links.mjs` + CI**, gating on raw `.md`
hrefs, missing targets, redirecting targets, relative hrefs, an
unrendered sidebar, and uniform sitemap dates.

The last two were both caught by the new verifier on its first run.

## Result

| | Before (production) | After (generated bundle) |
|---|---|---|
| Broken in-body links | 1,283 (98%) | **0** |
| Working in-body links | 23 | **1,501** |
| Crawlable nav links/page | 0 | **192** |
| Distinct sitemap dates | 1 | **24** (0 on shallow CI) |

`Crawlable-link contract passed: 41078 internal links across 194 pages
resolve in one hop.`

## Verified

Built and driven in a real browser at `localhost:4321`:

- Raw HTML (crawler / no-JS view): 192 inline sidebar links, breadcrumb
rendered, **0 local `.md` hrefs**, single H1. Remaining empty containers
are JS-only UI (search modal, drawer, runtime status).
- SPA intact, no reloads, no JS errors: in-article links, prev/next,
sidebar links, mobile drawer (opens, 192 links, closes on navigate),
search (8 results for "adapter"). Breadcrumb and active-link state
follow correctly throughout.
- Subpath build for gh-pages emits correct `/paperclip-docs/...` hrefs.
- Homepage unchanged: 15 landing cards, 192 directory links.
- Shallow-clone build confirmed to warn and emit zero `<lastmod>`.

## Notes for review

- **This can't ship until the Cloudflare GitHub App is unsuspended.**
Everything here is verified against a local build only.
- **CI will be red on one pre-existing, unrelated failure**:
`docs:test:skill-source-blocks` on
`docs/reference/skills/optional/content/simplified-english.md` (missing
its skill-source block, from release #95). Confirmed failing on clean
`main`. Left in the aggregate rather than weakening the suite — fixing
it needs the real `SKILL.md` from the parent repo, which is sync-docs
work.
- **Production will now ship no `lastmod` at all** on Cloudflare's
shallow clone. Correct versus lying. To get real dates back, set the
Pages build command to `git fetch --unshallow || true; npm run
docs:build` — documented in the generated `DEPLOY.md`.
- Page weight 67KB → 109KB from the inlined nav. Highly repetitive,
compresses well, but it is a real increase.
- Weak/duplicate titles were deliberately skipped, per the plan's own
ranking (secondary).
- Plan item 4 (contextual links from high-authority surfaces to 20–25
priority pages) is a `paperclip-website` change plus editorial judgment,
so it's out of scope here. Worth noting that fixing the internal graph
recovers most of what that item was meant to buy — the dominant
authority failure was internal, not off-site.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
2026-08-25 21:57:07 +02:00
Aron PrinsandClaude Opus 4.8 8a858777f2 sync-docs: tag-accuracy gate + release-channel-aware skill (#111)
Makes /sync-docs correct under the canary→nightly→beta→stable channel model. Adds the release-mode tag-accuracy gate (scripts/sync/check-tag-accuracy.mjs) that verifies every changed page against the stable tag and flags post-tag leaks; stable-CalVer guard + channel glossary, tag-scoped drift/verify, and Phase 5.7 in the skill; realign fix that keeps nightly's drafts; a release-channels watcher; the analysis/plan doc; and a hermetic test (sync:test 38/38).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-08-25 11:48:38 +02:00
631a6a0c53 Release docs for paperclip v2026.817.0 (content + screenshot overhaul) (#95)
Ships the v2026.817.0 docs to live: the doc content that was authored
and verified
earlier, plus a full screenshot overhaul.

The content half (`cdf81e2` and the nightly commits behind it) has
already been
reviewed. **The screenshots are the part that needs eyes** — `f24d734`,
342 PNGs.

## Screenshots

Everything was recaptured against the release commit
`213dabab4f8e1f3bb1803a2924c0fea1289fcd4c`
(`upstream/candidate/release-2026.817.0`). The previous shots were 375
parent-commits stale (v2026.720.0), with 228 of 310 entries flagged
pending. All
342 registry entries now carry that SHA.

> ⚠️ Worth knowing: the release commit is **not** an ancestor of the
parent's
> `master`, and local `master` was four days *older* than it. Capturing
against
> `master` would have both missed release UI and leaked 93 post-tag
commits' worth
> of UI into the release docs.

### New coverage (34 entries)

Three guides shipped with **no images at all** despite being 115–136
lines. They
now have them:

| Guide | Shots |
|---|---|
| `guides/day-to-day/decisions.md` | queue, an agent-proposed decision
with its options, triage strip, filter panel, named queue, Decided
curtain, empty state |
| `experimental/status-cards.md` | board, New card dialog, and all four
drawer tabs |
| `experimental/task-chat.md` | thread, composer mode picker, side pane
|
| `reference/api/secrets.md` | the board-side Proposals tab |

Chat-Style Tasks is captured in a **separate pass**:
`enableTaskChatRedesign` is
instance-wide, so leaving it on would have turned every classic
issue/task/work-mode
shot into the redesigned chat.

## Two defects that were already live

Both were shipping in the docs before this PR:

1. **`issues/detail-chat.png` and the `tasks/*` shots were mostly plugin
debug
output.** The Kitchen Sink example plugin mounts a panel into the issue
page
that dumps the raw issue JSON, and the seed installed it. Those guides
were
illustrating a debug panel instead of the task page. The seed no longer
   installs it.
2. **The seeded task thread was a monologue** — four board-user messages
in a row,
because the board actor cannot post agent comments. It is now a real
two-sided
   exchange.

## Targets repointed because the UI moved

| Target | Why |
|---|---|
| `activity/*` | `Activity.tsx` deleted; `/activity` renders
`pages/audit/CompanyActivity.tsx` |
| `experimental/cloud-upstream` | `CloudUpstream.tsx` deleted; the route
now redirects to `/company/export` |
| `settings/*`, `plugins/*`, `adapters/*` | `/instance/settings/*` are
legacy redirects now |
| `dashboard/stale-tasks-panel` | panel removed from `Dashboard.tsx` —
target dropped |

Plus eight targets with **silent selector drift**. A failed interaction
step falls
back to "whatever state was reached", so these had been quietly
producing wrong
images — a plain inbox where the doc promised a mode picker, a whole
dashboard
where it promised one panel. Full table in
`docs/user-guides/screenshots/SCREENSHOTS_PLAN_v2026.817.0.md` §C2.

## Pipeline

Decisions, status-card summaries and secret proposals are all
**agent-authored**,
and the board actor the seed runs as is refused by every one of them
(`"Agent run context required"`, `"Secret proposals require a verified
run-bound
agent token"`). Rather than insert rows behind the API,
`seed-new-surfaces.mjs`
borrows the two doors a real run already has — a board-minted agent API
key, and a
locally signed agent JWT — so every write goes through the production
code path.

Also:
- `capture.mjs` records a real `captured_against` on a detached checkout
instead of
the literal string `"HEAD"` (which is what every pre-2026.817 entry
recorded), and
  gains a `scrollTo` step for content below the fold.
- `run.mjs` gains `--serve` for iterating on the seed, the task-chat
phase, and a
keeper that holds the demo board's issue statuses steady — the demo
`process`
agents finish runs without declaring a disposition, so the stalled-work
sweep
re-blocks issues every few minutes over a capture that runs far longer.

## Reviewing

Light and dark both captured at 1440×900 @2x. The new surfaces are the
ones to
scrutinise; the rest is a like-for-like refresh.

### One leftover

Dropping `dashboard/stale-tasks-panel` leaves
`{light,dark}/dashboard/stale-tasks-panel.png`
tracked but unused — they need deleting by hand.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
Co-authored-by: DevRel Gemini <[email protected]>
Co-authored-by: Paperclip <[email protected]>
Co-authored-by: Dotta <[email protected]>
Co-authored-by: ClaudeCoder <[email protected]>
2026-08-18 12:43:56 +02:00
c7b3f4cacf Render full SKILL.md as a code snippet on per-skill pages (PAP-16980) (#89)
> **Updated on current main:** #87 and the #90 cache hotfix are merged.
This PR now targets `main`, was rebased onto merge commit `8c5976f`, and
has a fresh successful Cloudflare preview plus post-rebase browser smoke
evidence.

## What & why (PAP-16980)

Improves SEO/AEO on the bundled/optional **per-skill reference pages**
(from PAP-16670) by clearly separating the *human-readable catalog
summary* (top of page) from the *authoritative full skill definition*.

Previously the "Full skill definition" section rendered the `SKILL.md`
as **parsed Markdown**, so each skill's own `##` headings, lists, and
fenced examples became real page content — competing with the summary,
inflating the on-page TOC (e.g. qa-acceptance went from **16 → 6** "On
this page" entries), and confusing crawlers/answer engines about the
page's true structure.

Now each per-skill page shows the **complete, verbatim `SKILL.md`**
(frontmatter + body) inline, rendered through the **existing production
code-snippet treatment**.

## Changes

- **Content (10 per-skill pages):** replaced the old `### Skill
frontmatter` bullets + parsed `### Skill instructions` layout with the
full `SKILL.md` embedded in a fenced ````markdown skill-source` block.
Source bytes were taken verbatim from each skill's authoritative
`SKILL.md` at the page's pinned `paperclip_version`, verified against
the page's own prior instructions body + frontmatter (name/description)
so no content drifted.
- **Renderers (`site/build-release.mjs`, `site/app.js`):** a
`skill-source` fence renders as `<pre><code class="language-markdown"
data-skill-download="SKILL.md">`. Every other code block is delegated to
marked's default renderer, so existing snippets are byte-for-byte
unchanged. Rendered identically in the crawler-visible build HTML and on
client SPA navigation.
- **Copy + Download (`site/app.js`, `site/styles.css`):**
`decorateCodeBlocks` reuses the existing Copy affordance and adds a
**Download `SKILL.md`** control beside it. Both share dimensions,
styling, hover/focus visibility, and the copied-success state; both
carry accessible labels/titles.
- **Readable full-source wrapping (`site/styles.css`):** only the
downloadable `SKILL.md` block uses `white-space: pre-wrap` and safe
long-token wrapping. Ordinary code snippets retain the existing
horizontal-scroll treatment.
- **Test:** `scripts/verify-skill-source-blocks.mjs` (`npm run
docs:test:skill-source-blocks`) asserts the render contract (single H1,
single `<pre>`, frontmatter present, no legacy headings) and that
ordinary docs pages emit no `data-skill-download`.

## Scope statement

No catalog-page layout, navigation, typography, summary-copy,
metadata-card, or information-architecture changes. `paperclip-website`
and generated `.site/` output are untouched. `optional/finance/ramp.md`
is intentionally excluded — it is a newer summary page with no embedded
full-definition section to reformat. The diff is the 10 skill pages +
the narrow renderer/Copy-Download support + the test.

## Evidence

**1–2. Before/after (desktop, 1280×900) + mobile after (390×844)** —
attached to Paperclip issue
[PAP-16980](https://paperclip-dev.tail29c1aa.ts.net/PAP/issues/3098577a-4f6f-4eb2-9151-a4b61917dffd)
(`before-desktop.png`, `after-desktop-controls.png`,
`after-controls-zoom.png`, `after-mobile.png`). GitHub cannot render the
auth-gated attachment URLs inline, so they live on the issue for
reviewers.

**4. Raw DOM/HTML (build output, qa-acceptance):**
- Article renders exactly **one H1**: `<h1 id="qa-acceptance">QA
Acceptance</h1>`
- Full source inside a single code block:
```html
<pre><code class="language-markdown" data-skill-download="SKILL.md">---
name: qa-acceptance
description: Produce QA acceptance criteria and a manual validation plan …
key: paperclipai/bundled/quality/qa-acceptance
recommendedForRoles:
  - qa
  …
</code></pre>
```
- Article `<pre>` count: **1** (inner ````` fences stay literal — no
breakout). 10/10 skill pages carry the block; 0 non-skill pages do.

**5. Copy + Download behavior (Playwright against the built site):**
```json
{
  "downloadFilename": "SKILL.md",
  "downloadMatchesBlock": true,     // downloaded file === code block text, byte-identical
  "downloadBytes": 3853,
  "copyShowsSuccess": true,          // Copy toggles the existing is-copied success state
  "accessibleLabels": { "copy": "Copy code", "download": "Download SKILL.md" }
}
```
Both controls reach `opacity: 1` on `.code-wrap:hover` and on keyboard
`:focus-visible` (verified `matches(':focus-visible') === true` →
computed opacity `1`).

**H1 audit (every generated route, incl. all skill URLs — requested on
the issue):** built the site on current `main` and scanned **all 184
generated `index.html` routes** (16 skill routes among them). **Every
route has exactly one `<h1>`.** The skill source's own `#`/`##` headings
live *inside* the `<pre><code>` block as literal text, so they do
**not** create competing H1s — the SEO/AEO goal.

## Tests

Run against current `main` after #87 and #90:

```
docs:build ............................. ok (184 routes)
docs:test:static-routes ................ pass (5 routes + 404 + root + subpath)
docs:test:skill-source-blocks .......... pass (10 skill pages, 1 control page)
H1 audit (all 184 routes) .............. pass (exactly 1 h1 each; 16 skill routes)
```

**Do not merge/deploy** — returning to Dotta/reviewers for approval per
PAP-16980.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: DevRel Gemini <[email protected]>
Co-authored-by: Paperclip <[email protected]>
2026-08-10 14:03:47 -07:00
8c5976ffd3 URGENT: fingerprint docs client bundle to fix mixed-version cache regression (PAP-16990) (#90)
## Urgent hotfix — mixed-version asset cache regression (PAP-16990)

Restores reliable navigation on https://docs.paperclip.ing/ without
undoing the PAP-16670/#87 server-render + single-H1 SEO/AEO work.

### Root cause
The server-render change shipped new HTML that removed `#loading` /
`#error-state`, but every generated route still loaded the client bundle
from a **stable URL**: `<script src="app.js" defer>`.
Cloudflare/browsers cache `/app.js` for up to ~4h independently of the
HTML, so a returning visitor could pair freshly-revalidated new HTML
with a **pre-merge cached `app.js`**. The old click path looked for the
removed elements, threw before render, hid the homepage, and left a
blank `#main` (no URL update). Forced refresh recovered — not
acceptable.

CSS was never part of this: it is inlined into every page and travels
with the (revalidating) HTML. `content.json` is byte-identical
prod↔preview.

### Fix (narrow cache-bust, no rollback)
1. **Content-fingerprint the client bundle.** Emit `app.<hash>.js` (+
`styles.<hash>.css`) and rewrite the shell so *every* route references
the exact build's asset URL. A changed bundle gets a brand-new URL no
cache can satisfy with stale bytes — closes the mixed-version window in
**both** directions. No unversioned `/app.js` is emitted, so a stale
cache has nothing to pin.
2. **`_headers`:** fingerprinted JS/CSS cached `immutable` (1y); HTML
routes (`/`, `/*/`) and `content.json` set `max-age=0, must-revalidate`.
3. `inlineReleaseStyles` now matches the fingerprinted stylesheet link
so CSS stays inlined.

### Before / after
```
- <script src="app.js" defer></script>          # stable URL — cacheable across versions
+ <script src="app.1b669c8d0aec.js" defer></script>   # content-hash URL — cache miss on any change
```
`_headers` (new):
```
/app.*.js
  Cache-Control: public, max-age=31536000, immutable
/
/*/
  Cache-Control: public, max-age=0, must-revalidate
/content.json
  Cache-Control: public, max-age=0, must-revalidate
```

### Verification (local build, base path `/`)
- `npm run docs:build` → emits `app.1b669c8d0aec.js`,
`styles.9e3f24983c72.css`; **184/185** HTML files reference the
fingerprinted bundle (185th is the scriptless `404.html`); **no** bare
`app.js`/`styles.css` file or reference remains.
- `npm run docs:test:asset-fingerprints` ✅ (new) — proves the URL is the
content hash of the served bytes, changes on any content change, is
referenced identically by root + interior routes, has no unversioned
sibling, and the cache headers are present.
- `npm run docs:test:static-routes` ✅ — single-H1 interior pages, no-JS
server-render, homepage manifest completeness, 404 separation, root +
`/paperclip-docs/` builds.

### Remaining (post-merge, needs a real browser on the live domain)
Chromium can't launch in the CI/agent sandbox (missing system libs), so
**cold + returning/cached** browser smoke on https://docs.paperclip.ing/
must be run after merge → redeploy from `main`. Checklist: cold load,
homepage-card nav (URL updates, one H1, no blank), interior↔interior,
Back/Forward, All Docs, search, 404, and a returning/cached session
(prior `/app.js` in cache).

Does **not** touch the SKILL.md formatting PR (PAP-16980), per the
issue.

Co-authored-by: DevRel Gemini <[email protected]>
Co-authored-by: Claude Opus 4.8 <[email protected]>
2026-08-10 13:41:27 -07:00
e2adb1c167 PR1 — server-render the docs root and split it from interior routes (Phase 1) [DO NOT MERGE] (#87)
# PR1 — server-render the docs root and split it from interior routes
(Phase 1)

**Do not merge — Dotta alone may merge.** This PR is opened for review
only, per the hard write-gate on the approved plan.

## Provenance

| item | link |
|---|---|
| Accepted plan | [PAP-16672 · plan
document](https://paperclip-dev.tail29c1aa.ts.net/PAP/issues/PAP-16672#document-plan)
|
| Phase 0 review packet | [PAP-16671 · packet
comment](https://paperclip-dev.tail29c1aa.ts.net/PAP/issues/PAP-16671#comment-f653273d-6450-4f8d-bcd6-f805ad28b923)
|
| Implementation candidate |
[PAP-16682](https://paperclip-dev.tail29c1aa.ts.net/PAP/issues/PAP-16682)
|
| Independent QA — **PASS** |
[PAP-16683](https://paperclip-dev.tail29c1aa.ts.net/PAP/issues/PAP-16683)
|
| Finalization / this PR |
[PAP-16684](https://paperclip-dev.tail29c1aa.ts.net/PAP/issues/PAP-16684)
|
| Full evidence gallery (screenshots + raw JSON probes) |
https://pages.paperclip.ing/pap-16684-pr1-evidence/ |

Base: approved `main` @ `2ab76e8e4`. Head: `f5bbba24c` (exactly one
commit on top; `main` has not moved).

## What changed

- **1.1 — root-only landing shell.** The hero is *physically absent*
from interior documents (removed at build time, not CSS/JS/ARIA hidden);
the build throws if removal fails. Header, footer, search, sidebar,
breadcrumbs and article nav are preserved on every page.
- **1.2 — server-rendered homepage directory** generated from the same
canonical `site/content.json` manifest that already feeds the sidebar,
breadcrumbs, prev/next, routes and sitemap. No second URL manifest was
introduced.
- **Single descriptive H1 per interior page** (was 2 — the hero H1 bled
onto every route).
- **Truthful runtime UI.** `Loading…` / `Could not load this guide.` no
longer ship inside success HTML; they are produced only by `app.js` at
runtime on the empty, `hidden` `#runtime-status` mount, so they can only
appear during a genuine client transition or failure.

```
 scripts/verify-static-routes.mjs | 200 +++++++++++++++++++++++++++++++++-
 site/app.js                      |  90 ++++++++++++----
 site/build-release.mjs           | 189 ++++++++++++++++++++++++++++++--
 site/index.html                  |  17 ++--
 site/styles.css                  |  70 ++++++++++-
 5 files changed, 528 insertions(+), 38 deletions(-)
```

`.site/` is **generated build output and remains uncommitted**
(gitignored): `git ls-files | grep '^\.site/'` → 0 files.

## Before → after, raw HTTP/HTML for the six representative routes

Both trees built with the identical command and base path, then served
by a production-equivalent static server (real 404 status, honors
`_redirects`). "Before" is a real build of approved `main` @
`2ab76e8e4`.

| route | HTTP | content type | H1 count before → **after** | H1 text
(after) | `id="landing"` before → after | `Loading…` | `Could not load
this guide.` | internal directory anchors |
|---|---|---|---|---|---|---|---|---|
| `/` | 200 | `text/html` | 1 → **1** | Everything you need to run
Paperclip. | 1 → 1 (root-only ✓) | 1 → **0** | 1 → **0** | 4 → **184** |
| `/guides/welcome/what-is-paperclip/` | 200 | `text/html` | 2 → **1** |
What is Paperclip? | 1 → **0** | 1 → **0** | 1 → **0** | 4 → 4 |
| `/reference/api/overview/` | 200 | `text/html` | 2 → **1** | API
Overview | 1 → **0** | 1 → **0** | 1 → **0** | 4 → 4 |
| `/how-to/add-mcp-server-to-agent/` | 200 | `text/html` | 2 → **1** |
Add an MCP server to an agent's toolkit | 1 → **0** | 1 → **0** | 1 →
**0** | 4 → 4 |
| `/reference/changelog/` | 200 | `text/html` | 2 → **1** |
Documentation Changelog | 1 → **0** | 1 → **0** | 1 → **0** | 4 → 4 |
| `/guides/welcome/this-route-does-not-exist/` | **404** | `text/html;
charset=utf-8` | 1 → **1** | Not found | 0 → 0 | 0 → 0 | 0 → 0 | 0 → 0 |

Machine-readable probes:
[before-raw.json](https://pages.paperclip.ing/pap-16684-pr1-evidence/before-raw.json)
·
[after-raw.json](https://pages.paperclip.ing/pap-16684-pr1-evidence/after-raw.json).

### Homepage bleed and false state — absence proof

- `id="landing"` returns **zero** matches in every interior document.
Only inlined `#landing-*` **CSS selector text** remains (stylesheet, not
markup).
- Interiors carry no directory manifest (4 internal anchors — the
footer); the 184-anchor directory is root-only.
- The two false-state phrases appear in **0** built HTML files across
the whole bundle.

### 404 / noindex / sitemap

- Real HTTP **404** for the nonexistent route (root base and
`/paperclip-docs/` subpath build).
- `404.html`: exactly one `<h1>Not found</h1>`, `<meta name="robots"
content="noindex, nofollow">`, `<title>Not found | Paperclip
Docs</title>`.
- Absent from `sitemap.xml` (0 occurrences); no built file for the
route.
- `sitemap.xml` has 184 `<loc>` (183 routes + root) and the root
directory anchor set covers **183/183** non-root sitemap routes — 0
missing.
- `_redirects` contains **no wildcard `200` rewrite** (0 lines with a
`200` status), so unknown routes cannot be masked as success.
- `robots.txt`: `User-agent: * / Allow: /` + `Sitemap:
https://docs.paperclip.ing/sitemap.xml`.

## Focused checks — rerun on the final revision (`f5bbba24c`)

| command | result |
|---|---|
| `npm run docs:test:static-routes` | **PASS** — "Static route
verification passed (5 representative routes +
/guides/welcome/this-route-does-not-exist/, root and /paperclip-docs/
builds)." |
| `npm run docs:build` | **PASS** — "Generated 183 crawlable route pages
plus sitemap.xml and robots.txt." |

`git status` is clean after the build (no generated output enters the
tree).

## Browser matrix — desktop 1440×900 and mobile 390×844

Run with Playwright + Chromium 1228. The QA sandbox could not exercise
this (blank-glyph text rendering); the root cause turned out to be that
**no fonts are installed on the host at all** — installing DejaVu TTFs
with a minimal fontconfig makes text render correctly, which unblocked
the full interactive matrix here. Screenshots:
https://pages.paperclip.ing/pap-16684-pr1-evidence/

### Per-route, JavaScript enabled (both viewports)

All six routes on both viewports: expected HTTP status, **exactly 1
`<h1>`** with the correct text, `#landing` present **only** on `/`, no
`Loading`/`Could not load this guide.` text in the rendered body,
`#runtime-status` hidden, **no horizontal overflow**.

### Interactive

| check | result |
|---|---|
| root directory link → interior (client nav) | ✅
`/guides/welcome/what-is-paperclip/`, single H1 "What is Paperclip?",
hero gone, not stuck loading |
| direct load vs client-nav parity | ✅ identical H1 set |
| back / forward history | ✅ back → `/` with hero restored; forward →
interior with correct H1 |
| home nav from an interior doc | ✅ `/` with hero |
| theme toggle | ✅ toggles (`dark` → light) |
| desktop sidebar / TOC / breadcrumbs / prev-next / search / footer | ✅
191 sidebar links, 14 TOC links, breadcrumbs rendered, article nav
present, search control present, 15 footer links |
| mobile drawer | ✅ opens (screenshot `mobile-drawer-open.png`) |
| mobile horizontal scroll | ✅ none |
| unknown route | ✅ 404 page, single H1, noindex |

### JavaScript disabled

| check | result |
|---|---|
| `/` directory usable with JS off | ✅ 202 anchors present in raw
markup; hero + card directory fully rendered |
| clicking a directory link with JS off | ✅ full page load to
`/reference/api/overview/` |
| that interior page with JS off | ✅ 1 H1 ("API Overview"), no hero, no
false loading/error state, 6368 chars of real article text |
| mobile with JS off | ✅ root and interior both render correctly |

### Console / network

No JavaScript errors and no page errors on any route. Exactly two
non-2xx requests, **both reproduced identically on approved `main` @
`2ab76e8e4`** — neither is introduced by this PR:

- `GET /redirects.json` → 404. Pre-existing: neither the before nor
after build emits this file. Verified byte-for-byte identical behaviour
on `main`.
- `GET https://api.github.com/repos/paperclipai/paperclip` → 403.
Unauthenticated GitHub API rate limit for the header star counter;
environmental, external, not a product defect.

Also confirmed unchanged before → after on the same interior page:
header (1), footer (1), search controls (4), sidebar links (191), TOC
links (14), article nav (2), article text length (4328 chars). The
**only** rendered difference is the intended H1 2 → 1 and the removed
hero.

## Verified against the real Cloudflare Pages deploy, not just a local
server

The Cloudflare Pages check on this PR is **green** and produced a live
preview:
**https://pap-16682-server-render-root.paperclip-docs-74t.pages.dev**

I reran the entire matrix against that real deploy. Every invariant
reproduces **identically** to the local run — so these results hold on
actual production hosting, including Cloudflare's own 404 handling:

| route | HTTP | H1 | `#landing` | `Loading…` | `Could not load…` |
noindex | anchors |
|---|---|---|---|---|---|---|---|
| `/` | 200 | 1 — Everything you need to run Paperclip. | present
(root-only) | 0 | 0 | – | 184 |
| `/guides/welcome/what-is-paperclip/` | 200 | 1 — What is Paperclip? |
absent | 0 | 0 | – | 4 |
| `/reference/api/overview/` | 200 | 1 — API Overview | absent | 0 | 0 |
– | 4 |
| `/how-to/add-mcp-server-to-agent/` | 200 | 1 — Add an MCP server to an
agent's toolkit | absent | 0 | 0 | – | 4 |
| `/reference/changelog/` | 200 | 1 — Documentation Changelog | absent |
0 | 0 | – | 4 |
| nonexistent route | **404** | 1 — Not found | absent | 0 | 0 | **yes**
| 0 |

Browser matrix on the live preview, desktop 1440×900 and mobile 390×844:
identical outcomes — client nav, direct-load parity, back/forward,
home-nav, theme toggle, 191 sidebar links, 14 TOC links, mobile drawer
opens, no horizontal scroll, and with **JavaScript disabled** the root
directory (202 anchors) navigates by real page load into an interior
with 1 H1, no hero, no false state and 6368 chars of article text.

**Console/network on the live deploy: zero page errors.** The same two
known non-product requests appear (`/redirects.json` and the GitHub
star-count API). `/redirects.json` returns **404 on live production
`docs.paperclip.ing` today** and on the `main` branch preview —
conclusively pre-existing and unrelated to this PR.

Screenshots from both the Cloudflare deploy and the local server are in
the gallery: https://pages.paperclip.ing/pap-16684-pr1-evidence/

## Out of scope — pre-existing observation, not a regression

On the `--base-path /paperclip-docs/` subpath build, 4 footer links
(`/reference/api/overview`, `/guides/org/agents/`,
`/guides/org/adapters/`, `/guides/getting-started/five-minute-path/`)
are emitted un-prefixed. Building approved `main` @ `2ab76e8e4` with the
identical flag reproduces **exactly the same 4 links**, so this is a
pre-existing footer-template issue untouched by this PR. Smallest fix
would be routing the footer's hardcoded hrefs through the base-path
prefixer, in a separate ticket.

## Merge policy

`.site/` is generated output and is intentionally uncommitted. **This PR
must remain open and unmerged — Dotta alone may merge it.**

Co-authored-by: ClaudeCoder <[email protected]>
Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
2026-08-10 13:11:38 -07:00
Michael Nguyenandanicca f80e8a7289 Make docs navigation crawlable and sitemap dates accurate (#77)
## Summary
- emit previous and next article navigation as real anchors in generated
HTML
- preserve the existing client-side navigation behavior
- derive sitemap lastmod values from each Markdown file's Git history
- omit lastmod when history is unavailable instead of publishing the
build date
- remove ignored changefreq and priority values
- add regression assertions for crawlable links and sitemap dates

## Verification
- npm run docs:test:static-routes
- npm run sync:lint-links
- npm run docs:build
- generated 183 pages with zero server-rendered orphans, minimum one
inbound link, and 23 distinct lastmod dates
- git diff --check

## Risk
Low. No routes, redirect rules, canonicals, robots directives, or
index/noindex policy changed. Production still requires merge through
the existing workflow.

Co-authored-by: anicca <[email protected]>
2026-07-28 13:06:09 -05:00
175648e771 docs: add Experimental feature section and screenshots (#71)
## Summary

- adds a new **Experimental** documentation section with an overview and
10 feature pages covering motivation, enablement, usage, and caveats
- wires the section into `site/content.json` and refreshes the
experimental flag list in administration settings
- adds six screenshot capture targets and 12 QA-verified screenshots
(light and dark) for experimental feature surfaces
- includes the screenshot-pipeline fixes needed to seed and capture
those surfaces reliably

## Screenshots

Adds light and dark captures for:

- environments
- cloud upstream
- file viewer
- external objects
- server info
- recovery preview

The 12 PNGs were verified on Paperclip task PAP-14814 on July 21, 2026
and were preserved byte-for-byte during the rebase.

## Verification

- `npm run sync:lint-links` — pass; no broken internal links
- `npm run sync:verify-nav` — pass; only the two pre-existing CLI
orphans
- `npm run sync:verify-screenshots` — pass; every documented screenshot
is tracked and indexed
- `npm run docs:build` — pass

Paperclip: PAP-14705

---------

Co-authored-by: DevRel Gemini <[email protected]>
Co-authored-by: Paperclip <[email protected]>
Co-authored-by: Claude Fable 5 <[email protected]>
2026-07-21 10:39:28 -05:00
Aron PrinsandClaude Fable 5 5fdce2b098 screenshots: pre-seed capture phase for onboarding-wizard shots (#70)
Fixes the harness limitation flagged in #68: the seeded instance always
has a company, so the create-a-company wizard was unreachable and
onboarding shots fell back to the Dashboard.

**How:** `run.mjs` gains a phase 3.5 — after health check, before
seeding — that captures targets marked `phase: "pre-seed"` while the
instance is still company-less (`/onboarding` serves the wizard there).
`capture.mjs` gains a `phase` option (`--phase`); post-seed stays the
default, so existing invocations are unchanged.

**Retargeted:** the four true wizard shots to `/onboarding` (goal-field
fills the company name and advances to the Mission step); the two budget
shots to the agent configuration form, since the wizard has no budget UI
(verified at v2026.720.0).

**Validated with real runs against the v2026.720.0 tag** — all pre-seed
captures succeed with zero step failures, light and dark visually
verified (wizard step 1 empty, filled name, Mission step). Refreshed
PNGs included.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Fable 5 <[email protected]>
2026-07-20 21:16:15 +02:00
Aron PrinsandClaude Fable 5 215dc2ed2d screenshots: wire routes for 20 unrouted registry entries (#69)
Backfills `route` + `dependsOn` for the 20 registry entries flagged in
#68 as never wired for automated capture (plus marks the hand-annotated
`dashboard-overview-annotated` as intentionally manual instead of
leaving its stale `_todo`).

Routes verified against the v2026.720.0 route table in `ui/src/App.tsx`;
every `dependsOn` path verified to exist at that tag. Details and
caveats (dialog-step captures, the onboarding harness limitation) in the
commit message.

No images change in this PR — next capture pass picks these up.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Fable 5 <[email protected]>
2026-07-20 20:49:52 +02:00
8121a9c947 Release docs for paperclip v2026.720.0 (#67)
Ships the docs for **paperclip v2026.720.0** to `docs.paperclip.ing`.

Window: `v2026.707.0...v2026.720.0` — 196 commits, 1,523 changed files,
0 truncated leaves.

Most of this release was already drafted on `nightly` over the past
cycle (Cases, Folders, Decision Training, Attention, Built-in Agents,
company skill policy, inbox agent policy, `costStatus`, the ACP engine
graduation and `acpx_local` retirement, and
`PAPERCLIP_TOOL_ACTION_SIGNING_SECRET`). This PR adds the surfaces
nightly had **not** yet covered, then stamps the release version across
everything touched this cycle.

## New pages

**`docs/reference/api/tool-gateway.md`** — the MCP Tool Gateway, the
headline experimental feature. Covers applications and connections,
catalog entries and risk levels, profiles/entries/bindings, the
tool-access policy and its decision outcomes, named MCP gateways and
their tokens, the audit feed, and the Smoke Lab. Documents the five
`tools:*` permission keys and the viewer/membership rules on routes that
don't use a permission key. Flags both experimental gates (`enableApps`,
and `enableSmokeLab` separately).

**`docs/reference/api/summary-slots.md`** — the built-in Summarizer and
summary slots. Covers slot addressing (`scopeKind` / `scopeId` /
`slotKey`), generation, revisions, and the `enableSummaries` gate.
Cross-references Built-in Agents rather than duplicating it.

## Updated

**`docs/guides/org/skills.md`** — Skill Studio (the three-pane authoring
workspace, saved inputs, test runs and their unavailability reasons, run
templates, version history), nested skill folders and the My Skills
view, importing skills straight from a project, and company skill forks.
Cross-references the existing Folders and Company Skill Policy API pages
instead of restating them.

## Release stamping

`paperclip_version: v2026.720.0` applied to all 26 pages touched this
cycle — bumped on 10 that already had frontmatter, added to 13 that had
none (including the API pages nightly authored, which were intentionally
versionless until they merged to `main`).

## ↻ Renames detected

`detect-renames.mjs` reports no directory renames. It flags one
`removed_dirs_no_match`:

- `packages/adapters/acpx-local` — **already reconciled on nightly.**
The adapter was retired upstream (ACP became a capability of each
harness adapter rather than a standalone adapter).
`docs/reference/adapters/acpx-local.md` is now a retired stub that
points at Claude Code / Codex / Gemini CLI and documents the automatic
migration. No action needed.

## Screenshots — full overhaul recommended

**248 of 298** registry entries are stale. This release landed a
design-system convergence (single-source design tokens, retuned theme,
broad Card/Badge adoption, a multiplicative radius ladder, unified list
surfaces, Lucide task-status glyphs), so nearly every captured surface
moved. This is an overhaul cycle, not a targeted refresh:

```sh
npm run screenshots:refresh:all
```

Full per-entry breakdown in `SCREENSHOTS_PENDING.md`. Captures go to
their own PR for review — nothing is auto-pushed.

## Verification

- **Drift:** clean — 0 records against `903bd15` (8 parent paths, 57 CLI
commands, 66 env vars, 389 REST routes, 18 permission keys, 4 roles).
- **Claim verification:** `verify-edit.mjs` against `v2026.720.0` — **0
unverified, 0 suspicious** across all three authored files.
- **Reconciliation:** no disappeared manifest entries.
- **`npm run docs:build`:** passes — 169 markdown files, sitemap and
robots generated.
- **`npm run sync:check`:** links clean (172 files), nav clean,
screenshots indexed, drift clean.
- **Nav orphans:** `docs/reference/cli/commands.md` and
`docs/reference/cli/control-plane-commands.md` — intentional redirect
anchors, expected.

`.sync-state.json` bumped to `base_release_tag: v2026.720.0` /
`base_release_sha: 903bd157…`, which also repoints the drift checker's
pinned ref (the previous `f12bb27…` no longer resolves upstream).

No open `nightly-draft/*` PRs to fold in.

## Checklist

- [ ] Tool Gateway page reads correctly for an operator enabling
`enableApps` for the first time
- [ ] Summary Slots experimental gating is accurate
- [ ] Skill Studio guide matches what you see in the running UI
- [ ] Decide whether to run the screenshot overhaul before or after
merging this
- [ ] **After squash-merging: run `node scripts/sync/realign-nightly.mjs
release/v2026.720.0 --push` before the next nightly sync.** The squash
severs `main`↔`nightly` ancestry; the realign (shipped in this PR)
prevents add/add conflicts at the next nightly run.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
Co-authored-by: DevRel Gemini <[email protected]>
Co-authored-by: Paperclip <[email protected]>
2026-07-20 19:59:18 +02:00
Aron PrinsandClaude Opus 4.8 55de2cbb81 fix(sync): pin drift check to an immutable SHA, key cache by SHA (#62)
Ports the drift-checker fix to `main` (same change already merged to
`nightly` in #61). `check-drift.mjs` is byte-identical across branches,
so this cherry-pick applies cleanly.

## Problem

The drift checker printed the parent's **live** SHA in its header but
keyed its file cache by the moving name `drift-master` with no
invalidation — reusing days-old file contents while claiming to check
today's commit, silently hiding real drift.

## Fix

- Resolve the ref to a full commit SHA before any reads; cache key =
`drift-<sha>`, never `drift-master`.
- Fail closed if the ref can't be resolved.
- Mode-aware ref from `.sync-state.json` (release → `base_release_sha`,
nightly → `last_seen_parent_sha`) before falling back to the default
branch. `main` is release-mode, so its checks now pin to the release SHA
instead of moving `master`.
- Testable cache path (`PAPERCLIP_SYNC_CACHE_DIR` + fixture SHA stub);
+2 regression tests. `npm run sync:test`: 37 passed, 0 failed.

## Triage note

Running the fixed checker on `main`'s released docs against the release
tag `v2026.707.0` returns **0 drift** — released docs are correct about
the shipped product; this is a tooling fix only, no doc content changes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.8 <[email protected]>
2026-07-15 13:36:41 +02:00
DottaandPaperclip ad0d5a930b Glossary: add per-term stable anchors (#52)
Convert glossary terms into citable heading sections and add matching static heading IDs to the release build. Static-route verification now asserts representative glossary term anchors.

Verification:
- npm ci --include=dev
- npm run docs:build
- npm run docs:test:static-routes
- git diff --check origin/main...HEAD
- Cloudflare preview glossary contains id="adapter", id="board-operator", and id="heartbeat"

Co-Authored-By: Paperclip <[email protected]>
2026-07-09 11:45:07 -05:00
Aron Prins 7e25158fca Release docs for paperclip v2026.707.0 (#49)
Promotes v2026.707.0 docs from nightly: Custom sandbox images + Ramp skill (new), Work Timeline (#48) and Secret scopes (#47) content, screenshot capture targets, environments nav reconcile, sync-state bump to v2026.707.0, and accuracy fixes from adversarial verification. 0 drift.
2026-07-08 11:11:32 +02:00
ce13816179 [codex] Fix docs SEO crawl hygiene (#46)
## Summary

Fixes the docs-side causes behind the Google Search Console
duplicate/canonical SEO issues by tightening generated static routing
behavior.

## What changed

- Removed the Cloudflare Pages wildcard `/* /index.html 200` SPA
fallback from the generated docs release so deleted or unknown asset
URLs can return 404 instead of serving docs HTML.
- Removed the global `X-Robots-Tag: index, follow` header and replaced
it with noindex coverage for non-page static assets, `sitemap.xml`,
`robots.txt`, and the generated `404.html`.
- Added legacy route handling for removed docs URLs and extended static
route verification for redirects, removed assets, noindex headers, and
404 behavior.

## Root cause

The generated Cloudflare Pages release treated too many non-page/static
URLs as indexable page responses. That allowed removed assets or
auxiliary files to be crawled as duplicate indexable documents instead
of clear 404/noindex responses.

## Validation

- `npm run docs:test:static-routes`
- `npm run docs:build`

PAP-12839

---------

Co-authored-by: DevRel Gemini <[email protected]>
Co-authored-by: Paperclip <[email protected]>
2026-07-06 20:13:40 -05:00
Dotta ac9e4a35e0 docs: Work Modes guide (ask work mode) [v2026.626.0]
Publish the approved Work modes docs guide for ask work mode.\n\nSource: PAP-12809 / release-content docs-guide--ask-work-mode
2026-07-06 13:59:19 -05:00
b214cdebda [codex] Improve docs Lighthouse scores (#41)
## Summary

Improves the docs page Lighthouse profile for the report attached to
[PAP-12441](/PAP/issues/PAP-12441).

- Removed render-blocking third-party docs shell requests for Google Tag
Manager, Google Fonts, and Lucide.
- Vendored the existing `[email protected]` parser locally and copied
`site/vendor` into release builds.
- Replaced Lucide runtime icon rendering with inline SVG paths for the
existing docs section icons.
- Fixed reported accessibility issues: mobile zoom disabling, hidden
drawer focusability, TOC ARIA semantics, footer heading order,
muted-text contrast, TOC button accessible name, and article link
affordance.
- Added smaller responsive WebP variants for the dashboard overview
screenshot and explicit dimensions/fetch hints for article images.
- Minified CSS in release builds.

## Canary

- Commit preview: https://2f89e7fc.paperclip-docs-74t.pages.dev
- Branch preview:
https://codex-lighthouse-docs-scores.paperclip-docs-74t.pages.dev
- Target route from the report:
https://2f89e7fc.paperclip-docs-74t.pages.dev/guides/getting-started/five-minute-path/

## Root Cause

The docs shell was paying for several third-party render-blocking
requests before first contentful render, and the target guide loaded a
large full-size dashboard PNG for a small mobile viewport. Several
Lighthouse accessibility audits were caused by UI semantics rather than
content: a hidden but focusable drawer, menu roles around plain links, a
non-zoomable viewport, footer heading level skips, and color-only
article links.

## Validation

- `npm run docs:build` passes.
- `npm run docs:test:static-routes` passes.
- `npm run docs:test:hierarchical-skills-nav` passes.
- `node --check site/app.js`, `node --check .site/app.js`, and `node
--check site/build-release.mjs` pass.
- Static release checks pass for preserved SEO metadata, removed
third-party assets, zoomable viewport, inert drawer, no footer headings,
underlined article links, responsive screenshot wiring, TOC nav
semantics, and copied optimized assets.
- Cloudflare Pages check passed for commit `129baaa`.

Local Lighthouse could not complete in this container because the
available cached Chromium binaries fail to start without
`libatk-1.0.so.0`. PageSpeed Online is also quota-limited from this
environment. The canary URL above is ready for a browser-capable
Lighthouse run.

---------

Co-authored-by: DevRel Gemini <[email protected]>
Co-authored-by: Paperclip <[email protected]>
2026-07-02 13:39:51 -05:00
dd7fa3e1c6 Canonicalize docs route redirects (#40)
## Summary

- Generates explicit Cloudflare Pages `_redirects` entries for every
slash-terminated static docs route.
- Sends no-trailing-slash docs URLs to their canonical slash URL with a
one-hop 301 before the SPA fallback.
- Extends the static-route verifier to assert those redirects are
emitted and ordered before the catch-all fallback.

## Root cause

Google Search Console was inspecting the no-trailing-slash URL. The live
page currently reaches content after a redirect chain, while the sitemap
and canonical URL use the trailing-slash form. Making the redirect
explicit in `_redirects` removes ambiguity for crawlers and keeps the
canonical route consistent.

## Verification

- `npm run docs:test:static-routes`
- `git diff --check origin/main...HEAD`

Co-authored-by: DevRel Gemini <[email protected]>
Co-authored-by: Paperclip <[email protected]>
2026-07-01 17:57:14 -05:00
Aron PrinsandClaude Opus 4.8 1bba6f6601 docs(access): document members, roles, permissions, invites & offboarding (#38)
Back-fills documentation for the human multi-user collaboration surface
(company members, invites, roles, permissions, offboarding). These
features are already shipped and live; this fills doc gaps and fixes one
live permission-key drift. Branched off `main` (not `nightly`) because
it's editorial back-fill of released features, intended to ship
independently of the nightly sync cadence.

## Tier 1 — correctness
- **Fix live permission drift** in `administration/company.md`: the
grant list and Owner/Admin role descriptions were missing
`environments:manage` and `tasks:manage_active_checkouts` (both present
in `packages/shared/src/constants.ts` `PERMISSION_KEYS`;
`environments:manage` is an Owner/Admin default in
`server/src/services/company-member-roles.ts`).
- **New** `administration/roles-and-permissions.md`: canonical 8-key
catalog (what each gates), role→default-grant matrix, additive
precedence rule, `instance_admin` layer, and current limitations.
- `maintenance/follow-ups.md`: note to teach the drift checker the
permission catalog so this can't silently drift again. (Sync tooling
itself untouched.)

## Tier 2 — how-tos
- `how-to/add-a-human-teammate.md` — invite → join request → approve →
set role/grants (UI + CLI).
- `how-to/offboard-a-member.md` — suspend vs archive, work reassignment,
membership-status-gates-access, instance-level cleanup.
- `how-to/enable-multi-user-login.md` — `local_trusted → authenticated`,
board-claim handoff, then invite people.

## Tier 3 — concept
- `guides/org/members-and-access.md` — shared human+agent principal
model, roles vs grants, human roles ≠ agent org chart, instance admin,
the member profile page, and the "left a project ≠ lost access"
clarification.

## Verification
- All 5 new pages registered in `site/content.json` (valid JSON, +5
pages).
- `sync:lint-links` and `sync:verify-nav` clean for these changes. The
single link the linter reports pre-exists on `main` in a skills file
untouched here; the 2 nav orphans are the intentional CLI redirect
anchors.
- All content verified against `paperclipai/paperclip@master` source
(permission keys, role defaults, CLI syntax, deployment modes).

## Follow-up after merge
Back-merge `main → nightly` so the next release merge stays clean.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
2026-07-01 18:11:25 +02:00
Aron PrinsandClaude Opus 4.8 ae046f058b docs(screenshots): refresh all 98 stale shots + harden pipeline isolation
Recapture every screenshot flagged in SCREENSHOTS_PENDING.md (98 entries; 233
PNGs updated across light/dark) against parent `master`, and stamp registry.json
with the new captured_sha. Mark SCREENSHOTS_PENDING.md as caught up.

Also fix two isolation gaps that made `screenshots:refresh` unusable while a real
local Paperclip is running:

- Free embedded-Postgres port: onboard hard-codes port 54329 (no env/flag
  override; the port comes only from config.json), which collides with a real
  local instance. run.mjs now generates the config in external-DB mode (keeping
  the scratch data dir pristine) and rewrites database.embeddedPostgresPort to a
  scanned free port before boot.
- Parent .env neutralized: the server loads PARENT_REPO/.env from its cwd via
  dotenv (override: false), which leaked DATABASE_URL (real external DB on 5432)
  and SERVE_UI=false into the "isolated" instance. instanceEnv() now pins
  DATABASE_URL="", DATABASE_MIGRATION_URL="" and SERVE_UI="true" so these win.

seed-execution-workspace.mjs now throws instead of falling back to 54329, so the
direct-DB seed can never connect to a real database.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-27 11:36:27 +02:00
Aron PrinsandClaude Sonnet 4.6 e46c6631e0 fix(sync): teach verify-edit to resolve hermes-local/hermes-gateway → packages/adapters/hermes
The hermes adapter package was consolidated under packages/adapters/hermes/
in v2026.626.0, but the doc files keep the hermes-local.md and
hermes-gateway.md names. verify-edit.mjs derives the source path from the
doc basename, so it was searching packages/adapters/hermes-local and
packages/adapters/hermes-gateway (non-existent) and flagging all claims as
unverified — false positives.

Fix: add an adapter_doc_sources map to anchor-map.json that overrides the
source-path lookup for these two docs, and update fetchAdapterFiles() to
read and apply that map before falling back to the default
packages/adapters/${adapter} pattern.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-06-27 10:01:22 +02:00
DottaandPaperclip 5b4b489154 [codex] Add Skills docs hierarchy (#34)
## Summary

- Add generated reference pages for bundled and optional skills.
- Add Skills index pages and hierarchy-aware sidebar/breadcrumb
navigation.
- Add verification scripts for hierarchical Skills routes and static
docs routes.

## Verification

- `npm run sync:verify-nav`
- `npm run docs:test:static-routes`
- `npm run docs:build`
- QA in PAP-11775 also verified browser rendering for hierarchy, bundled
`task-planning`, and optional `last30days` pages with screenshots.

## Issues

- PAP-11770
- PAP-11783

---------

Co-authored-by: Paperclip <[email protected]>
2026-06-24 08:32:10 -05:00
DottaandPaperclip 91bbe2cdbd [codex] Add static SEO docs routes (#32)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The public docs site is how operators and contributors discover
reference material and guides.
> - The docs pages were routed through hash URLs, which makes individual
pages harder for crawlers and link previews to treat as first-class
documents.
> - The release build needs to emit static HTML pages for each docs
route while preserving the client-side docs experience.
> - This pull request adds static docs route generation and verification
around canonical, crawlable route output.
> - The benefit is that docs pages can be indexed and shared as normal
path-based URLs without losing local navigation behavior.

## Linked Issues or Issue Description

No public GitHub issue exists for this docs-site improvement.

Problem:
- Docs pages were reachable primarily through hash routes such as
`/#/reference/skills`.
- Crawlers and social previews benefit from static route-specific HTML
at normal paths such as `/reference/skills`.
- The release build should publish those pages predictably and verify
that they include canonical metadata, page titles, and visible article
content.

## What Changed

- Added static route generation to the docs release build so each nav
route gets an `index.html` output with route-specific title, canonical
URL, article content, and sitemap entry.
- Updated the browser app bootstrap to support path-based docs routes
and retain compatibility with hash links.
- Added `docs:test:static-routes` coverage for generated static route
output.
- Documented Cloudflare Pages preview and production deployment details.

## Verification

- `npm run docs:test:static-routes`
- `npm run docs:build`

## Risks

Low to medium risk. This changes release output shape for the docs site,
so the main risk is a Pages deployment configuration mismatch. The build
keeps existing client-side rendering behavior and includes a
static-route verification script to catch missing canonical pages before
publishing.

## Model Used

OpenAI GPT-5 Codex coding agent, tool-using software engineering mode.
Exact service context window was not exposed in this runtime.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <[email protected]>
2026-06-23 07:51:31 -05:00
Aron PrinsandClaude Opus 4.8 4ed3a26ff8 sync: bring verify-edit in line + scan adapter package sources
Two follow-ups to the server/src env-var scan widening:

1. verify-edit.mjs had its own copy of shouldFetchEnvSource with the same
   narrow server allowlist — apply the identical server/src/**/*.ts widening
   so the verify phase stops emitting unverified env-var false positives.

2. Both scripts now also scan all non-test packages/adapters/<name>/src/**/*.ts.
   Adapter packages read env vars directly in their server/index modules —
   e.g. SANDBOX_INSTALL_COMMAND (packages/adapters/{pi,claude,gemini,cursor}-local/src/...)
   and per-runtime API-key fallbacks — which the old allowlist never fetched.

Verified against parent v2026.618.0:
- check-drift: 0 drift (65 env vars checked).
- verify-edit docs/reference/adapters/sandbox-providers.md: 6/6 claims verified
  (SANDBOX_INSTALL_COMMAND, previously unverified, now resolves).
- sync:test 33/33.

Selection grows to ~452 files, still well under the 700 cap.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-19 09:48:43 +02:00
Aron PrinsandClaude Opus 4.8 c8e3aaf1f1 sync: widen drift checker env-var scan to all of server/src
The env-var drift checker only fetched a narrow allowlist of server files
(config.ts, a few auth/service files), so env vars read elsewhere in
server/src showed up as env-var-missing false positives every run.

Verified against parent v2026.618.0 that the 5 recurring false positives are
real, read env vars the old scan never looked at:
- TRUST_PROXY                  server/src/app.ts:167 (parseTrustProxyEnv(process.env.TRUST_PROXY))
- OTEL_EXPORTER_OTLP_ENDPOINT  server/src/instrumentation.ts:29
- OTEL_EXPORTER_OTLP_PROTOCOL  server/src/instrumentation.ts:69
- OTEL_SERVICE_NAME            server/src/instrumentation.ts:144
- OTEL_SERVICE_VERSION         server/src/instrumentation.ts:145

Fix: replace the three narrow server/src rules in shouldFetchEnvSource with a
single rule covering every non-test server/src/**/*.ts file (tests already
excluded above). Selection grows 130 → 326 files, well under the 700 cap.

Result: check-drift against both v2026.618.0 and master now reports 0 drift
(was 5 env-var-missing), with identical coverage (65 env vars, 235 routes,
57 CLI commands, 7 paths). sync:test 33/33 pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-19 09:39:24 +02:00
Aron PrinsandClaude Opus 4.8 c8bc5055c8 docs(workspaces): fix workspaces guide + regenerate detail screenshots
A user reported the Workspaces screen looked empty with "no options," and
that all but one of the workspace screenshots were blank/identical.

Both were real problems:

Docs (docs/guides/projects-workflow/workspaces.md)
- Add a "Before you start" section: workspaces are gated behind the
  experimental "Enable Isolated Workspaces" flag, the screen is monitor-only
  (no manual create), and it stays empty until an agent runs an isolated
  task — with the actual empty-state strings ("No workspace activity yet." /
  "No non-default workspace activity yet.").
- Correct the detail screen: it now has Tasks / Services / Configuration /
  Runtime logs / Routines tabs (+ plugin tabs), not "three tabs." Rename the
  Issues tab to Tasks (its real label) and add a Services tab section. The
  former "Workspace commands panel above the tabs" is now the Services tab
  plus header quick controls.
- Clarify the company-wide Workspaces screen vs. the per-project Workspaces
  tab and the surfacing rules. Fix the misleading "multiple isolated
  workspaces" caption.

Screenshots
- Root cause: the seed only created a *project* workspace and pointed the
  execution-workspace detail routes at its id, so those pages were captured
  mid "Loading workspace…". Execution workspaces have no REST create endpoint
  (they're provisioned by a real heartbeat), so seed-execution-workspace.mjs
  now inserts a realistic one directly into the instance's embedded Postgres:
  an isolated git-worktree workspace with runtime config, a running service,
  provision/start/failed-job operation logs, and linked tasks.
- routes.mjs: add the {executionWorkspaceId} token, repoint the detail routes
  to it, add a Services tab target, and drop the duplicate
  org/execution-workspaces-list target (same URL as workspaces/list).
- Recaptured workspaces/{list,configuration,services,runtime-logs,issues} in
  light + dark; all now render real content.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-11 12:03:39 +02:00
Aron PrinsandClaude Opus 4.8 1a28b59fbf anchor-map: add skills-catalog watcher
Closes the gap this run surfaced: packages/skills-catalog/** was unwatched, so
new bundled catalog skills (e.g. the wireframe product skill) weren't auto-detected.

Watches catalog/**/SKILL.md + generated/catalog.json, routes to docs/reference/skills.md
and docs/guides/org/skills.md (PR tier), distinct from the agent-skills watcher which
covers the server-forced bundled skills under skills/**.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-03 10:42:23 +02:00
Aron Prins d8a031897b Avoid env-controlled registry sync cwd 2026-05-30 17:54:06 +02:00
Aron Prins 17e046db5f Harden screenshot runner environment 2026-05-30 17:52:14 +02:00
Aron PrinsandClaude Opus 4.8 32a16b20f4 Recapture screenshots on a healthy demo seed
The seeded org agents were created as `process` adapters with an empty
adapterConfig. The screenshot instance runs with no LLM provider and the
scheduler heartbeats every enabled agent, so each agent's heartbeat failed
instantly — the captured UI was dominated by red "error" states ("5 errors"
on the dashboard, "Ada failed after 1 second" on agent detail).

Give every demo agent a shared DEMO_AGENT_CONFIG: a process command that
always exits 0. Heartbeats now complete cleanly, so agents render as healthy
idle/running/paused with tidy transcripts. Recaptured all targets (light +
dark) against paperclip 911a1e8 — dashboard now reads "0 errors".

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-05-30 17:41:27 +02:00
Aron PrinsandClaude Opus 4.8 e4be96d643 Add screenshot-coverage gate to sync:check
New scripts/sync/verify-screenshots.mjs asserts that every screenshot
referenced in a guide page is (a) a CAPTURE_TARGET in routes.mjs and (b)
indexed in registry.json with a non-empty depends_on. It exits non-zero
otherwise, so a doc image added without a capture target fails loudly instead
of silently going stale. Wired into `npm run sync:check`, which the /sync-docs
skill runs every sync.

Currently: 112 referenced screenshots, all tracked and indexed.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-05-30 14:42:14 +02:00
Aron PrinsandClaude Opus 4.8 9ad25322b5 Make the screenshot registry self-indexing
Previously sync-registry only *updated* existing registry entries, so a newly
introduced screenshot target was captured but never indexed — and the
/sync-docs staleness check only flags entries it can see, so such a shot would
silently drift out of date (exactly what happened to issues/inbox-unread).

sync-registry now appends a registry entry (file, theme, viewport, route,
depends_on) for any CAPTURE_TARGET that has none, and sorts entries for stable
diffs. run.mjs runs sync-registry on every capture, so the index now stays
complete automatically. Audit: 0 target files missing from the registry, 0
without depends_on — every documented screenshot is tracked for staleness.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-05-30 14:40:58 +02:00
Aron PrinsandClaude Opus 4.8 59b4d4a4fe Cover the last 8 shots: real process-adapter runs + doc repoint
Close the remaining gap so every screenshot referenced in the docs is current.

seed.mjs — process-adapter "runner" agents (no LLM needed; the process adapter
executes a shell command):
- "Task Runner" runs `sh -c "echo ..."` → a real completed run with a STDOUT
  transcript (run-transcript-view, test-environment-success via the config
  Test button which now passes: command sh is executable)
- "Live Task" runs `sh -c "sleep 3600"` and is woken last, so it stays
  in-flight through the whole capture phase → genuine "running" agent status
  and an in-progress run row

routes.mjs — targets for run-transcript-view, run-history-in-progress,
agent-status-running, test-environment-success (click "Test" → wait for the
Passed result), approvals/revision-request-input (the detail note box),
adapters/health (the adapter rows), and onboarding/goal-field (wizard step 1).

dashboard.md — the dashboard image pointed at a hand-annotated PNG that can't
be auto-captured; repoint it to the freshly captured dashboard-overview.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-05-30 14:28:19 +02:00
Aron PrinsandClaude Opus 4.8 73de0bb4b6 Extend screenshot coverage: interaction engine + richer seed
Grow capture coverage from 56 to 110 targets so the docs' UI screenshots are
refreshed end to end, not just the plain-URL surfaces.

capture.mjs — interaction engine:
- `steps` per target (click / fill / waitFor / press) run after the page
  settles; each step is best-effort (logs + continues) so selector drift
  degrades to a partial capture instead of aborting
- `clip` captures a single element (e.g. a dashboard panel), falling back to
  full-page if the element isn't found
- robust locator DSL: testid / role+name / label / title / placeholder / text / css

routes.mjs — +54 targets across dashboard, tasks, issues, activity, org,
routines, skills, workspaces, settings, costs (incl. budget-bar 50/80/100%
states), new-agent forms, approvals, and empty-state onboarding. New seed-id
tokens for empty company, budget-state agents, http agent, skill, approvals.
Documents the 8 shots that are genuinely not auto-capturable offline (live-run
transcripts/status, real adapter test-pass, a nonexistent revision input, a
nonexistent adapter-health route, the hand-annotated overview, onboarding goal).

seed.mjs — extended dataset: a second empty company for empty-state shots;
three budget-utilisation agents seeded to 50/80/100% (last one paused); an
http-adapter agent; four approval items (hire / strategy / board / approved)
via REST; a resolved skill id; and the isolated-workspaces experimental flag
(PATCH /api/instance/settings/experimental).

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-05-30 13:52:36 +02:00
Aron PrinsandClaude Opus 4.8 95c7ab5f67 Enrich screenshot seed + harden the runner
Validated the pipeline against a live local_trusted instance and fixed what
the dry run surfaced, plus made the demo company look genuinely in-use.

seed.mjs — rich, idempotent, soft-failing demo dataset:
- brand color + monthly budget; 5-agent org (Ada/Bob/Cleo/Dax/Eve) with
  titles, icons, instructions, per-agent budgets, assigned skills
- 4 company skills, 2 goals, 2 projects + a git workspace, 8 issues with
  mixed statuses/priorities/assignees, 2 sub-issues, a 4-message chat thread
- routine + one execution-history row, 2 invites, bundled plugins installed,
  32 cost events + 5 finance events so the Costs/Finance dashboards are non-zero
- enum/validation fixes from the live run: goal status "active" (not
  "in_progress"), workspace sourceType "git_repo", comment authorType "user"
  (a board actor cannot post as "agent")

run.mjs:
- kill the server's whole process group on teardown (was orphaning the
  server child and holding port 3197)
- pre-clean the scratch home at startup so every run gets a fresh DB and the
  one-shot seed steps (comments/invites/events) always fire

sync-registry.mjs: drop the scaffolder's _todo note once route/depends_on
are populated.

package-lock.json: pick up @playwright/test.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-05-30 12:55:04 +02:00
Aron PrinsandClaude Opus 4.8 5f00622542 Add automated screenshot capture pipeline + skill wiring
Builds an end-to-end pipeline that keeps docs screenshots in sync with the
latest Paperclip build, replacing the previously-manual capture step.

scripts/screenshots/:
- config.mjs       isolated-instance env helpers (local_trusted/loopback,
                   scratch PAPERCLIP_HOME, never touches ~/.paperclip)
- seed.mjs         idempotent demo-data seeding via REST (company/agents/
                   project/goal/issues/routine/workspace); writes .seed-ids.json
- routes.mjs       56 CAPTURE_TARGETS with real ui/src depends_on paths;
                   resolveRoute() uses the server-derived issuePrefix
- capture.mjs      Playwright capture (light+dark, 1440x900 @2x), theme seeded
                   to match ui/index.html, stamps registry captured_sha
- sync-registry.mjs back-fills route + depends_on into registry.json
- run.mjs          one-command orchestrator: onboard -> health -> seed ->
                   sync-registry -> capture -> teardown
- README.md        prerequisites, flow, overhaul mode, safety notes

Wiring:
- package.json: screenshots:{seed,capture,sync-registry,refresh,refresh:all}
  + @playwright/test devDependency
- screenshots:refresh:all is the full re-take mode for major UI/UX overhauls
- sync-docs SKILL.md Phase 6: capture is now automatable (still PR-reviewed,
  never auto-pushed); maintenance.md updated to match
- .gitignore: scripts/screenshots/.seed-ids.json

Auth is free in local_trusted mode (every request is admin), so no login flow
is needed. Capture/staleness still surface to a PR for human review.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-05-30 12:05:26 +02:00
Aron Prins 52542db923 Fix sync verification edge cases 2026-05-13 21:46:12 +02:00
Aron PrinsandClaude Opus 4.7 f68cbbd29a Wire detect-renames, frontmatter, and verify-edit into SKILL
Closes the design loop for the three helpers shipped in the
preceding commits and addresses the batched-exhaustiveness gap.

SKILL.md (+43 net):

- Phase 3: new substep runs detect-renames.mjs and routes detected
  renames to the EXISTING doc page with change_kind: renamed (not a
  new page). removed_dirs_no_match surfaces as a Reconcile-style
  flag. added_dirs_genuinely_new flow through unchanged.
- Phase 5: new bold paragraph stating --batched mode is exhaustive
  per window — no subsampling. Wet-run subsampling was scope-control
  for testing, not skill design. Also: paperclip_version frontmatter
  is now live (builder strips and surfaces it); added a new final
  voice-rule bullet requiring concrete identifiers (flags, env vars,
  routes, field names) be copied verbatim from parent code.
- New Phase 5.5: run verify-edit.mjs on every touched file. Auto-merge
  edits roll back on any high-confidence unverified claim. PR-tier
  edits get a Verification Failed callout; batched-release PRs never
  auto-merge when any verification fails. Suspicious claims log but
  never block.
- Phase 7 PR body template: three structured sections — Drift,
  Verification Failures, Renames detected. Each omitted if empty,
  never silently dropped.
- Helper-script index added near top.

anchor-map.json:

- adapters watcher detect rewritten to reference detect-renames.mjs
  as the canonical rename check (no more inline heuristic prose).
- agent-skills, plugin-sdk, server-adapters: parenthetical pointers
  added to detect-renames where renames apply.
- Other watchers unchanged (rename signal doesn't cleanly apply).

Follow-ups flagged but not done in this commit:
- Special-cases "Renames on parent" still describes the manual
  fix-anchor-map workflow; would benefit from a one-line distinction
  between watcher-path renames (manual) vs single-dir renames within
  a watcher (automatic).
- file-path drift kind and verify-edit's file-path kind overlap —
  worth deduping a future pass so one missing file doesn't appear
  under both Drift and Verification Failures.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
2026-05-13 13:57:26 +02:00