margi 0.1.0__py3-none-any.whl

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.
Files changed (55) hide show
  1. margi/__init__.py +3 -0
  2. margi/__main__.py +3 -0
  3. margi/_bundled/AGENTS.md +20 -0
  4. margi/_bundled/skills/margi/SKILL.md +64 -0
  5. margi/_bundled/skills/margi/commands/grade.md +58 -0
  6. margi/_bundled/skills/margi/commands/read.md +38 -0
  7. margi/_bundled/skills/margi/commands/todos.md +66 -0
  8. margi/_bundled/skills/margi/rubrics/default/alignment.md +11 -0
  9. margi/_bundled/skills/margi/rubrics/default/argument.md +10 -0
  10. margi/_bundled/skills/margi/rubrics/default/evidence.md +10 -0
  11. margi/_bundled/skills/margi/rubrics/default/method.md +11 -0
  12. margi/_bundled/skills/margi/rubrics/default/rubric.yml +38 -0
  13. margi/_bundled/skills/margi/rubrics/default/scholarship.md +10 -0
  14. margi/_bundled/skills/margi/rubrics/default/structure.md +10 -0
  15. margi/_bundled/skills/margi/rubrics/default/style.md +10 -0
  16. margi/_bundled/skills/margi/schema/feedback.schema.json +169 -0
  17. margi/_bundled/skills/margi-challenge/SKILL.md +58 -0
  18. margi/_bundled/skills/margi-challenge/lenses.md +35 -0
  19. margi/_bundled/skills/margi-onboard/SKILL.md +76 -0
  20. margi/_bundled/skills/margi-onboard/interview.md +36 -0
  21. margi/_bundled/skills/margi-onboard/templates/CHANGELOG.md +3 -0
  22. margi/_bundled/skills/margi-onboard/templates/constraints.md +15 -0
  23. margi/_bundled/skills/margi-onboard/templates/dataset.md +21 -0
  24. margi/_bundled/skills/margi-onboard/templates/field.md +15 -0
  25. margi/_bundled/skills/margi-onboard/templates/method.md +18 -0
  26. margi/_bundled/skills/margi-onboard/templates/open-questions.md +3 -0
  27. margi/_bundled/skills/margi-onboard/templates/research-question.md +21 -0
  28. margi/_bundled/skills/margi-onboard/templates/structure.md +24 -0
  29. margi/_bundled/templates/claude-settings.json +25 -0
  30. margi/_bundled/templates/commit-msg +14 -0
  31. margi/_bundled/templates/margi-README.md +13 -0
  32. margi/_bundled/templates/margi-guard.yml +25 -0
  33. margi/_bundled/templates/thesis.config.yml +32 -0
  34. margi/adapters/__init__.py +17 -0
  35. margi/adapters/base.py +85 -0
  36. margi/adapters/typst.py +198 -0
  37. margi/cli.py +264 -0
  38. margi/config.py +69 -0
  39. margi/docs_check.py +82 -0
  40. margi/finalize.py +286 -0
  41. margi/gitutil.py +104 -0
  42. margi/guard.py +106 -0
  43. margi/init.py +157 -0
  44. margi/outline.py +155 -0
  45. margi/pdf.py +45 -0
  46. margi/resources.py +31 -0
  47. margi/schema.py +25 -0
  48. margi/status.py +76 -0
  49. margi/todos_sync.py +110 -0
  50. margi/wrapper.py +125 -0
  51. margi-0.1.0.dist-info/METADATA +108 -0
  52. margi-0.1.0.dist-info/RECORD +55 -0
  53. margi-0.1.0.dist-info/WHEEL +4 -0
  54. margi-0.1.0.dist-info/entry_points.txt +2 -0
  55. margi-0.1.0.dist-info/licenses/LICENSE +21 -0
