diff --git a/.claude/rules/data-protection.md b/.claude/rules/data-protection.md deleted file mode 100644 index 47808c4..0000000 --- a/.claude/rules/data-protection.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -paths: - - "**/*" ---- - -# Data Protection — Treat As If Public - -Whether or not this repo is private today, treat everything in it as if it were -already public. A private repo can be made public, forked, cloned, or leaked, and -anything committed is permanent. The only safe assumption is that every file and -every past commit is visible to the world. - -## Hard rule (non-negotiable) - -Real person or student data must **NEVER** exist in this repo — or any repo — in -any form, anywhere in the working tree **or its git history**. Prevention is the -only safe path: once committed it lives in the history forever (see -"Already committed?" below). - -## NEVER write in files or commit messages: -- Personal names (colleagues, research participants, teachers, students) -- School names or abbreviations that identify specific schools -- University or institution names -- Research programme names (funded projects, grants) -- Place names (streets, buildings, venues) that identify locations -- Hardcoded file paths containing usernames (`/Users/...`, `/home/...`) -- Research questions specific enough to identify a study -- Chat history or session transcripts -- Secrets: API keys, tokens, passwords, `.env` contents, credentials - -## ALWAYS use instead: -- `School A`, `School B`, `Colleague_A` for anonymised references -- `/path/to/project` for file path examples -- `SPEAKER_01`, `L1` for participant references -- Generic descriptions for research programmes -- Synthetic/fabricated data in examples - -## Check before committing: -- Think before writing — does this text contain any personal names, paths, or identifiers? -- Would a reader identify a specific person, school, or study from this text — - **directly**, OR by combining quasi-identifiers (e.g. class + date + subject can - identify a student without naming them)? -- This is your judgement. The `pii_scan` commit gate is the deterministic backstop — - it catches what you miss, but it is not a substitute for the check above. - -## Already committed? Deletion is NOT enough. - -If real data is found already in the repo, removing the file in a new commit does -**not** remove it from git history — it remains in every past commit, clone, and -fork. To actually remove it you must scrub the history (fresh-repo rebuild or a -history filter) **and** rotate any exposed secret. Stop and escalate before -publishing or flipping such a repo. - -## This applies to ALL content: -- Source code, comments, error messages -- Documentation, RFCs, changelogs, roadmaps -- Commit messages -- Test data and examples diff --git a/.claude/rules/internal-docs-boundary.md b/.claude/rules/internal-docs-boundary.md deleted file mode 100644 index 193f36d..0000000 --- a/.claude/rules/internal-docs-boundary.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -paths: - - "**/*" ---- - -# Internal Documentation Boundary - -## These belong in the repo (public): -- Source code, tests, build config -- **Decision records** — `ADR-NNN` in `docs/decisions/` (the repo's design-record) -- Methodology documents (`methodology/`) -- Example files (`examples/`) — with fabricated data only -- User-facing docs: README, GETTING_STARTED, API, CONTRIBUTING, CHANGELOG -- Public design specs (`specs/`) — if intentionally public -- Templates (`templates/`) - -## These do NOT belong in the repo (→ project's Nextcloud internal-documentation): -- Handoff documents (`type: handoff`, HANDOFF_*, *_HANDOFF_*) -- **Ideas** (`type: idea`, `docs/ideas/`) — quick internal captures -- **RFCs** (`type: rfc`) — design proposals; internal until ratified, then they become an ADR in `docs/decisions/` -- **Explorations and shapes** (`type: exploration` / `type: shape`) — strategic deliberation -- Internal planning docs / plans (CODE_HANDOFF_*) -- Development notes (`notes/`, `_internal/`) -- Chat history or session exports -- Process memos from actual research projects -- Files from Nextcloud, Dropbox, OneDrive or other external sync services - -## If you are about to create or edit a file: -- Is this something a user who clones the repo needs? → Repo -- Is this internal planning, handoff, or development thinking? → NOT repo (use `save_document(doc_type=…)` → Nextcloud) - -## The document model (ratified 2026-06-21) -Repo = **ADR** (the ratified decision-record) + code / methodology / examples / user-docs. ALL -deliberation (idea / rfc / exploration / shape / handoff) is **internal** → the project's Nextcloud -`_internal_documentation/` (routed via `save_document(doc_type=…)`). Enforced deterministically -by `internal_docs_guard` (gate on a doc's frontmatter `type:`): unambiguously-internal types are blocked -from the repo (git pre-commit), optional-public (rfc/plan/todo/spec) only warn. diff --git a/.claude/rules/publish-readiness.md b/.claude/rules/publish-readiness.md deleted file mode 100644 index d333b31..0000000 --- a/.claude/rules/publish-readiness.md +++ /dev/null @@ -1,106 +0,0 @@ ---- -paths: - - "**/*" ---- - -# Publish Readiness — Pre-publish checklist - -This rule defines what makes a repository ready to flip from private to public. Used by the `/publish-check` slash-command. - -## Severity rubric - -### Blocker — MUST fix before public - -A finding that, if left in, exposes personal data, breaks user trust, or makes the repository misleading. Public-flip is unsafe until resolved. - -Examples: -- Personal names, hardcoded user-home paths, e-mail addresses -- README claims that contradict source code (false advertising) - -### Warning — SHOULD fix before public - -A finding that signals carelessness or inconsistency to public readers. Public-flip is possible but degrades reception. - -Examples: -- British-English drift in user-facing prose -- Missing community files referenced from README -- Outdated supported-versions in `SECURITY.md` - -### Nice-to-have — MAY add or improve - -A finding that, if added, increases professionalism but is not expected by readers. - -Examples: -- `CODE_OF_CONDUCT.md` -- `.github/dependabot.yml` -- Issue / pull-request templates - -## Scan axes - -The `/publish-check` command runs five scans: - -1. **data-protection** — sources truth from `data-protection.md` rule (user-home paths, personal names, e-mail addresses) -2. **language** — sources truth from `language-british-english.md` rule (American-English drift in prose) -3. **docs-freshness** — `README`, `ROADMAP`, `SECURITY` versions and counts vs the source (`package.json`, `src/`) -4. **release-hygiene** — community files exist and are current -5. **readme-sections** — README carries the golden-standard mandatory sections (see "README golden standard" below); sources truth from `readme_check.py` - -## README golden standard - -Every project README must clear one bar: **a newcomer understands what the project is -within the first ~15 lines** — the situation in plain language, before any architecture, -philosophy or jargon, defining terms the first time they are used. Complete structure is -not enough; comprehension is the test. - -The canonical template lives in ACDM at `templates/README.template.md`. It is a *reference*, -**not** seeded into projects (per ADR-016 + the doc-model: `templates/` is a repo-side -artifact ACDM owns; `init_project` distributes enforcement, not content scaffold). Copy its -structure when writing or revising a README. - -**Mandatory sections** (enforced by Scan 5 / `readme_check.py`): - -- **What is ``?** — the plain-language on-ramp. -- **Development status** (or **Status and maturity**) — honest maturity; early publication - is fine, overclaiming is not. -- **Data & privacy** — mandatory *only* when the tool touches personal data (human - judgement; deliberately not auto-checked). - -Recommended (not auto-enforced): ecosystem block (if part of a family), "who is this for?" -doors, how it works, Documentation, Requirements, Licence, Support, Acknowledgements. See -the template for the full shape and per-section guidance. - -## Out of scope (v1) - -- Auto-fix (report-only) -- Continuous-integration enforcement -- Pre-commit hook integration -- Security review (`/security-review` — separate skill) -- Code-quality review (`/simplify` — separate skill) -- README *quality* / textual review — does the prose actually communicate? (manual pass, or the `doc-reviewer` agent; Scan 5 checks section *presence*, not quality) -- INSTALL / LICENSE textual review (manual pass required) -- Version-bump decisions (project-internal) - -These are documented as v2 promotions or out-of-tool concerns. - -## Consuming the report safely - -When `/publish-check` produces findings and you start fixing them: - -1. **Verify the working tree is clean first** — `git status` shows no untracked or modified files you didn't expect. After `init_project(update=True)` the disk holds new files not yet visible to git. -2. **Stage explicit per finding** — `git add `, not `git add -A`. The `-A` form picks up unrelated upstream drift. -3. **Verify the diff per file before commit** — `git diff --staged `. -4. **Be extra careful immediately after `init_project --update`** — distributed templates may overwrite earlier per-project fixes; the report you ran against may not reflect the disk state. - -Context: Teacher_MCP PR #61 (2026-05-05) used `git add -A` against undetected upstream drift and introduced 2 new BE-drift findings while fixing 9. Explicit staging would have prevented this. - -## Building the public artifact (fresh-repo flips) - -When the flip strategy is a fresh repository (no carried-over git history), the published repo is *built* from the working tree through an include/exclude step. Three principles keep that build trustworthy: - -1. **Verify the built artifact, not the working tree.** A scan against the source tree never tests the include/exclude list itself — a file the list fails to exclude still sits in the tree the scan passed. Build the fresh repo into a staging location, then run the publish scans against *that*, before publishing. The artifact is what readers get; the artifact is what you verify. (This is distinct from "verify the working tree is clean" above: that guards the fixing step; this guards the published output.) -2. **Allowlist what ships; do not denylist what doesn't.** Start the fresh repo from empty and copy in only named paths. A denylist (copy everything, minus exclusions) fails open — anything you forget to list is published. An allowlist fails closed. -3. **Run the gate as a reproducible script against a committed checkpoint.** A single ad-hoc grep pass is not a gate — globs and mounts misfire silently. Commit the prep work to the still-private branch first, so there is an auditable diff and a stable state to build from, then run the scan as a script the human can re-run. - -A token grep (names, course codes) finds known strings; it cannot find sensitive content that lacks them (personal reflections, opinions about colleagues, self-flagged private documents). Where shipping files carry a privacy field in front-matter (e.g. `privacy: private`), treat that field — not a name grep — as the primary ship / no-ship filter. - -Context: the Teacher_MCP private→public flip (2026-05-27) scanned the working tree before the fresh-repo build, leaving the include/exclude list unverified; an independent grep pass misfired (wrong glob, slow mount) before being corrected; and a self-flagged `privacy: private` document was caught only by chance through a name grep. diff --git a/.gitignore b/.gitignore index f071327..10a7667 100644 --- a/.gitignore +++ b/.gitignore @@ -66,15 +66,9 @@ coverage/ .env.local *.local -# ACDM config — gitignored (local / path-sensitive). EXCEPT the repo-policy rules -# below, which describe the repo / are read by repo-tooling and must travel with a -# clone (ADR-015 "protection travels with the repo"). Process rules + acdm.json + -# .mcp.json + CLAUDE.md stay ignored. -.claude/* -!.claude/rules/ -.claude/rules/* -!.claude/rules/data-protection.md -!.claude/rules/internal-docs-boundary.md -!.claude/rules/publish-readiness.md +# Claude Code / ACDM config — local development tooling (path-sensitive or +# personal); none of it ships with the repo. The human-facing data-protection +# policy lives in SECURITY.md. +.claude/ .mcp.json CLAUDE.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 6677d4c..49302c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,24 @@ All notable changes to QuestionForge are documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Added + +- **README — a "Development status" section** (the honest maturity framing the sibling suites carry) and a **Support** section. + +### Changed + +- **Data-protection policy moved to SECURITY.md** — a new *Data protection* section + states the non-negotiable "no real personal data in the repo" rule where readers + expect it. The three `.claude/rules/` policy files are no longer shipped; + `.claude/` is local development tooling and is fully git-ignored again + (ADR-017 marked superseded). +- **CONTRIBUTING — sentence-case headings and a standardised licence line.** Corrected + documentation pointers: ADRs live in `docs/decisions/` (not `docs/adr/`), and + significant changes start as an issue or discussion (the repo carries no RFC folder). +- **SECURITY — vulnerability reporting standardised** to GitHub's private vulnerability reporting link, with an aligned supported-versions table and a response-time expectation. + ## [0.1.0] — First public release First public release of QuestionForge: a teacher-led, AI-assisted framework for @@ -23,4 +41,5 @@ exporting them to QTI. - Methodology guides (M1–M5) and a question-format reference. - Getting-started and workflow documentation. +[Unreleased]: https://github.com/tikankika/question-forge/compare/v0.1.0...HEAD [0.1.0]: https://github.com/tikankika/question-forge/releases/tag/v0.1.0 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f5d576a..bcd57b1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,9 +2,27 @@ Thank you for your interest in contributing to QuestionForge! -## How to Contribute +## Critical rules — data protection -### Reporting Bugs +QuestionForge reads real teaching materials (lectures, slides, course documents). +This is a public repository — never let real personal data into the repo, in code, +tests, comments, documentation, examples or commit messages. Git history is permanent. + +- **Never commit real personal data:** names (students, colleagues, teachers), + school or institution names, identifying places, personal-identity numbers, file + paths containing a username (`/Users/...`), secrets (API keys, tokens, `.env`), + and real course materials that identify people or institutions. +- **Use fabricated or anonymised data in every example and test** — for example + `School A`, `Colleague_A`, `/path/to/project`, a fake course code. +- **Watch quasi-identifiers:** a class plus a date plus a subject can identify a + student even with no name attached. +- **Already committed something real?** Deleting the file is not enough — it stays + in the git history forever. Stop, scrub the history, rotate any exposed secret, + and escalate before the next push. + +## How to contribute + +### Reporting bugs 1. Check if the bug is already reported in [Issues](https://github.com/tikankika/question-forge/issues) 2. If not, create a new issue with: @@ -13,15 +31,15 @@ Thank you for your interest in contributing to QuestionForge! - Expected vs actual behaviour - Environment (OS, Python/Node version, Claude Desktop version) -### Suggesting Features +### Suggesting features 1. Open an issue with the `enhancement` label 2. Describe the use case and proposed solution -3. Reference relevant ADRs or RFCs if applicable +3. Reference relevant ADRs (`docs/decisions/`) if applicable -### Code Contributions +### Code contributions -#### Setup Development Environment +#### Setup development environment ```bash # Clone your fork @@ -39,15 +57,15 @@ cd ../qf-scaffolding npm install ``` -#### Development Workflow +#### Development workflow -1. **Check existing ADRs** in `docs/adr/` for architectural context -2. **Create RFC** for significant changes (see `docs/rfcs/` for examples) +1. **Check existing ADRs** in `docs/decisions/` for architectural context +2. **Open an issue or discussion first** for significant changes, so the approach can be agreed before you build 3. **Write tests** for new functionality 4. **Follow code style** (see below) 5. **Update documentation** if needed -#### Code Style +#### Code style **Python (qf-pipeline, qti-core):** - Follow PEP 8 @@ -59,7 +77,7 @@ npm install - Explicit types (avoid `any`) - JSDoc for public functions -#### Commit Messages +#### Commit messages Follow conventional commits: @@ -74,7 +92,7 @@ refactor(step3): simplify fix rule matching Types: `feat`, `fix`, `docs`, `refactor`, `test`, `chore` -#### Pull Request Process +#### Pull request process 1. Update documentation if needed 2. Add tests for new functionality @@ -82,7 +100,7 @@ Types: `feat`, `fix`, `docs`, `refactor`, `test`, `chore` 4. Reference related issues in PR description 5. Request review -### Documentation Contributions +### Documentation contributions Documentation improvements are always welcome: @@ -91,14 +109,13 @@ Documentation improvements are always welcome: - Improve getting started guide - Translate to other languages -## Architecture Overview +## Architecture overview Before contributing code, familiarise yourself with: -- **ADR-001**: Two-MCP architecture (qf-scaffolding + qf-pipeline) -- **ADR-014**: Shared session management -- **docs/rfcs/**: Design proposals and specifications -- **WORKFLOW.md**: Complete workflow documentation +- **README.md**: the two-MCP architecture (qf-scaffolding + qf-pipeline) +- **WORKFLOW.md**: complete workflow documentation +- **docs/decisions/**: architecture decision records (ADRs) ## Communication @@ -106,9 +123,9 @@ Before contributing code, familiarise yourself with: - **Discussions**: Questions and ideas - **Pull Requests**: Code contributions -## License +## Licence -By contributing, you agree that your contributions will be licensed under PolyForm Noncommercial 1.0.0. +By contributing, you agree that your contributions will be licensed under PolyForm Noncommercial 1.0.0 (see [LICENSE](LICENSE)). --- diff --git a/README.md b/README.md index ccb2fbd..50a95f1 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,16 @@ QuestionForge helps educators create pedagogically sound assessment questions th The teacher stays in control at every step — the tools scaffold and document the method; they do not replace the teacher's judgement. +## Development status + +> **This is an active development project, published early.** The end-to-end chain — analyse teaching materials, author questions, validate, and export a QTI package for Inspera — works and is in use. It is shared at this stage deliberately, to invite use and critique. + +**What is solid, and what is still developing:** + +- The **pipeline** (validate question markdown, auto-fix, export to QTI) is the most developed part. +- **M1 (content analysis)** and **M5 (question formatting)** have built scaffolding; **M2–M4** (assessment planning, generation, quality assurance) are methodology-driven through guided dialogue rather than module-specific tools, by design. +- The methodology guides and generated question content are under continual refinement. + ## Part of a teaching-and-assessment ecosystem These tools share one philosophy — *teacher-led: scaffolding, not automation* — and @@ -157,6 +167,11 @@ Instructional materials QuestionForge builds on established research in assessment design — constructive alignment (Biggs & Tang), formative assessment (Black & Wiliam), and Swedish assessment research (Lundahl, Hirsh). +## Support + +- Questions and bugs: [GitHub Issues](https://github.com/tikankika/question-forge/issues) +- Discussion: [GitHub Discussions](https://github.com/tikankika/question-forge/discussions) + --- *QuestionForge — forging quality questions.* diff --git a/SECURITY.md b/SECURITY.md index 85232c0..df002bb 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -2,21 +2,16 @@ ## Supported versions -QuestionForge is in early release. Security fixes are provided for the latest -published version only. - | Version | Supported | |---------|-----------| -| 0.1.x | ✅ | -| < 0.1 | ❌ | +| 0.1.x | ✅ | +| < 0.1 | ❌ | ## Reporting a vulnerability Please **do not** open a public issue for security problems. -Report vulnerabilities privately through GitHub's -[private vulnerability reporting](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability) -on this repository (the **Security** tab → **Report a vulnerability**). +Report vulnerabilities privately through GitHub's [private vulnerability reporting](https://github.com/tikankika/question-forge/security/advisories/new) (the **Security** tab → **Report a vulnerability**). Please include: @@ -24,9 +19,30 @@ Please include: - steps to reproduce (a minimal example if possible), - any suggested mitigation. -You can expect an acknowledgement within a reasonable time, and we will keep you -informed as the issue is assessed and resolved. Responsible disclosure is -appreciated — please give us time to release a fix before any public disclosure. +You can expect an acknowledgement within a week, and responsible disclosure is appreciated — please allow time for a fix before any public disclosure. + +## Data protection + +QuestionForge processes real teaching materials (lectures, slides, course +documents), and this is a public repository. One rule is non-negotiable: +**no real personal data may ever enter the repo** — in code, tests, examples, +documentation or commit messages, anywhere in the working tree or its git +history. + +- Never commit real names (students, colleagues, teachers), school or + institution names, identifying places, personal-identity numbers, file paths + containing a username (`/Users/...`), or secrets (API keys, tokens, `.env` + contents). +- Use fabricated or anonymised data in every example and test — `School A`, + `Colleague_A`, `/path/to/project`. +- Watch quasi-identifiers: a class plus a date plus a subject can identify a + student even with no name attached. +- Found real personal data already committed? Deleting the file is not enough — + it remains in the git history. Report it privately (see above) so the history + can be scrubbed and any exposed secret rotated. + +See [CONTRIBUTING](CONTRIBUTING.md) for the contributor-facing version of these +rules. ## Scope notes diff --git a/docs/decisions/017-track-repo-policy-rules.md b/docs/decisions/017-track-repo-policy-rules.md index 509c773..147e5d1 100644 --- a/docs/decisions/017-track-repo-policy-rules.md +++ b/docs/decisions/017-track-repo-policy-rules.md @@ -1,7 +1,8 @@ --- type: decision -status: active +status: superseded created: 2026-06-24 +superseded: 2026-07-07 origin: code project: QuestionForge relates_to: [ADR-015, ADR-016] @@ -9,6 +10,18 @@ relates_to: [ADR-015, ADR-016] # ADR-017: Track the three repo-policy rules in `.claude/rules/` +> **Superseded (2026-07-07).** Reversed on review: `.claude/` is development +> tooling — local assistant configuration, not part of the project — and the +> premise that the rule files are "read by repo-tooling" did not hold (the +> tooling reads them from the local disk, not from a clone). The human-facing +> policy the rules were meant to carry now travels with the repo where readers +> expect it: the data-protection rule as a **Data protection** section in +> [SECURITY.md](../../SECURITY.md) (with the contributor-facing version in +> [CONTRIBUTING.md](../../CONTRIBUTING.md)), the repo boundary implicitly in +> CONTRIBUTING. The three rule files are untracked and the full `.claude/` +> directory is git-ignored again. The text below is kept as the historical +> record of the original decision. + ## Context `.claude/` holds Claude Code / ACDM configuration. Historically the whole