margi 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- margi-0.1.0/.gitignore +6 -0
- margi-0.1.0/AGENTS.md +20 -0
- margi-0.1.0/LICENSE +21 -0
- margi-0.1.0/PKG-INFO +108 -0
- margi-0.1.0/README.md +79 -0
- margi-0.1.0/pyproject.toml +58 -0
- margi-0.1.0/skills/margi/SKILL.md +64 -0
- margi-0.1.0/skills/margi/commands/grade.md +58 -0
- margi-0.1.0/skills/margi/commands/read.md +38 -0
- margi-0.1.0/skills/margi/commands/todos.md +66 -0
- margi-0.1.0/skills/margi/rubrics/default/alignment.md +11 -0
- margi-0.1.0/skills/margi/rubrics/default/argument.md +10 -0
- margi-0.1.0/skills/margi/rubrics/default/evidence.md +10 -0
- margi-0.1.0/skills/margi/rubrics/default/method.md +11 -0
- margi-0.1.0/skills/margi/rubrics/default/rubric.yml +38 -0
- margi-0.1.0/skills/margi/rubrics/default/scholarship.md +10 -0
- margi-0.1.0/skills/margi/rubrics/default/structure.md +10 -0
- margi-0.1.0/skills/margi/rubrics/default/style.md +10 -0
- margi-0.1.0/skills/margi/schema/feedback.schema.json +169 -0
- margi-0.1.0/skills/margi-challenge/SKILL.md +58 -0
- margi-0.1.0/skills/margi-challenge/lenses.md +35 -0
- margi-0.1.0/skills/margi-onboard/SKILL.md +76 -0
- margi-0.1.0/skills/margi-onboard/interview.md +36 -0
- margi-0.1.0/skills/margi-onboard/templates/CHANGELOG.md +3 -0
- margi-0.1.0/skills/margi-onboard/templates/constraints.md +15 -0
- margi-0.1.0/skills/margi-onboard/templates/dataset.md +21 -0
- margi-0.1.0/skills/margi-onboard/templates/field.md +15 -0
- margi-0.1.0/skills/margi-onboard/templates/method.md +18 -0
- margi-0.1.0/skills/margi-onboard/templates/open-questions.md +3 -0
- margi-0.1.0/skills/margi-onboard/templates/research-question.md +21 -0
- margi-0.1.0/skills/margi-onboard/templates/structure.md +24 -0
- margi-0.1.0/src/margi/__init__.py +3 -0
- margi-0.1.0/src/margi/__main__.py +3 -0
- margi-0.1.0/src/margi/adapters/__init__.py +17 -0
- margi-0.1.0/src/margi/adapters/base.py +85 -0
- margi-0.1.0/src/margi/adapters/typst.py +198 -0
- margi-0.1.0/src/margi/cli.py +264 -0
- margi-0.1.0/src/margi/config.py +69 -0
- margi-0.1.0/src/margi/docs_check.py +82 -0
- margi-0.1.0/src/margi/finalize.py +286 -0
- margi-0.1.0/src/margi/gitutil.py +104 -0
- margi-0.1.0/src/margi/guard.py +106 -0
- margi-0.1.0/src/margi/init.py +157 -0
- margi-0.1.0/src/margi/outline.py +155 -0
- margi-0.1.0/src/margi/pdf.py +45 -0
- margi-0.1.0/src/margi/resources.py +31 -0
- margi-0.1.0/src/margi/schema.py +25 -0
- margi-0.1.0/src/margi/status.py +76 -0
- margi-0.1.0/src/margi/todos_sync.py +110 -0
- margi-0.1.0/src/margi/wrapper.py +125 -0
- margi-0.1.0/templates/claude-settings.json +25 -0
- margi-0.1.0/templates/commit-msg +14 -0
- margi-0.1.0/templates/margi-README.md +13 -0
- margi-0.1.0/templates/margi-guard.yml +25 -0
- margi-0.1.0/templates/thesis.config.yml +32 -0
- margi-0.1.0/tests/conftest.py +58 -0
- margi-0.1.0/tests/fixtures/typst-thesis/README.md +3 -0
- margi-0.1.0/tests/fixtures/typst-thesis/chapters/prior-work.typ +19 -0
- margi-0.1.0/tests/fixtures/typst-thesis/main.typ +14 -0
- margi-0.1.0/tests/test_docs_check.py +16 -0
- margi-0.1.0/tests/test_finalize.py +103 -0
- margi-0.1.0/tests/test_guard.py +92 -0
- margi-0.1.0/tests/test_outline.py +39 -0
- margi-0.1.0/tests/test_todos_sync.py +54 -0
- margi-0.1.0/tests/test_wrapper.py +70 -0
margi-0.1.0/.gitignore
ADDED
margi-0.1.0/AGENTS.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
## margi rules (AI feedback layer for this thesis)
|
|
2
|
+
|
|
3
|
+
This repository contains a thesis written **entirely by a human**. AI agents working here
|
|
4
|
+
through margi skills give feedback in the margins; they never write the text.
|
|
5
|
+
|
|
6
|
+
1. **Never edit anything outside `margi/`.** No thesis source (`*.typ`, `*.bib`, figures, …),
|
|
7
|
+
no config, no README. Read anything; write only to `margi/docs/`, `margi/todos/` and
|
|
8
|
+
`margi/.staging/`.
|
|
9
|
+
2. **Never write thesis prose.** Comments name the problem and why it matters ("the argument
|
|
10
|
+
in §2.1 assumes X without evidence"). They never contain replacement sentences,
|
|
11
|
+
rewritten paragraphs, or "you could write: …".
|
|
12
|
+
3. **Never write provenance.** Do not add timestamps, SHAs, hashes or model ids to drafts.
|
|
13
|
+
`margi finalize` injects them.
|
|
14
|
+
4. **`margi/feedback/` is append-only.** Never modify or delete existing records.
|
|
15
|
+
5. **Never commit, push, reset or checkout.** `margi finalize` commits margi/ as the margi
|
|
16
|
+
bot. Human work and margi work are never mixed in one commit.
|
|
17
|
+
6. **Don't invent facts about the project.** Everything in `margi/docs/` cites a source file
|
|
18
|
+
and line range or the date the user said it in an interview. Unknown → `open-questions.md`.
|
|
19
|
+
7. **Start every run with `margi finalize --check`** and stop if it fails. End every run with
|
|
20
|
+
`margi finalize`.
|
margi-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Nico Benz
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
margi-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: margi
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: AI in the margins, never in the text. A feedback layer for human-written theses.
|
|
5
|
+
Project-URL: Homepage, https://github.com/nicobenz/margi
|
|
6
|
+
Project-URL: Repository, https://github.com/nicobenz/margi
|
|
7
|
+
Project-URL: Issues, https://github.com/nicobenz/margi/issues
|
|
8
|
+
Author: Nico Benz
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: academic-writing,agent-skills,ai,digital-humanities,feedback,thesis,typst
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Education
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Topic :: Text Processing :: Markup
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Requires-Dist: click>=8.1
|
|
25
|
+
Requires-Dist: jsonschema>=4.20
|
|
26
|
+
Requires-Dist: pypdf>=4.0
|
|
27
|
+
Requires-Dist: pyyaml>=6.0
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
# margi
|
|
31
|
+
|
|
32
|
+
**AI in the margins, never in the text.**
|
|
33
|
+
|
|
34
|
+
margi is a feedback layer for a thesis that you write 100% by hand. Short terminal commands
|
|
35
|
+
launch an AI agent with a specific skill. The agent reads your thesis and writes documentation,
|
|
36
|
+
grades, literature ratings and todos, but **only inside `margi/`**, and always in commits that
|
|
37
|
+
are kept separate from yours. Git hooks and CI enforce this. You don't have to take it on trust.
|
|
38
|
+
|
|
39
|
+
## Install
|
|
40
|
+
|
|
41
|
+
```sh
|
|
42
|
+
uv tool install margi # or: pipx install margi
|
|
43
|
+
cd my-thesis && margi init
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
`margi init` vendors the skills to `.agents/skills/` and symlinks them from `.claude/skills/`,
|
|
47
|
+
so Claude Code, Codex, Cursor and other agents that read `SKILL.md` can use them. It also
|
|
48
|
+
writes `thesis.config.yml`, installs the commit guard and the CI workflow, creates `margi/`,
|
|
49
|
+
and then starts onboarding.
|
|
50
|
+
|
|
51
|
+
## Commands
|
|
52
|
+
|
|
53
|
+
| Command | |
|
|
54
|
+
|---|---|
|
|
55
|
+
| `margi onboard [--from expose.md]` | Reads your README or exposé, then **interviews you** to document the research question, dataset, method, field, structure and constraints in `margi/docs/`. Every other command grades against these docs. |
|
|
56
|
+
| `margi challenge <aspect>` | A devil's-advocate dialogue about any aspect of the project. The refinements you confirm are written back into `margi/docs/`. |
|
|
57
|
+
| `margi grade <section>` | Rubric-based scores per category with comments anchored to file, lines and a verbatim quote. Refuses to run while the docs are incomplete (override with `--force`). |
|
|
58
|
+
| `margi outline` | Character counts and their distribution across sections and subsections, compared against targets from `structure.md`. No AI involved. |
|
|
59
|
+
| `margi read [pdf…]` | Rates literature PDFs for relevance to your research question and outline. |
|
|
60
|
+
| `margi todos` | Proposes todos as Markdown files and suggests closing issues that look done. You accept, reject or request changes, and only accepted items go to GitHub. |
|
|
61
|
+
| `margi status` | Shows docs completeness, latest grades, outline, todos and recent runs. |
|
|
62
|
+
|
|
63
|
+
Inside an agent session you can use the same commands as `/margi grade 2.1`,
|
|
64
|
+
`/margi-onboard` and `/margi-challenge research question`.
|
|
65
|
+
|
|
66
|
+
## How the separation works
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
your commits → everything except margi/ (never prefixed "margi:")
|
|
70
|
+
margi commits → only margi/ ("margi: grade 2.1", author margi-bot)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
- **`margi finalize`** runs at the end of every AI command.
|
|
74
|
+
- It aborts if anything outside `margi/` changed.
|
|
75
|
+
- It validates the agent's draft against `skills/margi/schema/feedback.schema.json`.
|
|
76
|
+
- It checks every quoted anchor against `HEAD`.
|
|
77
|
+
- It **injects the provenance itself**: HEAD SHA, file hashes, rubric version and hash,
|
|
78
|
+
docs completeness, model, timestamp.
|
|
79
|
+
- It commits only `margi/`, as the bot.
|
|
80
|
+
- **`.githooks/commit-msg`** (`margi guard --staged`) rejects mixed commits, `margi:`
|
|
81
|
+
commits outside `margi/`, unprefixed commits inside it, and any change to an existing
|
|
82
|
+
record in `margi/feedback/` (which is append-only).
|
|
83
|
+
- **CI** (`margi guard --range`) repeats the hook's checks, so `--no-verify` doesn't bypass them.
|
|
84
|
+
- **Agent permissions**: the wrapper only allows reads, `Edit(margi/**)` and a handful of
|
|
85
|
+
`margi`/`git status` commands, and `.claude/settings.json` denies edits to thesis sources.
|
|
86
|
+
|
|
87
|
+
`git log -- margi/` is the complete AI audit trail for your advisors.
|
|
88
|
+
|
|
89
|
+
## Layout
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
skills/margi/ SKILL.md, commands/{grade,read,todos}.md, rubrics/default/, schema/
|
|
93
|
+
skills/margi-onboard/ SKILL.md, interview.md, templates/ (the margi/docs files)
|
|
94
|
+
skills/margi-challenge/ SKILL.md, lenses.md
|
|
95
|
+
AGENTS.md hard rules, merged into the thesis repo's AGENTS.md
|
|
96
|
+
templates/ config, commit-msg hook, CI workflow, Claude settings
|
|
97
|
+
src/margi/ CLI (finalize, guard, outline, adapters/typst, wrapper, init, …)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The only supported format is Typst; the adapters in `src/margi/adapters/` are the extension
|
|
101
|
+
point for LaTeX, Quarto and Markdown. To use your own rubric, put it in
|
|
102
|
+
`margi/rubrics/<id>/` in the thesis repo.
|
|
103
|
+
|
|
104
|
+
## Development
|
|
105
|
+
|
|
106
|
+
```sh
|
|
107
|
+
uv sync && uv run pytest
|
|
108
|
+
```
|
margi-0.1.0/README.md
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# margi
|
|
2
|
+
|
|
3
|
+
**AI in the margins, never in the text.**
|
|
4
|
+
|
|
5
|
+
margi is a feedback layer for a thesis that you write 100% by hand. Short terminal commands
|
|
6
|
+
launch an AI agent with a specific skill. The agent reads your thesis and writes documentation,
|
|
7
|
+
grades, literature ratings and todos, but **only inside `margi/`**, and always in commits that
|
|
8
|
+
are kept separate from yours. Git hooks and CI enforce this. You don't have to take it on trust.
|
|
9
|
+
|
|
10
|
+
## Install
|
|
11
|
+
|
|
12
|
+
```sh
|
|
13
|
+
uv tool install margi # or: pipx install margi
|
|
14
|
+
cd my-thesis && margi init
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`margi init` vendors the skills to `.agents/skills/` and symlinks them from `.claude/skills/`,
|
|
18
|
+
so Claude Code, Codex, Cursor and other agents that read `SKILL.md` can use them. It also
|
|
19
|
+
writes `thesis.config.yml`, installs the commit guard and the CI workflow, creates `margi/`,
|
|
20
|
+
and then starts onboarding.
|
|
21
|
+
|
|
22
|
+
## Commands
|
|
23
|
+
|
|
24
|
+
| Command | |
|
|
25
|
+
|---|---|
|
|
26
|
+
| `margi onboard [--from expose.md]` | Reads your README or exposé, then **interviews you** to document the research question, dataset, method, field, structure and constraints in `margi/docs/`. Every other command grades against these docs. |
|
|
27
|
+
| `margi challenge <aspect>` | A devil's-advocate dialogue about any aspect of the project. The refinements you confirm are written back into `margi/docs/`. |
|
|
28
|
+
| `margi grade <section>` | Rubric-based scores per category with comments anchored to file, lines and a verbatim quote. Refuses to run while the docs are incomplete (override with `--force`). |
|
|
29
|
+
| `margi outline` | Character counts and their distribution across sections and subsections, compared against targets from `structure.md`. No AI involved. |
|
|
30
|
+
| `margi read [pdf…]` | Rates literature PDFs for relevance to your research question and outline. |
|
|
31
|
+
| `margi todos` | Proposes todos as Markdown files and suggests closing issues that look done. You accept, reject or request changes, and only accepted items go to GitHub. |
|
|
32
|
+
| `margi status` | Shows docs completeness, latest grades, outline, todos and recent runs. |
|
|
33
|
+
|
|
34
|
+
Inside an agent session you can use the same commands as `/margi grade 2.1`,
|
|
35
|
+
`/margi-onboard` and `/margi-challenge research question`.
|
|
36
|
+
|
|
37
|
+
## How the separation works
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
your commits → everything except margi/ (never prefixed "margi:")
|
|
41
|
+
margi commits → only margi/ ("margi: grade 2.1", author margi-bot)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
- **`margi finalize`** runs at the end of every AI command.
|
|
45
|
+
- It aborts if anything outside `margi/` changed.
|
|
46
|
+
- It validates the agent's draft against `skills/margi/schema/feedback.schema.json`.
|
|
47
|
+
- It checks every quoted anchor against `HEAD`.
|
|
48
|
+
- It **injects the provenance itself**: HEAD SHA, file hashes, rubric version and hash,
|
|
49
|
+
docs completeness, model, timestamp.
|
|
50
|
+
- It commits only `margi/`, as the bot.
|
|
51
|
+
- **`.githooks/commit-msg`** (`margi guard --staged`) rejects mixed commits, `margi:`
|
|
52
|
+
commits outside `margi/`, unprefixed commits inside it, and any change to an existing
|
|
53
|
+
record in `margi/feedback/` (which is append-only).
|
|
54
|
+
- **CI** (`margi guard --range`) repeats the hook's checks, so `--no-verify` doesn't bypass them.
|
|
55
|
+
- **Agent permissions**: the wrapper only allows reads, `Edit(margi/**)` and a handful of
|
|
56
|
+
`margi`/`git status` commands, and `.claude/settings.json` denies edits to thesis sources.
|
|
57
|
+
|
|
58
|
+
`git log -- margi/` is the complete AI audit trail for your advisors.
|
|
59
|
+
|
|
60
|
+
## Layout
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
skills/margi/ SKILL.md, commands/{grade,read,todos}.md, rubrics/default/, schema/
|
|
64
|
+
skills/margi-onboard/ SKILL.md, interview.md, templates/ (the margi/docs files)
|
|
65
|
+
skills/margi-challenge/ SKILL.md, lenses.md
|
|
66
|
+
AGENTS.md hard rules, merged into the thesis repo's AGENTS.md
|
|
67
|
+
templates/ config, commit-msg hook, CI workflow, Claude settings
|
|
68
|
+
src/margi/ CLI (finalize, guard, outline, adapters/typst, wrapper, init, …)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
The only supported format is Typst; the adapters in `src/margi/adapters/` are the extension
|
|
72
|
+
point for LaTeX, Quarto and Markdown. To use your own rubric, put it in
|
|
73
|
+
`margi/rubrics/<id>/` in the thesis repo.
|
|
74
|
+
|
|
75
|
+
## Development
|
|
76
|
+
|
|
77
|
+
```sh
|
|
78
|
+
uv sync && uv run pytest
|
|
79
|
+
```
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "margi"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "AI in the margins, never in the text. A feedback layer for human-written theses."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.10"
|
|
7
|
+
authors = [{ name = "Nico Benz" }]
|
|
8
|
+
license = "MIT"
|
|
9
|
+
license-files = ["LICENSE"]
|
|
10
|
+
keywords = ["thesis", "academic-writing", "digital-humanities", "ai", "feedback", "typst", "agent-skills"]
|
|
11
|
+
classifiers = [
|
|
12
|
+
"Development Status :: 3 - Alpha",
|
|
13
|
+
"Environment :: Console",
|
|
14
|
+
"Intended Audience :: Education",
|
|
15
|
+
"Intended Audience :: Science/Research",
|
|
16
|
+
"Operating System :: OS Independent",
|
|
17
|
+
"Programming Language :: Python :: 3",
|
|
18
|
+
"Programming Language :: Python :: 3.10",
|
|
19
|
+
"Programming Language :: Python :: 3.11",
|
|
20
|
+
"Programming Language :: Python :: 3.12",
|
|
21
|
+
"Programming Language :: Python :: 3.13",
|
|
22
|
+
"Topic :: Text Processing :: Markup",
|
|
23
|
+
]
|
|
24
|
+
dependencies = [
|
|
25
|
+
"click>=8.1",
|
|
26
|
+
"pyyaml>=6.0",
|
|
27
|
+
"jsonschema>=4.20",
|
|
28
|
+
"pypdf>=4.0",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
[project.urls]
|
|
32
|
+
Homepage = "https://github.com/nicobenz/margi"
|
|
33
|
+
Repository = "https://github.com/nicobenz/margi"
|
|
34
|
+
Issues = "https://github.com/nicobenz/margi/issues"
|
|
35
|
+
|
|
36
|
+
[project.scripts]
|
|
37
|
+
margi = "margi.cli:main"
|
|
38
|
+
|
|
39
|
+
[dependency-groups]
|
|
40
|
+
dev = ["pytest>=8"]
|
|
41
|
+
|
|
42
|
+
[build-system]
|
|
43
|
+
requires = ["hatchling"]
|
|
44
|
+
build-backend = "hatchling.build"
|
|
45
|
+
|
|
46
|
+
[tool.hatch.build.targets.wheel]
|
|
47
|
+
packages = ["src/margi"]
|
|
48
|
+
|
|
49
|
+
[tool.hatch.build.targets.wheel.force-include]
|
|
50
|
+
"skills" = "margi/_bundled/skills"
|
|
51
|
+
"templates" = "margi/_bundled/templates"
|
|
52
|
+
"AGENTS.md" = "margi/_bundled/AGENTS.md"
|
|
53
|
+
|
|
54
|
+
[tool.hatch.build.targets.sdist]
|
|
55
|
+
include = ["src", "skills", "templates", "tests", "AGENTS.md", "README.md", "LICENSE"]
|
|
56
|
+
|
|
57
|
+
[tool.pytest.ini_options]
|
|
58
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: margi
|
|
3
|
+
description: AI feedback in the margins of a human-written thesis. Use for /margi grade, read, todos, outline, status, onboard and challenge. Writes only to margi/ and never writes thesis text.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# margi
|
|
7
|
+
|
|
8
|
+
You are margi, a critical, careful reader of a thesis that a human writes **entirely by
|
|
9
|
+
hand**. You give feedback in the margins. You never write the text.
|
|
10
|
+
|
|
11
|
+
## Hard rules (always)
|
|
12
|
+
|
|
13
|
+
- Read anything. **Write only inside `margi/`**: `margi/.staging/`, `margi/docs/`, `margi/todos/`.
|
|
14
|
+
- **Never write thesis prose.** Say what is wrong and why, never "rewrite as …".
|
|
15
|
+
- **Never write provenance** (timestamps, SHAs, hashes, model ids). Scripts add it.
|
|
16
|
+
- Never modify existing files in `margi/feedback/`. Never run `git commit`/`push`/`reset`/`checkout`.
|
|
17
|
+
- See `../../../AGENTS.md` (repo root) if present. Its margi section is authoritative.
|
|
18
|
+
|
|
19
|
+
## Every run
|
|
20
|
+
|
|
21
|
+
1. Run `margi finalize --check`. If it fails, show the message and **stop**. The user must
|
|
22
|
+
commit their own work first.
|
|
23
|
+
2. Read `thesis.config.yml` and the project docs in `margi/docs/`. These documents define the
|
|
24
|
+
goals that all feedback is measured against.
|
|
25
|
+
3. Do the command (below).
|
|
26
|
+
4. Run `margi finalize`. This validates your draft, injects provenance and commits `margi/`.
|
|
27
|
+
If you know your model id, pass it with `--model <id>`. If finalize reports a schema
|
|
28
|
+
error, fix the draft and run it again.
|
|
29
|
+
5. Report the result briefly to the user.
|
|
30
|
+
|
|
31
|
+
## Commands
|
|
32
|
+
|
|
33
|
+
An invocation ending in `--headless` was launched by the `margi` CLI without a human in the
|
|
34
|
+
loop. In that case don't ask questions; make reasonable choices and record them in `summary`.
|
|
35
|
+
|
|
36
|
+
| Invocation | What to do |
|
|
37
|
+
|---|---|
|
|
38
|
+
| `/margi grade <section>` | Follow `commands/grade.md` |
|
|
39
|
+
| `/margi read [pdf…]` | Follow `commands/read.md` |
|
|
40
|
+
| `/margi todos` | Follow `commands/todos.md` |
|
|
41
|
+
| `/margi onboard [--from <file>]` | Follow `../margi-onboard/SKILL.md` |
|
|
42
|
+
| `/margi challenge <aspect>` | Follow `../margi-challenge/SKILL.md` |
|
|
43
|
+
| `/margi outline` | Run `margi outline` and show the output. No draft is needed. |
|
|
44
|
+
| `/margi status` | Run `margi status` and show the output. |
|
|
45
|
+
|
|
46
|
+
## Drafts
|
|
47
|
+
|
|
48
|
+
Write exactly one JSON draft per command to `margi/.staging/<command>.json`, matching
|
|
49
|
+
`$defs/draft` in `schema/feedback.schema.json`. Fields:
|
|
50
|
+
|
|
51
|
+
- `command`, `scope`: required. `scope` is e.g. the section id `2.1`, `all`, or the aspect.
|
|
52
|
+
- `summary`: 2–5 sentences.
|
|
53
|
+
- `files_read`: every repo-relative file you read. They are hashed for the audit trail.
|
|
54
|
+
- `scores`: `{category: {score, max, rationale, comment_ids}}`.
|
|
55
|
+
- `comments`: `{id: "c1", category, severity: major|minor|note, body, anchor}`.
|
|
56
|
+
- `anchor`: `{file, line_start, line_end, quote}`.
|
|
57
|
+
- `quote` must be copied **verbatim** from that file and those lines (≤ 400 chars). Finalize
|
|
58
|
+
verifies it.
|
|
59
|
+
- `body` ≤ 1200 chars and names the problem. It never contains replacement prose.
|
|
60
|
+
- `payload`: command-specific data (see each command file).
|
|
61
|
+
- No other fields. Never include `provenance`, `run` or `schema`.
|
|
62
|
+
|
|
63
|
+
Get line numbers by reading the file with line numbers. Section ids and line ranges come from
|
|
64
|
+
`margi outline --no-save` (numbering) and the files listed in `thesis.config.yml`.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# /margi grade <section>
|
|
2
|
+
|
|
3
|
+
Grade one section against the rubric **and** against the documented project goals.
|
|
4
|
+
|
|
5
|
+
## Inputs
|
|
6
|
+
|
|
7
|
+
1. `margi/docs/*.md`: research question, dataset, method, field, structure, constraints.
|
|
8
|
+
If `margi finalize --check` warns that the docs are below the threshold:
|
|
9
|
+
- **Headless** (the invocation ends in `--headless`): the `margi` CLI already applied the
|
|
10
|
+
gate and the user chose `--force`. Grade, and say in `summary` which docs are missing.
|
|
11
|
+
- **Interactive**: tell the user and recommend `/margi onboard` first. Grade only if
|
|
12
|
+
they confirm, and say in `summary` that the result is low-confidence.
|
|
13
|
+
2. The rubric: `margi/rubrics/<id>/` if it exists, otherwise `rubrics/<id>/` in this skill.
|
|
14
|
+
`<id>` is `rubric` in `thesis.config.yml`. Read `rubric.yml` and every category file.
|
|
15
|
+
3. The section text. Run `margi outline --no-save` to see section ids, then read the
|
|
16
|
+
section's file(s) **with line numbers**. A section spans from its heading to the next
|
|
17
|
+
heading of the same or higher level, possibly across `#include`d files.
|
|
18
|
+
4. Recent records for this section in `margi/feedback/*_grade_<section>*.json`, if any.
|
|
19
|
+
Note what improved since then.
|
|
20
|
+
|
|
21
|
+
## Procedure
|
|
22
|
+
|
|
23
|
+
1. For each rubric category, decide a score on the rubric's scale using its descriptors.
|
|
24
|
+
Always judge against what the docs say this thesis is trying to do (its research question,
|
|
25
|
+
method and audience), not against a generic ideal.
|
|
26
|
+
2. Write 1–3 sentences of rationale per category, referencing comment ids.
|
|
27
|
+
3. Write anchored comments: 3–12 in total. Prioritise `major` problems such as the argument,
|
|
28
|
+
evidence, alignment with the research question, or method transparency over `minor` ones
|
|
29
|
+
(clarity, terminology, citation form). Use `note` for strengths worth keeping.
|
|
30
|
+
4. Every comment must point to a concrete passage (anchor with a verbatim quote) unless it is
|
|
31
|
+
about something missing. Missing things go without an anchor and say where the gap is.
|
|
32
|
+
5. **Never propose wording.** Say "this claim needs a source" or "the transition hides a
|
|
33
|
+
jump from X to Y". Do not say "replace with: …".
|
|
34
|
+
|
|
35
|
+
## Draft
|
|
36
|
+
|
|
37
|
+
`margi/.staging/grade.json`:
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{
|
|
41
|
+
"command": "grade",
|
|
42
|
+
"scope": "2.1",
|
|
43
|
+
"summary": "...",
|
|
44
|
+
"files_read": ["chapters/02-prior-work.typ", "margi/docs/research-question.md", "..."],
|
|
45
|
+
"scores": {
|
|
46
|
+
"argument": {"score": 3, "max": 5, "rationale": "...", "comment_ids": ["c1", "c4"]}
|
|
47
|
+
},
|
|
48
|
+
"comments": [
|
|
49
|
+
{"id": "c1", "category": "argument", "severity": "major",
|
|
50
|
+
"body": "...", "anchor": {"file": "chapters/02-prior-work.typ", "line_start": 41,
|
|
51
|
+
"line_end": 43, "quote": "verbatim text from those lines"}}
|
|
52
|
+
],
|
|
53
|
+
"payload": {"section_title": "Prior Work", "previous_record": "<file name or null>"}
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Then run `margi finalize` and show the user a compact table of the scores plus the major
|
|
58
|
+
comments with their line numbers.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# /margi read [pdf…]
|
|
2
|
+
|
|
3
|
+
Rate literature PDFs for their relevance to **this** thesis.
|
|
4
|
+
|
|
5
|
+
## Inputs
|
|
6
|
+
|
|
7
|
+
1. `margi/docs/*.md`, especially `research-question.md`, `field.md`, `method.md` and `structure.md`.
|
|
8
|
+
Below the docs threshold, apply the same rule as in `grade.md`.
|
|
9
|
+
2. Extracted text: run `margi extract-pdfs [pdf…]`. It prints `pdf<TAB>text-file`. Read the
|
|
10
|
+
text files, which contain `--- page N ---` markers. With no arguments, all PDFs in the
|
|
11
|
+
configured literature directory are processed.
|
|
12
|
+
3. The bibliography (`literature.bib` in the config), if any, to match PDFs to cite keys.
|
|
13
|
+
4. Previous `margi/feedback/*_read_*.json` records. Don't re-rate unchanged PDFs unless asked.
|
|
14
|
+
|
|
15
|
+
## Per PDF
|
|
16
|
+
|
|
17
|
+
- `relevance`: 0–5. 5 = central to the research question or method, 0 = unrelated.
|
|
18
|
+
- `why`: 1–3 sentences tied to a specific part of the docs.
|
|
19
|
+
- `sections`: the outline section(s) where it matters (ids or titles from `structure.md`).
|
|
20
|
+
- `role`: one of `theory | method | data | related-work | counterposition | background`.
|
|
21
|
+
- `key_passages`: up to 5 entries of `{page, quote (verbatim, ≤ 300 chars), why}`.
|
|
22
|
+
- `cite_key`: the bib key if one matches, else null.
|
|
23
|
+
- `cited_in_thesis`: true or false (grep the thesis sources for the cite key).
|
|
24
|
+
- `caveats`: limits, date, or a disputed status.
|
|
25
|
+
|
|
26
|
+
High-relevance PDFs that are not yet cited should appear first in `summary`.
|
|
27
|
+
|
|
28
|
+
## Draft
|
|
29
|
+
|
|
30
|
+
`margi/.staging/read.json`:
|
|
31
|
+
- `command`: `read`
|
|
32
|
+
- `scope`: `all` or a short list of file names
|
|
33
|
+
- `files_read`: the PDFs, the text cache files and the docs you used
|
|
34
|
+
- `payload`: `{"ratings": [{"pdf": "lit/foo.pdf", ...fields above}]}`
|
|
35
|
+
- `comments`: optional. Use them only to point at places in the thesis where a rated source
|
|
36
|
+
should be engaged with, anchored as usual.
|
|
37
|
+
|
|
38
|
+
Then run `margi finalize`.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# /margi todos
|
|
2
|
+
|
|
3
|
+
Curate a todo list **with** the human. Nothing goes to GitHub without explicit acceptance.
|
|
4
|
+
|
|
5
|
+
## 1. Gather
|
|
6
|
+
|
|
7
|
+
- The latest records in `margi/feedback/` for grade, read, outline and challenge, and their open `major` comments.
|
|
8
|
+
- `margi/docs/open-questions.md` and `structure.md` (planned vs. written, via the latest outline record).
|
|
9
|
+
- Existing proposals in `margi/todos/proposed/` and synced todos in `margi/todos/synced/`.
|
|
10
|
+
- Open GitHub issues: `gh issue list --label margi --state open --json number,title,body`.
|
|
11
|
+
If `gh` is unavailable, skip the GitHub parts and say so.
|
|
12
|
+
|
|
13
|
+
## 2. Propose todos
|
|
14
|
+
|
|
15
|
+
Write **one file per todo** to `margi/todos/proposed/<id>-<slug>.md`, where `<id>` is `t` plus
|
|
16
|
+
the date plus a counter, e.g. `t20261007-01`. Do not duplicate open issues or existing
|
|
17
|
+
proposals.
|
|
18
|
+
|
|
19
|
+
```markdown
|
|
20
|
+
---
|
|
21
|
+
id: t20261007-01
|
|
22
|
+
title: Engage with Moretti's critics in 2.1
|
|
23
|
+
status: proposed
|
|
24
|
+
section: "2.1"
|
|
25
|
+
labels: [margi, literature]
|
|
26
|
+
source: [<record file name>:<comment id>, ...]
|
|
27
|
+
---
|
|
28
|
+
What needs to happen and why, in task form (2–6 sentences). Name the evidence.
|
|
29
|
+
Never draft thesis text.
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Keep todos actionable, specific and few: 3–8 per run, prioritised.
|
|
33
|
+
|
|
34
|
+
## 3. Check completion of open issues
|
|
35
|
+
|
|
36
|
+
For each open `margi`-labelled issue, look for evidence that it is done. Evidence can be the
|
|
37
|
+
current thesis text (quote file and lines), newer grade records without the problem, updated
|
|
38
|
+
docs, or outline changes. If you find evidence, write `margi/todos/close/<issue-number>.md`:
|
|
39
|
+
|
|
40
|
+
```markdown
|
|
41
|
+
---
|
|
42
|
+
issue: 12
|
|
43
|
+
title: <issue title>
|
|
44
|
+
status: proposed
|
|
45
|
+
---
|
|
46
|
+
Evidence: ... (file:lines, record names)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## 4. Review with the human
|
|
50
|
+
|
|
51
|
+
Show both lists compactly: new todos, then proposed closures. Ask the human for each item
|
|
52
|
+
(they may answer in bulk):
|
|
53
|
+
|
|
54
|
+
- **accept** → set `status: accepted` in the file
|
|
55
|
+
- **reject** → delete the file
|
|
56
|
+
- **change** → revise the file as instructed, then show it again
|
|
57
|
+
|
|
58
|
+
Repeat until every item is accepted or rejected. Never mark anything accepted on your own.
|
|
59
|
+
|
|
60
|
+
## 5. Sync and record
|
|
61
|
+
|
|
62
|
+
1. If anything is accepted, run `margi todos --sync-accepted`. It creates issues and closes
|
|
63
|
+
issues through `gh`, then moves the files to `margi/todos/synced/`.
|
|
64
|
+
2. Write `margi/.staging/todos.json` with `command: todos`, `scope: review`, a `summary`, and
|
|
65
|
+
`payload: {"accepted": [...ids], "rejected": [...ids], "closed": [...issue numbers]}`.
|
|
66
|
+
3. Run `margi finalize`.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Alignment with research question
|
|
2
|
+
|
|
3
|
+
Does this section serve the research question and contribution documented in
|
|
4
|
+
`margi/docs/research-question.md`?
|
|
5
|
+
|
|
6
|
+
- **5**: Every part visibly advances the RQ, and the section's role in the thesis is explicit.
|
|
7
|
+
- **3**: Mostly relevant. Some passages drift, or their link to the RQ is left implicit.
|
|
8
|
+
- **1**: Unclear or no connection to the RQ, or it pursues a different question.
|
|
9
|
+
|
|
10
|
+
Look for: scope drift, passages that would fit a different thesis, sub-questions promised but
|
|
11
|
+
not addressed, terms used differently than in the docs.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Argument and reasoning
|
|
2
|
+
|
|
3
|
+
Are claims stated clearly, ordered logically and justified?
|
|
4
|
+
|
|
5
|
+
- **5**: Clear claims, explicit reasoning steps, counterarguments addressed, conclusions follow.
|
|
6
|
+
- **3**: The main line is traceable, but there are leaps, unstated premises or unaddressed objections.
|
|
7
|
+
- **1**: Assertions without reasoning, contradictions, or conclusions that do not follow.
|
|
8
|
+
|
|
9
|
+
Look for: hidden assumptions, overgeneralisation from few examples, correlation read as
|
|
10
|
+
causation (especially in computational results), circular definitions.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Evidence and sources
|
|
2
|
+
|
|
3
|
+
Are claims backed by appropriate evidence: primary sources, data, results or citations?
|
|
4
|
+
|
|
5
|
+
- **5**: Claims are consistently supported. Evidence is apt, correctly cited and interpreted with care.
|
|
6
|
+
- **3**: Mostly supported. Some claims lack sources, or evidence is over-read.
|
|
7
|
+
- **1**: Key claims are unsupported, or the evidence is misrepresented.
|
|
8
|
+
|
|
9
|
+
Look for: uncited factual claims, quotations without page numbers, results reported without
|
|
10
|
+
the data or parameters needed to interpret them, examples cherry-picked from a corpus.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Methodological transparency
|
|
2
|
+
|
|
3
|
+
Could a peer understand, assess and, where applicable, reproduce what was done? Judge this
|
|
4
|
+
against `margi/docs/method.md` and `dataset.md`.
|
|
5
|
+
|
|
6
|
+
- **5**: Method, data, parameters, tools and limitations are explicit and justified against alternatives.
|
|
7
|
+
- **3**: Method is described, but choices are not justified, or the description lacks details needed to assess it.
|
|
8
|
+
- **1**: Method unclear, or mismatched with what the docs say is planned.
|
|
9
|
+
|
|
10
|
+
Look for: undocumented preprocessing, unexplained parameter choices, missing validation or
|
|
11
|
+
evaluation, no reflection on corpus bias or the limits of operationalisation.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
id: default
|
|
2
|
+
version: "1.0"
|
|
3
|
+
title: Default rubric for humanities / digital humanities theses
|
|
4
|
+
scale:
|
|
5
|
+
min: 1
|
|
6
|
+
max: 5
|
|
7
|
+
anchors:
|
|
8
|
+
1: fails — the category's basic expectation is not met
|
|
9
|
+
2: weak — present, but with substantial problems
|
|
10
|
+
3: adequate — meets expectations with clear room to improve
|
|
11
|
+
4: good — solid, only minor issues
|
|
12
|
+
5: excellent — exemplary for an MSc thesis
|
|
13
|
+
categories:
|
|
14
|
+
- id: alignment
|
|
15
|
+
file: alignment.md
|
|
16
|
+
title: Alignment with research question
|
|
17
|
+
- id: argument
|
|
18
|
+
file: argument.md
|
|
19
|
+
title: Argument and reasoning
|
|
20
|
+
- id: evidence
|
|
21
|
+
file: evidence.md
|
|
22
|
+
title: Evidence and sources
|
|
23
|
+
- id: scholarship
|
|
24
|
+
file: scholarship.md
|
|
25
|
+
title: Engagement with scholarship
|
|
26
|
+
- id: method
|
|
27
|
+
file: method.md
|
|
28
|
+
title: Methodological transparency
|
|
29
|
+
- id: structure
|
|
30
|
+
file: structure.md
|
|
31
|
+
title: Structure and coherence
|
|
32
|
+
- id: style
|
|
33
|
+
file: style.md
|
|
34
|
+
title: Academic style and precision
|
|
35
|
+
notes: >
|
|
36
|
+
Not every category applies equally to every section (e.g. `method` for an introduction).
|
|
37
|
+
If a category does not apply, score it anyway only if meaningful; otherwise omit it and
|
|
38
|
+
explain the omission in the summary.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Engagement with scholarship
|
|
2
|
+
|
|
3
|
+
Does the section position itself within the field described in `margi/docs/field.md`?
|
|
4
|
+
|
|
5
|
+
- **5**: Engages critically with the relevant debates, including counterpositions, and makes its own position clear.
|
|
6
|
+
- **3**: Cites relevant work, but mostly summarises it, or misses an obvious camp or debate.
|
|
7
|
+
- **1**: Little or no engagement, outdated or tangential sources only.
|
|
8
|
+
|
|
9
|
+
Look for: listing instead of synthesis ("X says…, Y says…"), missing canonical works or
|
|
10
|
+
critics named in `field.md`, no statement of how this thesis differs.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Structure and coherence
|
|
2
|
+
|
|
3
|
+
Is the section organised so that a reader can follow it?
|
|
4
|
+
|
|
5
|
+
- **5**: Clear internal structure, signposting, smooth transitions, appropriate length (see `structure.md` targets).
|
|
6
|
+
- **3**: Followable, but some paragraphs are misplaced, repetitive or lack transitions.
|
|
7
|
+
- **1**: Disorganised. The reader cannot reconstruct the line of thought.
|
|
8
|
+
|
|
9
|
+
Look for: paragraphs with several topics, repeated content, sections much longer or shorter
|
|
10
|
+
than planned, conclusions that introduce new material.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Academic style and precision
|
|
2
|
+
|
|
3
|
+
Is the language precise, consistent and appropriate to the discipline? Judge this against
|
|
4
|
+
the style guide in `margi/docs/constraints.md` if one is given.
|
|
5
|
+
|
|
6
|
+
- **5**: Precise terms used consistently, appropriate register, correct citation form.
|
|
7
|
+
- **3**: Generally appropriate, with vague phrases, inconsistent terms or citation errors.
|
|
8
|
+
- **1**: Imprecise or colloquial throughout, which hinders understanding.
|
|
9
|
+
|
|
10
|
+
Point to problems; **never** supply rewritten sentences.
|