margi/__init__.py ADDED
@@ -0,0 +1,3 @@
1
+ """margi: AI in the margins, never in the text."""
2
+
3
+ __version__ = "0.1.0"
margi/__main__.py ADDED
@@ -0,0 +1,3 @@
1
+ from .cli import main
2
+
3
+ main()
@@ -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`.
@@ -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.
@@ -0,0 +1,169 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/nicobenz/margi/schema/feedback.schema.json",
4
+ "title": "margi feedback",
5
+ "description": "Draft = what the agent writes to margi/.staging/. Record = draft + run + provenance, written only by `margi finalize`.",
6
+ "$defs": {
7
+ "command": {
8
+ "enum": ["onboard", "challenge", "grade", "outline", "read", "todos"]
9
+ },
10
+ "anchor": {
11
+ "type": "object",
12
+ "additionalProperties": false,
13
+ "required": ["file", "line_start", "line_end", "quote"],
14
+ "properties": {
15
+ "file": { "type": "string", "minLength": 1 },
16
+ "line_start": { "type": "integer", "minimum": 1 },
17
+ "line_end": { "type": "integer", "minimum": 1 },
18
+ "quote": { "type": "string", "minLength": 1, "maxLength": 400 },
19
+ "anchor_status": {
20
+ "description": "Set by finalize only.",
21
+ "enum": ["ok", "relocated", "unresolved"]
22
+ }
23
+ }
24
+ },
25
+ "comment": {
26
+ "type": "object",
27
+ "additionalProperties": false,
28
+ "required": ["id", "category", "severity", "body"],
29
+ "properties": {
30
+ "id": { "type": "string", "pattern": "^[A-Za-z0-9_.:-]+$" },
31
+ "anchor": { "$ref": "#/$defs/anchor" },
32
+ "category": { "type": "string", "minLength": 1 },
33
+ "severity": { "enum": ["major", "minor", "note"] },
34
+ "body": {
35
+ "description": "Names the problem. Never contains replacement prose for the thesis.",
36
+ "type": "string",
37
+ "minLength": 1,
38
+ "maxLength": 1200
39
+ }
40
+ }
41
+ },
42
+ "score": {
43
+ "type": "object",
44
+ "additionalProperties": false,
45
+ "required": ["score", "max", "rationale"],
46
+ "properties": {
47
+ "score": { "type": "number", "minimum": 0 },
48
+ "max": { "type": "number", "exclusiveMinimum": 0 },
49
+ "rationale": { "type": "string", "minLength": 1, "maxLength": 1500 },
50
+ "comment_ids": { "type": "array", "items": { "type": "string" } }
51
+ }
52
+ },
53
+ "draft_properties": {
54
+ "command": { "$ref": "#/$defs/command" },
55
+ "scope": { "type": "string", "minLength": 1, "maxLength": 120 },
56
+ "summary": { "type": "string", "maxLength": 3000 },
57
+ "files_read": {
58
+ "description": "Repo-relative paths the agent read. Finalize hashes them.",
59
+ "type": "array",
60
+ "items": { "type": "string" }
61
+ },
62
+ "scores": {
63
+ "type": "object",
64
+ "additionalProperties": { "$ref": "#/$defs/score" }
65
+ },
66
+ "comments": {
67
+ "type": "array",
68
+ "items": { "$ref": "#/$defs/comment" }
69
+ },
70
+ "payload": {
71
+ "description": "Command-specific data (outline counts, read ratings, onboard sources, challenge log, todo ids).",
72
+ "type": "object"
73
+ },
74
+ "agent": {
75
+ "description": "Self-reported by the agent; finalize records it with model_source=self-reported.",
76
+ "type": "object",
77
+ "additionalProperties": false,
78
+ "properties": {
79
+ "model": { "type": "string" },
80
+ "harness": { "type": "string" }
81
+ }
82
+ }
83
+ },
84
+ "draft": {
85
+ "type": "object",
86
+ "additionalProperties": false,
87
+ "required": ["command", "scope"],
88
+ "properties": {
89
+ "command": { "$ref": "#/$defs/draft_properties/command" },
90
+ "scope": { "$ref": "#/$defs/draft_properties/scope" },
91
+ "summary": { "$ref": "#/$defs/draft_properties/summary" },
92
+ "files_read": { "$ref": "#/$defs/draft_properties/files_read" },
93
+ "scores": { "$ref": "#/$defs/draft_properties/scores" },
94
+ "comments": { "$ref": "#/$defs/draft_properties/comments" },
95
+ "payload": { "$ref": "#/$defs/draft_properties/payload" },
96
+ "agent": { "$ref": "#/$defs/draft_properties/agent" }
97
+ }
98
+ },
99
+ "provenance": {
100
+ "type": "object",
101
+ "additionalProperties": false,
102
+ "required": ["head_sha", "files", "model", "model_source", "margi_version", "timestamp", "docs"],
103
+ "properties": {
104
+ "head_sha": { "type": ["string", "null"] },
105
+ "files": {
106
+ "type": "array",
107
+ "items": {
108
+ "type": "object",
109
+ "additionalProperties": false,
110
+ "required": ["path", "sha256"],
111
+ "properties": {
112
+ "path": { "type": "string" },
113
+ "sha256": { "type": ["string", "null"] },
114
+ "source": { "enum": ["HEAD", "worktree", "missing"] }
115
+ }
116
+ }
117
+ },
118
+ "rubric": {
119
+ "type": ["object", "null"],
120
+ "additionalProperties": false,
121
+ "properties": {
122
+ "id": { "type": "string" },
123
+ "version": { "type": "string" },
124
+ "sha256": { "type": "string" },
125
+ "path": { "type": "string" }
126
+ }
127
+ },
128
+ "docs": {
129
+ "type": "object",
130
+ "additionalProperties": false,
131
+ "required": ["sha256", "completeness"],
132
+ "properties": {
133
+ "sha256": { "type": ["string", "null"] },
134
+ "completeness": { "type": "number", "minimum": 0, "maximum": 1 },
135
+ "low_confidence": { "type": "boolean" }
136
+ }
137
+ },
138
+ "model": { "type": ["string", "null"] },
139
+ "model_source": { "enum": ["wrapper", "self-reported", "none"] },
140
+ "harness": { "type": ["string", "null"] },
141
+ "margi_version": { "type": "string" },
142
+ "timestamp": { "type": "string" }
143
+ }
144
+ },
145
+ "record": {
146
+ "type": "object",
147
+ "additionalProperties": false,
148
+ "required": ["schema", "run", "provenance", "command", "scope"],
149
+ "properties": {
150
+ "schema": { "const": "margi/record@1" },
151
+ "run": {
152
+ "type": "object",
153
+ "additionalProperties": false,
154
+ "required": ["id"],
155
+ "properties": { "id": { "type": "string" } }
156
+ },
157
+ "provenance": { "$ref": "#/$defs/provenance" },
158
+ "command": { "$ref": "#/$defs/draft_properties/command" },
159
+ "scope": { "$ref": "#/$defs/draft_properties/scope" },
160
+ "summary": { "$ref": "#/$defs/draft_properties/summary" },
161
+ "files_read": { "$ref": "#/$defs/draft_properties/files_read" },
162
+ "scores": { "$ref": "#/$defs/draft_properties/scores" },
163
+ "comments": { "$ref": "#/$defs/draft_properties/comments" },
164
+ "payload": { "$ref": "#/$defs/draft_properties/payload" },
165
+ "agent": { "$ref": "#/$defs/draft_properties/agent" }
166
+ }
167
+ }
168
+ }
169
+ }
@@ -0,0 +1,58 @@
1
+ ---
2
+ name: margi-challenge
3
+ description: Critically challenge the assumptions behind one aspect of the thesis project (research question, dataset, method, positioning, ...) in a dialogue, and write agreed refinements back into margi/docs/. Use for /margi challenge <aspect> or /margi-challenge.
4
+ ---
5
+
6
+ # margi challenge <aspect>
7
+
8
+ You are a demanding but fair advisor. Your job is to **sharpen** the user's own thinking
9
+ about `<aspect>` by finding weak points. You do not take over the project. The user decides;
10
+ you probe, record and refine the documentation.
11
+
12
+ Write only to `margi/docs/` and `margi/.staging/`. Never touch thesis text.
13
+
14
+ ## 0. Preflight
15
+
16
+ Run `margi finalize --check`. Stop if it fails.
17
+
18
+ ## 1. Load context
19
+
20
+ - `margi/docs/*.md`, all of them. The aspect usually maps to one main doc (e.g. "dataset"
21
+ maps to `dataset.md`), but contradictions often hide across docs.
22
+ - Earlier challenge records (`margi/feedback/*_challenge_*.json`), so you don't repeat
23
+ settled points.
24
+ - The thesis text only where it shows how the aspect is actually handled.
25
+ - `lenses.md` in this skill: pick the 2–4 lenses that fit the aspect.
26
+
27
+ If the docs say nothing about the aspect, say so and suggest `margi onboard` first, or
28
+ gather the basics in this session.
29
+
30
+ ## 2. Dialogue
31
+
32
+ - Start with a 2–3 sentence restatement of the user's current position on the aspect, with
33
+ citations to the docs, and ask whether it is accurate.
34
+ - Then pose **numbered challenges**, 1–3 at a time. Each one is a concrete question that
35
+ names the assumption being tested and why it matters for the thesis. Examples: "C3: your
36
+ RQ asks *why* X changed, but the method only measures *that* it changed. What licenses the
37
+ causal reading?"
38
+ - The user answers, concedes or defends. Follow up on weak answers once, then move on.
39
+ A defended position is a valid outcome.
40
+ - When a challenge leads to a refinement, restate it precisely and **ask for confirmation**
41
+ before writing it down.
42
+ - Stop after about 5–10 challenges, or when the user wants to stop.
43
+
44
+ ## 3. Write back
45
+
46
+ 1. Apply **only confirmed** refinements to the matching `margi/docs/*.md` sections, tagged
47
+ `(user, <date>, challenge)`. Keep superseded statements only if the user wants the history
48
+ visible; the changelog records the change either way.
49
+ 2. Add unresolved challenges to `open-questions.md` with the date.
50
+ 3. Append a `CHANGELOG.md` entry: date, `challenge: <aspect>`, files changed, and one line
51
+ per refinement.
52
+ 4. Write `margi/.staging/challenge.json`:
53
+ - `command`: `challenge`
54
+ - `scope`: the aspect (short)
55
+ - `summary`: 3–6 sentences on what was tested and what changed
56
+ - `files_read`: the docs and thesis files you used
57
+ - `payload`: `{"challenges": [{"id": "C1", "lens": "...", "question": "...", "outcome": "refined|defended|open|conceded", "note": "..."}], "docs_changed": [...]}`
58
+ 5. Run `margi finalize`.
@@ -0,0 +1,35 @@
1
+ # Challenge lenses
2
+
3
+ Use the lenses that fit the aspect, and phrase every challenge concretely for this thesis.
4
+
5
+ ## Assumptions
6
+ What has to be true for the plan to work? Which of those is unexamined? What happens if it is false?
7
+
8
+ ## Scope
9
+ Is the question answerable within the deadline, length and corpus documented in
10
+ `constraints.md` and `dataset.md`? Is it too broad ("literature in the 19th century") or too
11
+ narrow to matter?
12
+
13
+ ## Operationalisation
14
+ How do abstract concepts (e.g. "canon", "style", "influence") become something measurable or
15
+ observable? Is the operationalisation defensible in the discipline? What does it miss?
16
+
17
+ ## Validity
18
+ - Do the methods actually answer the question (construct validity)?
19
+ - Could results come from corpus artefacts, OCR noise, selection or parameter choices?
20
+ - How far can conclusions generalise beyond the corpus?
21
+
22
+ ## Alternatives
23
+ What is the obvious alternative method, corpus or framing, and why is it not used? Would a
24
+ reviewer from the neighbouring camp (e.g. close reading vs. distant reading) accept the choice?
25
+
26
+ ## Positioning and contribution
27
+ So what? What will the field know afterwards that it did not know before? Who has done
28
+ something close, and what exactly is different?
29
+
30
+ ## Consistency
31
+ Do the research question, method, dataset and planned structure fit together? Does the
32
+ structure give the most space to what the RQ makes central?
33
+
34
+ ## Ethics and data
35
+ Copyright, licensing, personal data, representation of marginalised voices in the corpus.