From df48790a7d10c2470bf19a1639a51e60677c7490 Mon Sep 17 00:00:00 2001 From: hyperpolymath <6759885+hyperpolymath@users.noreply.github.com> Date: Sun, 27 Sep 2026 11:34:22 +0000 Subject: [PATCH 1/6] fix(rust): resolve clippy map_clone and unnecessary_cast Two lints in rust/pdftool_core/src/lib.rs are the only thing keeping the `Rust core (tests, formatting, lint)` job red at e1b6225 (run 36296845297): `cargo fmt -- --check` and `cargo test --locked` both pass; only the Clippy step fails. - resolve_object: `doc.get_object(*id).map(Clone::clone)` -> `.cloned()` (clippy::map_clone). lopdf 0.34 `Document::get_object` returns `Result<&Object>`, and `Result<&T, E>::cloned() -> Result where T: Clone` is stable since 1.59.0. `Object` derives `Clone`, so the function's declared `Result` return type is unchanged. - object_to_number: `Object::Real(v) => Some(*v as f32)` -> `Some(*v)` (clippy::unnecessary_cast). `Object::Real(f32)`, so `v` is `&f32` and the cast was an identity cast. The neighbouring `Object::Integer(v) => Some(*v as f32)` is deliberately left alone: `v` is `&i64` there and that cast is real. docs/ci/CHECK-DETERMINATIONS.adoc: the rust-core row claimed the job had never executed. It has -- once, at e1b6225, and it reached its third step. The row now records fmt+tests green (run 36296845297), the two Clippy lints, and this repair, and stays open until an owner-triggered run is green on main. It is not marked plain "Fixed", because no such run exists yet. No workflow, actions.lock or dependabot change: this touches no `uses:` line, so the Lock Sync Gate is unaffected. Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com> --- docs/ci/CHECK-DETERMINATIONS.adoc | 28 +++++++++++++++++++--------- rust/pdftool_core/src/lib.rs | 4 ++-- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/docs/ci/CHECK-DETERMINATIONS.adoc b/docs/ci/CHECK-DETERMINATIONS.adoc index ff9fe57..ca3fee7 100644 --- a/docs/ci/CHECK-DETERMINATIONS.adoc +++ b/docs/ci/CHECK-DETERMINATIONS.adoc @@ -37,16 +37,26 @@ muting it (`continue-on-error`, demotion to a warning, or silent removal). gone until the thing it would build exists. | `rust-core` (CI) -| *Fixed -- verification pending an owner-actor run* +| *Fixed -- awaiting one owner-triggered green run on `main`* | 2026-09-27 -| Replacement for both retired jobs: `cargo fmt --check`, `cargo test - --locked`, `cargo clippy -D warnings` on `rust/pdftool_core`. It has never - once executed: every `ci.yml` run before #71 died on the Deno tasks, #71's - own PR and merge were bot-triggered and refused at startup (<>), and - the fix PR for #67 is bot-triggered too. The first run that can execute it - is one triggered by `hyperpolymath` (re-run, close/reopen, or push). If that - run is red, the crate has a real defect and this row becomes a repair item; - it is not closed until a green run on `main` exists. +| Replacement for both retired jobs: `cargo fmt -- --check`, `cargo test + --locked`, `cargo clippy --all-targets -- -D warnings` on + `rust/pdftool_core`. It did execute once, contrary to the previous revision + of this row: run 36296845297 (push, `e1b6225`, actor `hyperpolymath`) got as + far as three of its steps -- *Check formatting* `success`, *Run unit tests* + `success` (6/6), *Run Clippy* `failure`. Clippy was the only red step and it + reported exactly two lints, both in `rust/pdftool_core/src/lib.rs`: + `clippy::map_clone` on `doc.get_object(*id).map(Clone::clone)` and + `clippy::unnecessary_cast` on `Object::Real(v) => Some(*v as f32)`. Both are + repaired in #73 (`.cloned()` and `Some(*v)` respectively); neither repair + weakens the gate, and the adjacent `Object::Integer(v) => Some(*v as f32)` + is deliberately left alone because that `i64` -> `f32` cast is real. The job + has *not* run with the repair in it: every run on #73's branch is + bot-triggered and refused at startup (<>), so the step is verified by + inspection only. This row therefore stays open until one run triggered by + `hyperpolymath` is green on `main`; if that run is red, the crate has a real + defect and this row becomes a repair item. It is not closed until such a run + exists. | `Lock Sync Gate` / `actions.lock is in sync with the workflow YAML` | *Fixed* diff --git a/rust/pdftool_core/src/lib.rs b/rust/pdftool_core/src/lib.rs index 4ed0ee2..c6ceba9 100644 --- a/rust/pdftool_core/src/lib.rs +++ b/rust/pdftool_core/src/lib.rs @@ -48,7 +48,7 @@ fn core_error_to_js(payload: CoreErrorPayload) -> JsValue { fn resolve_object(doc: &Document, obj: &Object) -> Result { match obj { - Object::Reference(id) => doc.get_object(*id).map(Clone::clone), + Object::Reference(id) => doc.get_object(*id).cloned(), _ => Ok(obj.clone()), } } @@ -56,7 +56,7 @@ fn resolve_object(doc: &Document, obj: &Object) -> Result fn object_to_number(obj: &Object) -> Option { match obj { Object::Integer(v) => Some(*v as f32), - Object::Real(v) => Some(*v as f32), + Object::Real(v) => Some(*v), _ => None, } } From 4d5510e2f6f9347667bf95ed666064983d6b76c4 Mon Sep 17 00:00:00 2001 From: hyperpolymath <6759885+hyperpolymath@users.noreply.github.com> Date: Sun, 27 Sep 2026 12:35:26 +0000 Subject: [PATCH 2/6] docs(ecosystem): state the suite boundary and link the other components MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Satisfies the first acceptance criterion of docmatrix#71: "Each repository README and GitHub description states its own boundary and links to the other optional components." - README.adoc gains an "Ecosystem position" section: what blocky-writer owns (fixed-layout PDF and application-form placement), what it does not, and who owns each of those instead, with links. - docs/ecosystem/ECOSYSTEM.adoc — the long-form boundary: the suite table, the adjacent-project list, the composition contract (clause 4 is the one this project is most likely to break), the "proof obligations do not transfer" list, and the working norm for cross-repo communication. - .machine_readable/6a2/ECOSYSTEM.a2ml expanded from `type = "component"` to carry the same boundary so machine readers get it without parsing prose. No workflow, actions.lock or dependabot change: nothing here touches a `uses:` line, so the Lock Sync Gate is unaffected. Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com> --- .machine_readable/6a2/ECOSYSTEM.a2ml | 44 +++++++ README.adoc | 24 ++++ docs/ecosystem/ECOSYSTEM.adoc | 164 +++++++++++++++++++++++++++ 3 files changed, 232 insertions(+) create mode 100644 docs/ecosystem/ECOSYSTEM.adoc diff --git a/.machine_readable/6a2/ECOSYSTEM.a2ml b/.machine_readable/6a2/ECOSYSTEM.a2ml index 2840c66..386b989 100644 --- a/.machine_readable/6a2/ECOSYSTEM.a2ml +++ b/.machine_readable/6a2/ECOSYSTEM.a2ml @@ -1,6 +1,10 @@ # SPDX-License-Identifier: MPL-2.0 # ECOSYSTEM.a2ml — Ecosystem position # Converted from ECOSYSTEM.scm on 2026-03-15 +# Expanded 2026-09-27 to carry the suite boundary, so machine readers get it +# without parsing prose. The authoritative, versioned contract is +# https://github.com/hyperpolymath/docmatrix/issues/71 — if this file and that +# issue disagree, the issue wins and this file is stale. [metadata] project = "blocky-writer" @@ -8,3 +12,43 @@ ecosystem = "hyperpolymath" [position] type = "component" +suite = "precision document suite" +contract = "https://github.com/hyperpolymath/docmatrix/issues/71" +contract-owner = "hyperpolymath/docmatrix" + +[boundary] +owns = "fitting and placement into fixed-layout PDF and application-form boxes, baselines and per-character cells designed for hand spacing" +does-not-own = [ + "multi-format viewing and editing — hyperpolymath/formatrix-docs", + "multi-format conversion and precision coordination — hyperpolymath/docmatrix", + "OCR, NER and metadata extraction — hyperpolymath/docudactyl", + "print routing — hyperpolymath/presswerk", + "cross-document consistency reconciliation — hyperpolymath/recon-silly-ation", + "capability-bounded critical execution — ForthWall, proposed and unbuilt", +] +hard-constraint = "never silently normalise page geometry — composition contract clause 4" + +[suite] +docmatrix = "multi-format conversion and precision coordination" +formatrix-docs = "tabbed multi-format viewing and editing" +blocky-writer = "fixed-layout PDF and application-form placement (this repo)" +forthwall = "proposed capability-bounded execution layer — not implemented" + +[adjacent] +affinescript = "hyperpolymath/affinescript — frontend language, real consumer" +docudactyl = "hyperpolymath/docudactyl — OCR/NER/metadata extraction" +dotmatrix-fileprinter = "hyperpolymath/dotmatrix-fileprinter — filesystem-side sibling" +presswerk = "hyperpolymath/presswerk — print routing, downstream of a filled PDF" +recon-silly-ation = "hyperpolymath/recon-silly-ation — cross-document reconciler" +universal-language-server-plugin = "hyperpolymath/universal-language-server-plugin — overlaps docmatrix's remit" +gv-clade-index = "hyperpolymath/gv-clade-index — taxonomy registry; CLADE.a2ml registered here" +deed-ecosystem = "hyperpolymath/deed-ecosystem — .deed manifest format" +standards = "hyperpolymath/standards — estate governance" +ddraig-ssg = "hyperpolymath/ddraig-ssg — Pages SSG (Idris 2), one of two, undecided" +casket-ssg = "hyperpolymath/casket-ssg — Pages SSG (Haskell), one of two, undecided" +berrywiki = "metadatastician/berrywiki — this project's wiki format and tooling" +rsr-template-repo = "hyperpolymath/rsr-template-repo — the template this repo was minted from" + +[communication] +norm = "each repo states its own boundary in its README and links the others; a short issue is filed on a neighbour when a status change unblocks or affects it" +no-standing-integration-programme = true diff --git a/README.adoc b/README.adoc index 24c0719..0f6ce52 100644 --- a/README.adoc +++ b/README.adoc @@ -62,6 +62,30 @@ See TOPOLOGY for a visual architecture map and completion dashboard. Wondering how this works? See EXPLAINME.adoc. +== Ecosystem position + +blocky-writer is one component of the hyperpolymath *precision document suite*. +It owns exactly one thing: **fitting and placement into fixed-layout PDF and +application-form boxes, baselines and per-character cells designed for hand +spacing rather than reliable computer entry.** + +It deliberately does *not* do any of the following, and each has an owner: + +* Multi-format viewing and editing — https://github.com/hyperpolymath/formatrix-docs[Formatrix Docs] +* Multi-format conversion and precision coordination — https://github.com/hyperpolymath/docmatrix[DocMatrix] +* OCR / metadata extraction — https://github.com/hyperpolymath/docudactyl[Docudactyl] +* Print routing — https://github.com/hyperpolymath/presswerk[Presswerk] + +The versioned composition contract — including the clause that forbids any +component from silently normalising *page geometry* — is +https://github.com/hyperpolymath/docmatrix/issues/71[docmatrix#71]. The long-form +boundary statement, with the full adjacent-project list, is +`+docs/ecosystem/ECOSYSTEM.adoc+`. + +The project wiki (BerryWiki format) is at +https://github.com/hyperpolymath/blocky-writer/wiki and its source lives in +`+wiki/+`. + == License SPDX-License-Identifier: CC-BY-SA-4.0 + diff --git a/docs/ecosystem/ECOSYSTEM.adoc b/docs/ecosystem/ECOSYSTEM.adoc new file mode 100644 index 0000000..734247a --- /dev/null +++ b/docs/ecosystem/ECOSYSTEM.adoc @@ -0,0 +1,164 @@ +// SPDX-License-Identifier: MPL-2.0 += Ecosystem position — blocky-writer +:toc: +:toc-placement: preamble +:icons: font + +This file exists because of an acceptance criterion in +https://github.com/hyperpolymath/docmatrix/issues/71[docmatrix#71]: + +[quote] +____ +Each repository README and GitHub description states its own boundary and links +to the other optional components. +____ + +It is the long-form version of the boundary statement in the README. The +authoritative, versioned contract is docmatrix#71 itself — if the two disagree, +docmatrix#71 wins and this file is the thing that is stale. + +== What blocky-writer is + +A Mozilla Firefox extension for fitting and placing content into +**fixed-layout PDF and application-form boxes, baselines and per-character +cells** — the kind that were designed for hand spacing rather than reliable +computer entry. + +Concretely, today: an AcroForm field walker and writeback engine in Rust +(`rust/pdftool_core`), compiled to WASM, with two exported functions +(`detect_blocks`, `fill_blocks`) and a structured `BW_*` error taxonomy. + +== What blocky-writer is not + +* *Not a document viewer or editor.* Tabbed multi-format viewing and editing is + https://github.com/hyperpolymath/formatrix-docs[Formatrix Docs]. +* *Not a conversion engine.* Multi-format conversion and precision + coordination is https://github.com/hyperpolymath/docmatrix[DocMatrix]. +* *Not an OCR or extraction pipeline.* That is + https://github.com/hyperpolymath/docudactyl[Docudactyl]. +* *Not a print router.* That is https://github.com/hyperpolymath/presswerk[Presswerk]. +* *Not a cross-document consistency reconciler.* That is + https://github.com/hyperpolymath/recon-silly-ation[recon-silly-ation]. +* *Not a general PDF library.* It fills forms; it does not render, typeset or + lay out pages. +* *Not ForthWall.* ForthWall is a proposed, unbuilt, capability-bounded + execution layer. It is never a mandatory end-user product. + +== The suite + +[cols="1,2,2",options="header"] +|=== +| Project | Owns | Repo + +| blocky-writer +| Fixed-layout PDF and application-form placement +| https://github.com/hyperpolymath/blocky-writer[this repo] + +| DocMatrix +| Multi-format conversion and precision coordination for the suite +| https://github.com/hyperpolymath/docmatrix[hyperpolymath/docmatrix] + +| Formatrix Docs +| Tabbed viewing/editing of one logical document across TXT, tabular text, + Markdown, AsciiDoc, Djot, DEED, Org, reStructuredText and Typst +| https://github.com/hyperpolymath/formatrix-docs[hyperpolymath/formatrix-docs] + +| ForthWall +| Optional capability-bounded execution layer for critical operations + (_proposed, not implemented_) +| — + +|=== + +== Adjacent, not in the suite + +These are separate projects with their own boundaries. They are listed because +blocky-writer plausibly touches them, not because anyone has agreed a contract. + +[cols="1,2,2",options="header"] +|=== +| Project | Why it is adjacent | Repo + +| AffineScript +| The language `src/*.affine` targets. blocky-writer is a real consumer. +| https://github.com/hyperpolymath/affinescript[hyperpolymath/affinescript] + +| Docudactyl +| OCR, NER and metadata extraction — a plausible future source of field labels. +| https://github.com/hyperpolymath/docudactyl[hyperpolymath/docudactyl] + +| dotmatrix-fileprinter +| Sibling in the "matrix" naming line; filesystem-side manipulation. +| https://github.com/hyperpolymath/dotmatrix-fileprinter[hyperpolymath/dotmatrix-fileprinter] + +| Presswerk +| High-assurance local print routing; downstream of a filled PDF. +| https://github.com/hyperpolymath/presswerk[hyperpolymath/presswerk] + +| recon-silly-ation +| Cross-document consistency reconciler. Distinct from ForthWall. +| https://github.com/hyperpolymath/recon-silly-ation[hyperpolymath/recon-silly-ation] + +| universal-language-server-plugin +| Universal document conversion across editors; overlaps DocMatrix's remit. +| https://github.com/hyperpolymath/universal-language-server-plugin[hyperpolymath/universal-language-server-plugin] + +| gv-clade-index +| Taxonomy registry. `.machine_readable/CLADE.a2ml` registers this repo there. +| https://github.com/hyperpolymath/gv-clade-index[hyperpolymath/gv-clade-index] + +| deed-ecosystem / standards +| Governance and the `.deed` manifest format. +| https://github.com/hyperpolymath/deed-ecosystem[deed-ecosystem] / + https://github.com/hyperpolymath/standards[standards] + +| ddraig-ssg / casket-ssg +| The two SSGs behind the Pages workflows (see the conflict noted in + link:../ci/CHECK-DETERMINATIONS.adoc[the CI ledger]). +| https://github.com/hyperpolymath/ddraig-ssg[ddraig-ssg] / + https://github.com/hyperpolymath/casket-ssg[casket-ssg] + +| BerryWiki +| The format and tooling used by this project's wiki. +| https://github.com/metadatastician/berrywiki[metadatastician/berrywiki] + +|=== + +== The composition contract (summary) + +From docmatrix#71. blocky-writer is a party to all eight clauses, but clause 4 +is the one it is most likely to break: + +[quote] +____ +No component silently normalises punctuation, Unicode/whitespace, attribution, +terminology, document structure, or page geometry. +____ + +Page geometry is this project's entire subject. Normalising a rectangle "to be +helpful" is precisely the failure the contract forbids. + +== Proof obligations do not transfer + +* Conversion round-trip tests do not prove synchronised editor state. +* Editor tests do not prove fixed-layout PDF geometry. +* Exact page coordinates do not prove semantic correctness. +* Deterministic Forth execution does not prove the chosen operation or location + was correct. + +A green badge on a neighbour is not evidence about this repository, and this +repository's green `cargo test` is not evidence about a neighbour's. + +== How cross-repo communication works here + +There is no standing integration programme and none is planned. The working +pattern is deliberately light: + +. Each repo states its own boundary in its README and links the others. +. When a repo's status changes in a way that unblocks or affects a neighbour, + it files a short issue on that neighbour saying what changed and what the + neighbour can now progress with or consume. +. The neighbour decides whether to act. Nothing is merged across repos. + +If you are about to build something that belongs to a project in the table +above, stop and check that project's README and open issues first. From f2d888c0cf4dbf0e662b541a21e5222ba167df56 Mon Sep 17 00:00:00 2001 From: hyperpolymath <6759885+hyperpolymath@users.noreply.github.com> Date: Sun, 27 Sep 2026 12:35:36 +0000 Subject: [PATCH 3/6] docs: correct the documents that were describing a different project MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A recon found six documents materially out of date. Each was corrected against what the repository actually contains, and the corrections are recorded in CHANGELOG.adoc and in docs/tech-debt-2026-05-26.adoc's new status section. - .github/CONTRIBUTING.md — was describing hyperpolymath/language-bridges: it cloned the wrong repo, documented a lib/ + extensions/ + plugins/ + tools/ layout that does not exist here, and told readers to run `just check`, `mix compile` and `guix develop`. It also referenced an issue template that did not exist. Rewritten against this repository: real clone, real layout, the three Rust commands, the lock-sync rule, and the bot-actor caveat. - TOPOLOGY.adoc — claimed a "Deno-first" toolchain (deno.json was deleted by #43) and reported the AffineScript frontend at 100% "stateful forms stable" with an overall "~90% Production-ready extension". Both were false; the frontend is a prototype with no build pipeline. Dashboard corrected, the missing "Last updated" date added, and a rule-of-honesty note explaining that a bar describes working verified code, not files on disk. - EXPLAINME.adoc — listed Deno as a technology choice and mapped a `lib/` directory that does not exist. Replaced with the real dependency set and a claims-and-where-they-are-checked table. - www/.well-known/humans.txt — described an "Idris2 ABI, Zig FFI" project and was dated 2026-03-28. Corrected to the actual stack and date. - www/.well-known/ai.txt — pointed at an `AI.a2ml` that does not exist. - TEST-NEEDS.adoc — "CI workflows | 15" (there are 14 .yml files; the 15th file is actions.lock), a stale `TEST-NEEDS.md` header, and a "What's Covered" section that predated the clippy fix. - docs/tech-debt-2026-05-26.adoc — the 2026-05-26 snapshot claimed CHANGELOG.md was missing (CHANGELOG.adoc now exists) and CONTRIBUTING.md was present and adequate (it was present and wrong). A status-as-of-2026-09-27 section now records which findings are resolved and which numbers are stale, so the snapshot cannot be mistaken for current state. - CHANGELOG.adoc — the [Unreleased] section was a raw, partly mangled commit dump (including one entry with an inline `-Authored-By:` trailer and a duplicated TEST-NEEDS line). Regrouped into Keep-a-Changelog prose. Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com> --- .github/CONTRIBUTING.md | 230 +++++++++++++++++++++------------ CHANGELOG.adoc | 106 ++++++++++----- EXPLAINME.adoc | 53 ++++++-- TEST-NEEDS.adoc | 32 +++-- TOPOLOGY.adoc | 54 ++++++-- docs/tech-debt-2026-05-26.adoc | 31 +++++ www/.well-known/ai.txt | 5 +- www/.well-known/humans.txt | 10 +- 8 files changed, 369 insertions(+), 152 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 117714a..dc54f48 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1,121 +1,187 @@ -# Clone the repository + -git clone https://github.com/hyperpolymath/language-bridges.git +# Contributing to blocky-writer + +**Read `README.adoc` first.** The short version of where this project stands: +the Rust/WASM core (`rust/pdftool_core`) is implemented, unit-tested and green +in CI. The AffineScript frontend (`src/*.affine`) is a prototype with no build +pipeline in this checkout. Nothing here is release-ready as a Firefox extension +yet. + +--- + +## Clone and set up + +```bash +git clone https://github.com/hyperpolymath/blocky-writer.git cd blocky-writer +``` -# Using Guix (recommended for reproducibility) +You need **Rust stable** with the `rustfmt` and `clippy` components. Nothing else +is required for the only checks that exist: -guix develop +```bash +rustup toolchain install stable --component rustfmt clippy +``` + +There is **no** Node, Deno, npm, `wasm-pack` or Guix requirement. Older documents +in this repository describe a different project shape — if a file tells you to +run `deno task`, `just check`, or `guix develop`, it is stale. Please report it +with the *Documentation* issue template. -# Or using toolbox/distrobox +### Optional tooling in the tree -toolbox create language-bridges-dev -toolbox enter language-bridges-dev -# Install dependencies manually +| File | What it is | +| --- | --- | +| `Justfile`, `contractile.just` | `just` recipes: `just doctor`, `just tour`, `just help-me`, `just aspect`, `just crg-grade`. Run `just --list` for the current set. | +| `mise.toml`, `.tool-versions` | Tool version pinning. | +| `Containerfile`, `stapeln.toml`, `selur-compose/compose.toml` | Container and compose definitions. | +| `setup.sh` | Bootstrap script. | +| `scripts/build-wasm.sh` | Builds the WASM package. Needs `wasm-pack` + `wasm32-unknown-unknown`. Nothing in CI runs it and nothing consumes the output yet. | -# Verify setup +Several of these were minted from `hyperpolymath/rsr-template-repo` and describe +a project shape this repository does not have. Treat them as scaffolding. -just check # or: cargo check / mix compile / etc. -just test # Run test suite +--- -### Repository Structure +## Repository structure ```text blocky-writer/ -├── src/ # Source code (Perimeter 1-2) -├── lib/ # Library code (Perimeter 1-2) -├── extensions/ # Extensions (Perimeter 2) -├── plugins/ # Plugins (Perimeter 2) -├── tools/ # Tooling (Perimeter 2) -├── docs/ # Documentation (Perimeter 3) -│ ├── architecture/ # ADRs, specs (Perimeter 2) -│ └── proposals/ # RFCs (Perimeter 3) -├── examples/ # Examples (Perimeter 3) -├── spec/ # Spec tests (Perimeter 3) -├── tests/ # Test suite (Perimeter 2-3) -├── .well-known/ # Protocol files (Perimeter 1-3) -├── .github/ # GitHub config (Perimeter 1) -│ ├── CONTRIBUTING.md # This file -│ ├── ISSUE_TEMPLATE/ -│ └── workflows/ -├── CHANGELOG.md -├── CODE_OF_CONDUCT.md -├── GOVERNANCE.md -├── LICENSE -├── MAINTAINERS.md -├── README.adoc -├── SECURITY.md -├── flake.guix # Guix flake (Perimeter 1) -└── justfile # Task runner (Perimeter 1) +├── rust/pdftool_core/ # Rust → WASM core (the only tested code) +│ ├── src/lib.rs # detect_blocks, fill_blocks, BW_* taxonomy +│ ├── Cargo.toml +│ └── Cargo.lock # committed; CI runs with --locked +├── src/ # AffineScript prototype (not buildable here) +│ ├── popup.affine, content.affine, background.affine +│ ├── components/ # Block.affine, FormFiller.affine +│ └── core/ # PdfTool, ProvenMount, Storage +├── public/ # manifest.json, popup.html, icons +├── tests/ # aspect + fuzz placeholder +├── scripts/ # build-wasm.sh, check-lock-sync.sh +├── wiki/ # BerryWiki-format wiki source (see wiki/README.adoc) +├── docs/ +│ ├── ci/CHECK-DETERMINATIONS.adoc # the CI ledger — read the standing rules +│ ├── ecosystem/ECOSYSTEM.adoc # suite boundary and neighbours +│ └── reports/, tech-debt-*.adoc +├── .machine_readable/ # machine-readable state; load-bearing, do not restructure +├── www/.well-known/ # ai.txt, humans.txt, security.txt +├── README.adoc # the README (AsciiDoc, not Markdown) +├── TOPOLOGY.adoc # architecture map + completion dashboard +├── EXPLAINME.adoc +├── TEST-NEEDS.adoc # CRG test grade +├── CHANGELOG.adoc +├── CODE_OF_CONDUCT.adoc +├── SECURITY.adoc +├── GOVERNANCE.adoc +├── Containerfile +├── Justfile +└── .github/ + ├── ISSUE_TEMPLATE/ # bug_report, feature_request, documentation, config + ├── PULL_REQUEST_TEMPLATE.md + ├── workflows/ + └── actions.lock ``` - --- +Note the `.adoc` extensions. This repository documents itself in AsciiDoc, not +Markdown. + +--- + +## How to contribute -## How to Contribute +### Reporting bugs -### Reporting Bugs +Use the [bug report template](.github/ISSUE_TEMPLATE/bug_report.yml). Include: - **Before reporting**: - 1. Search existing issues - 2. Check if it's already fixed in `main` - 3. Determine which perimeter the bug affects +* Which area — Rust core, frontend prototype, CI, docs or packaging. +* Steps to reproduce. For core bugs, a minimal PDF and the field map you passed. +* The **whole** error payload if you got one. Core failures carry a stable + machine code plus message and context; the code alone is not enough. - **When reporting**: +Before reporting, search existing issues and check whether the bug is in the +core (actionable) or the frontend prototype (may not be). - Use the [bug report template](.github/ISSUE_TEMPLATE/bug_report.md) and include: +### Suggesting features - - Clear, descriptive title - - Environment details (OS, versions, toolchain) - - Steps to reproduce - - Expected vs actual behaviour - - Logs, screenshots, or minimal reproduction +Use the [feature request template](.github/ISSUE_TEMPLATE/feature_request.yml). +Check `docs/ecosystem/ECOSYSTEM.adoc` first — blocky-writer owns fixed-layout PDF +and application-form placement *only*. Viewing, editing, conversion, OCR and +print routing belong to other projects in the suite. -### Suggesting Features +### Reporting documentation problems - **Before suggesting**: - 1. Check the [roadmap](ROADMAP.md) if available - 2. Search existing issues and discussions - 3. Consider which perimeter the feature belongs to +Use the [documentation template](.github/ISSUE_TEMPLATE/documentation.yml). +Documentation drift is a defect here, not a nit. - **When suggesting**: +### Security - Use the [feature request template](.github/ISSUE_TEMPLATE/feature_request.md) and include: +Do **not** open a public issue. Use +[GitHub Security Advisories](https://github.com/hyperpolymath/blocky-writer/security/advisories/new). +See `SECURITY.adoc`. - - Problem statement (what pain point does this solve?) - - Proposed solution - - Alternatives considered - - Which perimeter this affects +### Opening a pull request -### Your First Contribution +1. Fork and branch from `main`. +2. Make your change. +3. Run the three core checks — **all three must pass**: - Look for issues labelled: + ```bash + cargo fmt --manifest-path rust/pdftool_core/Cargo.toml -- --check + cargo test --manifest-path rust/pdftool_core/Cargo.toml --locked + cargo clippy --manifest-path rust/pdftool_core/Cargo.toml --locked --all-targets -- -D warnings + ``` - - [`good first issue`](https://github.com/hyperpolymath/language-bridges/labels/good%20first%20issue) — Simple Perimeter 3 tasks - - [`help wanted`](https://github.com/hyperpolymath/language-bridges/labels/help%20wanted) — Community help needed - - [`documentation`](https://github.com/hyperpolymath/language-bridges/labels/documentation) — Docs improvements - - [`perimeter-3`](https://github.com/hyperpolymath/language-bridges/labels/perimeter-3) — Community sandbox scope + `cargo test` runs 6 tests. If you get a different number, something changed + and the wiki is stale — fix the wiki too. - --- + If you cannot run these — no Rust toolchain, no crates.io access — **say so + explicitly in the PR** rather than implying you did. CI is the only authority + on green. -## Development Workflow +4. **If you changed a `uses:` line in any workflow**, regenerate + `.github/workflows/actions.lock` in the *same commit* and run + `scripts/check-lock-sync.sh` (needs `gawk`). A stale lock entry is as fatal as + a missing one, and the failure is silent — `startup_failure`, zero jobs, no + log. +5. **If you removed or retired a CI check**, add or update a row in + `docs/ci/CHECK-DETERMINATIONS.adoc`. +6. Fill in `.github/PULL_REQUEST_TEMPLATE.md`. Do not delete the checklist. -### Branch Naming +### House rules -docs/short-description # Documentation (P3) test/what-added # Test -additions (P3) feat/short-description # New features (P2) -fix/issue-number-description # Bug fixes (P2) refactor/what-changed # -Code improvements (P2) security/what-fixed # Security fixes (P1-2) +* AsciiDoc (`.adoc`) for repository documentation. SPDX header on every file. +* MPL-2.0 licence, Palimpsest philosophy. +* Conventional commits: `fix(rust): …`, `docs(ci): …`, `ci: …`. +* No new TypeScript, Python or Go. No npm/bun/yarn/pnpm dependencies. +* No `unsafe` blocks in Rust without a safety comment. The core is + `#![forbid(unsafe_code)]` — keep it that way. +* `.machine_readable/` is load-bearing. Do not restructure it casually. +* `BW_*` error codes are stable API. Adding or renaming one is a breaking change. +* **Never** silence a gate. No `continue-on-error`, no `if: false`, no quiet + deletion of a job. +### CI you cannot trigger -### Commit Messages +Every Actions run whose actor is `arena-ai-coding-agent[bot]` is refused at +startup (`Actor is not allowed to trigger Actions workflows`). A bot-authored PR +shows **no** repository checks at all — not red, absent — because a startup +failure creates no check run. This is an org-side policy; no file change cures +it. Bot PRs must be merged by the repository owner so the merge push carries an +allowed actor. See the `<>` section of `docs/ci/CHECK-DETERMINATIONS.adoc`. - We follow [Conventional Commits](https://www.conventionalcommits.org/): +--- -type(scope): description +## The wiki -Body: what changed and why. +The project wiki lives at + in BerryWiki format. Its +source of truth is `wiki/` in this repository. See `wiki/README.adoc` for how to +edit and publish it. -Footer: issue reference, e.g. Closes #123 -\[optional body\] +## Questions -\[optional footer\] +Open an issue, or see `GOVERNANCE.adoc` for how decisions are made. diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index ab27262..26a94c3 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -16,58 +16,96 @@ https://semver.org/spec/v2.0.0.html[Semantic Versioning]. === [Unreleased] +Entries below are grouped by Keep-a-Changelog section. Raw commit subjects are +not repeated verbatim — where a commit subject was mangled or carried an inline +`+Authored-By:+` trailer, it has been tidied here. + ==== Added -* feat(crg): add crg-grade and crg-badge justfile recipes -* feat: add wokelangiser accessibility+consent manifest -* feat: add UX Justfile with doctor, tour, help-me, assail recipes -* feat: add stapeln.toml layer-based container definitionfrom existing -Containerfile to stapeln format.Chainguard base, security hardening, -SBOM generation.-Authored-By: Claude Opus 4.6 (1M context) -noreply@anthropic.com -* feat: deploy UX Manifesto infrastructure -* feat: add CLADE.a2ml — clade taxonomy declaration -* feat: add mirror.yml workflow for GitLab/Bitbucket mirroring +* `+wiki/+` — BerryWiki-format wiki source (tree, backlinks, tags, zero + JavaScript) with `+_Sidebar.md+` generated from it, and `+wiki/README.adoc+` + documenting the format and the publish step. +* `+docs/ecosystem/ECOSYSTEM.adoc+` — the suite boundary statement required by + docmatrix#71, with the adjacent-project list and the composition contract. +* `+.github/ISSUE_TEMPLATE/+` — `+bug_report.yml+`, `+feature_request.yml+`, + `+documentation.yml+` and `+config.yml+`. There were previously no issue + templates at all, despite `+CONTRIBUTING.md+` referencing one. +* `+.github/PULL_REQUEST_TEMPLATE.md+` — including the "if you changed a `+uses:+` + line, ship the lock change" and "never silence a gate" checks. +* `+.machine_readable/6a2/STATE.a2ml+` — `+verified+`, `+not-implemented+`, + `+known-red-on-main+` and `+open-decisions+` sections, replacing a bare + `+completion-percentage+` that had been stale since 2026-03-15. +* UX Justfile recipes: `+doctor+`, `+tour+`, `+help-me+`, `+assail+`. +* CRG grade recipes: `+crg-grade+`, `+crg-badge+`. +* `+wokelangiser.toml+` accessibility and consent manifest. +* `+stapeln.toml+` — layer-based container definition converted from the existing + `+Containerfile+` (Chainguard base, security hardening, SBOM generation). +* `+CLADE.a2ml+` — clade taxonomy declaration, registered with `+gv-clade-index+`. +* `+mirror.yml+` — GitLab/Bitbucket (and Disroot, Gitea, Codeberg, SourceHut, + Radicle) mirroring. ==== Fixed -* fix(ci): resync actions.lock after #69/#70/#71 desync that startup-killed -every workflow on main; re-pin codeql-action to the held v4.38.0; correct the -dependabot codeql ignore glob; retire `core-fill-tests`/`extension-build` with -a written determination in docs/ci/CHECK-DETERMINATIONS.adoc (#67) -* fix(ci): sync hypatia-scan.yml to canonical (#5) -* fix(ci): adopt canonical hypatia-scan.yml (#4) -* fix(scorecard): enforce granular permissions and add fuzzing -placeholder -* fix(ci): Resolve workflow-linter self-matching and metadata issues -* fix: SPDX headers (AGPL→PMPL), email, author name -* fix(license): SPDX AGPL-3.0 → PMPL-1.0-or-later in dotfiles -* fix: security hardening and CI workflow pinning +* `+rust/pdftool_core+`: resolved the two Clippy lints that were the only thing + keeping the `+Rust core (tests, formatting, lint)+` job red — + `+clippy::map_clone+` on `+doc.get_object(*id).map(Clone::clone)+` (now + `+.cloned()+`) and `+clippy::unnecessary_cast+` on + `+Object::Real(v) => Some(*v as f32)+` (now `+Some(*v)+`). The adjacent + `+Object::Integer+` cast was left alone because that `+i64+` → `+f32+` cast is real. + (#73) +* `+rust/pdftool_core+`: `+rustfmt+` applied so the formatting step of the + `+rust-core+` job passes. (e1b6225) +* `+actions.lock+` resynchronised after the #69/#70/#71 desync that startup-killed + every workflow on `+main+`; `+codeql-action+` re-pinned to the held v4.38.0; the + Dependabot codeql ignore glob corrected to `+github/codeql-action*+`; the dead + `+core-fill-tests+` and `+extension-build+` jobs retired with a written + determination in `+docs/ci/CHECK-DETERMINATIONS.adoc+`. (#67) +* Documentation drift: `+.github/CONTRIBUTING.md+` rewritten (it described + `+hyperpolymath/language-bridges+` and a repo layout that does not exist here); + `+TOPOLOGY.adoc+` corrected (it claimed a Deno-first toolchain and 100% frontend + completion); `+EXPLAINME.adoc+` corrected (it listed Deno as a technology + choice); `+www/.well-known/humans.txt+` corrected (it described an Idris2/Zig + project); `+0-AI-MANIFEST.a2ml+` broken references fixed. +* `+docs/ci/CHECK-DETERMINATIONS.adoc+`: the `+rust-core+` row corrected — the job + *has* executed (run 36296845297 at `+e1b6225+`), reaching its third step with + `+fmt+` and `+test+` green and only Clippy red. The previous revision claimed it + had never run. +* `+hypatia-scan.yml+` synced to the canonical estate version. +* Scorecard: granular permissions enforced; fuzzing placeholder added. +* Workflow linter self-matching and metadata issues resolved. +* SPDX headers corrected (AGPL → PMPL) along with author name and email. ==== Changed -* refactor: migrate 6SCM → 6A2 (.scm → .a2ml format) +* `+.machine_readable/+` migrated from 6SCM to 6A2 (`+.scm+` → `+.a2ml+`). +* `+README.adoc+` gained an *Ecosystem position* section stating the boundary and + linking the other suite components, satisfying the first acceptance criterion + of docmatrix#71. +* CodeQL Action v3 → v4. ==== Documentation -* docs: add TEST-NEEDS.md (CRG C) -* docs: add TEST-NEEDS.md (CRG C) -* docs: restore README.md lost in Floor Raise campaign -* docs: add EXPLAINME.adoc — prove-it file backing README claims -* docs: add 0-AI-MANIFEST.a2ml (RSR compliance) +* `+TEST-NEEDS.adoc+` — CRG grade C. +* `+EXPLAINME.adoc+` — prove-it file backing README claims. +* `+0-AI-MANIFEST.a2ml+` — RSR compliance entry point. +* `+REQUIRES_INITIALISATION.adoc+` — rewritten as a resolution record; all + inherited substitution tokens are now filled. ==== CI -* ci: deploy dogfood-gate, fix hypatia-scan, add pre-commit hooks -* ci: migrate CodeQL Action v3 → v4 -* ci: update SHA pins for codeql-action and trufflehog -* ci: deploy missing standard workflows (10 added) +* `+lock-sync-gate.yml+` added as the authoritative `+actions.lock+` gate; the + duplicate in-workflow lock job removed from `+ci.yml+` because a workflow that + GitHub refuses to start when the lock is broken can never report the fault it + exists to catch. +* Dogfood gate deployed; pre-commit hooks added. +* SHA pins updated for `+codeql-action+` and `+trufflehog+`. +* Ten standard estate workflows deployed. === Pre-history -Prior commits to this file’s introduction are recorded in git history +Prior commits to this file's introduction are recorded in git history but not formally classified into Keep-a-Changelog sections. To backfill, -run `+git cliff -o CHANGELOG.md+` locally using the canonical +run `+git cliff -o CHANGELOG.adoc+` locally using the canonical https://github.com/hyperpolymath/standards/blob/main/templates/cliff.toml[`+cliff.toml+`] — this is one-shot mechanical work. diff --git a/EXPLAINME.adoc b/EXPLAINME.adoc index f018288..632b7c6 100644 --- a/EXPLAINME.adoc +++ b/EXPLAINME.adoc @@ -5,30 +5,63 @@ The README makes claims. This file backs them up. -[quote, README] -____ -See the link:README.adoc[README] for details. -____ - == Technology Choices [cols="1,2"] |=== | Technology | Learn More -| **Deno** | https://deno.land -| **AffineScript** | https://affinescript-lang.org +| **Rust** | https://www.rust-lang.org +| **lopdf** | https://crates.io/crates/lopdf — PDF object model, parsing, serialisation +| **wasm-bindgen** | https://rustwasm.github.io/wasm-bindgen — the export surface +| **AffineScript** | https://affinescript-lang.org — the frontend language (prototype; no toolchain here) |=== +NOTE: Deno is *not* used. `deno.json` and every `deno task` were removed in #43 +(2026-08-24). The `deno.lock` file still in the tree is a leftover, not a +declaration of anything. + == File Map [cols="1,2"] |=== | Path | What's There -| `src/` | Source code -| `lib/` | Library code -| `test(s)/` | Test suite +| `rust/pdftool_core/src/lib.rs` | The whole core: `detect_blocks`, `fill_blocks`, the field walkers, the `BW_*` error taxonomy, and 6 unit tests. ~1030 lines. +| `src/*.affine` | AffineScript prototype: popup, content script, background script, `core/PdfTool`, `core/Storage`, `core/ProvenMount`, `components/Block`, `components/FormFiller`. Not buildable in this checkout. +| `public/` | `manifest.json`, `popup.html`, icons. +| `tests/aspect/` | Aspect-oriented test shell script. +| `tests/fuzz/` | Placeholder only. +| `scripts/build-wasm.sh` | WASM package build. Not run by CI; output unconsumed. +| `scripts/check-lock-sync.sh` | The `actions.lock` gate (needs `gawk`). +| `wiki/` | BerryWiki-format wiki source. See `wiki/README.adoc`. +| `docs/ci/CHECK-DETERMINATIONS.adoc` | The CI ledger and its standing rules. +| `docs/ecosystem/ECOSYSTEM.adoc` | Suite boundary and adjacent projects. +| `.machine_readable/` | Machine-readable state, contractiles, clade declaration. +| `www/.well-known/` | `ai.txt`, `humans.txt`, `security.txt`. +|=== + +== Claims, and where they are checked + +[cols="1,2",options="header"] +|=== +| Claim in the README | Where it is checked + +| The Rust core is implemented and has unit tests +| `cargo test --manifest-path rust/pdftool_core/Cargo.toml --locked` — 6 tests, including AcroForm writeback for text/select and button widgets and the structured error taxonomy. + +| `cargo fmt`, `cargo test` and `cargo clippy -D warnings` all pass +| `.github/workflows/ci.yml`, job `Rust core (tests, formatting, lint)`. As of 2026-09-27 this job is green on `main` at `e1b6225`. + +| The frontend is a prototype with no build pipeline +| There is no AffineScript compiler configuration and no JavaScript package manifest in the tree. `deno.json` was deleted by #43. + +| `fill_blocks` performs AcroForm-aware writeback +| `apply_field_value` in `rust/pdftool_core/src/lib.rs`, dispatched on field type `Tx` / `Ch` / `Btn`. + +| Errors carry structured codes +| `CoreErrorPayload { code, message, context }`; 20 `BW_*` codes. + |=== == Questions? diff --git a/TEST-NEEDS.adoc b/TEST-NEEDS.adoc index a6e05b9..761b2a3 100644 --- a/TEST-NEEDS.adoc +++ b/TEST-NEEDS.adoc @@ -1,30 +1,43 @@ -== TEST-NEEDS.md — blocky-writer +// SPDX-License-Identifier: MPL-2.0 +== TEST-NEEDS.adoc — blocky-writer === CRG Grade: C — ACHIEVED 2026-04-04 +Last reviewed: 2026-09-27. + === Current Test State [cols=",,",options="header",] |=== |Category |Count |Notes |Test directories |1 |Location(s): /tests (aspect + fuzz placeholder) -|CI workflows |15 |`ci.yml` runs the Rust core checks; see docs/ci/CHECK-DETERMINATIONS.adoc -|Unit tests |Implemented |Rust `pdftool_core` (`cargo test --locked`) +|CI workflows |14 |`.github/workflows/*.yml`. `ci.yml` runs the Rust core checks; `actions.lock` is a file, not a workflow. See docs/ci/CHECK-DETERMINATIONS.adoc +|Unit tests |6 |Rust `pdftool_core` — `cargo test --manifest-path rust/pdftool_core/Cargo.toml --locked` |=== -=== What’s Covered +=== What's Covered -* [x] Rust core unit tests (block detection, `fill_blocks_*` AcroForm writeback, taxonomy errors) -* [x] `cargo fmt --check` and `cargo clippy -D warnings` in CI +* [x] Rust core unit tests (block detection, `fill_blocks_*` AcroForm writeback for + `Tx`/`Ch`/`Btn` fields, taxonomy errors) — 6 tests, all green on `main` at `e1b6225` +* [x] `cargo fmt -- --check` in CI — green +* [x] `cargo clippy --all-targets -- -D warnings` in CI — green (the two remaining + lints were fixed in #73) +* [x] `actions.lock` synchronisation gate (`lock-sync-gate.yml`) — green on `main` === Still Missing (for CRG B+) * [ ] Extension frontend build + tests — no AffineScript/bundle toolchain in this checkout (retired CI job `extension-build`; see docs/ci/CHECK-DETERMINATIONS.adoc) * [ ] Code coverage reports (codecov integration) -* [ ] Detailed test documentation in CONTRIBUTING.md -* [ ] Integration tests beyond unit tests +* [ ] Detailed test documentation in `.github/CONTRIBUTING.md` — the file now exists and + documents how to run the core checks, but there is no test-authoring guide +* [ ] Integration tests beyond unit tests — in particular, no test loads a real-world + AcroForm PDF from disk; the fixture is synthesised in `mod tests` +* [ ] Property tests for the field walkers (`collect_field_ids`, `field_full_name`, + `field_type`) — these recurse and are cycle-guarded, which is exactly the shape + property tests pay off on * [ ] Performance benchmarking suite +* [ ] Ruled-line, per-character-cell and baseline detection — unimplemented, so untestable === Run Tests @@ -34,3 +47,6 @@ cargo fmt --manifest-path rust/pdftool_core/Cargo.toml -- --check cargo test --manifest-path rust/pdftool_core/Cargo.toml --locked cargo clippy --manifest-path rust/pdftool_core/Cargo.toml --locked --all-targets -- -D warnings ---- + +If you cannot run these — no Rust toolchain, no crates.io access — say so in the +PR rather than implying you did. CI is the only authority on green. diff --git a/TOPOLOGY.adoc b/TOPOLOGY.adoc index 412decc..beb35f1 100644 --- a/TOPOLOGY.adoc +++ b/TOPOLOGY.adoc @@ -1,5 +1,10 @@ == blocky-writer — Project Topology +.... +Last updated: 2026-09-27 +Status: Rust core green (fmt + 6 tests + clippy); frontend prototype, no build pipeline +.... + === System Architecture .... @@ -11,7 +16,7 @@ ▼ ┌─────────────────────────────────────────┐ │ EXTENSION UI LAYER │ - │ (AffineScript + React + Office.js) │ + │ (AffineScript — prototype) │ │ ┌───────────┐ ┌───────────────────┐ │ │ │ Popup UI │ │ Content Script │ │ │ └─────┬─────┘ └────────┬──────────┘ │ @@ -20,7 +25,7 @@ ▼ ▼ ┌─────────────────────────────────────────┐ │ BACKGROUND SERVICE │ - │ (AffineScript, State Management) │ + │ (AffineScript — prototype) │ └───────────────────┬─────────────────────┘ │ ▼ @@ -37,34 +42,43 @@ ┌─────────────────────────────────────────┐ │ REPO INFRASTRUCTURE │ - │ Deno-first scripts .machine_readable/ │ - │ webpack.config.cjs Containerfile │ + │ .machine_readable/ Containerfile │ + │ .github/workflows/ wiki/ │ └─────────────────────────────────────────┘ .... === Completion Dashboard +Read this as *what exists and is verified*, not as *what is written down*. +The AffineScript layers are prototypes: the sources exist, but there is no +compiler configuration, no package manifest and no bundle pipeline in this +checkout, so there is nothing to build, run or release. Percentages below +reflect working, verified code — not the presence of files. + .... COMPONENT STATUS NOTES ───────────────────────────────── ────────────────── ───────────────────────────────── EXTENSION LAYERS - Popup UI (AffineScript/React) ██████████ 100% Stateful forms stable - Background Script ██████████ 100% WASM bridge active - Content Script ████████░░ 80% PDF block detection refining + Popup UI (AffineScript) ██░░░░░░░░ 20% src/popup.affine prototype; no build + Background Script ██░░░░░░░░ 20% src/background.affine prototype + Content Script █░░░░░░░░░ 10% src/content.affine prototype + Extension bundle pipeline ░░░░░░░░░░ 0% deno.json removed in #43; no toolchain CORE (RUST/WASM) - pdftool_core (WASM) ██████████ 100% Core logic stable - AcroForm Writeback ██████████ 100% Text/Select widgets verified - Error Taxonomy ██████████ 100% Structured error codes active + pdftool_core (WASM) ████████░░ 80% detect_blocks + fill_blocks, 6 tests green + AcroForm Writeback ████████░░ 80% Tx / Ch / Btn only; no Sig + Ruled-line & cell detection ░░░░░░░░░░ 0% NOT IMPLEMENTED — the "hand spacing" case + Error Taxonomy ██████████ 100% 20 stable BW_* codes REPO INFRASTRUCTURE - Rust CI (fmt/test/clippy) ██████████ 100% ci.yml rust-core job - Extension bundle pipeline ░░░░░░░░░░ 0% deno.json removed in #43; no toolchain + Rust CI (fmt/test/clippy) ██████████ 100% ci.yml rust-core job — green + Lock Sync Gate ██████████ 100% lock-sync-gate.yml — green on main + Documentation ████████░░ 80% README/TOPOLOGY/wiki corrected 2026-09-27 .machine_readable/ ██████████ 100% STATE.a2ml tracking Containerfile ██████████ 100% Reproducible dev env ───────────────────────────────────────────────────────────────────────────── -OVERALL: █████████░ ~90% Production-ready extension +OVERALL: █████░░░░░ ~50% Rust core ready; extension not release-ready .... === Key Dependencies @@ -72,8 +86,17 @@ OVERALL: █████████░ ~90% Produ .... Block Detection ───► AcroForm Parser ───► WASM Bridge ───► Extension UI (Rust) (Rust) (JS) (AffineScript) + +lopdf 0.34 ─────────► rust/pdftool_core ─────────► detect_blocks / fill_blocks .... +=== Ecosystem + +See `+docs/ecosystem/ECOSYSTEM.adoc+` for the boundary statement and the +adjacent-project list, and +https://github.com/hyperpolymath/docmatrix/issues/71[docmatrix#71] for the +versioned composition contract. + === Update Protocol This file is maintained by both humans and AI agents. When updating: @@ -86,3 +109,8 @@ This file is maintained by both humans and AI agents. When updating: Progress bars use: `+█+` (filled) and `+░+` (empty), 10 characters wide. Percentages: 0%, 10%, 20%, … 100% (in 10% increments). + +*Rule of honesty:* a bar describes **working, verified code**. A file that +exists but cannot be compiled, run or tested is 0%, however large it is. The +`+deno.json+` deletion in #43 (2026-08-24) is why the extension layers are low +despite having sources. diff --git a/docs/tech-debt-2026-05-26.adoc b/docs/tech-debt-2026-05-26.adoc index cee2985..46a08b8 100644 --- a/docs/tech-debt-2026-05-26.adoc +++ b/docs/tech-debt-2026-05-26.adoc @@ -1,5 +1,36 @@ == Tech-Debt Audit — blocky-writer — 2026-05-26 +''''' + +IMPORTANT: The sections below are a *snapshot taken on 2026-05-26*. Several +findings have since been resolved and some numbers are now wrong. Read +<> before acting on anything here. + +[[status-2026-09-27]] +== Status as of 2026-09-27 + +[cols="2,1,3",options="header"] +|=== +| Finding | Now | Evidence + +| `CHANGELOG.md` missing | *Resolved* | `CHANGELOG.adoc` exists and has an `[Unreleased]` section. It is still generated from commit subjects rather than maintained by hand, so the *quality* finding stands even though the *existence* finding does not. +| `CONTRIBUTING.md` present but wrong | *Resolved* | `.github/CONTRIBUTING.md` was rewritten on 2026-09-27. It had described `hyperpolymath/language-bridges`, a `lib/`/`extensions/`/`plugins/` layout, `just check`, `mix compile` and `flake.guix` — none of which exist here. +| No `docs/` directory | *Resolved* | `docs/` now holds `ci/CHECK-DETERMINATIONS.adoc`, `ecosystem/ECOSYSTEM.adoc`, `accessibility/`, `compliance/`, `reports/audit/` and the tech-debt files. +| `docs/` LoC 490, README 87 lines | *Stale numbers* | Both have grown. Recount rather than trusting these figures. +| README doing the work of `docs/` | *Partly resolved* | README is still the entry point, but `docs/ecosystem/ECOSYSTEM.adoc`, `TOPOLOGY.adoc`, `EXPLAINME.adoc` and `wiki/` now carry the detail. +| Documentation debt overall | *Reduced, not closed* | `TOPOLOGY.adoc` claimed a Deno-first toolchain and 100% frontend completion; `EXPLAINME.adoc` listed Deno as a technology choice; `www/.well-known/humans.txt` described an Idris2/Zig project. All three corrected on 2026-09-27. +| Proof debt (no `*.v`/`*.lean`/…) | *Unchanged* | Still none. See section 1 below. +| Licence debt | *Unchanged, still ok* | See section 2 below. + +|=== + +New debt introduced or discovered since the snapshot is recorded in +`.machine_readable/agent_instructions/debt.a2ml` and in the +`known-red-on-main` and `open-decisions` sections of +`.machine_readable/6a2/STATE.a2ml`. + +''''' + *Source:* estate-wide automated scan 2026-05-26. *Companion:* https://github.com/hyperpolymath/standards/tree/main/docs/audits[`+hyperpolymath/standards+` 2026-05-26-estate-*-debt audits]. *Combined severity:* `+MEDIUM+`. diff --git a/www/.well-known/ai.txt b/www/.well-known/ai.txt index 334b406..24ae030 100644 --- a/www/.well-known/ai.txt +++ b/www/.well-known/ai.txt @@ -13,6 +13,7 @@ Disallow-Generation: yes # AI agents must preserve Emotional Lineage per PMPL Section 3. # # For AI agent integration instructions, see: -# 0-AI-MANIFEST.a2ml (universal AI entry point) -# AI.a2ml (Claude-specific instructions) +# 0-AI-MANIFEST.a2ml (universal AI entry point — read this first) # .machine_readable/ (structured project state) +# .machine_readable/agent_instructions/ (coverage, debt, methodology) +# wiki/Home.md (project wiki, BerryWiki format) diff --git a/www/.well-known/humans.txt b/www/.well-known/humans.txt index 5b6216d..d283597 100644 --- a/www/.well-known/humans.txt +++ b/www/.well-known/humans.txt @@ -7,8 +7,12 @@ Contact: j.d.a.jewell@open.ac.uk From: United Kingdom /* SITE */ -Last update: 2026-03-28 +Last update: 2026-09-27 Standards: RSR (Rhodium Standard Repository) License: MPL-2.0 (Palimpsest MPL) -Components: Idris2 ABI, Zig FFI -Tools: just, Podman, Guix +Components: Rust/WASM core (lopdf), AffineScript frontend prototype +Site generator: casket-ssg (Haskell) — see the duplicate-workflow note in docs/ci/CHECK-DETERMINATIONS.adoc + +/* THANKS */ +The hyperpolymath estate, and the precision document suite: +docmatrix, formatrix-docs, and the proposed ForthWall. From 151e2aed1267c986c95c8ab70da47fafd1fe2b0c Mon Sep 17 00:00:00 2001 From: hyperpolymath <6759885+hyperpolymath@users.noreply.github.com> Date: Sun, 27 Sep 2026 12:35:42 +0000 Subject: [PATCH 4/6] feat(templates): add issue and pull-request templates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The repository had no .github/ISSUE_TEMPLATE/ directory at all, even though CONTRIBUTING.md told contributors to use a bug report template, and no pull request template. Both gaps meant every issue and PR arrived with whatever context the author happened to think of. Added, in the estate's YAML issue-form style: - bug_report.yml — area picker (rust-core / frontend prototype / ci / docs / packaging), reproduction steps, environment, and a dedicated field for the whole BW_* error payload, because the code alone is not enough to diagnose. - feature_request.yml — problem, solution, alternatives, layer, plus a boundary check prompt pointing at docs/ecosystem/ECOSYSTEM.adoc. - documentation.yml — stale / wrong / missing / contradictory / unfindable, which is how drift actually gets reported. - config.yml — links to the wiki, the docmatrix#71 boundary contract, and the security advisory route (explicitly not a public issue). - PULL_REQUEST_TEMPLATE.md — what changed, type of change, local verification (with an explicit instruction to say when something could not be run rather than implying it was), the lock-sync and determination-ledger checks, and the owner-merge note for bot-authored PRs. Labels referenced are all present in the repository's label set. Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com> --- .github/ISSUE_TEMPLATE/bug_report.yml | 116 +++++++++++++++++++++ .github/ISSUE_TEMPLATE/config.yml | 14 +++ .github/ISSUE_TEMPLATE/documentation.yml | 57 ++++++++++ .github/ISSUE_TEMPLATE/feature_request.yml | 83 +++++++++++++++ .github/PULL_REQUEST_TEMPLATE.md | 52 +++++++++ 5 files changed, 322 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/documentation.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yml create mode 100644 .github/PULL_REQUEST_TEMPLATE.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..638b044 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,116 @@ +# SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell +# SPDX-License-Identifier: MPL-2.0 +# Bug report issue template for hyperpolymath/blocky-writer +name: Bug Report +description: Create a report to help us improve +title: "[Bug]: " +labels: ["bug", "priority:p2"] +assignees: [] +body: + - type: markdown + attributes: + value: | + Thank you for taking the time to report a bug. Please fill out the sections below + so we can reproduce and fix the issue. + + **Before filing:** check whether the bug is in the Rust core or in the + AffineScript frontend prototype. Only the Rust core is implemented and + tested today; the frontend has no build pipeline, so frontend bugs may + not be actionable. + + - type: dropdown + id: area + attributes: + label: Which area? + description: Pick the closest match. Used for triage only. + options: + - "rust-core — rust/pdftool_core (detect_blocks / fill_blocks)" + - "rust-core — error taxonomy (BW_* codes)" + - "frontend — src/*.affine prototype (no build pipeline)" + - "ci — workflows, actions.lock, gates" + - "docs — README, wiki, docs/" + - "packaging — Containerfile, manifest, selur-compose" + validations: + required: true + + - type: textarea + id: description + attributes: + label: Describe the bug + description: A clear and concise description of what the bug is. + placeholder: When I do X, Y happens instead of Z. + validations: + required: true + + - type: textarea + id: reproduction + attributes: + label: Steps to reproduce + description: Detailed steps to reproduce the behavior. A minimal PDF and field map is ideal. + placeholder: | + 1. Load a PDF with an AcroForm containing ... + 2. Call `fill_blocks(pdf, blocks, { "Name": "Ada" })` + 3. The returned PDF has ... + value: | + 1. + 2. + 3. + validations: + required: true + + - type: textarea + id: expected + attributes: + label: Expected behavior + description: A clear and concise description of what you expected to happen. + validations: + required: true + + - type: textarea + id: environment + attributes: + label: Environment + description: Versions and platform. For core bugs, the Rust toolchain and lopdf version matter. + placeholder: | + - OS: + - Rust: + - blocky-writer commit: + - Firefox version (if frontend): + value: | + - OS: + - Rust: + - blocky-writer commit: + validations: + required: false + + - type: textarea + id: error-code + attributes: + label: Error code, if any + description: | + Core failures carry a stable machine code (`BW_*`) plus a message and + optional context. Paste the whole payload — the code alone is not enough. + placeholder: | + { "code": "BW_FILL_NO_MATCHING_FIELDS", "message": "...", "context": "..." } + validations: + required: false + + - type: textarea + id: logs + attributes: + label: Logs or output + description: Any relevant output. For CI failures, link the run. + validations: + required: false + + - type: checkboxes + id: checks + attributes: + label: Pre-flight + options: + - label: I searched existing issues and this is not a duplicate. + required: true + - label: I ran the three core checks (`cargo fmt --check`, `cargo test --locked`, `cargo clippy -D warnings`) where applicable. + required: false + - label: I have read the current status in the repository README and understand the frontend is a prototype. + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..4c0fc49 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell +# SPDX-License-Identifier: MPL-2.0 +# Issue template chooser configuration for hyperpolymath/blocky-writer +blank_issues_enabled: true +contact_links: + - name: Project wiki + url: https://github.com/hyperpolymath/blocky-writer/wiki + about: BerryWiki-format wiki — architecture, Rust core, CI gates, ecosystem and glossary. Source of truth is wiki/ in this repository. + - name: Ecosystem boundary + url: https://github.com/hyperpolymath/docmatrix/issues/71 + about: The versioned composition contract for the precision document suite, and where each project's boundary is declared. + - name: Security vulnerabilities + url: https://github.com/hyperpolymath/blocky-writer/security/advisories/new + about: Report security vulnerabilities privately via GitHub Security Advisories. Do not open a public issue. diff --git a/.github/ISSUE_TEMPLATE/documentation.yml b/.github/ISSUE_TEMPLATE/documentation.yml new file mode 100644 index 0000000..0ea0a06 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/documentation.yml @@ -0,0 +1,57 @@ +# SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell +# SPDX-License-Identifier: MPL-2.0 +# Documentation issue template for hyperpolymath/blocky-writer +name: Documentation +description: Report wrong, missing or stale documentation +title: "[Docs]: " +labels: ["documentation"] +assignees: [] +body: + - type: markdown + attributes: + value: | + Use this for anything in `README.adoc`, `TOPOLOGY.adoc`, `docs/`, the + wiki, or `.github/` that is wrong, missing or out of date. + + Documentation drift is treated as a defect here, not a nit. If a document + told you something untrue about the state of the project, that is a bug + in the document. + + - type: dropdown + id: kind + attributes: + label: What kind of problem? + options: + - "Stale — describes a state that is no longer true" + - "Wrong — describes something that was never true" + - "Missing — the information does not exist anywhere" + - "Contradictory — two documents disagree" + - "Unfindable — exists but is not linked from where you looked" + validations: + required: true + + - type: input + id: location + attributes: + label: Which file or page? + description: Path in the repository, or the wiki page name. + placeholder: "TOPOLOGY.adoc — Completion Dashboard section" + validations: + required: true + + - type: textarea + id: problem + attributes: + label: What is wrong? + description: Quote the offending text if you can. + placeholder: "It says the Popup UI is 100% complete, but there is no build pipeline for it." + validations: + required: true + + - type: textarea + id: correction + attributes: + label: What should it say? + description: If you know. If you do not, say so — that is useful information too. + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..53d86df --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,83 @@ +# SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell +# SPDX-License-Identifier: MPL-2.0 +# Feature request issue template for hyperpolymath/blocky-writer +name: Feature Request +description: Suggest an idea or enhancement for this project +title: "[Feature]: " +labels: ["enhancement", "priority:p2"] +assignees: [] +body: + - type: markdown + attributes: + value: | + Thank you for suggesting a feature. Please describe your idea clearly so we can + evaluate and prioritize it. + + **Before filing:** check the boundary statement in + `docs/ecosystem/ECOSYSTEM.adoc`. blocky-writer owns fixed-layout PDF and + application-form placement only. Viewing, editing, conversion, OCR and + print routing belong to other projects in the suite — if your idea is + one of those, it probably belongs there instead. + + - type: textarea + id: problem + attributes: + label: Problem statement + description: Is your feature request related to a problem? Describe the pain point. + placeholder: "I'm always frustrated when [...]. Currently there is no way to [...]." + validations: + required: true + + - type: textarea + id: solution + attributes: + label: Proposed solution + description: A clear and concise description of what you want to happen. + placeholder: "I'd like a command/option/feature that [...]." + validations: + required: true + + - type: textarea + id: alternatives + attributes: + label: Alternatives considered + description: Any alternative solutions or features you have considered. + placeholder: "I considered using X, but it doesn't work because [...]." + validations: + required: false + + - type: dropdown + id: scope + attributes: + label: Which layer? + options: + - "rust-core — rust/pdftool_core" + - "frontend — src/*.affine prototype" + - "packaging / extension build" + - "ci / governance" + - "docs / wiki" + - "not sure" + validations: + required: false + + - type: textarea + id: boundary + attributes: + label: Boundary check + description: | + Does this belong to blocky-writer, or to another project in the suite? + If another, name it and say why. This is not a blocker, but it speeds + triage considerably. + placeholder: "This belongs here because ... / This may belong to docmatrix because ..." + validations: + required: false + + - type: checkboxes + id: checks + attributes: + label: Pre-flight + options: + - label: I searched existing issues and discussions and this is not a duplicate. + required: true + - label: I have read `docs/ecosystem/ECOSYSTEM.adoc` and believe this is in scope. + required: false diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..9fd79a3 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,52 @@ + + +## What changed + + + +## Type of change + +- [ ] Bug fix (`fix:`) +- [ ] New feature (`feat:`) +- [ ] Documentation (`docs:`) +- [ ] CI / workflow / lockfile (`ci:`) +- [ ] Refactor, no behaviour change (`refactor:`) +- [ ] Chore (`chore:`) + +## Local verification + + + +```bash +cargo fmt --manifest-path rust/pdftool_core/Cargo.toml -- --check +cargo test --manifest-path rust/pdftool_core/Cargo.toml --locked +cargo clippy --manifest-path rust/pdftool_core/Cargo.toml --locked --all-targets -- -D warnings +``` + +## Checklist + +- [ ] I ran the three commands above (or explained why I could not). +- [ ] **If I changed a `uses:` line**, `actions.lock` is updated in this same commit and I ran `scripts/check-lock-sync.sh`. +- [ ] **If I removed or retired a CI check**, there is a matching row in `docs/ci/CHECK-DETERMINATIONS.adoc`. +- [ ] I have not added `continue-on-error`, `if: false`, or weakened any gate. +- [ ] If I changed a component's state, `TOPOLOGY.adoc` is updated. +- [ ] If I changed something the wiki asserts, the matching `wiki/` page is updated. +- [ ] Documentation that this PR makes stale has been updated in the same PR. + +## Owner actions + + + +- [ ] Merge as the repository owner, not via the bot. Runs triggered by + `arena-ai-coding-agent[bot]` are refused at startup + (`Actor is not allowed to trigger Actions workflows`), so a bot-authored PR + shows **no** repository checks at all — not red, absent. + +## Notes for the reviewer + + From 4f3def44082d7a4b817f333db667a3580fcd1f3a Mon Sep 17 00:00:00 2001 From: hyperpolymath <6759885+hyperpolymath@users.noreply.github.com> Date: Sun, 27 Sep 2026 12:35:50 +0000 Subject: [PATCH 5/6] wiki: seed the project wiki in BerryWiki format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The GitHub wiki is enabled on this repository but has never been initialised — the .wiki.git repository 404s. This adds the source for it, in the BerryWiki format adopted from the metadatastician estate, so the wiki is versioned, diffable and reviewable in this repository rather than only editable through GitHub's web UI. Eight pages: Home, Architecture, Rust-Core, CI-and-Gates, Ecosystem, Contributing, Contributing--Dev-Setup, Glossary. Content is written against what the repository actually contains — the two-function WASM boundary, the name-driven (not coordinate-driven) writeback, the 20 BW_* codes, the six unit tests, and the things that are deliberately not implemented. Structure validated programmatically: 8 pages, unique ids, every `parent` id resolves, sibling positions distinct, no broken [[WikiLinks]], every _Sidebar link resolves. The metadata block is the first non-blank content of each file, as BerryWiki's parser requires; the SPDX header follows it as a second HTML comment so it stays invisible in GitHub's renderer. wiki/README.adoc documents the format, the three rules that make it work, the publish step, and how to add a page. The wiki is also pushed to hyperpolymath/blocky-writer.wiki.git so it is live. Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com> --- wiki/Architecture.md | 91 +++++++++++++++++++++++++++ wiki/CI-and-Gates.md | 89 ++++++++++++++++++++++++++ wiki/Contributing--Dev-Setup.md | 81 ++++++++++++++++++++++++ wiki/Contributing.md | 75 ++++++++++++++++++++++ wiki/Ecosystem.md | 91 +++++++++++++++++++++++++++ wiki/Glossary.md | 82 ++++++++++++++++++++++++ wiki/Home.md | 59 +++++++++++++++++ wiki/README.adoc | 108 ++++++++++++++++++++++++++++++++ wiki/Rust-Core.md | 90 ++++++++++++++++++++++++++ wiki/_Sidebar.md | 10 +++ 10 files changed, 776 insertions(+) create mode 100644 wiki/Architecture.md create mode 100644 wiki/CI-and-Gates.md create mode 100644 wiki/Contributing--Dev-Setup.md create mode 100644 wiki/Contributing.md create mode 100644 wiki/Ecosystem.md create mode 100644 wiki/Glossary.md create mode 100644 wiki/Home.md create mode 100644 wiki/README.adoc create mode 100644 wiki/Rust-Core.md create mode 100644 wiki/_Sidebar.md diff --git a/wiki/Architecture.md b/wiki/Architecture.md new file mode 100644 index 0000000..a59ad17 --- /dev/null +++ b/wiki/Architecture.md @@ -0,0 +1,91 @@ + + + + +# Architecture + +## Layers + +``` +┌──────────────────────────────────────────────┐ +│ USER / BROWSER (Firefox, PDF forms) │ +└───────────────────────┬──────────────────────┘ + ▼ +┌──────────────────────────────────────────────┐ +│ EXTENSION UI LAYER │ +│ popup.affine content.affine │ +│ components/Block.affine components/FormFiller.affine +└───────────────────────┬──────────────────────┘ + ▼ +┌──────────────────────────────────────────────┐ +│ BACKGROUND SERVICE │ +│ background.affine core/Storage.affine │ +│ core/ProvenMount.affine │ +└───────────────────────┬──────────────────────┘ + ▼ +┌──────────────────────────────────────────────┐ +│ CORE PROCESSING (Rust → WASM) │ +│ rust/pdftool_core │ +│ detect_blocks() fill_blocks() │ +└───────────────────────┬──────────────────────┘ + ▼ +┌──────────────────────────────────────────────┐ +│ DATA LAYER │ +│ IndexedDB / local storage │ +└──────────────────────────────────────────────┘ +``` + +## What actually exists + +| Layer | Reality | +| --- | --- | +| Rust/WASM core | **Implemented and tested.** `rust/pdftool_core/src/lib.rs`, ~1030 lines, 6 unit tests. | +| AffineScript surfaces | **Prototype.** `src/*.affine` sources exist; no compiler config, no bundle pipeline. | +| Extension packaging | **Absent.** `public/manifest.json` and icons are present; nothing produces a loadable `.xpi`. | +| Storage | **Prototype.** `src/core/Storage.affine` only. | + +## The seam that matters + +Everything the extension does to a PDF goes through exactly two exported +functions. That boundary is the whole contract: + +```rust +#[wasm_bindgen] pub fn detect_blocks(pdf_data: &[u8]) -> Result +#[wasm_bindgen] pub fn fill_blocks(pdf_data: &[u8], blocks: JsValue, fields: JsValue) + -> Result +``` + +* `detect_blocks` walks every page's `Annots`, keeps the ones that are widget + annotations with a usable `Rect`, and returns a `Block { label, x, y, width, + height }` per widget. Labels come from the field's `/T`, falling back to the + parent field's `/T`, falling back to `field__`. +* `fill_blocks` takes the original PDF bytes plus a `field name → value` map, + writes the values into the AcroForm, and returns new PDF bytes. It is + **name-driven, not coordinate-driven** — the `blocks` argument is parsed and + validated but the writeback is keyed on field names. + +That last point is worth internalising: blocky-writer's contribution to the +document suite is *placement into fixed-layout forms*, not free-form layout. +See [Ecosystem](Ecosystem). + +## Error taxonomy + +Failures never cross the WASM boundary as strings. They are structured payloads +with a stable machine code, a human message, and optional context: + +```json +{ "code": "BW_FILL_NO_MATCHING_FIELDS", "message": "…", "context": "Choice" } +``` + +There are 20 `BW_*` codes. Codes are stable API — treat adding or renaming one +as a breaking change, not a tidy-up. diff --git a/wiki/CI-and-Gates.md b/wiki/CI-and-Gates.md new file mode 100644 index 0000000..08f599c --- /dev/null +++ b/wiki/CI-and-Gates.md @@ -0,0 +1,89 @@ + + + + +# CI and Gates + +Start here before you touch a workflow, a pin, or anything under `.github/`. + +## The gate that actually matters + +`.github/workflows/lock-sync-gate.yml` — **`actions.lock is in sync with the +workflow YAML`**. It carries no `uses:` of its own, so it is immune to the +failure it detects. + +GitHub refuses to *start* any workflow whose step-level `uses:` refs are not +recorded, under that workflow's own path, in `.github/workflows/actions.lock`. +The refusal is silent: `startup_failure`, zero jobs, no log. A stale lock entry +is as fatal as a missing one. + +**Rule: any change to a `uses:` line ships with the matching `actions.lock` +change in the same commit.** Verify with: + +```bash +scripts/check-lock-sync.sh # needs gawk +``` + +## The Rust gate + +`.github/workflows/ci.yml`, job **`Rust core (tests, formatting, lint)`** — the +only job in that workflow: + +| Step | Command | +| --- | --- | +| Check formatting | `cargo fmt --manifest-path rust/pdftool_core/Cargo.toml -- --check` | +| Run unit tests | `cargo test --manifest-path rust/pdftool_core/Cargo.toml --locked` | +| Run Clippy | `cargo clippy --manifest-path rust/pdftool_core/Cargo.toml --locked --all-targets -- -D warnings` | + +## Other workflows + +| Workflow | Purpose | +| --- | --- | +| `lock-sync-gate.yml` | The lockfile gate above. | +| `ci.yml` | The Rust core job. Deliberately contains **no** lockfile job — a lockfile checker inside a workflow that cannot start when the lock is broken can never report. | +| `codeql.yml` | CodeQL Advanced. | +| `governance.yml` | Governance checks. | +| `secret-scanner.yml` | Secret scanning. | +| `hypatia-scan.yml` | Neurosymbolic governance scan. | +| `mirror.yml` | Mirrors to GitLab, Bitbucket, Disroot, Gitea, Codeberg, SourceHut, Radicle. | +| `pages.yml` | Builds the Pages site with **Ddraig** (Idris 2). | +| `casket-pages.yml` | Builds the Pages site with **casket-ssg** (Haskell). | +| `boj-build.yml`, `instant-sync.yml`, `push-email-notify.yml`, `label-triage.yml`, `labels.yml` | Estate plumbing. | + +## Known problems — read before you trust a green + +* **Two Pages workflows.** `pages.yml` and `casket-pages.yml` both build and + deploy to the `github-pages` environment under the same `pages` concurrency + group, so they cancel each other. `pages.yml` also looks for `README.md`, + which does not exist here (this repo uses `README.adoc`), so it would publish + a bare `# hyperpolymath/blocky-writer` index. `casket-pages.yml` handles + `README.adoc` correctly. **Which one is canonical is undecided.** +* **The bot cannot trigger Actions.** Every run whose actor is + `arena-ai-coding-agent[bot]` is refused at startup with + `Actor is not allowed to trigger Actions workflows`. A bot-authored PR shows + *no* repository checks at all — not red, absent — because a startup failure + creates no check run. This is an org-side policy, not something a file change + can cure. Consequence: **the owner must trigger or merge**, and a bot merge + leaves `main` looking red even when the files are correct. +* **`Branch-Floor` has no `required_status_checks` rule.** So "removed from the + required set" is vacuously satisfied, and a red gate is a convention rather + an enforcement. The permanent cure is owner-side. + +## Where the determinations live + +`docs/ci/CHECK-DETERMINATIONS.adoc` is the ledger. Every CI check that has ever +been red on `main` has exactly one determination — *fixed*, *retired* or +*exempt* — and none is ever closed by muting it (`continue-on-error`, demotion +to a warning, or silent removal). Read the standing rules at the bottom before +you diagnose anything. diff --git a/wiki/Contributing--Dev-Setup.md b/wiki/Contributing--Dev-Setup.md new file mode 100644 index 0000000..3ca9620 --- /dev/null +++ b/wiki/Contributing--Dev-Setup.md @@ -0,0 +1,81 @@ + + + + +# Dev Setup + +## What you actually need + +For the Rust core — the only thing with tests — you need: + +* Rust stable with `rustfmt` and `clippy` components +* Network access to crates.io (or a vendored registry) + +```bash +rustup toolchain install stable --component rustfmt clippy +``` + +That is it. There is no Node, Deno, npm or wasm-pack requirement for the core +checks, despite what older documents in this repo may say. + +## What you do **not** need, and cannot currently use + +* **Deno** — `deno.json` was removed in #43 (2026-08-24) along with every + `deno task`. The `deno.lock` file still in the tree is a leftover. +* **wasm-pack** — only needed for `scripts/build-wasm.sh`, which produces a WASM + package nothing in this repo currently consumes. +* **An AffineScript toolchain** — `src/*.affine` cannot be compiled here. There + is no compiler configuration in this checkout. + +If a document tells you to run `just check`, `mix compile`, or `guix develop`, +it is describing a different repository. See +[Contributing](Contributing) for what is real. + +## First run + +```bash +git clone https://github.com/hyperpolymath/blocky-writer.git +cd blocky-writer + +cargo fmt --manifest-path rust/pdftool_core/Cargo.toml -- --check +cargo test --manifest-path rust/pdftool_core/Cargo.toml --locked +cargo clippy --manifest-path rust/pdftool_core/Cargo.toml --locked --all-targets -- -D warnings +``` + +`cargo test` runs 6 tests. If you get a different number, something changed and +the wiki is stale — fix the wiki. + +## Building the WASM package (optional) + +```bash +scripts/build-wasm.sh +``` + +Requires `wasm-pack` and the `wasm32-unknown-unknown` target. Nothing in CI does +this, and nothing consumes the output yet. + +## Tooling files in the tree, and what they are for + +| File | Status | +| --- | --- | +| `Justfile`, `contractile.just` | Task runner recipes. | +| `mise.toml`, `.tool-versions` | Tool version pinning. | +| `stapeln.toml` | Layer-based container definition. | +| `Containerfile` | Container build. | +| `selur-compose/compose.toml` | Compose definition. | +| `.editorconfig`, `.gitattributes` | Editor and git hygiene. | +| `setup.sh` | Bootstrap script. | + +Several of these were minted from `rsr-template-repo` and describe a project +shape this repo does not have. Treat them as scaffolding, not as instructions. diff --git a/wiki/Contributing.md b/wiki/Contributing.md new file mode 100644 index 0000000..e8a2786 --- /dev/null +++ b/wiki/Contributing.md @@ -0,0 +1,75 @@ + + + + +# Contributing + +## Before you open a PR + +1. Run the three Rust commands from [Home](Home). All three must pass. +2. If you touched a `uses:` line, regenerate `actions.lock` in the same commit + and run `scripts/check-lock-sync.sh`. +3. If you removed or retired a CI check, add or update a row in + `docs/ci/CHECK-DETERMINATIONS.adoc`. Never silence a gate with + `continue-on-error`, `if: false`, or a quiet deletion. +4. Update `TOPOLOGY.adoc` if you changed a component's completion state. + +## House style + +* AsciiDoc (`.adoc`) for repository documentation. SPDX header on every file. +* `MPL-2.0` licence. Palimpsest philosophy. +* Conventional commits: `fix(rust): …`, `docs(ci): …`, `ci: …`. +* No new TypeScript, Python or Go. No npm/bun/yarn/pnpm dependencies. +* `.machine_readable/` is load-bearing — do not restructure it casually. + +## The `REQUIRES_INITIALISATION` gate + +`0-AI-MANIFEST.a2ml` points at `REQUIRES_INITIALISATION.adoc`, which lists +substitution tokens the repo template could not fill because they need a human +decision. Resolve what you legitimately can from evidence; leave the rest. Do +not delete the file to make a gate go green. + +## Editing this wiki + +The wiki is BerryWiki-format. Two ways to work on it: + +**Directly in the GitHub wiki** — fine for prose tweaks. The pages stay plain +Markdown and GitHub renders them natively. + +**From the repo** — preferred for anything reviewable: + +```bash +# wiki/ in this repo is the source of truth +berrywiki check wiki # tree + diagnostics; exit 1 on any error +berrywiki sidebar wiki --write # regenerate _Sidebar.md +``` + +Then push `wiki/` to the wiki remote: + +```bash +git clone https://github.com/hyperpolymath/blocky-writer.wiki.git +cp wiki/*.md blocky-writer.wiki/ +cd blocky-writer.wiki && git add -A && git commit -m "wiki: sync from wiki/" && git push +``` + +The metadata block at the top of each page is what BerryWiki reads. It must be +the **first non-blank content** of the file. Hierarchy comes from the `parent` +id chain, never from the filename; the `--` in filenames is a human-friendly +slug only. `berrywiki check` catches broken links, missing parents, cycles and +duplicate ids. + +Never serve `