From e9cd3e819494a1079089eb893acb7b0a1868b47a Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 29 Jul 2026 12:04:26 +0000 Subject: [PATCH 1/4] feat(works): public Related Works registry with moderated issue-form submissions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Others can now add works engaging The Interdependent Way: - .github/ISSUE_TEMPLATE/related-work.yml — structured public submission form (title, creator, https link, type, relation, description, rights consent); applies the related-work label. - scripts/fetch-works.mjs — build-time fetch of issues carrying both related-work and approved labels from this repo via the allowlisted GitHub API; parses issue-form bodies, validates fail-closed with visible exclusions, writes generated/works.json plus a last-known-good snapshot; OFFLINE=1 uses the snapshot. Moderation is the label pair: add approved to publish, remove to delist. - /works/ page — registry with attribution, per-work issue provenance, the no-endorsement/no-status-transfer boundary, submission instructions (issue form + email fallback), and visible gaps for approved-but-invalid entries. - Nav link, refresh:works wired into refresh:data and prepare-tests, docs/related-works.md, and tests/works-registry.test.mjs (parser, validator, moderation gating, generated-dataset schema). npm test: 24 passed. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01E93Rxmrs8bXHtWjD7z94bi --- .github/ISSUE_TEMPLATE/related-work.yml | 77 +++++++ docs/related-works.md | 25 +++ package.json | 11 +- scripts/fetch-works.mjs | 200 ++++++++++++++++++ scripts/prepare-tests.mjs | 3 +- src/_data/generated/works.json | 8 + .../snapshots/works.last-known-good.json | 8 + src/_includes/layouts/base.njk | 1 + src/works/index.njk | 58 +++++ tests/works-registry.test.mjs | 76 +++++++ 10 files changed, 462 insertions(+), 5 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/related-work.yml create mode 100644 docs/related-works.md create mode 100644 scripts/fetch-works.mjs create mode 100644 src/_data/generated/works.json create mode 100644 src/_data/snapshots/works.last-known-good.json create mode 100644 src/works/index.njk create mode 100644 tests/works-registry.test.mjs diff --git a/.github/ISSUE_TEMPLATE/related-work.yml b/.github/ISSUE_TEMPLATE/related-work.yml new file mode 100644 index 0000000..017ffad --- /dev/null +++ b/.github/ISSUE_TEMPLATE/related-work.yml @@ -0,0 +1,77 @@ +name: Submit a related work +description: Propose a work (essay, paper, art, music, video, code, response, …) for the site's Related Works registry. +title: "[work] " +labels: ["related-work"] +body: + - type: markdown + attributes: + value: | + Thank you for engaging with The Interdependent Way. Submissions are reviewed by the + maintainer; approval lists the work on the public Related Works page with your + attribution. Listing is not endorsement, transfers no review or theorem status, and + never modifies canon or the research ledgers. Your GitHub username and everything you + write here are public. + - type: input + id: title + attributes: + label: Work title + description: The title of the work being submitted. + validations: + required: true + - type: input + id: creator + attributes: + label: Creator + description: Who made it — the name that should be credited. + validations: + required: true + - type: input + id: link + attributes: + label: Link + description: An https URL where the work lives (page, repository, video, gallery, …). + validations: + required: true + - type: dropdown + id: type + attributes: + label: Work type + options: + - essay + - paper + - art + - music + - video + - code + - response + - other + validations: + required: true + - type: textarea + id: relation + attributes: + label: Relation to The Interdependent Way + description: Which Article, chapter, or concept does this work engage, and how? + validations: + required: true + - type: textarea + id: description + attributes: + label: Description + description: A short description for the listing (a few sentences). + validations: + required: true + - type: input + id: license + attributes: + label: License note + description: Optional — the work's license or usage terms, if you want them shown. + validations: + required: false + - type: checkboxes + id: rights + attributes: + label: Rights and permission + options: + - label: I have the right to share this link, and I consent to it being listed publicly with the details above. + required: true diff --git a/docs/related-works.md b/docs/related-works.md new file mode 100644 index 0000000..d1b857a --- /dev/null +++ b/docs/related-works.md @@ -0,0 +1,25 @@ +# Related Works registry + +Public submissions of works engaging The Interdependent Way, moderated by label. + +## Flow + +1. A visitor submits via the structured issue form (`.github/ISSUE_TEMPLATE/related-work.yml`), + which applies the `related-work` label — or emails the same fields to the maintainer, + who files the issue on their behalf. +2. The maintainer reviews. Adding the `approved` label publishes the listing on the next + site build; removing either label delists it. Closing the issue does not delist — + the labels are the single switch. +3. `scripts/fetch-works.mjs` (in `refresh:data`) fetches all issues carrying both labels, + parses the issue-form body, validates each submission (required fields, https link, + allowed type), and writes `src/_data/generated/works.json` plus a last-known-good + snapshot. Invalid-but-approved submissions surface on the page as visible gaps rather + than disappearing. `OFFLINE=1` uses the snapshot. +4. `/works/` renders the registry with attribution, per-work provenance (issue link), + and the boundary statement. + +## Boundary + +Listing is moderation, not review: it transfers no endorsement, no research or review +status, and no theorem/proof/empirical status, and it never modifies canon or the +Article Lab research ledgers. Works remain at their own links under their own licenses. diff --git a/package.json b/package.json index 81b49a5..0680a92 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "type": "module", "scripts": { "dev": "npm run refresh:data && eleventy --serve", - "refresh:data": "npm run refresh:canon && npm run refresh:github && npm run refresh:textbook", + "refresh:data": "npm run refresh:canon && npm run refresh:github && npm run refresh:textbook && npm run refresh:works", "refresh:canon": "node scripts/fetch-canon.mjs && node scripts/parse-canon.mjs", "refresh:github": "node scripts/fetch-github-org.mjs", "refresh:textbook": "node scripts/fetch-textbook.mjs", @@ -15,14 +15,15 @@ "validate": "node scripts/validate-content.mjs && node scripts/verify-generated-routes.mjs && node scripts/verify-article-canon.mjs", "build": "npm run validate && eleventy && pagefind --site _site && node scripts/write-build-info.mjs", "pretest": "node scripts/prepare-tests.mjs", - "test": "node --test tests/canon-parser.test.mjs tests/canon-integrity.test.mjs tests/textbook-integrity.test.mjs tests/math-rendering.test.mjs tests/offline-project-snapshot.test.mjs tests/repo-coverage.test.mjs tests/research-ledger.test.mjs tests/site-contract.test.mjs", + "test": "node --test tests/canon-parser.test.mjs tests/canon-integrity.test.mjs tests/textbook-integrity.test.mjs tests/math-rendering.test.mjs tests/offline-project-snapshot.test.mjs tests/repo-coverage.test.mjs tests/research-ledger.test.mjs tests/works-registry.test.mjs tests/site-contract.test.mjs", "test:generated": "node --test tests/generated-site.test.mjs tests/textbook-generated.test.mjs tests/math-generated.test.mjs && node tests/links.test.mjs", "test:browser": "playwright test", "test:e2e": "playwright test tests/site.spec.mjs", "test:a11y": "playwright test tests/accessibility.spec.mjs", "test:links": "node tests/links.test.mjs", "test:performance": "node scripts/performance-placeholder.mjs", - "check": "npm run audit:workflows && npm run build && npm test && npm run test:generated" + "check": "npm run audit:workflows && npm run build && npm test && npm run test:generated", + "refresh:works": "node scripts/fetch-works.mjs" }, "dependencies": { "@11ty/eleventy": "3.1.2", @@ -39,5 +40,7 @@ "axe-core": "4.10.3", "pagefind": "1.3.0" }, - "engines": { "node": "24.x" } + "engines": { + "node": "24.x" + } } diff --git a/scripts/fetch-works.mjs b/scripts/fetch-works.mjs new file mode 100644 index 0000000..f43a853 --- /dev/null +++ b/scripts/fetch-works.mjs @@ -0,0 +1,200 @@ +import { execFileSync } from 'node:child_process'; +import { mkdir, readFile, writeFile } from 'node:fs/promises'; + +// === MODULE_BUILD === +// id: related_works_registry_fetch +// module_name: fetch-works +// module_kind: instrument +// summary: Resolves maintainer-approved related-work submissions from GitHub issues into one provenance-bearing works registry dataset. +// owner: Erin Spencer +// public_surface: npm run refresh:works, generated.works +// internal_surface: issue-form body parsing, per-submission validation with visible exclusions, snapshot fallback +// auth_boundary: optional read-only GITHUB_TOKEN +// storage_boundary: writes generated works data and a last-known-good snapshot +// network_boundary: allowlisted read-only HTTPS to api.github.com +// user_data_boundary: publishes only fields submitters place in a public GitHub issue +// admin_only: false +// tests: tests/works-registry.test.mjs +// rollout: included in refresh:data before validation and Eleventy generation +// rollback: remove refresh:works and the /works/ route; submissions remain as ordinary GitHub issues +// === END MODULE_BUILD === +// Usage: run `npm run refresh:works`; set OFFLINE=1 to use the retained snapshot or an empty registry. +// Limits: listing is maintainer moderation only — it transfers no endorsement, review status, or +// theorem/proof/empirical status, and it never touches the research ledgers or canon. + +// === BOUNDARIES === +// id: related_works_network_boundary +// summary: Reads only issues labeled related-work and approved from this repository via the allowlisted GitHub API. +// auth_boundary: optional GitHub read token +// storage_boundary: write beneath src/_data/generated and src/_data/snapshots +// network_boundary: external read-only +// user_data_boundary: public issue content only; submitter login retained as provenance +// admin_only: false +// pii: none beyond what submitters publish themselves +// secrets: GITHUB_TOKEN is passed only as an HTTPS authorization header and never written +// side_effects: generated dataset and snapshot writes +// owner: Erin Spencer +// === END BOUNDARIES === + +const apiOrigin = 'https://api.github.com'; +const registryRepository = 'The-Interdependency/The-Interdependency.github.io'; +const submissionLabel = 'related-work'; +const approvalLabel = 'approved'; +const snapshotPath = 'src/_data/snapshots/works.last-known-good.json'; +const generatedPath = 'src/_data/generated/works.json'; + +export const WORK_TYPES = ['essay', 'paper', 'art', 'music', 'video', 'code', 'response', 'other']; + +export const REQUIRED_FIELDS = { + 'Work title': 'title', + 'Creator': 'creator', + 'Link': 'url', + 'Work type': 'type', + 'Relation to The Interdependent Way': 'relation', + 'Description': 'description' +}; + +const OPTIONAL_FIELDS = { 'License note': 'license' }; + +// GitHub issue forms render each field as "###