crewforge 0.1.0__tar.gz → 0.2.1__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.
Files changed (81) hide show
  1. {crewforge-0.1.0 → crewforge-0.2.1}/PKG-INFO +113 -41
  2. crewforge-0.1.0/src/crewforge.egg-info/PKG-INFO → crewforge-0.2.1/README.md +97 -83
  3. {crewforge-0.1.0 → crewforge-0.2.1}/pyproject.toml +48 -6
  4. crewforge-0.2.1/src/crewforge/__init__.py +3 -0
  5. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/cli.py +11 -3
  6. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/core/config.py +1 -0
  7. crewforge-0.2.1/src/crewforge/recipes/__init__.py +1 -0
  8. crewforge-0.2.1/src/crewforge/recipes/academic/__init__.py +46 -0
  9. crewforge-0.2.1/src/crewforge/recipes/academic/agents.py +375 -0
  10. crewforge-0.2.1/src/crewforge/recipes/academic/citations.py +287 -0
  11. crewforge-0.2.1/src/crewforge/recipes/academic/cli.py +360 -0
  12. crewforge-0.2.1/src/crewforge/recipes/academic/disclosure.py +184 -0
  13. crewforge-0.2.1/src/crewforge/recipes/academic/language.py +87 -0
  14. crewforge-0.2.1/src/crewforge/recipes/academic/locales/en.yaml +122 -0
  15. crewforge-0.2.1/src/crewforge/recipes/academic/locales/ms.yaml +174 -0
  16. crewforge-0.2.1/src/crewforge/recipes/academic/pipeline.py +359 -0
  17. crewforge-0.2.1/src/crewforge/recipes/academic/report.py +247 -0
  18. crewforge-0.2.1/src/crewforge/recipes/academic/settings.py +46 -0
  19. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/api/agents.py +3 -1
  20. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/docs/agents.py +6 -4
  21. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/docs/ingest.py +2 -2
  22. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/docs/pipeline.py +13 -7
  23. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/review/agents.py +2 -2
  24. crewforge-0.1.0/README.md → crewforge-0.2.1/src/crewforge.egg-info/PKG-INFO +155 -36
  25. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge.egg-info/SOURCES.txt +11 -0
  26. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge.egg-info/requires.txt +2 -0
  27. crewforge-0.1.0/src/crewforge/__init__.py +0 -3
  28. crewforge-0.1.0/src/crewforge/recipes/__init__.py +0 -1
  29. {crewforge-0.1.0 → crewforge-0.2.1}/LICENSE +0 -0
  30. {crewforge-0.1.0 → crewforge-0.2.1}/setup.cfg +0 -0
  31. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/__main__.py +0 -0
  32. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/cli_support.py +0 -0
  33. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/core/__init__.py +0 -0
  34. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/core/agent.py +0 -0
  35. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/core/client.py +0 -0
  36. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/core/crew.py +0 -0
  37. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/core/errors.py +0 -0
  38. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/core/parsing.py +0 -0
  39. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/core/providers.py +0 -0
  40. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/core/usage.py +0 -0
  41. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/py.typed +0 -0
  42. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/api/__init__.py +0 -0
  43. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/api/analytics.py +0 -0
  44. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/api/appcheck.py +0 -0
  45. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/api/cli.py +0 -0
  46. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/api/formatters.py +0 -0
  47. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/api/generator.py +0 -0
  48. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/api/pipeline.py +0 -0
  49. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/api/scaffold.py +0 -0
  50. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/api/templates/docker-compose.j2 +0 -0
  51. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/api/templates/dockerfile.j2 +0 -0
  52. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/api/templates/env.example.j2 +0 -0
  53. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/api/templates/fastapi_main.j2 +0 -0
  54. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/api/templates/model.j2 +0 -0
  55. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/api/templates/requirements.j2 +0 -0
  56. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/api/templates/route.j2 +0 -0
  57. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/api/templates/test.j2 +0 -0
  58. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/api/utils.py +0 -0
  59. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/content/__init__.py +0 -0
  60. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/content/agents.py +0 -0
  61. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/content/cli.py +0 -0
  62. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/content/export.py +0 -0
  63. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/content/pipeline.py +0 -0
  64. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/content/settings.py +0 -0
  65. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/content/text.py +0 -0
  66. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/docs/__init__.py +0 -0
  67. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/docs/cli.py +0 -0
  68. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/docs/export.py +0 -0
  69. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/docs/index.py +0 -0
  70. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/docs/retrieve.py +0 -0
  71. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/docs/settings.py +0 -0
  72. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/review/__init__.py +0 -0
  73. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/review/cli.py +0 -0
  74. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/review/pipeline.py +0 -0
  75. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/review/report.py +0 -0
  76. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/review/sources.py +0 -0
  77. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge.egg-info/dependency_links.txt +0 -0
  78. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge.egg-info/entry_points.txt +0 -0
  79. {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge.egg-info/top_level.txt +0 -0
  80. {crewforge-0.1.0 → crewforge-0.2.1}/tests/test_honest_failure_e2e.py +0 -0
  81. {crewforge-0.1.0 → crewforge-0.2.1}/tests/test_readme.py +0 -0
@@ -1,17 +1,22 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: crewforge
3
- Version: 0.1.0
4
- Summary: One crew of LLM agents, four recipes: code review, document Q&A, API scaffolding and content — on any OpenAI-compatible provider.
3
+ Version: 0.2.1
4
+ Summary: One crew of LLM agents, five recipes: code review, document Q&A, API scaffolding, content and honest academic-writing help — on any OpenAI-compatible provider.
5
5
  Author: Muhammad Aiman
6
6
  License-Expression: MIT
7
7
  Project-URL: Homepage, https://github.com/aimanmalib/crewforge
8
- Project-URL: Repository, https://github.com/aimanmalib/crewforge
9
- Project-URL: Issues, https://github.com/aimanmalib/crewforge/issues
8
+ Project-URL: Documentation, https://github.com/aimanmalib/crewforge#readme
10
9
  Project-URL: Changelog, https://github.com/aimanmalib/crewforge/blob/main/CHANGELOG.md
11
- Keywords: llm,agents,multi-agent,openai,code-review,rag,fastapi,content-generation,cli
10
+ Project-URL: Issues, https://github.com/aimanmalib/crewforge/issues
11
+ Project-URL: Source, https://github.com/aimanmalib/crewforge
12
+ Project-URL: Security, https://github.com/aimanmalib/crewforge/security/policy
13
+ Keywords: llm,agents,multi-agent,ai-agents,openai,openai-compatible,code-review,rag,document-qa,fastapi,api-scaffolding,content-generation,academic-writing,cli
12
14
  Classifier: Development Status :: 3 - Alpha
13
15
  Classifier: Environment :: Console
14
16
  Classifier: Intended Audience :: Developers
17
+ Classifier: Intended Audience :: Education
18
+ Classifier: Natural Language :: English
19
+ Classifier: Natural Language :: Malay
15
20
  Classifier: Operating System :: OS Independent
16
21
  Classifier: Programming Language :: Python :: 3
17
22
  Classifier: Programming Language :: Python :: 3 :: Only
@@ -19,8 +24,12 @@ Classifier: Programming Language :: Python :: 3.10
19
24
  Classifier: Programming Language :: Python :: 3.11
20
25
  Classifier: Programming Language :: Python :: 3.12
21
26
  Classifier: Programming Language :: Python :: 3.13
27
+ Classifier: Programming Language :: Python :: 3.14
28
+ Classifier: Topic :: Education
22
29
  Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
30
+ Classifier: Topic :: Software Development :: Code Generators
23
31
  Classifier: Topic :: Software Development :: Quality Assurance
32
+ Classifier: Topic :: Text Processing :: General
24
33
  Classifier: Typing :: Typed
25
34
  Requires-Python: >=3.10
26
35
  Description-Content-Type: text/markdown
@@ -41,16 +50,20 @@ Requires-Dist: pytest>=8.0; extra == "dev"
41
50
  Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
42
51
  Requires-Dist: pytest-cov>=5.0; extra == "dev"
43
52
  Requires-Dist: ruff>=0.6; extra == "dev"
53
+ Requires-Dist: mypy>=1.10; extra == "dev"
54
+ Requires-Dist: types-PyYAML>=6.0; extra == "dev"
44
55
  Requires-Dist: fastapi>=0.110; extra == "dev"
45
56
  Requires-Dist: httpx>=0.27; extra == "dev"
46
57
  Dynamic: license-file
47
58
 
48
59
  # crewforge
49
60
 
50
- **One crew of LLM agents, four recipes — code review, document Q&A, API scaffolding and content — on any OpenAI-compatible provider, and it fails loudly instead of pretending.**
61
+ **One crew of LLM agents, five recipes — code review, document Q&A, API scaffolding, content and honest academic-writing help — on any OpenAI-compatible provider, and it fails loudly instead of pretending.**
51
62
 
52
63
  [![CI](https://github.com/aimanmalib/crewforge/actions/workflows/ci.yml/badge.svg)](https://github.com/aimanmalib/crewforge/actions/workflows/ci.yml)
53
- ![Python 3.10–3.13](https://img.shields.io/badge/python-3.10%E2%80%933.13-blue)
64
+ [![PyPI](https://img.shields.io/pypi/v/crewforge)](https://pypi.org/project/crewforge/)
65
+ [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/aimanmalib/crewforge/badge)](https://scorecard.dev/viewer/?uri=github.com/aimanmalib/crewforge)
66
+ ![Python 3.10–3.14](https://img.shields.io/badge/python-3.10%E2%80%933.14-blue)
54
67
  ![License: MIT](https://img.shields.io/badge/license-MIT-green)
55
68
 
56
69
  ```bash
@@ -58,6 +71,7 @@ crewforge review src/ # six reviewers + a summa
58
71
  crewforge ask handbook.pdf -q "How many leave days?" --verify
59
72
  crewforge scaffold "Todo API: list, create and delete todos" -o todo-api
60
73
  crewforge write "Why unit tests matter" -f markdown -f html
74
+ crewforge academic feedback draft.md --brief brief.md --language ms
61
75
  ```
62
76
 
63
77
  <p align="center">
@@ -65,7 +79,7 @@ crewforge write "Why unit tests matter" -f markdown -f html
65
79
  </p>
66
80
  <p align="center"><sub>A real run of <code>crewforge review</code>: seven agents, ~25 s, provider-reported tokens. Recorded with <a href="https://github.com/charmbracelet/vhs">VHS</a> from <a href="https://github.com/aimanmalib/crewforge/blob/main/docs/demo/review.tape"><code>docs/demo/review.tape</code></a> using Gemini 3.8 Flash through an OpenAI-compatible gateway (the <code>custom</code> provider). The wait for the model is shown in full.</sub></p>
67
81
 
68
- ## Why one crew, four recipes
82
+ ## Why one crew, many recipes
69
83
 
70
84
  crewforge started as four separate command-line tools —
71
85
  [codeguard](https://github.com/aimanmalib/codeguard),
@@ -87,6 +101,10 @@ apply to every recipe: non-streaming requests, bounded retries, usage numbers
87
101
  taken only from the provider, keys only from the environment, and no run that
88
102
  reports success when an agent produced nothing.
89
103
 
104
+ A fifth recipe, `academic`, replaces a standalone "academic writing pipeline"
105
+ that drafted essays and marketed itself as AI-detector-resistant. Only the
106
+ honest parts were kept; see [docs/porting.md](https://github.com/aimanmalib/crewforge/blob/main/docs/porting.md#academic-from-hermes-mimo-writer).
107
+
90
108
  ## 60-second quickstart
91
109
 
92
110
  ```bash
@@ -128,6 +146,10 @@ tables are trimmed to their totals.
128
146
  | `scaffold "DESCRIPTION"` | parser → schema → router, model, auth, test_gen, doc_gen (parallel) → validator | A runnable FastAPI project with `openapi.json`, tests and docs |
129
147
  | `validate PATH` | validator (no LLM) | Spec check; for a project directory, also checks the app serves every spec operation |
130
148
  | `write "TOPIC"` | research → outline → writer → SEO → editor ⇄ quality → translator → publisher | Article as Markdown/HTML/JSON, social snippets, a usage file |
149
+ | `academic plan BRIEF` | brief → planner | Research questions, an outline with a word budget that adds up, sources to find, suggested readings labelled UNVERIFIED |
150
+ | `academic feedback DRAFT` | structure, argument, clarity, citations (parallel) + a citation cross-check (no LLM) | Comments tied to quoted text in your draft; no rewriting |
151
+ | `academic cite REFS` | formatter | Your references in APA 7, IEEE or Harvard; nothing added, missing details listed |
152
+ | `academic disclose` | none (no LLM) | An AI-use statement built from the record of what the tool did |
131
153
 
132
154
  ### `review`
133
155
 
@@ -151,6 +173,11 @@ total 7 calls 22,366 tokens (provider-reported)
151
173
 
152
174
  ### `ask` and `summarize`
153
175
 
176
+ <p align="center">
177
+ <img src="https://raw.githubusercontent.com/aimanmalib/crewforge/main/docs/demo/ask.gif" alt="Terminal demo: crewforge ask --verify answers two questions about a short project brief with [Source N] citations; the second answer says the document does not give the cost, and both answers are fact-checked claim by claim" width="900">
178
+ </p>
179
+ <p align="center"><sub>A real run of <code>crewforge ask --verify</code>: the answerer cites the passages it used as <code>[Source N]</code>, a second agent checks every claim against those passages, and the question the document does not answer is answered as such. Provider-reported tokens. Recorded with <a href="https://github.com/charmbracelet/vhs">VHS</a> from <a href="https://github.com/aimanmalib/crewforge/blob/main/docs/demo/ask.tape"><code>docs/demo/ask.tape</code></a> (the document is invented) using Gemini 3.8 Flash through an OpenAI-compatible gateway (the <code>custom</code> provider). The wait for the model is shown in full.</sub></p>
180
+
154
181
  ```text
155
182
  $ crewforge ask kestrel.md -q "How many sensors does Project Kestrel use, and who leads it?" --verify --export session.md
156
183
  ✓ ingested kestrel.md (1 chunks)
@@ -212,6 +239,73 @@ length (`--words` is a target given to the agents, not a hard limit), and the
212
239
  research agent has no web access, so statistics it quotes come from the model's
213
240
  training data. Review articles before publishing them.
214
241
 
242
+ ### `academic`
243
+
244
+ An honest assistant for a student's or researcher's **own** work. It plans,
245
+ comments and formats; it does not write the assignment, does not invent
246
+ references, and has no "humanise" or AI-detector-evasion feature. Output in
247
+ English or Malaysian Malay (`--language en|ms`; Malay output is checked for
248
+ Indonesian forms such as *karena* or *kualitas*). Every step is recorded
249
+ (file names and hashes, never content or keys) so `disclose` can write the
250
+ AI-use statement many universities now ask for.
251
+
252
+ <p align="center">
253
+ <img src="https://raw.githubusercontent.com/aimanmalib/crewforge/main/docs/demo/academic.gif" alt="Terminal demo: crewforge academic feedback --language ms comments in Malay on a student's essay draft, quoting the sentences it refers to, then a no-AI citation check lists (Lim, 2024) as cited in the text but missing from the reference list" width="900">
254
+ </p>
255
+ <p align="center"><sub>A real run of <code>crewforge academic feedback --language ms</code> on a short essay draft in Malay. Each comment quotes the student's own sentence and suggests a fix; nothing is rewritten. The citation check after it uses no AI: it finds <em>(Lim, 2024)</em> cited in the text but missing from the reference list. Only the <code>argument</code> reviewer is run so the result fits on one screen. Recorded with <a href="https://github.com/charmbracelet/vhs">VHS</a> from <a href="https://github.com/aimanmalib/crewforge/blob/main/docs/demo/academic.tape"><code>docs/demo/academic.tape</code></a> (draft, brief and reference are invented) using Gemini 3.8 Flash through an OpenAI-compatible gateway (the <code>custom</code> provider). The wait for the model is shown in full.</sub></p>
256
+
257
+ ```text
258
+ $ crewforge academic plan brief.md -f markdown # a 1,200-word TSL3013 essay brief
259
+ # Assignment plan: Regulated Integration over Prohibition: ...
260
+ - **Target length:** 1,200 words
261
+ - **Citation style:** APA 7th edition
262
+ ## Research questions
263
+ 1. What pedagogical benefits does generative AI offer secondary school students completing homework tasks?
264
+ ...
265
+ | # | Section | Words | Purpose |
266
+ | 1 | Introduction | 150 | ... | ... Total: 1,200 words
267
+ ## Suggested readings (UNVERIFIED)
268
+ > The AI proposed these. They may not exist, or may not say what is claimed. ...
269
+ - ⚠ **UNVERIFIED: proposed or altered by the AI, check it** — Holmes, W., & Tuomi, I. (2022). ...
270
+ total 2 calls 9,034 tokens (provider-reported)
271
+
272
+ $ crewforge academic feedback draft.md --brief brief.md -f markdown
273
+ ## Argument
274
+ - **Paragraph 2** (major): “Everyone knows that tuition in Malaysia is very expensive.”
275
+ - This is an unsupported generalization and an informal assertion rather than an evidence-based academic claim.
276
+ - *Suggestion:* Replace the appeal to common knowledge with scholarly evidence or empirical data ...
277
+ ## Citation check (no AI)
278
+ **Cited in the text but not in the reference list:**
279
+ - Lim, 2024
280
+ total 4 calls 17,892 tokens (provider-reported)
281
+
282
+ $ crewforge academic cite refs.txt --style ieee --language ms -f markdown
283
+ [4] W. Holmes, M. Bialik, and C. Fadel, *Artificial Intelligence in Education: ...*. Center for Curriculum Redesign, 2019, ISBN: 978-1-7941-1293-0.
284
+ - ⚠ nombor semak ISBN salah: 9781794112930
285
+ - Butiran yang perlu ditambah: tempat penerbitan
286
+
287
+ $ crewforge academic disclose --language ms # no LLM, no key
288
+ ## Pernyataan Penggunaan AI
289
+ Saya menggunakan crewforge academic (versi 0.1.0), sebuah alat berbantukan AI, dengan model gemini-3.8-flash (melalui gateway serasi OpenAI), bagi bahagian tugasan berikut:
290
+ - 22 Oktober 2026: Perancangan: alat ini menukar taklimat tugasan (brief-ms.md) kepada 3 soalan kajian, rangka 5 bahagian dan peruntukan perkataan. ...
291
+ ```
292
+
293
+ How sources are labelled — there is no "verified" status, because the tool
294
+ cannot check that a source exists:
295
+
296
+ | Source | Label |
297
+ |---|---|
298
+ | You supplied it | *supplied by you (not checked online)* |
299
+ | The model proposed it, with a DOI, URL or valid ISBN | **UNVERIFIED** — check it |
300
+ | The model proposed it with none of those | **LIKELY FABRICATED** |
301
+ | The model added a DOI/URL/ISBN to a reference you supplied | **UNVERIFIED**, naming the added identifier |
302
+
303
+ A DOI the model proposes can be made up too, which is why even those stay
304
+ unverified. All text the student sees lives in
305
+ `src/crewforge/recipes/academic/locales/{en,ms}.yaml`; defaults (language,
306
+ style, log file, input size, suggestion length) are the `academic:` section of
307
+ `crewforge.yaml`.
308
+
215
309
  ## Providers
216
310
 
217
311
  The table is checked against the code by `tests/test_readme.py`.
@@ -237,35 +331,9 @@ An unknown provider name is a configuration error, not a silent fallback.
237
331
 
238
332
  ## Architecture
239
333
 
240
- ```mermaid
241
- flowchart LR
242
- CLI["crewforge CLI<br/>review · ask · summarize · ingest<br/>scaffold · validate · write"] --> R
243
-
244
- subgraph R["Recipes (src/crewforge/recipes)"]
245
- RV[review]
246
- DC[docs]
247
- AP[api]
248
- CT[content]
249
- end
250
-
251
- R --> CREW
252
-
253
- subgraph CORE["Core (src/crewforge/core)"]
254
- CREW["Crew<br/>step() · parallel()<br/>names failed agents"]
255
- AG["Agent<br/>ask() · ask_json()<br/>rejects empty output"]
256
- PA["parsing<br/>tolerant JSON + schema"]
257
- CL["LLMClient<br/>stream=false · retries 429/5xx only"]
258
- US["UsageTracker<br/>provider-reported tokens"]
259
- CF["LLMConfig + provider presets<br/>keys from env only"]
260
- CREW --> AG
261
- AG --> PA
262
- AG --> CL
263
- AG --> US
264
- CL --> CF
265
- end
266
-
267
- CL -->|"/chat/completions"| P[("Any OpenAI-compatible provider")]
268
- ```
334
+ <p align="center"><img src="https://raw.githubusercontent.com/aimanmalib/crewforge/main/docs/architecture.png" alt="Architecture: the CLI dispatches to five recipes; each recipe builds a Crew of Agents on the shared core (parsing, LLMClient, LLMConfig, UsageTracker), which talks to any OpenAI-compatible provider over /chat/completions" width="100%"></p>
335
+
336
+ <sub>Source: [docs/architecture.mmd](https://github.com/aimanmalib/crewforge/blob/main/docs/architecture.mmd) (re-render with `scripts/render_architecture.py`).</sub>
269
337
 
270
338
  - **`core/client.py`** — one async client. It always sends `"stream": false`,
271
339
  retries only HTTP 429, 5xx and network/timeout errors (with capped exponential
@@ -317,7 +385,7 @@ Validation: INVALID · 0/100 (0 operation(s) checked, 1 error(s), 0 warning(s))
317
385
  ERROR: No endpoints defined (paths is empty)
318
386
  ```
319
387
 
320
- | Situation | Before (the four tools) | crewforge |
388
+ | Situation | Before (the earlier tools) | crewforge |
321
389
  |---|---|---|
322
390
  | Every reviewer returns nothing | "Review Complete!", exit 0 | exit 1, names each reviewer |
323
391
  | A reviewer answers in prose | treated as a review | exit 1, `agent 'style' (parse)` |
@@ -327,6 +395,9 @@ Validation: INVALID · 0/100 (0 operation(s) checked, 1 error(s), 0 warning(s))
327
395
  | Quality never reaches the threshold | article published | exit 1 unless `--accept-below-threshold` |
328
396
  | Question matches no passage | model asked to answer from nothing | exit 1, names `retriever`, no LLM call |
329
397
  | Generated code does not compile | template silently reused | exit 1, names the agent |
398
+ | Model proposes a reference with no DOI/URL/ISBN | hermes-mimo-writer put invented "plausible" references in the bibliography | labelled LIKELY FABRICATED, never verified |
399
+ | Formatter skips a reference you supplied | n/a | exit 1, names `formatter` |
400
+ | `disclose` finds no recorded AI use | n/a | exit 1, no statement written |
330
401
 
331
402
  Exit codes: `0` success · `1` run failed (agent, validator or provider) · `2`
332
403
  usage or configuration error (bad flag, unknown provider, missing key).
@@ -346,14 +417,15 @@ were carried over into this repository (see [docs/porting.md](https://github.com
346
417
  for what was ported, re-targeted at the shared core, or dropped and why).
347
418
 
348
419
  The evidence that it works is meant to be checkable: the test suite (run
349
- `pytest`; it needs no key and no network), CI on Python 3.10–3.13, and the
420
+ `pytest`; it needs no key and no network), CI on Python 3.10–3.14, and the
350
421
  real-provider runs shown above, two of which found bugs that were fixed with
351
422
  tests before the output was recorded.
352
423
 
353
424
  ## Contributing
354
425
 
355
- See [CONTRIBUTING.md](https://github.com/aimanmalib/crewforge/blob/main/CONTRIBUTING.md). In short: `pip install -e ".[dev,docs]"`,
356
- `pytest`, `ruff check . && ruff format --check .`, and every new failure path
426
+ See [CONTRIBUTING.md](https://github.com/aimanmalib/crewforge/blob/main/CONTRIBUTING.md). In short: `uv sync --extra dev --extra docs`
427
+ (versions from the committed `uv.lock`, as in CI), `uv run pytest`,
428
+ `uv run ruff check . && uv run ruff format --check .`, and every new failure path
357
429
  needs a test that fails if the guard is removed.
358
430
 
359
431
  ## Security
@@ -1,56 +1,11 @@
1
- Metadata-Version: 2.4
2
- Name: crewforge
3
- Version: 0.1.0
4
- Summary: One crew of LLM agents, four recipes: code review, document Q&A, API scaffolding and content — on any OpenAI-compatible provider.
5
- Author: Muhammad Aiman
6
- License-Expression: MIT
7
- Project-URL: Homepage, https://github.com/aimanmalib/crewforge
8
- Project-URL: Repository, https://github.com/aimanmalib/crewforge
9
- Project-URL: Issues, https://github.com/aimanmalib/crewforge/issues
10
- Project-URL: Changelog, https://github.com/aimanmalib/crewforge/blob/main/CHANGELOG.md
11
- Keywords: llm,agents,multi-agent,openai,code-review,rag,fastapi,content-generation,cli
12
- Classifier: Development Status :: 3 - Alpha
13
- Classifier: Environment :: Console
14
- Classifier: Intended Audience :: Developers
15
- Classifier: Operating System :: OS Independent
16
- Classifier: Programming Language :: Python :: 3
17
- Classifier: Programming Language :: Python :: 3 :: Only
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 :: Scientific/Engineering :: Artificial Intelligence
23
- Classifier: Topic :: Software Development :: Quality Assurance
24
- Classifier: Typing :: Typed
25
- Requires-Python: >=3.10
26
- Description-Content-Type: text/markdown
27
- License-File: LICENSE
28
- Requires-Dist: httpx>=0.27
29
- Requires-Dist: pydantic>=2.5
30
- Requires-Dist: click>=8.1
31
- Requires-Dist: rich>=13.0
32
- Requires-Dist: pyyaml>=6.0
33
- Requires-Dist: jinja2>=3.1
34
- Provides-Extra: docs
35
- Requires-Dist: pymupdf>=1.24; extra == "docs"
36
- Requires-Dist: python-docx>=1.1; extra == "docs"
37
- Provides-Extra: api
38
- Requires-Dist: fastapi>=0.110; extra == "api"
39
- Provides-Extra: dev
40
- Requires-Dist: pytest>=8.0; extra == "dev"
41
- Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
42
- Requires-Dist: pytest-cov>=5.0; extra == "dev"
43
- Requires-Dist: ruff>=0.6; extra == "dev"
44
- Requires-Dist: fastapi>=0.110; extra == "dev"
45
- Requires-Dist: httpx>=0.27; extra == "dev"
46
- Dynamic: license-file
47
-
48
1
  # crewforge
49
2
 
50
- **One crew of LLM agents, four recipes — code review, document Q&A, API scaffolding and content — on any OpenAI-compatible provider, and it fails loudly instead of pretending.**
3
+ **One crew of LLM agents, five recipes — code review, document Q&A, API scaffolding, content and honest academic-writing help — on any OpenAI-compatible provider, and it fails loudly instead of pretending.**
51
4
 
52
5
  [![CI](https://github.com/aimanmalib/crewforge/actions/workflows/ci.yml/badge.svg)](https://github.com/aimanmalib/crewforge/actions/workflows/ci.yml)
53
- ![Python 3.10–3.13](https://img.shields.io/badge/python-3.10%E2%80%933.13-blue)
6
+ [![PyPI](https://img.shields.io/pypi/v/crewforge)](https://pypi.org/project/crewforge/)
7
+ [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/aimanmalib/crewforge/badge)](https://scorecard.dev/viewer/?uri=github.com/aimanmalib/crewforge)
8
+ ![Python 3.10–3.14](https://img.shields.io/badge/python-3.10%E2%80%933.14-blue)
54
9
  ![License: MIT](https://img.shields.io/badge/license-MIT-green)
55
10
 
56
11
  ```bash
@@ -58,6 +13,7 @@ crewforge review src/ # six reviewers + a summa
58
13
  crewforge ask handbook.pdf -q "How many leave days?" --verify
59
14
  crewforge scaffold "Todo API: list, create and delete todos" -o todo-api
60
15
  crewforge write "Why unit tests matter" -f markdown -f html
16
+ crewforge academic feedback draft.md --brief brief.md --language ms
61
17
  ```
62
18
 
63
19
  <p align="center">
@@ -65,7 +21,7 @@ crewforge write "Why unit tests matter" -f markdown -f html
65
21
  </p>
66
22
  <p align="center"><sub>A real run of <code>crewforge review</code>: seven agents, ~25 s, provider-reported tokens. Recorded with <a href="https://github.com/charmbracelet/vhs">VHS</a> from <a href="https://github.com/aimanmalib/crewforge/blob/main/docs/demo/review.tape"><code>docs/demo/review.tape</code></a> using Gemini 3.8 Flash through an OpenAI-compatible gateway (the <code>custom</code> provider). The wait for the model is shown in full.</sub></p>
67
23
 
68
- ## Why one crew, four recipes
24
+ ## Why one crew, many recipes
69
25
 
70
26
  crewforge started as four separate command-line tools —
71
27
  [codeguard](https://github.com/aimanmalib/codeguard),
@@ -87,6 +43,10 @@ apply to every recipe: non-streaming requests, bounded retries, usage numbers
87
43
  taken only from the provider, keys only from the environment, and no run that
88
44
  reports success when an agent produced nothing.
89
45
 
46
+ A fifth recipe, `academic`, replaces a standalone "academic writing pipeline"
47
+ that drafted essays and marketed itself as AI-detector-resistant. Only the
48
+ honest parts were kept; see [docs/porting.md](https://github.com/aimanmalib/crewforge/blob/main/docs/porting.md#academic-from-hermes-mimo-writer).
49
+
90
50
  ## 60-second quickstart
91
51
 
92
52
  ```bash
@@ -128,6 +88,10 @@ tables are trimmed to their totals.
128
88
  | `scaffold "DESCRIPTION"` | parser → schema → router, model, auth, test_gen, doc_gen (parallel) → validator | A runnable FastAPI project with `openapi.json`, tests and docs |
129
89
  | `validate PATH` | validator (no LLM) | Spec check; for a project directory, also checks the app serves every spec operation |
130
90
  | `write "TOPIC"` | research → outline → writer → SEO → editor ⇄ quality → translator → publisher | Article as Markdown/HTML/JSON, social snippets, a usage file |
91
+ | `academic plan BRIEF` | brief → planner | Research questions, an outline with a word budget that adds up, sources to find, suggested readings labelled UNVERIFIED |
92
+ | `academic feedback DRAFT` | structure, argument, clarity, citations (parallel) + a citation cross-check (no LLM) | Comments tied to quoted text in your draft; no rewriting |
93
+ | `academic cite REFS` | formatter | Your references in APA 7, IEEE or Harvard; nothing added, missing details listed |
94
+ | `academic disclose` | none (no LLM) | An AI-use statement built from the record of what the tool did |
131
95
 
132
96
  ### `review`
133
97
 
@@ -151,6 +115,11 @@ total 7 calls 22,366 tokens (provider-reported)
151
115
 
152
116
  ### `ask` and `summarize`
153
117
 
118
+ <p align="center">
119
+ <img src="https://raw.githubusercontent.com/aimanmalib/crewforge/main/docs/demo/ask.gif" alt="Terminal demo: crewforge ask --verify answers two questions about a short project brief with [Source N] citations; the second answer says the document does not give the cost, and both answers are fact-checked claim by claim" width="900">
120
+ </p>
121
+ <p align="center"><sub>A real run of <code>crewforge ask --verify</code>: the answerer cites the passages it used as <code>[Source N]</code>, a second agent checks every claim against those passages, and the question the document does not answer is answered as such. Provider-reported tokens. Recorded with <a href="https://github.com/charmbracelet/vhs">VHS</a> from <a href="https://github.com/aimanmalib/crewforge/blob/main/docs/demo/ask.tape"><code>docs/demo/ask.tape</code></a> (the document is invented) using Gemini 3.8 Flash through an OpenAI-compatible gateway (the <code>custom</code> provider). The wait for the model is shown in full.</sub></p>
122
+
154
123
  ```text
155
124
  $ crewforge ask kestrel.md -q "How many sensors does Project Kestrel use, and who leads it?" --verify --export session.md
156
125
  ✓ ingested kestrel.md (1 chunks)
@@ -212,6 +181,73 @@ length (`--words` is a target given to the agents, not a hard limit), and the
212
181
  research agent has no web access, so statistics it quotes come from the model's
213
182
  training data. Review articles before publishing them.
214
183
 
184
+ ### `academic`
185
+
186
+ An honest assistant for a student's or researcher's **own** work. It plans,
187
+ comments and formats; it does not write the assignment, does not invent
188
+ references, and has no "humanise" or AI-detector-evasion feature. Output in
189
+ English or Malaysian Malay (`--language en|ms`; Malay output is checked for
190
+ Indonesian forms such as *karena* or *kualitas*). Every step is recorded
191
+ (file names and hashes, never content or keys) so `disclose` can write the
192
+ AI-use statement many universities now ask for.
193
+
194
+ <p align="center">
195
+ <img src="https://raw.githubusercontent.com/aimanmalib/crewforge/main/docs/demo/academic.gif" alt="Terminal demo: crewforge academic feedback --language ms comments in Malay on a student's essay draft, quoting the sentences it refers to, then a no-AI citation check lists (Lim, 2024) as cited in the text but missing from the reference list" width="900">
196
+ </p>
197
+ <p align="center"><sub>A real run of <code>crewforge academic feedback --language ms</code> on a short essay draft in Malay. Each comment quotes the student's own sentence and suggests a fix; nothing is rewritten. The citation check after it uses no AI: it finds <em>(Lim, 2024)</em> cited in the text but missing from the reference list. Only the <code>argument</code> reviewer is run so the result fits on one screen. Recorded with <a href="https://github.com/charmbracelet/vhs">VHS</a> from <a href="https://github.com/aimanmalib/crewforge/blob/main/docs/demo/academic.tape"><code>docs/demo/academic.tape</code></a> (draft, brief and reference are invented) using Gemini 3.8 Flash through an OpenAI-compatible gateway (the <code>custom</code> provider). The wait for the model is shown in full.</sub></p>
198
+
199
+ ```text
200
+ $ crewforge academic plan brief.md -f markdown # a 1,200-word TSL3013 essay brief
201
+ # Assignment plan: Regulated Integration over Prohibition: ...
202
+ - **Target length:** 1,200 words
203
+ - **Citation style:** APA 7th edition
204
+ ## Research questions
205
+ 1. What pedagogical benefits does generative AI offer secondary school students completing homework tasks?
206
+ ...
207
+ | # | Section | Words | Purpose |
208
+ | 1 | Introduction | 150 | ... | ... Total: 1,200 words
209
+ ## Suggested readings (UNVERIFIED)
210
+ > The AI proposed these. They may not exist, or may not say what is claimed. ...
211
+ - ⚠ **UNVERIFIED: proposed or altered by the AI, check it** — Holmes, W., & Tuomi, I. (2022). ...
212
+ total 2 calls 9,034 tokens (provider-reported)
213
+
214
+ $ crewforge academic feedback draft.md --brief brief.md -f markdown
215
+ ## Argument
216
+ - **Paragraph 2** (major): “Everyone knows that tuition in Malaysia is very expensive.”
217
+ - This is an unsupported generalization and an informal assertion rather than an evidence-based academic claim.
218
+ - *Suggestion:* Replace the appeal to common knowledge with scholarly evidence or empirical data ...
219
+ ## Citation check (no AI)
220
+ **Cited in the text but not in the reference list:**
221
+ - Lim, 2024
222
+ total 4 calls 17,892 tokens (provider-reported)
223
+
224
+ $ crewforge academic cite refs.txt --style ieee --language ms -f markdown
225
+ [4] W. Holmes, M. Bialik, and C. Fadel, *Artificial Intelligence in Education: ...*. Center for Curriculum Redesign, 2019, ISBN: 978-1-7941-1293-0.
226
+ - ⚠ nombor semak ISBN salah: 9781794112930
227
+ - Butiran yang perlu ditambah: tempat penerbitan
228
+
229
+ $ crewforge academic disclose --language ms # no LLM, no key
230
+ ## Pernyataan Penggunaan AI
231
+ Saya menggunakan crewforge academic (versi 0.1.0), sebuah alat berbantukan AI, dengan model gemini-3.8-flash (melalui gateway serasi OpenAI), bagi bahagian tugasan berikut:
232
+ - 22 Oktober 2026: Perancangan: alat ini menukar taklimat tugasan (brief-ms.md) kepada 3 soalan kajian, rangka 5 bahagian dan peruntukan perkataan. ...
233
+ ```
234
+
235
+ How sources are labelled — there is no "verified" status, because the tool
236
+ cannot check that a source exists:
237
+
238
+ | Source | Label |
239
+ |---|---|
240
+ | You supplied it | *supplied by you (not checked online)* |
241
+ | The model proposed it, with a DOI, URL or valid ISBN | **UNVERIFIED** — check it |
242
+ | The model proposed it with none of those | **LIKELY FABRICATED** |
243
+ | The model added a DOI/URL/ISBN to a reference you supplied | **UNVERIFIED**, naming the added identifier |
244
+
245
+ A DOI the model proposes can be made up too, which is why even those stay
246
+ unverified. All text the student sees lives in
247
+ `src/crewforge/recipes/academic/locales/{en,ms}.yaml`; defaults (language,
248
+ style, log file, input size, suggestion length) are the `academic:` section of
249
+ `crewforge.yaml`.
250
+
215
251
  ## Providers
216
252
 
217
253
  The table is checked against the code by `tests/test_readme.py`.
@@ -237,35 +273,9 @@ An unknown provider name is a configuration error, not a silent fallback.
237
273
 
238
274
  ## Architecture
239
275
 
240
- ```mermaid
241
- flowchart LR
242
- CLI["crewforge CLI<br/>review · ask · summarize · ingest<br/>scaffold · validate · write"] --> R
243
-
244
- subgraph R["Recipes (src/crewforge/recipes)"]
245
- RV[review]
246
- DC[docs]
247
- AP[api]
248
- CT[content]
249
- end
250
-
251
- R --> CREW
252
-
253
- subgraph CORE["Core (src/crewforge/core)"]
254
- CREW["Crew<br/>step() · parallel()<br/>names failed agents"]
255
- AG["Agent<br/>ask() · ask_json()<br/>rejects empty output"]
256
- PA["parsing<br/>tolerant JSON + schema"]
257
- CL["LLMClient<br/>stream=false · retries 429/5xx only"]
258
- US["UsageTracker<br/>provider-reported tokens"]
259
- CF["LLMConfig + provider presets<br/>keys from env only"]
260
- CREW --> AG
261
- AG --> PA
262
- AG --> CL
263
- AG --> US
264
- CL --> CF
265
- end
266
-
267
- CL -->|"/chat/completions"| P[("Any OpenAI-compatible provider")]
268
- ```
276
+ <p align="center"><img src="https://raw.githubusercontent.com/aimanmalib/crewforge/main/docs/architecture.png" alt="Architecture: the CLI dispatches to five recipes; each recipe builds a Crew of Agents on the shared core (parsing, LLMClient, LLMConfig, UsageTracker), which talks to any OpenAI-compatible provider over /chat/completions" width="100%"></p>
277
+
278
+ <sub>Source: [docs/architecture.mmd](https://github.com/aimanmalib/crewforge/blob/main/docs/architecture.mmd) (re-render with `scripts/render_architecture.py`).</sub>
269
279
 
270
280
  - **`core/client.py`** — one async client. It always sends `"stream": false`,
271
281
  retries only HTTP 429, 5xx and network/timeout errors (with capped exponential
@@ -317,7 +327,7 @@ Validation: INVALID · 0/100 (0 operation(s) checked, 1 error(s), 0 warning(s))
317
327
  ERROR: No endpoints defined (paths is empty)
318
328
  ```
319
329
 
320
- | Situation | Before (the four tools) | crewforge |
330
+ | Situation | Before (the earlier tools) | crewforge |
321
331
  |---|---|---|
322
332
  | Every reviewer returns nothing | "Review Complete!", exit 0 | exit 1, names each reviewer |
323
333
  | A reviewer answers in prose | treated as a review | exit 1, `agent 'style' (parse)` |
@@ -327,6 +337,9 @@ Validation: INVALID · 0/100 (0 operation(s) checked, 1 error(s), 0 warning(s))
327
337
  | Quality never reaches the threshold | article published | exit 1 unless `--accept-below-threshold` |
328
338
  | Question matches no passage | model asked to answer from nothing | exit 1, names `retriever`, no LLM call |
329
339
  | Generated code does not compile | template silently reused | exit 1, names the agent |
340
+ | Model proposes a reference with no DOI/URL/ISBN | hermes-mimo-writer put invented "plausible" references in the bibliography | labelled LIKELY FABRICATED, never verified |
341
+ | Formatter skips a reference you supplied | n/a | exit 1, names `formatter` |
342
+ | `disclose` finds no recorded AI use | n/a | exit 1, no statement written |
330
343
 
331
344
  Exit codes: `0` success · `1` run failed (agent, validator or provider) · `2`
332
345
  usage or configuration error (bad flag, unknown provider, missing key).
@@ -346,14 +359,15 @@ were carried over into this repository (see [docs/porting.md](https://github.com
346
359
  for what was ported, re-targeted at the shared core, or dropped and why).
347
360
 
348
361
  The evidence that it works is meant to be checkable: the test suite (run
349
- `pytest`; it needs no key and no network), CI on Python 3.10–3.13, and the
362
+ `pytest`; it needs no key and no network), CI on Python 3.10–3.14, and the
350
363
  real-provider runs shown above, two of which found bugs that were fixed with
351
364
  tests before the output was recorded.
352
365
 
353
366
  ## Contributing
354
367
 
355
- See [CONTRIBUTING.md](https://github.com/aimanmalib/crewforge/blob/main/CONTRIBUTING.md). In short: `pip install -e ".[dev,docs]"`,
356
- `pytest`, `ruff check . && ruff format --check .`, and every new failure path
368
+ See [CONTRIBUTING.md](https://github.com/aimanmalib/crewforge/blob/main/CONTRIBUTING.md). In short: `uv sync --extra dev --extra docs`
369
+ (versions from the committed `uv.lock`, as in CI), `uv run pytest`,
370
+ `uv run ruff check . && uv run ruff format --check .`, and every new failure path
357
371
  needs a test that fails if the guard is removed.
358
372
 
359
373
  ## Security
@@ -4,18 +4,36 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "crewforge"
7
- version = "0.1.0"
8
- description = "One crew of LLM agents, four recipes: code review, document Q&A, API scaffolding and content — on any OpenAI-compatible provider."
7
+ version = "0.2.1"
8
+ description = "One crew of LLM agents, five recipes: code review, document Q&A, API scaffolding, content and honest academic-writing help — on any OpenAI-compatible provider."
9
9
  readme = "README.md"
10
10
  license = "MIT"
11
11
  license-files = ["LICENSE"]
12
12
  requires-python = ">=3.10"
13
13
  authors = [{ name = "Muhammad Aiman" }]
14
- keywords = ["llm", "agents", "multi-agent", "openai", "code-review", "rag", "fastapi", "content-generation", "cli"]
14
+ keywords = [
15
+ "llm",
16
+ "agents",
17
+ "multi-agent",
18
+ "ai-agents",
19
+ "openai",
20
+ "openai-compatible",
21
+ "code-review",
22
+ "rag",
23
+ "document-qa",
24
+ "fastapi",
25
+ "api-scaffolding",
26
+ "content-generation",
27
+ "academic-writing",
28
+ "cli",
29
+ ]
15
30
  classifiers = [
16
31
  "Development Status :: 3 - Alpha",
17
32
  "Environment :: Console",
18
33
  "Intended Audience :: Developers",
34
+ "Intended Audience :: Education",
35
+ "Natural Language :: English",
36
+ "Natural Language :: Malay",
19
37
  "Operating System :: OS Independent",
20
38
  "Programming Language :: Python :: 3",
21
39
  "Programming Language :: Python :: 3 :: Only",
@@ -23,8 +41,12 @@ classifiers = [
23
41
  "Programming Language :: Python :: 3.11",
24
42
  "Programming Language :: Python :: 3.12",
25
43
  "Programming Language :: Python :: 3.13",
44
+ "Programming Language :: Python :: 3.14",
45
+ "Topic :: Education",
26
46
  "Topic :: Scientific/Engineering :: Artificial Intelligence",
47
+ "Topic :: Software Development :: Code Generators",
27
48
  "Topic :: Software Development :: Quality Assurance",
49
+ "Topic :: Text Processing :: General",
28
50
  "Typing :: Typed",
29
51
  ]
30
52
  dependencies = [
@@ -44,15 +66,19 @@ dev = [
44
66
  "pytest-asyncio>=0.23",
45
67
  "pytest-cov>=5.0",
46
68
  "ruff>=0.6",
69
+ "mypy>=1.10",
70
+ "types-PyYAML>=6.0",
47
71
  "fastapi>=0.110",
48
72
  "httpx>=0.27",
49
73
  ]
50
74
 
51
75
  [project.urls]
52
76
  Homepage = "https://github.com/aimanmalib/crewforge"
53
- Repository = "https://github.com/aimanmalib/crewforge"
54
- Issues = "https://github.com/aimanmalib/crewforge/issues"
77
+ Documentation = "https://github.com/aimanmalib/crewforge#readme"
55
78
  Changelog = "https://github.com/aimanmalib/crewforge/blob/main/CHANGELOG.md"
79
+ Issues = "https://github.com/aimanmalib/crewforge/issues"
80
+ Source = "https://github.com/aimanmalib/crewforge"
81
+ Security = "https://github.com/aimanmalib/crewforge/security/policy"
56
82
 
57
83
  [project.scripts]
58
84
  crewforge = "crewforge.cli:main"
@@ -61,7 +87,7 @@ crewforge = "crewforge.cli:main"
61
87
  where = ["src"]
62
88
 
63
89
  [tool.setuptools.package-data]
64
- crewforge = ["py.typed", "recipes/api/templates/*.j2"]
90
+ crewforge = ["py.typed", "recipes/api/templates/*.j2", "recipes/academic/locales/*.yaml"]
65
91
 
66
92
  [tool.pytest.ini_options]
67
93
  testpaths = ["tests"]
@@ -80,6 +106,22 @@ select = ["E", "F", "W", "I", "UP", "B"]
80
106
  [tool.ruff.lint.per-file-ignores]
81
107
  "tests/**" = ["B011"]
82
108
 
109
+ [tool.mypy]
110
+ # CI runs `mypy` (lint job). Bodies of unannotated functions are checked too.
111
+ files = ["src/crewforge"]
112
+ python_version = "3.10"
113
+ plugins = ["pydantic.mypy"]
114
+ check_untyped_defs = true
115
+ strict_equality = true
116
+ warn_redundant_casts = true
117
+ warn_unused_ignores = true
118
+ warn_unused_configs = true
119
+
120
+ [[tool.mypy.overrides]]
121
+ # Pre-1.24 PyMuPDF import name, used only as a fallback; it ships no type information.
122
+ module = ["fitz"]
123
+ ignore_missing_imports = true
124
+
83
125
  [tool.coverage.run]
84
126
  source = ["crewforge"]
85
127
  branch = true
@@ -0,0 +1,3 @@
1
+ """crewforge — one crew of LLM agents, five recipes, any OpenAI-compatible provider."""
2
+
3
+ __version__ = "0.2.1"