This release is a pre-release and may not be stable for production use.
Papyrus
Papyrus is an open-source engine for a continuous, steerable feed of insight about a subject. It watches sources, decides what is relevant from an editor's include and exclude decisions, has editor agents research, write and check up to the publication's policies, and publishes the result for people and agents. The subject is configuration (doctrine, sections, corpus, steering), never code.
This repository is the engine. It ships two packages in lockstep, @anthusai/papyrus on npm and papyrus-newsroom on PyPI, and every Papyrus site installs both at one exact version. A site repository holds only what is specific to that site. Fix the engine here, release it, then bump the pin in the site. Do not copy engine code into a site.
New to the repo? Read this page, then AGENTS.md (the operating manual for agents and people), then the docs index.
How it relates to the other repositories
| Repository | Role |
|---|---|
| Papyrus (this repo) | The engine: the newsroom console, the CMS backend (Amplify Gen 2), the standard Markus projector, the papyrus CLI, plugins, infrastructure templates and the shared monitoring and procedure stacks |
Site repositories, for example AnthusAI/Shipped-web, Distinctive-web, Pilobol.us, Anth.us-Papyrus, Threat-Intelligence, p.apyr.us, DataParade-newsroom |
One per site: papyrus.config.ts, web/projection.json, theme, infra/site.json, the exact Papyrus pins. They are generic containers; sections, missions and scoring live in the site's backend data |
Cyclotron (AnthusAI/Cyclotron) |
The decision engine. One shared relevance Cyclotron answers include/exclude for the Hacker News router and several sites. The cyclotron Poetry group in this repo pins its commit |
Prospectus (AnthusAI/Prospectus) |
Accounts and sign-in for reader sites. A site's reader features open when Prospectus returns a per-site subject (see reader steering). Tell the Prospectus owner before merging to its main |
| Biblicus | The knowledge layer (corpora, topic models, extraction). Installed from PyPI (biblicus >=1.15.0) |
| Tactus | The procedure runtime. Newsroom procedures are .tac files run by Tactus (tactus >=0.53.4) |
Markus (anthus-markus) |
The content markup and renderer behind Markus sites (papyrus-newsroom[markus]) |
| Kanbus | The work board (project key PPY) and its kbs CLI |
Where it runs
- AWS account
papyrus-production, id712236451410, regionus-east-1hosts the sites that belong to the Papyrus platform: Shipped, Distinctive Mark, Pilobol.us, Anth.us, Threat Intelligence, p.apyr.us and Data Parade. UseAWS_PROFILE=papyrus-production(SSO; only the person can runaws sso login). Sites whose product has its own account (Apricity, Auritus, Kanbus, Cyclotron and Prospectus, Chattic.us) are deployed there instead; each site records its account ininfra/site.jsonunderaws. See Which account hosts a site. - Shared stacks (hand-run CloudFormation or CDK in
712236451410):papyrus-monitoring(collectors and the router),papyrus-procedure-runner, the knowledge cloud run and the projection lease table (infra/scheduled-jobs),papyrus-newsletter-sending-<siteId>(SES), and one edge stackpapyrus-edge-<siteId>per site. - Per site: a CMS Amplify app (
<siteId>-cms, platformWEB_COMPUTE) that owns the backend (AppSync, DynamoDB, Lambdas, S3), a versioned S3 site bucket, and the site's own CloudFront distribution (papyrus-edge-<siteId>, an origin access control to the bucket,/newsroom*,/_next/*and/api/*going to the CMS app). Amplify app ids and distribution ids live in each site'sinfra/site.json(Shipped: appdkycd9pntgo6d, distributionEUQZ249T4OKXH,https://shipped.anth.us). - Hosts:
shipped.anth.us,distinctive-mark.com,pilobol.us,anth.us,threat-intelligence.anth.us,p.apyr.us,dataparade.io/posts. Editors sign in with Google at/newsroom. - Legacy account
335163751677still holds personal sandboxes (see aws-sandbox-personal) and stale pre-move copies of some apps. Do not create or change production resources there. A gitignoredAGENTS.local.mdon a developer machine may describe that account as production; the repository docs are the reference.
The runtime picture, in short:
- Save is live. For a Markus site (
s3-projection, the default for new sites) thecontent-actionsLambda saves an item and renders only the pages that depend on it into the S3 bucket; CloudFront serves it. There is no build job. - Git holds code, theme and settings, not articles. Content lives in DynamoDB and the site can always be re-projected with
papyrus ops content project --all. - Pretext (a Next.js server on Amplify that renders on request) is the alternative publication kind, used by Threat Intelligence and p.apyr.us.
- Local vs cloud.
papyrusruns against a local pod or the cloud GraphQL API with the same argv (--backend local|cloud, operator CLI). Procedures run locally under Tactus or in the cloud in the procedure runner Lambda. The weekly knowledge run runs on a workstation (runbook) or unattended in AWS (cloud run). The Hacker News collector has a local SQLite worker and the cloud stack (monitoring).
Detail: How a publish flows, Site hosting, the standard site design.
What exists today
Status words: Live (in production on at least one site), Beta, In progress, Planned.
- Standard Markus projector and front end. One renderer for every Markus site, driven by
web/projection.json: pages, listings, tags, sitemap, feeds, Markdown twins,llms.txt. Live. Building a static site, agent-readable sites. - Plugins and the edge. Deploy-time plugins (
signup,newsletter,reader-steering) and thepapyrus-edge-*CloudFront stacks with the Lambda@Edge 404 handler for sites that mix S3 and the CMS app (#560). Live. Plugins, edge README. - Reader steering. Votes on any subject, flags, ratings, comments, submissions, moderation, snapshots, and Proposals (PPY-c97ce4, PPY-409d96). Built and tested; reader writes stay closed in production until Prospectus returns a site subject. Reader steering.
- Newsletter. Double opt-in, clean
/newsletter/*pages, branded email theme, roundup issues, alerts, paced sending through SES. Live on Shipped. Newsletter. - Analytics. GA4 with Consent Mode v2, a first-party banner and address redaction.
analytics_onlyexists and stays off on every site. Site hosting: Analytics. - Monitoring and the router. The collector and router (
papyrus-monitoring) and the Monitoring page. The shared relevance Cyclotron decides which Hacker News items each site wants (Anth.us, p.apyr.us, Threat Intelligence, Data Parade, Pilobolus); the TTAB monitor feeds Distinctive Mark directly. Beta. Monitoring, steering and relevance. - Procedure runner and site procedures. A site registers its own Tactus procedure with
papyrus procedures register; the runner executes it in the cloud when a monitor delivers a new Reference. Live for Distinctive Mark. Procedure runner. - Knowledge run. Weekly topic model, extraction, AI review, snapshot, archive, wiki and projection, local or unattended in AWS, guarded by the projection lease. Beta (Shipped first). Cloud run.
- Automations. Records that bind a monitor to a procedure, with
enabled, concurrency and budget limits, cost and run history, and Run now (PPY-9ff95b slices 1 and 2). Monitor triggers are live; schedule, event and manual triggers are stored but not started. Automations. - Idea pipeline v0.
papyrus ideas digestandsynthesizeturn recent references into private story ideas, run by hand, with--store proposalsfiling them asstory_draftProposals (needs apapyrus loginsession; IAM cannot file). Merged todevelop; scheduling and weekly trends are in progress (PPY-8ffc18). Idea pipeline. - Review requests and the Notification Center as the console home: flags, timed soft reviews and hard gates, ignore-safe, with steering read back by the step that raised them (
papyrus reviews). Merged todevelop(#642, PPY-ab6a50, PPY-1cd261); it takes effect on a site only after that site's data API is deployed with a release that has it. In progress: email, filters and ground-truth correction. Notification Center, review requests. - Reconcile guard. A reconcile refuses to run without the deployed plugin list and never deletes a plugin's pages (#594). Live. Site hosting: reconcile.
- Pretext newspaper layout lab, newsroom, knowledge base, editor agents. Live. Layout system, newsroom operations, editor agents.
Quick start
Prerequisites: Node 22 and npm, Python 3.12 or 3.13 (CI uses 3.12), Poetry, kbs for the board, and an AWS SSO profile for anything that touches the cloud.
npm ci
poetry install --extras "newsroom markus priming" --with cyclotron # what CI installs
poetry run papyrus --help
echo '{}' > amplify_outputs.json # git-ignored stub so the type check resolves; no secrets
npm run typecheck
npm run lint
npm run dev:preview # seeded newsroom at http://127.0.0.1:3002/newsroom/work, no AWS
Other local servers: npm run dev:127 serves the app on http://127.0.0.1:3001 and needs a real amplify_outputs.json (npm run outputs:sandbox or npm run outputs:production). cp .env.example .env holds app-level settings only, never credentials; the shell environment wins over .env.
Tests (what CI runs is in .github/workflows/tests.yml):
npm run test:bdd:backend # behave: features_backend/
poetry run pytest -q procedures/newsroom/tests/test_ideas.py # one Python test file
npm run test:schema-parity # schema.ts against resource.ts
npm test # all scripts/test-*.ts and Lambda tests
npm run test:bdd # cucumber: layout and reader (needs Playwright chromium)
More: verification, Python CLI and testing, local preview.
How a change reaches production
- Branch from
origin/develop(feature/PPY-xxxxxx-slug,fix/...,chore/...,docs/...) and open a pull request todevelop. Behaviour changes ship with Gherkin specs. - CI (
tests.yml, pluspackage-smoke.ymlwhen packages, app or Python code changes) runs the type check, lint, the TypeScript tests, the app-shell CDK build, the Python tests and the pilot-identifier guard. Merge todevelopwith a merge commit once it is green. - A push to
developpublishes a prereleaseX.Y.Z-next.N(npm dist-tagnext, PyPIX.Y.Z.devN). - Promote
developtomainwith a pull request and a merge commit (never a squash). A push tomainrunsrelease.yml: semantic-release (conventional commits) cuts the stable version and publishes@anthusai/papyrusto npm andpapyrus-newsroomto PyPI at the same number, through trusted publishing (OIDC), with no stored tokens.feat:releases a minor,fix:a patch,feat!:orBREAKING CHANGEa major.chore:,docs:,test:,refactor:andci:do not release. Versions are stamped into the staged packages and never committed back. Agents promote only when told to; see AGENTS.md. - A site picks up a release by bumping its pin by hand in four places:
package.json,infra/package.json,infra/site.json(papyrusVersion) andrequirements-publication.txt(papyrus-newsroom[markus]==X). Merging that to the site'smaindeploys it:- Public site repositories run Actions CI, and a green push to
mainstarts the Amplify job through GitHub OIDC (the reusable workflow.github/workflows/amplify-deploy.yml). Amplify auto-build is off onmain. - Private site repositories run all CI and CD in AWS (Amplify auto-build or CodePipeline).
- The deploy renders the whole site again (
reprojectOnDeploy), so merging is the only step. Backend changes ride the same deploy.
- Public site repositories run Actions CI, and a green push to
Details: Releasing, Deploy on merge to main. This repository's own main does not deploy a site; the engine ships as packages. Production deploys through ampx pipeline-deploy are never run from a laptop.
Start a new Papyrus site
The steps below are the real sequence; each links to the page that holds the detail. A site repository starts from the layout of a recent one (Shipped-web is the cleanest example) and contains no engine code.
-
Create the site repository with
papyrus.config.ts(defineSite),web/projection.json,web/css/,amplify.yml,infra/site.jsonandrequirements-publication.txt. Building a static site, standard site layout. -
Write
infra/site.jsonwith anawsblock (profile,accountId,region). There is no default account, and a file withoutaws.accountIdandaws.regionfails withdoes not say where it deploys. Also setcms.cognitoDomainPrefix(distinct per site),cms.siteOriginfor a site behind its own edge, and thegithubblock withownerIdandrepoId. Examples:infra/amplify-app-shell/examples/, reference: app-shell README. -
Pin the engine to one released version in the four places listed above.
-
Deploy the app shell from a Papyrus checkout (a human approves the change set; connect the GitHub App once per app and approve a new CodeConnections connection by hand):
cd infra/amplify-app-shell && npm ci SITE=/absolute/path/to/site/infra/site.json AWS_PROFILE=papyrus-production npm run diff SITE=/absolute/path/to/site/infra/site.json AWS_PROFILE=papyrus-production npm run deploy
-
Secrets. Create the site's Google OAuth client, then from the site repository run
papyrus site google-secrets set(it stores SSM SecureString secrets after asserting the account) andpapyrus site google-secrets check. Add editors to a Cognito group after their first sign-in. Google sign-in, OAuth setup. -
Edge. Give the site its own CloudFront:
backend.publication.distributioninpapyrus.config.ts, or apapyrus-edge-<siteId>stack frominfra/edge/s3-projection-cms.yaml(use this one when/newsroom*and/api/*share the host: it carries the 404 handler). DNS and certificates: edge README, own CloudFront. -
First content and projection.
papyrus publication init --key <key> --name <name>, thenpapyrus ops content project --all. How a publish flows. -
Mission doctrine. Write the mission (three lines: what it is and for whom, what coverage includes, what readers take away) and the policy, then
papyrus sections doctrine set --kind mission --file mission.mdand--kind policy. The relevance Cyclotron seeds its rubric from them. Editorial context, steering and relevance. -
Newsletter (optional). Deploy the SES stack
infra/newsletter/papyrus-newsletter-sending.yamlfor the site, then enable thenewsletterplugin inpapyrus.config.ts. SES starts in the sandbox. Newsletter, sending stack. -
GA4 (optional).
chrome.ga_measurement_idpluschrome.consent_modeinprojection.json(the standard Consent Mode v2 banner; leaveanalytics_onlyoff). Analytics. -
Hacker News routing (optional). Add the site's AppSync grants to
infra/monitoring/papyrus-monitoring.yaml, deploypapyrus-monitoringwith a change set, add the publication to the router config withinfra/monitoring/seed_router_config.py, and make sure the shared Cyclotron has a<publicationId>-relevanceoutput. The router starts indry-run. Monitoring: the router, AGENTS.md. -
Register the site in Prospectus if it has reader features (
cms.prospectusAccountsApiStageArn). Reader steering.
Where to read next
- AGENTS.md: the operating manual, hard rules, common tasks with exact commands, ownership and current state.
- docs/README.md: the index of every documentation page, grouped by task.
- CONTRIBUTING_AGENT.md: the Kanbus workflow ("The Way") for the PPY board.
- docs/code-map.md: where the main files live.
Built by Anthus AI Solutions. We run this class of system in production. If you need this operated, not just cloned, talk to us.
Metadata
Release files for papyrus-newsroom 2.0.0.dev76
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| papyrus_newsroom-2.0.0.dev76.tar.gz | 1.4 MB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| papyrus_newsroom-2.0.0.dev76-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 3.0 MB
Release files / papyrus_newsroom-2.0.0.dev76.tar.gz
| Download URL | papyrus_newsroom-2.0.0.dev76.tar.gz |
|---|---|
| Size | 1.4 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
96017c7fc305ad6b5d91be87bba5244b56c9190bb49680ceb2603e4d5d49e50a
|
|
BLAKE2b-256 checksum How to use checksums |
65980239f334c7a04bbcb0652c41a11ebc6e1202b47afffb133f7ad1e57fe282
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logRelease files / papyrus_newsroom-2.0.0.dev76-py3-none-any.whl
| Download URL | papyrus_newsroom-2.0.0.dev76-py3-none-any.whl |
|---|---|
| Size | 1.6 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
26ed24702259220238c0561a015423b739b3537848f54060eba409b22d52db9c
|
|
BLAKE2b-256 checksum How to use checksums |
d407c5c627beda0fd1a53d885089fc29cb939b9b8f2d18798dd03bfb3a1ba9e1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logSecurity for papyrus-newsroom 2.0.0.dev76
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for papyrus_newsroom-2.0.0.dev76.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.