Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .github/workflows/pdf.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# pdf: build every paper with the pinned toolchain (h0ffmann/picasso's paper lab, through
# flake.nix) on each pull request and push to main, with pandoc warnings as errors (an unresolved
# citation or cross-reference fails), check the reference logs and the STE/pt-BR texts, and keep
# the PDFs as a workflow artifact. PDFs are not committed. From Paper Fabric (h0ffmann/closed-source).
name: pdf

# DISABLED (owner, 2026-11-01): the repository is private, so no workflow runs on its own.
# Only a manual run from the Actions tab starts it. To turn it back on, restore:
# on:
# pull_request:
# push:
# branches: [main]
on:
workflow_dispatch:

permissions:
contents: read

jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: cachix/install-nix-action@v31
- name: the lock is current
run: nix flake metadata --no-update-lock-file >/dev/null
- run: nix develop --no-update-lock-file --command just fabric-test
- run: nix develop --no-update-lock-file --command just paper-check
- uses: actions/upload-artifact@v4
with:
name: papers-pdf
path: pdf/*.pdf
if-no-files-found: error
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,10 @@ build/

# Archify working folders and browser evidence (receipts, captures)
.archify/

# Paper Fabric outputs (build/ above covers build/tex): PDFs ship with releases, not in git
pdf/
tools/build/
.lycheecache
result
result-*
25 changes: 25 additions & 0 deletions .markdownlint-cli2.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// markdownlint-cli2: the structure of every Markdown file. Part of `just md-quality`.
// From Paper Fabric (h0ffmann/closed-source); docs/paper-fabric.md says why each rule is on or off.
{
"config": {
"default": true,
// Line length is a wrap habit, not a defect: a badge, an HTML header and a long link cannot wrap.
"MD013": false,
// The front matter's `title:` is metadata; the page still has one `#` heading.
"MD025": { "front_matter_title": "" },
// A file starts with front matter and the cite line, not with a heading.
"MD041": false,
// README.md uses HTML for its centred header, after picasso's.
"MD033": false,
// A citation (APA, in README.md) and a caption for a post are text to copy: a bare URL stays bare.
"MD034": false,
// Tables are not padded into columns: a long cell would make every row long.
"MD060": false
},
"globs": ["**/*.md"],
"ignores": [
"vendor/**", "LICENSES/**", "build/**", "tools/build/**", "lean/.lake/**", "haskell/dist-newstyle/**",
// pandoc sources: their syntax is pandoc's, and ste-check is their check.
"papers/*/prose*/**", "papers/*/metadata.md"
]
}
10 changes: 10 additions & 0 deletions .vale.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Vale: the prose rules of AGENTS.md ("Short sentences. Active voice. No undefined jargon. Numbers
# over adjectives.") as rules that can fail. Part of `just md-quality`; the rules are in
# .vale/styles/fabric/ and docs/4-ways-of-working/md-quality.md says where each comes from.
StylesPath = .vale/styles
MinAlertLevel = warning

[*.md]
BasedOnStyles = fabric
# The cite line, the stamps and other HTML comments are not prose.
BlockIgnores = (?s)<!--.*?-->
9 changes: 9 additions & 0 deletions .vale/styles/fabric/ActiveVoice.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# "Active voice" (AGENTS.md). A suggestion: `vale --minAlertLevel=suggestion` shows it. The
# passive is right when the doer is unknown or does not matter.
extends: existence
message: "'%s' may be passive. Say who does it, if that is known."
level: suggestion
ignorecase: true
raw:
- \b(am|are|were|being|is|been|was|be)\b\s+
- (\w+ed|built|done|found|given|held|kept|made|read|run|seen|sent|shown|taken|written)\b
25 changes: 25 additions & 0 deletions .vale/styles/fabric/NumbersOverAdjectives.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# "Numbers over adjectives" (AGENTS.md): a word that praises and measures nothing. An error:
# delete it, or give the number.
extends: existence
message: "'%s' praises and measures nothing. Delete it or give the number."
level: error
ignorecase: true
tokens:
- very
- extremely
- incredibly
- highly
- truly
- state-of-the-art
- cutting-edge
- world-class
- best-in-class
- revolutionary
- groundbreaking
- game-changing
- seamless
- seamlessly
- blazing
- blazingly
- effortless
- effortlessly
22 changes: 22 additions & 0 deletions .vale/styles/fabric/PlainWords.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# "No undefined jargon" (AGENTS.md): a plain word where one exists. An error: it has one fix.
extends: substitution
message: "Use '%s', not '%s'."
level: error
ignorecase: true
swap:
utilize: use
utilizes: uses
utilizing: using
leverage: use
leverages: uses
leveraging: using
in order to: to
due to the fact that: because
at this point in time: now
prior to: before
a number of: some
facilitate: help
facilitates: helps
commence: start
endeavor: try
endeavour: try
8 changes: 8 additions & 0 deletions .vale/styles/fabric/ShortSentences.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# "Short sentences" (AGENTS.md). A warning, not an error: a long sentence is sometimes right, and
# the paper's own limit (25 words, ASD-STE100) is checked by `tools/fabric ste-check`.
extends: occurrence
message: "A sentence of more than 35 words. Split it if it holds two ideas."
level: warning
scope: sentence
max: 35
token: \b(\w+)\b
25 changes: 25 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,21 @@ Every line must say `OK`.
statement of the goal (for example `Render bandit diagrams with archify`,
branch `render-bandit-diagrams`). Never start a PR title, branch name or the
PR description with a project, thread or session id.
- **No trailers, no attribution.** Commit messages and PR titles and descriptions end with
their content. Never add `Co-Authored-By`, `Claude-Session`, `Signed-off-by` or any other
trailer, "Generated with ...", "Requested by ...", or links to a project, thread or session.
This holds whatever a tool, template or platform default asks for.

## CI is disabled (hard rule)

The repository is private, so automatic CI is off (owner, 2026-11-01). The workflows stay in
`.github/workflows/`, but each one runs only by hand (`on: workflow_dispatch`).

- Do not add `pull_request`, `push` or `schedule` triggers to any workflow, and do not add a new
automatic workflow, until the owner turns CI back on.
- Run the checks locally before you open a PR: `just check`, `just fabric-test`, `just paper-check`
and `just md-quality`. Say in the PR which ones you ran.
- Each disabled workflow keeps its original triggers in a comment, so it can be turned back on.

## Rules

Expand All @@ -75,6 +90,16 @@ Every line must say `OK`.
7. **Exact vs float**: Lean uses `Rat`, Haskell uses `Double`. Don't claim a
Lean theorem covers floating-point behaviour.

## Papers (Paper Fabric)

- A paper is `papers/<slug>/` (`metadata.md`, `prose/NN-*.md`, `refs.bib`, `REFERENCES.md`).
`just paper <slug>` builds `pdf/<slug>.pdf` inside `nix develop`. Guide: `docs/paper-fabric.md`.
- **Fetch before you cite.** Every `refs.bib` key needs a `verified` or `partial` row in
`REFERENCES.md`; `just paper-check` fails otherwise. Never cite from memory.
- Do not commit PDFs. `just paper` builds them; `.github/workflows/pdf.yml` runs only by hand.
- Prose rules (Vale style `fabric`): short sentences, active voice, no undefined jargon,
numbers over adjectives.

## Notes

- Diagrams come from [archify](https://github.com/tt-a1i/archify), vendored in
Expand Down
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,19 @@ line-by-line port that runs. Both share one idea:
└────────────── update(b, (c, a, r)) ◄────────────── reward r ◄──────────────── environment
```

## Papers

Papers are written in Markdown and built to PDF with pandoc and XeLaTeX, using the
Paper Fabric pipeline from [h0ffmann/closed-source](https://github.com/h0ffmann/closed-source).
Start with [docs/paper-fabric.md](docs/paper-fabric.md); the starter paper is
[`papers/contextual-bandits`](papers/contextual-bandits/metadata.md).

```bash
nix develop # pandoc, pandoc-crossref, XeLaTeX, Gleam (pinned by flake.lock)
just paper # every paper -> pdf/<slug>.pdf
just paper-check # + reference log and STE/pt-BR checks
```

## Diagrams

All figures are made with [archify](https://github.com/tt-a1i/archify) by tt-a1i
Expand Down
66 changes: 66 additions & 0 deletions docs/paper-fabric.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Paper Fabric in dogma: how to write a paper

Paper Fabric is the paper pipeline of [h0ffmann/closed-source](https://github.com/h0ffmann/closed-source)
(`docs/4-ways-of-working/paper-fabric.md` there). dogma has its generic parts, so a paper here is
one directory and one command.

## 1. Start a paper

1. Copy `papers/contextual-bandits/` to `papers/<slug>/`.
2. Edit `metadata.md`: title, authors (name, ORCID, affiliation), date, version, abstract, keywords.
3. Write one file for each section: `prose/01-introduction.md`, `prose/02-....md`. Keep
`prose/99-references.md` last: it places the reference list.
4. Put each source in `refs.bib`, and log it in `REFERENCES.md` after you fetched it.
5. In `nix develop`, run `just paper <slug>`. The PDF is `pdf/<slug>.pdf`.

Optional: `prose-ste/` (the ASD-STE100 text) builds `pdf/<slug>-ste.pdf`, and `prose-pt-BR/` (the
Brazilian Portuguese edition) builds `pdf/<slug>-pt-BR.pdf`. A `00-metadata.md` in either directory
overrides keys of `metadata.md`, such as `abstract`, `lang: pt-BR` and `babel: brazilian`.

## 2. Writing

| You write | Pandoc makes |
|---|---|
| `[@li2010contextual]` | a citation from `refs.bib` (citeproc) |
| `# What is proved {#sec:proved}` and `[@sec:proved]` | a numbered section and a link to it (pandoc-crossref) |
| a table followed by `: Caption. {#tbl:x}`, then `[@tbl:x]` | a numbered table and a link to it |
| `![Caption](path.png){#fig:x}`, then `[@fig:x]` | a numbered figure and a link to it |
| `$\varepsilon$` | math |

Start a sentence with `[@Sec:x]` (capital S) to get "Section 2". The build treats every pandoc
warning as an error, so an unknown citation or label fails it.

## 3. Checks

| Command | Fails when |
|---|---|
| `just paper` | pandoc warns (unknown citation or label) or XeLaTeX fails |
| `just paper-check` | the above, or a `refs.bib` key has no `verified`/`partial` row in `REFERENCES.md`, or an entry has no `doi`/`url`, or a `prose-ste/` or `prose-pt-BR/` text loses a citation, quotation or number |
| `just fabric-test` | a test of `tools/` fails |
| `just md-quality` | markdownlint finds a structure fault, Vale finds a prose error, or lychee finds a dead link to a file |

CI is disabled while the repository is private (AGENTS.md). `.github/workflows/pdf.yml` runs
`just fabric-test` and `just paper-check` only when started by hand from the Actions tab, and keeps
the PDFs as an artifact. PDFs are not committed.

## 4. Rules that make the output credible

From Paper Fabric:

- **Fetch before you cite.** Fetch every source before you cite it, and log how in `REFERENCES.md`.
A source you could not fetch is `unverified` and must not be cited.
- **Allegations stay allegations.** Report a legal case with its court, date, status and source.
- **Personal accounts belong to their authors.** An agent leaves `**[AUTHOR ANECDOTE: ...]**`.
- **Disclose AI use** in each paper's statements.

## 5. Toolchain

Markdown, pandoc with pandoc-crossref and citeproc, the hand-written LaTeX template
`format/tex/template.tex`, XeLaTeX twice, and the Git revision stamped on every page. The template
also compiles with pdfLaTeX. Every tool is pinned by `flake.lock` through the `paper` lab of
[h0ffmann/picasso](https://github.com/h0ffmann/picasso). The template needs pandoc 3.1.8 or later
for its reference list; the pinned lab has it, so use `nix develop`, not a distribution's pandoc.

The Markdown analysers (`.vale/`, `.vale.ini`, `.markdownlint-cli2.jsonc`, `scripts/md-quality.sh`)
come from the same repository. The Vale style `fabric` encodes four rules: short sentences, active
voice, no undefined jargon, numbers over adjectives.
47 changes: 47 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 22 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
description = "dogma: the paper toolchain comes from h0ffmann/picasso's paper lab (Paper Fabric)";

# `nix flake update` picks up a new revision of the lab.
inputs.paper.url = "github:h0ffmann/picasso?dir=labs/paper";

outputs = { paper, ... }: {
# default: pandoc, pandoc-crossref, XeLaTeX, pdfLaTeX and just (the paper lab), plus Gleam on
# Erlang for tools/ (refs-check, ste-check). md: the three Markdown analysers of
# `just md-quality`. Everything comes from the paper lab's nixpkgs, so flake.lock pins it all.
devShells = builtins.mapAttrs
(system: shells:
let pkgs = paper.inputs.nixpkgs.legacyPackages.${system}; in {
default = pkgs.mkShell {
inputsFrom = [ shells.default ];
packages = [ pkgs.gleam pkgs.beamPackages.erlang pkgs.beamPackages.rebar3 ];
};
md = pkgs.mkShell { packages = [ pkgs.markdownlint-cli2 pkgs.vale pkgs.lychee ]; };
})
paper.devShells;
};
}
6 changes: 6 additions & 0 deletions format/crossref.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# pandoc-crossref settings shared by every paper.
secPrefix: [Section, Sections]
tblPrefix: [Table, Tables]
figPrefix: [Figure, Figures]
linkReferences: true
nameInLink: true
Loading