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.
- {crewforge-0.1.0 → crewforge-0.2.1}/PKG-INFO +113 -41
- crewforge-0.1.0/src/crewforge.egg-info/PKG-INFO → crewforge-0.2.1/README.md +97 -83
- {crewforge-0.1.0 → crewforge-0.2.1}/pyproject.toml +48 -6
- crewforge-0.2.1/src/crewforge/__init__.py +3 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/cli.py +11 -3
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/core/config.py +1 -0
- crewforge-0.2.1/src/crewforge/recipes/__init__.py +1 -0
- crewforge-0.2.1/src/crewforge/recipes/academic/__init__.py +46 -0
- crewforge-0.2.1/src/crewforge/recipes/academic/agents.py +375 -0
- crewforge-0.2.1/src/crewforge/recipes/academic/citations.py +287 -0
- crewforge-0.2.1/src/crewforge/recipes/academic/cli.py +360 -0
- crewforge-0.2.1/src/crewforge/recipes/academic/disclosure.py +184 -0
- crewforge-0.2.1/src/crewforge/recipes/academic/language.py +87 -0
- crewforge-0.2.1/src/crewforge/recipes/academic/locales/en.yaml +122 -0
- crewforge-0.2.1/src/crewforge/recipes/academic/locales/ms.yaml +174 -0
- crewforge-0.2.1/src/crewforge/recipes/academic/pipeline.py +359 -0
- crewforge-0.2.1/src/crewforge/recipes/academic/report.py +247 -0
- crewforge-0.2.1/src/crewforge/recipes/academic/settings.py +46 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/api/agents.py +3 -1
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/docs/agents.py +6 -4
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/docs/ingest.py +2 -2
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/docs/pipeline.py +13 -7
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/review/agents.py +2 -2
- crewforge-0.1.0/README.md → crewforge-0.2.1/src/crewforge.egg-info/PKG-INFO +155 -36
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge.egg-info/SOURCES.txt +11 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge.egg-info/requires.txt +2 -0
- crewforge-0.1.0/src/crewforge/__init__.py +0 -3
- crewforge-0.1.0/src/crewforge/recipes/__init__.py +0 -1
- {crewforge-0.1.0 → crewforge-0.2.1}/LICENSE +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/setup.cfg +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/__main__.py +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/cli_support.py +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/core/__init__.py +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/core/agent.py +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/core/client.py +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/core/crew.py +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/core/errors.py +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/core/parsing.py +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/core/providers.py +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/core/usage.py +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/py.typed +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/api/__init__.py +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/api/analytics.py +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/api/appcheck.py +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/api/cli.py +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/api/formatters.py +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/api/generator.py +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/api/pipeline.py +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/api/scaffold.py +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/api/templates/docker-compose.j2 +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/api/templates/dockerfile.j2 +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/api/templates/env.example.j2 +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/api/templates/fastapi_main.j2 +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/api/templates/model.j2 +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/api/templates/requirements.j2 +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/api/templates/route.j2 +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/api/templates/test.j2 +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/api/utils.py +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/content/__init__.py +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/content/agents.py +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/content/cli.py +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/content/export.py +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/content/pipeline.py +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/content/settings.py +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/content/text.py +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/docs/__init__.py +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/docs/cli.py +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/docs/export.py +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/docs/index.py +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/docs/retrieve.py +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/docs/settings.py +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/review/__init__.py +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/review/cli.py +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/review/pipeline.py +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/review/report.py +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge/recipes/review/sources.py +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge.egg-info/dependency_links.txt +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge.egg-info/entry_points.txt +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/src/crewforge.egg-info/top_level.txt +0 -0
- {crewforge-0.1.0 → crewforge-0.2.1}/tests/test_honest_failure_e2e.py +0 -0
- {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
|
|
4
|
-
Summary: One crew of LLM agents,
|
|
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:
|
|
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
|
-
|
|
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,
|
|
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
|
[](https://github.com/aimanmalib/crewforge/actions/workflows/ci.yml)
|
|
53
|
-
](https://pypi.org/project/crewforge/)
|
|
65
|
+
[](https://scorecard.dev/viewer/?uri=github.com/aimanmalib/crewforge)
|
|
66
|
+

|
|
54
67
|

|
|
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,
|
|
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
|
-
|
|
241
|
-
|
|
242
|
-
|
|
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
|
|
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.
|
|
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: `
|
|
356
|
-
|
|
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,
|
|
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
|
[](https://github.com/aimanmalib/crewforge/actions/workflows/ci.yml)
|
|
53
|
-
](https://pypi.org/project/crewforge/)
|
|
7
|
+
[](https://scorecard.dev/viewer/?uri=github.com/aimanmalib/crewforge)
|
|
8
|
+

|
|
54
9
|

|
|
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,
|
|
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
|
-
|
|
241
|
-
|
|
242
|
-
|
|
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
|
|
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.
|
|
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: `
|
|
356
|
-
|
|
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
|
|
8
|
-
description = "One crew of LLM agents,
|
|
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 = [
|
|
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
|
-
|
|
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
|