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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -175,19 +175,18 @@ templates
/prepared
/Lab9_out*
*.fish
!scripts/update-notes.fish
.scriptmark_extracted/
.remember/
tests/geec/
tests_submission/

# P-669 test fixtures — the broad rules above (*.csv, submissions, templates, config.toml)
# must not swallow committed test data.
!crates/scriptmark/tests/fixtures/**
!src/crates/scriptmark/tests/fixtures/**
# ...but not what running the suite over them produces.
crates/scriptmark/tests/fixtures/**/__pycache__/
crates/scriptmark/tests/fixtures/**/.scriptmark_extracted/
crates/scriptmark/tests/fixtures/**/.DS_Store
src/crates/scriptmark/tests/fixtures/**/__pycache__/
src/crates/scriptmark/tests/fixtures/**/.scriptmark_extracted/
src/crates/scriptmark/tests/fixtures/**/.DS_Store

# P-674 example bundles ship their students; `submissions` above would drop them.
!examples/bundles/*/submissions/
Expand Down
78 changes: 38 additions & 40 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,39 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
`CLAUDE.md` is the canonical project instruction file; `AGENTS.md` and
`.github/copilot-instructions.md` are symlinks to it.

- Documentation is in the `notes/` git submodule:
- Public documentation belongs in `docs/`. Private documentation is in the `notes/` git submodule:
`https://github.com/Acture/obsidian-vault.git`, branch `project/scriptmark`.
Start at `notes/README.md`; the teacher contract is
`notes/docs/test-bundles.md`, and plans are in
`notes/docs/plans/`. Do not recreate a maintained root `docs/` tree.
`notes/docs/plans/`. Do not copy private notes into the public documentation tree.
The project branch root contains only this project's notes; the vault's `master`
places them under `scriptmark/`. Keep shared automation and vault configuration on master.
- Default to the latest remote `project/scriptmark` notes. At the start of every
session, after pulling code, and before reading or editing notes, run
`fish scripts/update-notes.fish` from this repository. This initializes missing
notes, fetches the configured project branch, fast-forwards it and leaves that branch
checked out. It handles single-branch clones. Never assume the gitlink is the latest.
session, after pulling code, and before reading or editing notes, follow the native
Git update sequence in README's "Documentation and checkout" section. It explicitly
fetches the project branch, checks for local work, switches to `project/scriptmark`
and fast-forwards it. It handles single-branch clones. Never assume the gitlink is latest.
- Clone with `git clone https://github.com/Acture/scriptmark.git`, enter the clone,
then run the same helper. It stops on local notes edits, unpushed commits or divergence;
preserve and reconcile them instead of resetting or force-pushing. If fetching fails,
report that the latest notes were not verified; do not silently describe stale notes as current.
- Edit only `notes/`. A newer notes checkout can make the parent's gitlink
then initialize with `git submodule update --init --remote --no-single-branch -- notes`
and `git -C notes switch project/scriptmark`. For existing notes, use the guarded
update sequence instead. Stop on local edits, unpushed commits or divergence; preserve
and reconcile them instead of resetting or force-pushing. If fetching fails, report
that the latest notes were not verified; do not describe stale notes as current.
Shared synchronization and submission tooling belongs to the notes repository;
do not add a project-local notes updater.
- Edit private documentation only in `notes/`. A newer notes checkout can make the parent's gitlink
dirty; review `git diff --submodule=log -- notes` and include the updated reference in
the next code commit. Do not reset notes just to remove that expected difference.
- The gitlink remains a concrete saved checkpoint because Git requires one. Use
`git submodule update --init --checkout -- notes` only for an explicitly requested
historical reproduction, with clean notes. Pinned checkout is not the daily workflow.
- Stage with `git -C notes add README.md`, commit in `notes`, and push with
`python3 (git -C notes rev-parse --path-format=absolute --git-common-dir)/hooks/notes-boundary/submit_project.py --repo notes`. Only after that push
succeeds, stage `notes` in this repository and commit/push its new gitlink. A failed
push must never leave a published parent pointer to unavailable notes.
- Stage specific documents in `notes/` and commit there. Publish with the master-owned
`hooks/notes-boundary/submit_project.py --repo notes` under the notes repository's
common Git directory; it runs the required remote check before pushing that SHA.
The remote requires `notes-boundary/root/scriptmark` from GitHub Actions.
Install/update this helper from the notes repository's trusted `origin/master` as
shown in README. Direct pushes of unchecked commits are rejected. Only after a
successful submission, stage `notes` here and commit/push its new gitlink.
- The README contains the complete command sequence. Keep original histories and
resolve divergence without overwriting either side.
- Linear is the execution home. Keep runnable examples, code, measurements and raw
Expand Down Expand Up @@ -62,6 +71,11 @@ default Python is newer than the PyO3 version supports; see the P-676 validation

Single `scriptmark` crate (lib + bin) with `scriptmark-py` as separate cdylib for PyO3.

All product source is under `src/`: Rust packages live in `src/crates/` and the
Python package entry point in `src/python/scriptmark/`. Workspace/build configuration
stays at the repository root, where Cargo and Maturin commands are run. The module
paths below are relative to `src/crates/scriptmark/src/`.

Data flows: TOML specs + student files → Runner → grading record (evidence + score
revisions) → Display/DB/HTML/Canvas. `rescore` adds a revision from saved evidence.

Expand Down Expand Up @@ -96,21 +110,21 @@ Zero and withheld grades stay distinct. See the notes' teacher contract for poli

## Critical Files

- `crates/scriptmark/src/runner/python.rs` — PythonExecutor + embedded helper scripts (HELPER_SCRIPT, CHAIN_HELPER_SCRIPT). Contains import allowlist, env sanitization, `sandboxed_cmd()`, `spawn_with_timeout()`.
- `crates/scriptmark/src/runner/sandbox.rs` — SandboxConfig + setrlimit application. Platform-conditional: RLIMIT_AS skipped on macOS, RLIMIT_* constants differ between Linux (c_uint) and macOS (c_int).
- `crates/scriptmark/src/runner/orchestrator.rs` — Runs vars→setup→expand→oracle→execute pipeline per student, tokio parallel.
- `crates/scriptmark/src/models/spec.rs` — All TOML spec structs (TestSpec, TestCase, SetupStep, Parametrize, Oracle, LintConfig, CheckMethod).
- `crates/scriptmark/src/discovery.rs` — File discovery + ZIP archive extraction with size/count limits.
- `crates/scriptmark/src/record.rs` — The grading record every consumer reads (`--output`): evidence with submission/spec fingerprints, append-only score revisions, `check()` refusing evidence whose tests, submissions or matching changed.
- `crates/scriptmark/src/grading.rs` — GradingPolicy dispatch (templates + Rhai formulas).
- `crates/scriptmark/src/main.rs` — All CLI command handlers.
- `crates/scriptmark-py/src/lib.rs` — PyO3 bindings: grade(), run(), discover(), load_spec(), StudentResult, TestSpec classes.
- `src/crates/scriptmark/src/runner/python.rs` — PythonExecutor + embedded helper scripts (HELPER_SCRIPT, CHAIN_HELPER_SCRIPT). Contains import allowlist, env sanitization, `sandboxed_cmd()`, `spawn_with_timeout()`.
- `src/crates/scriptmark/src/runner/sandbox.rs` — SandboxConfig + setrlimit application. Platform-conditional: RLIMIT_AS skipped on macOS, RLIMIT_* constants differ between Linux (c_uint) and macOS (c_int).
- `src/crates/scriptmark/src/runner/orchestrator.rs` — Runs vars→setup→expand→oracle→execute pipeline per student, tokio parallel.
- `src/crates/scriptmark/src/models/spec.rs` — All TOML spec structs (TestSpec, TestCase, SetupStep, Parametrize, Oracle, LintConfig, CheckMethod).
- `src/crates/scriptmark/src/discovery.rs` — File discovery + ZIP archive extraction with size/count limits.
- `src/crates/scriptmark/src/record.rs` — The grading record every consumer reads (`--output`): evidence with submission/spec fingerprints, append-only score revisions, `check()` refusing evidence whose tests, submissions or matching changed.
- `src/crates/scriptmark/src/grading.rs` — GradingPolicy dispatch (templates + Rhai formulas).
- `src/crates/scriptmark/src/main.rs` — All CLI command handlers.
- `src/crates/scriptmark-py/src/lib.rs` — PyO3 bindings: grade(), run(), discover(), load_spec(), StudentResult, TestSpec classes.

## Conventions

- Workspace dependencies in root `Cargo.toml`, crates reference with `{ workspace = true }`
- `thiserror` for library error types, `anyhow` for CLI/binary error handling
- All checkers implement `Checker` trait in `crates/scriptmark/src/checker/mod.rs`
- All checkers implement `Checker` trait in `src/crates/scriptmark/src/checker/mod.rs`
- Integration tests spawn real Python processes — need `python3` available
- `scriptmark-py` has `publish = false` (cdylib, distributed via PyPI/maturin, not crates.io)
- Platform-specific code uses `#[cfg(target_os = "macos")]` / `#[cfg(target_os = "linux")]` for rlimit types
Expand Down Expand Up @@ -150,19 +164,3 @@ seed = 42
[cases.parametrize.oracle]
rhai = "if a >= b { a } else { b }"
```


## Project notes submission

`docs/` is reserved for public documentation. Private research notes live in `notes/`, which tracks `project/scriptmark` in `Acture/obsidian-vault`; start at `notes/README.md`. This checkout's root contains only this project's notes. Master places these notes under `scriptmark/`. Keep automation and vault configuration on master. Preserve existing local edits when updating a checkout.

Install or refresh the trusted submission tools in Git metadata, including in new clones:

```fish
git -C notes fetch origin refs/heads/master:refs/remotes/origin/master
set notes_common_gitdir (git -C notes rev-parse --path-format=absolute --git-common-dir)
git -C notes show origin/master:.github/scripts/install_push_hook.py > "$notes_common_gitdir/install_push_hook.py"
python3 "$notes_common_gitdir/install_push_hook.py" --repo notes --source-ref origin/master
```

After committing specific note files, submit through `python3 "$notes_common_gitdir/hooks/notes-boundary/submit_project.py" --repo notes`. The remote requires `notes-boundary/root/scriptmark` from GitHub Actions. Only after successful submission should this repository commit and push the `notes` gitlink. See the central repository's `项目接入.md` for initialization, updates and conflict handling.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[workspace]
resolver = "2"
members = [
"crates/scriptmark",
"crates/scriptmark-py",
"src/crates/scriptmark",
"src/crates/scriptmark-py",
]

[workspace.package]
Expand Down
Loading
Loading