docs(readme): polish launch highlights and banner (#261)

* docs: simplify README launch highlights

* docs(readme): use six launch highlights

* docs(readme): use optimized banner asset

* ci: lint pull request titles
This commit is contained in:
Elliot Chen
2026-06-06 19:49:59 +08:00
committed by GitHub
parent 0a99922f24
commit 79b3df4de2
6 changed files with 173 additions and 62 deletions

View File

@ -13,6 +13,18 @@ concurrency:
cancel-in-progress: true
jobs:
title:
name: pull request title
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Validate Conventional Commit PR title
env:
PR_TITLE: ${{ github.event.pull_request.title }}
run: make check-pr-title
messages:
name: commit messages
runs-on: ubuntu-latest

View File

@ -1,4 +1,4 @@
.PHONY: help install install-deps lint docs-check check-commits check-assets check-deprecated-names check-cjk check-datetime openapi check-openapi format test integration package cov ci clean
.PHONY: help install install-deps lint docs-check check-commits check-pr-title check-assets check-deprecated-names check-cjk check-datetime openapi check-openapi format test integration package cov ci clean
help:
@echo "Targets:"
@ -7,6 +7,7 @@ help:
@echo " lint ruff + import-linter + repo hygiene + datetime discipline + openapi drift"
@echo " docs-check Validate Markdown links, use-case banners, and issue template YAML"
@echo " check-commits Validate Conventional Commit subjects for a git range"
@echo " check-pr-title Validate PR title uses Conventional Commit format"
@echo " check-assets Block committed images, videos, and asset/media directories"
@echo " check-deprecated-names Block deprecated product names"
@echo " check-cjk Scan for CJK outside the language-policy allowlist (advisory)"
@ -48,6 +49,9 @@ docs-check:
check-commits:
python3 scripts/check_commit_messages.py $(RANGE)
check-pr-title:
python3 scripts/check_pr_title.py
# Repository media hygiene gate. Images/videos belong in external hosting,
# release artifacts, or other approved storage, then linked from docs.
check-assets:

View File

@ -1,6 +1,6 @@
<div align="center" id="readme-top">
![EverOS banner](https://github.com/EverMind-AI/EverOS/releases/download/v1.0.0/everos-readme-banner.jpg)
![EverOS banner](https://github.com/EverMind-AI/EverOS/releases/download/v1.0.0/everos-readme-banner-optimized.jpg)
<p align="center">
<a href="https://x.com/evermind"><img src="https://img.shields.io/badge/EverMind-000000?labelColor=gray&style=for-the-badge&logo=x&logoColor=white" alt="X"></a>
@ -54,53 +54,36 @@
<table>
<tr>
<td width="33%" valign="top">
<strong>Markdown-First Memory</strong><br>
Memory is persisted as plain Markdown: visible, auditable, hand-editable,
Git-friendly, and owned by the user.
<strong>Markdown As Source Of Truth</strong><br>
All memory is persisted as <code>.md</code> files: readable, editable,
grep-able, Git-versioned, and openable directly in Obsidian.
</td>
<td width="33%" valign="top">
<strong>Lightweight Local Stack</strong><br>
Install with Python. SQLite tracks runtime state; LanceDB powers vector,
BM25, and scalar-filter retrieval locally.
<strong>Local Three-Part Stack</strong><br>
Markdown + SQLite + LanceDB keep vectors, BM25, and scalar filters
local. No MongoDB, Elasticsearch, or Redis required.
</td>
<td width="33%" valign="top">
<strong>Layered Memory Model</strong><br>
User memory and agent memory are first-class today. Wiki-style knowledge
is the next layer in the roadmap.
<strong>Dual-Track Memory</strong><br>
Agent memory (<code>cases</code> / <code>skills</code>) and user memory
(<code>episodes</code> / <code>profile</code>) are extracted independently.
</td>
</tr>
<tr>
<td width="33%" valign="top">
<strong>Self-Evolving Agents</strong><br>
Agent memory can extract reusable cases and skills from repeated
experience, so workflows become smarter over time.
</td>
<td width="33%" valign="top">
<strong>Multimodal Ingestion</strong><br>
Text, image, audio, documents, PDF, HTML, and email can be parsed into
memory through the optional multimodal pipeline.
Text, images, audio, documents, PDFs, HTML, and email are unified into
searchable memory.
</td>
<td width="33%" valign="top">
<strong>Online And Offline Strategy Control</strong><br>
Online extraction and offline evolution stay separate, with configurable
prompts and models at each step. Dreaming is coming next.
</td>
</tr>
<tr>
<td width="33%" valign="top">
<strong>Orthogonal Memory Scope</strong><br>
Owner, memory type, and scope are independent: search by user, agent,
app, project, session, and structured filters.
<strong>Self-Evolution</strong><br>
Common skills are extracted from real usage; repeated patterns become
reusable workflows, no retraining required.
</td>
<td width="33%" valign="top">
<strong>Progressive Disclosure</strong><br>
Readable memory surfaces stay simple while deeper facts, cases, and
skills remain available.
</td>
<td width="33%" valign="top">
<strong>Modular By Design</strong><br>
EverAlgo owns algorithms; EverOS owns runtime, persistence, online flows,
and offline evolution.
<strong>Orthogonal Retrieval</strong><br>
Search independently by <code>user_id</code>, <code>agent_id</code>,
<code>app_id</code>, <code>project_id</code>, and <code>session_id</code>.
</td>
</tr>
</table>

View File

@ -1,6 +1,6 @@
<div align="center" id="readme-top">
![EverOS banner](https://github.com/EverMind-AI/EverOS/releases/download/v1.0.0/everos-readme-banner.jpg)
![EverOS banner](https://github.com/EverMind-AI/EverOS/releases/download/v1.0.0/everos-readme-banner-optimized.jpg)
<p align="center">
<a href="https://x.com/evermind"><img src="https://img.shields.io/badge/EverMind-000000?labelColor=gray&style=for-the-badge&logo=x&logoColor=white" alt="X"></a>
@ -54,44 +54,30 @@
<table>
<tr>
<td width="33%" valign="top">
<strong>Markdown-First Memory</strong><br>
记忆以普通 Markdown 持久化:可、可审计、可手动编辑、Git 友好,并由用户自己拥有
<strong>Markdown As Source Of Truth</strong><br>
所有记忆持久化为 <code>.md</code> 文件:可、可改、可 grep、可 Git 版本化,也可直接用 Obsidian 打开
</td>
<td width="33%" valign="top">
<strong>Lightweight Local Stack</strong><br>
用 Python 即可安装。SQLite 负责运行时状态;LanceDB 在本地提供向量、BM25 和结构化过滤检索。
<strong>Local Three-Part Stack</strong><br>
Markdown + SQLite + LanceDB 在本地完成向量、BM25 和标量过滤检索,无需 MongoDB、Elasticsearch 或 Redis
</td>
<td width="33%" valign="top">
<strong>Layered Memory Model</strong><br>
用户记忆和 Agent 记忆现在是一等公民。Wiki 式知识层是路线图中的下一层
<strong>Dual-Track Memory</strong><br>
Agent 记忆<code>cases</code> / <code>skills</code>)与用户记忆(<code>episodes</code> / <code>profile</code>)独立提取,互不污染
</td>
</tr>
<tr>
<td width="33%" valign="top">
<strong>Self-Evolving Agents</strong><br>
Agent 记忆可以从重复经验中提取可复用的 cases 和 skills让工作流随着时间变得更聪明。
</td>
<td width="33%" valign="top">
<strong>Multimodal Ingestion</strong><br>
文本、图、音频、文档、PDF、HTML 和邮件都可以通过可选的多模态管线解析进记忆
文本、图、音频、文档、PDF、HTML 和邮件统一抽取为可检索的记忆形态
</td>
<td width="33%" valign="top">
<strong>Online And Offline Strategy Control</strong><br>
在线提取和离线进化保持分离,并且每一步都可以配置 prompts 和 models。Dreaming 即将到来
</td>
</tr>
<tr>
<td width="33%" valign="top">
<strong>Orthogonal Memory Scope</strong><br>
Owner、memory type 和 scope 相互独立:可以按 user、agent、app、project、session 和结构化 filters 搜索。
<strong>Self-Evolution</strong><br>
从真实使用经验中自动抽取共性 skills重复模式沉淀为可复用流程无需重训
</td>
<td width="33%" valign="top">
<strong>Progressive Disclosure</strong><br>
可读记忆界面保持简单,同时更深层的 facts、cases 和 skills 仍然可以被系统使用
</td>
<td width="33%" valign="top">
<strong>Modular By Design</strong><br>
EverAlgo 负责算法EverOS 负责运行时、持久化、在线流程和离线进化。
<strong>Orthogonal Retrieval</strong><br>
<code>user_id</code><code>agent_id</code><code>app_id</code><code>project_id</code><code>session_id</code> 五维独立检索
</td>
</tr>
</table>

70
scripts/check_pr_title.py Normal file
View File

@ -0,0 +1,70 @@
"""Validate pull request titles against the EverOS Conventional Commits policy."""
from __future__ import annotations
import importlib.util
import os
import sys
from pathlib import Path
from types import ModuleType
_SCRIPT_DIR = Path(__file__).resolve().parent
def _load_commit_policy() -> ModuleType:
policy_path = _SCRIPT_DIR / "check_commit_messages.py"
spec = importlib.util.spec_from_file_location("_commit_message_policy", policy_path)
if spec is None or spec.loader is None:
raise RuntimeError(f"Unable to load commit policy from {policy_path}")
module = importlib.util.module_from_spec(spec)
sys.modules[spec.name] = module
spec.loader.exec_module(module)
return module
_POLICY = _load_commit_policy()
ALLOWED_TYPES = _POLICY.ALLOWED_TYPES
MAX_TITLE_LENGTH = _POLICY.MAX_TITLE_LENGTH
TITLE_RE = _POLICY.TITLE_RE
def validate_title(title: str) -> list[str]:
title = title.strip()
if not title:
return ["missing PR title"]
if len(title) > MAX_TITLE_LENGTH:
return [f"PR title is {len(title)} chars; max is {MAX_TITLE_LENGTH}: {title}"]
if not TITLE_RE.match(title):
allowed = ", ".join(ALLOWED_TYPES)
return [
f"invalid PR title: {title}\n"
" expected: <type>[(scope)][!]: <description>\n"
f" allowed types: {allowed}"
]
return []
def _title_from_args_or_env(argv: list[str]) -> str:
if argv:
return " ".join(argv)
return os.getenv("PR_TITLE", "")
def main(argv: list[str] | None = None) -> int:
title = _title_from_args_or_env(sys.argv[1:] if argv is None else argv)
failures = validate_title(title)
if failures:
print("Pull request title check failed:")
print("\n".join(failures))
return 1
print("Pull request title follows Conventional Commits.")
return 0
if __name__ == "__main__":
raise SystemExit(main())

View File

@ -0,0 +1,56 @@
"""Self-tests for ``scripts/check_pr_title.py``."""
from __future__ import annotations
import importlib.util
import sys
from pathlib import Path
_REPO_ROOT = Path(__file__).resolve().parents[3]
_CHECKER_PATH = _REPO_ROOT / "scripts" / "check_pr_title.py"
def _load_checker():
assert _CHECKER_PATH.exists(), "PR title checker should exist"
spec = importlib.util.spec_from_file_location("_pr_title_checker", _CHECKER_PATH)
assert spec and spec.loader
mod = importlib.util.module_from_spec(spec)
sys.modules[spec.name] = mod
spec.loader.exec_module(mod)
return mod
def test_conventional_pr_title_is_allowed() -> None:
checker = _load_checker()
assert checker.validate_title("docs(readme): polish launch highlights") == []
def test_bracketed_codex_pr_title_is_blocked() -> None:
checker = _load_checker()
failures = checker.validate_title("[codex] simplify README launch highlights")
assert len(failures) == 1
assert "invalid PR title" in failures[0]
assert "expected: <type>[(scope)][!]: <description>" in failures[0]
def test_long_pr_title_is_blocked() -> None:
checker = _load_checker()
title = (
"docs(readme): polish launch highlights and banner with a title that is "
"too long"
)
failures = checker.validate_title(title)
assert len(failures) == 1
assert "max is 72" in failures[0]
def test_main_reads_pr_title_environment(monkeypatch) -> None:
checker = _load_checker()
monkeypatch.setenv("PR_TITLE", "docs(readme): polish launch highlights")
assert checker.main([]) == 0