From 74fae6394627d2658b04c46d7fdbc8d8fb857a1d Mon Sep 17 00:00:00 2001 From: Muhammad Aiman <84276911+aimanmalib@users.noreply.github.com> Date: Fri, 6 Nov 2026 22:54:31 +0000 Subject: [PATCH] docs: README in the shared project layout, add logo; release 0.2.2 Centred header with a project logo (brand/logo.svg, rendered to PNG by brand/jana-aset.py), a Bahasa Melayu summary after the English text, and absolute links and image URLs so the README also renders on PyPI. No code change; the patch release only updates the README shown on PyPI. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 10 ++++++ CITATION.cff | 2 +- README.md | 62 +++++++++++++++++++++++++++++++------- brand/jana-aset.py | 24 +++++++++++++++ brand/logo-512.png | Bin 0 -> 31157 bytes brand/logo-64.png | Bin 0 -> 2984 bytes brand/logo.svg | 24 +++++++++++++++ pyproject.toml | 2 +- src/crewforge/__init__.py | 2 +- uv.lock | 2 +- 10 files changed, 113 insertions(+), 15 deletions(-) create mode 100644 brand/jana-aset.py create mode 100644 brand/logo-512.png create mode 100644 brand/logo-64.png create mode 100644 brand/logo.svg diff --git a/CHANGELOG.md b/CHANGELOG.md index 6abcaa2..f4db4a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,15 @@ All notable changes to this project are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project uses [Semantic Versioning](https://semver.org/). +## [0.2.2] - 2026-11-06 + +Documentation only; no change to the code or to what the recipes do. + +### Changed +- README follows the layout shared by the author's other open-source projects: a centred header with a project logo + (`brand/logo.svg`, rendered to PNG by `brand/jana-aset.py`), a Bahasa Melayu summary after the English text, and + absolute links and image URLs so the page also renders on PyPI. + ## [0.2.1] - 2026-10-22 No change to what the recipes do; this release makes the package easier to trust and to install. @@ -78,6 +87,7 @@ First version: one framework replacing four separate tools ### Removed - apiforge's web dashboard and the illustrative token "stats"/daily estimates. +[0.2.2]: https://github.com/aimanmalib/crewforge/compare/v0.2.1...v0.2.2 [0.2.1]: https://github.com/aimanmalib/crewforge/compare/v0.2.0...v0.2.1 [0.2.0]: https://github.com/aimanmalib/crewforge/compare/v0.1.0...v0.2.0 [0.1.0]: https://github.com/aimanmalib/crewforge/releases/tag/v0.1.0 diff --git a/CITATION.cff b/CITATION.cff index 8f9dfc5..fd25fc0 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -5,7 +5,7 @@ type: software authors: - given-names: Muhammad family-names: Aiman -version: 0.2.1 +version: 0.2.2 license: MIT repository-code: "https://github.com/aimanmalib/crewforge" abstract: >- diff --git a/README.md b/README.md index 98230e3..28be7b8 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,18 @@ -# crewforge +

crewforge

-**One crew of LLM agents, five recipes: code review, document Q&A, API scaffolding, content and honest academic-writing help. It works with any OpenAI-compatible provider and fails loudly instead of pretending.** +

crewforge

-[![CI](https://github.com/aimanmalib/crewforge/actions/workflows/ci.yml/badge.svg)](https://github.com/aimanmalib/crewforge/actions/workflows/ci.yml) -[![PyPI](https://img.shields.io/pypi/v/crewforge)](https://pypi.org/project/crewforge/) -[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/aimanmalib/crewforge/badge)](https://scorecard.dev/viewer/?uri=github.com/aimanmalib/crewforge) -![Python 3.10–3.14](https://img.shields.io/badge/python-3.10%E2%80%933.14-blue) -![License: MIT](https://img.shields.io/badge/license-MIT-green) +

CI PyPI OpenSSF Scorecard Python 3.10–3.14 License: MIT

+ +

One crew of LLM agents, five recipes, any OpenAI-compatible provider. · Satu kru ejen LLM, lima resipi, mana-mana penyedia serasi OpenAI.
+PyPI · changelog · porting notes · Built in Malaysia by Aiman Malib

+ +crewforge is a command-line tool and Python library that runs a crew of LLM agents through five recipes: code +review, document Q&A, API scaffolding, content writing and honest academic-writing help. It works with any +OpenAI-compatible provider, reads API keys only from the environment, and fails loudly instead of pretending: a run +in which an agent produced nothing exits with code 1 and names that agent. + +[Bahasa Melayu ↓](#bahasa-melayu) ```bash crewforge review src/ # six reviewers + a summary @@ -377,13 +383,47 @@ Please report vulnerabilities privately through See [SECURITY.md](https://github.com/aimanmalib/crewforge/blob/main/SECURITY.md) for scope notes (what is sent to your provider, and what `validate` executes). -## License +## Bahasa Melayu + +crewforge ialah alat baris arahan dan pustaka Python yang menjalankan satu kru ejen LLM melalui lima resipi: +semakan kod (`review`), soal jawab dokumen (`ask`, `summarize`), penjanaan projek API FastAPI (`scaffold`, +`validate`), penulisan kandungan (`write`) dan bantuan penulisan akademik yang jujur (`academic`). Ia berfungsi +dengan mana-mana penyedia serasi OpenAI, termasuk model tempatan melalui Ollama atau llama.cpp. Kunci API hanya +dibaca dari pemboleh ubah persekitaran, tidak pernah ditulis ke fail. + +**Mengapa satu kru.** crewforge menggabungkan empat alat lama (codeguard, documind, apiforge, contentforge) yang +masing-masing menyimpan salinan sendiri bagi rangka yang sama. Salinan itu sudah berbeza dan setiap satu +menyembunyikan kegagalan dengan cara sendiri. Kini teras dikongsi: pembaikan dibuat sekali, dan setiap alat menjadi +resipi di atas teras itu. + +**Gagal dengan jelas.** Larian yang ejennya memulangkan jawapan kosong atau tidak boleh dihurai, atau pengesah +yang tidak menyemak apa-apa, keluar dengan kod 1 dan menamakan ejen itu. Kod keluar: `0` berjaya, `1` larian +gagal, `2` ralat penggunaan atau konfigurasi. Bilangan token diambil daripada laporan penyedia sahaja, tidak +dianggar. + +**Resipi `academic`.** Membantu pelajar dan penyelidik dengan kerja mereka **sendiri**: merancang dari taklimat +tugasan, memberi ulasan atas draf tanpa menulis semula, memformat rujukan yang diberi pengguna (APA 7, IEEE, +Harvard) tanpa menambah rujukan baharu, dan menulis pernyataan penggunaan AI daripada rekod langkah yang +dijalankan. Output dalam bahasa Inggeris atau Bahasa Melayu (`--language ms`); output BM disemak untuk bentuk +Indonesia seperti *karena* atau *kualitas*. Sumber yang dicadangkan model dilabel UNVERIFIED, atau LIKELY +FABRICATED jika tiada DOI, URL atau ISBN. Tiada ciri "humanise" atau mengelak pengesan AI. + +**Pasang dan guna.** + +```bash +pip install crewforge # Python 3.10 hingga 3.14 +pip install "crewforge[docs,api]" # pilihan: PDF/DOCX dan semakan aplikasi FastAPI +export OPENAI_API_KEY=sk-... # atau penyedia lain, lihat `crewforge providers` +crewforge review src/ +crewforge academic feedback draf.md --brief taklimat.md --language ms +``` -[MIT](https://github.com/aimanmalib/crewforge/blob/main/LICENSE) © Muhammad Aiman +Senarai penyedia, contoh setiap resipi dan seni bina ada dalam bahagian bahasa Inggeris di atas +([Providers](https://github.com/aimanmalib/crewforge#providers), [Recipes](https://github.com/aimanmalib/crewforge#recipes)). ---- +## Licence -Built by [Sasa Teguh](https://sasateguh.com) · Malaysia +[MIT](https://github.com/aimanmalib/crewforge/blob/main/LICENSE) © Muhammad Aiman. Made by [Aiman Malib](https://aimanmalib.com), Malaysia. ## Work with Sasa Teguh diff --git a/brand/jana-aset.py b/brand/jana-aset.py new file mode 100644 index 0000000..b8553ca --- /dev/null +++ b/brand/jana-aset.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 +"""Render brand/logo.svg to brand/logo-512.png and brand/logo-64.png with Chromium (Playwright). + + uv run --with playwright==1.58.0 python3 brand/jana-aset.py + +Same script as sasateguh/codr and sasateguh/mypii. The PNGs are committed because the README is also +shown on PyPI, and not every renderer there draws an SVG with gradients reliably. +""" + +import os + +from playwright.sync_api import sync_playwright + +HERE = os.path.dirname(os.path.abspath(__file__)) +with open(os.path.join(HERE, "logo.svg"), encoding="utf-8") as f: + svg = f.read() +with sync_playwright() as p: + b = p.chromium.launch() + for size in (512, 64): + pg = b.new_page(viewport={"width": size, "height": size}, device_scale_factor=1) + inner = svg.replace('width="256" height="256"', f'width="{size}" height="{size}"') + pg.set_content(f'{inner}') + pg.screenshot(path=os.path.join(HERE, f"logo-{size}.png"), omit_background=True) + b.close() diff --git a/brand/logo-512.png b/brand/logo-512.png new file mode 100644 index 0000000000000000000000000000000000000000..89f63285e041d418457402480e46e9e8038cd563 GIT binary patch literal 31157 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 Hv*7;+`8~>2 literal 0 HcmV?d00001 diff --git a/brand/logo-64.png b/brand/logo-64.png new file mode 100644 index 0000000000000000000000000000000000000000..04bf5ebbe1bf6fe172e905e35860b94a3aa863b6 GIT binary patch literal 2984 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 e21!IgR09B^r8_on4)7!Z0000 + crewforge + + + + + + + + + + + + + + + + + + + + + + diff --git a/pyproject.toml b/pyproject.toml index f1f68ad..30ca010 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "crewforge" -version = "0.2.1" +version = "0.2.2" 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." readme = "README.md" license = "MIT" diff --git a/src/crewforge/__init__.py b/src/crewforge/__init__.py index 6119fb9..3560360 100644 --- a/src/crewforge/__init__.py +++ b/src/crewforge/__init__.py @@ -1,3 +1,3 @@ """crewforge — one crew of LLM agents, five recipes, any OpenAI-compatible provider.""" -__version__ = "0.2.1" +__version__ = "0.2.2" diff --git a/uv.lock b/uv.lock index 57aa7d1..a949222 100644 --- a/uv.lock +++ b/uv.lock @@ -275,7 +275,7 @@ toml = [ [[package]] name = "crewforge" -version = "0.2.1" +version = "0.2.2" source = { editable = "." } dependencies = [ { name = "click" },