Doramagic 项目包 · 项目说明书

grainulation 项目

grainulation 生态系统:为 AI 智能体提供结构化研究、决策制定与知识管理能力。

项目概览与生态地图

Grainulation 是一个面向"决策可信化"场景的开源工具集,它把"问题 → 证据 → 决策"这条链路产品化为可编译、可审计的工作流。根据 README.md 的描述,项目的核心信条是:大多数决策失败并不是因为数据匮乏,而是因为缺少把数据升格为证据、把证据升格为共识的流程。其 README 自述的使命是 "turn questions into evidence an...

章节 相关页面

继续阅读本节完整说明和来源证据。

一、项目定位与核心目标

Grainulation 是一个面向"决策可信化"场景的开源工具集,它把"问题 → 证据 → 决策"这条链路产品化为可编译、可审计的工作流。根据 README.md 的描述,项目的核心信条是:*大多数决策失败并不是因为数据匮乏,而是因为缺少把数据升格为证据、把证据升格为共识的流程*。其 README 自述的使命是 *"turn questions into evidence and evidence into conviction"*。

落地的具体形态是八个零依赖的 CLI 工具组成的小型生态(参见 site/llms.txt)。每个工具都只做一件事,单独可运行,组合后可串联起"研究 → 编译 → 评审 → 导出 → 复盘"的完整闭环。package.json 明确指出本仓库是 umbre 包,仅保留 @grainulation/barn 这一个运行时依赖 资料来源:[package.json:1-50],这印证了"零依赖"在工程层面的承诺。

整套体系的工程基线是 Node.js 20+ 内建能力优先,engines.node = ">=20" 资料来源:[package.json:1-50],MIT 协议公开分发到 npm。

二、生态地图:八个工具的角色分工

生态地图是理解本项目的关键。下表梳理了 lib/ecosystem.js 中登记的工具元数据,并参照 site/llms.txt 中的姊妹包说明做了交叉验证。

工具角色类别端口一句话职责
barn共享工具库foundation速写检测、清单生成、HTML/PDF 模板、MCP 崩溃处理
wheat研究引擎research9091类型化声明(typed claim)与七轮编译器(7-pass compiler)
farmer权限代理research9092为自治智能体提供人机审批的 SSE 仪表盘
mill导出引擎output9094将编译后的研究转成 PDF、幻灯片与 Wiki
silo知识库storage9095跨速写复用经过验证的声明
harvest数据分析analytics9096多速写组合的校准、速率与证据分布看板
orchard编排层orchestration9097多速写协同、并行子任务调度
grainulation统一 CLI 入口meta聚合上述工具并提供 doctor / setup 诊断

资料来源:[lib/ecosystem.js:1-100] 与 site/llms.txt 共同登记了以上条目。值得注意的是,wheat 是通常的入门入口(npx @grainulation/wheat init),而 grainulation 自身只承担"路由 + 健康检查"的元角色——这与 README.md 中的 quickstart 段落 grainulation doctor / grainulation setup 形成自洽。

为了直观呈现用户在生态中的导航路径,下图给出一张简化的工具选择流程图:

flowchart LR
  A[提出技术问题] --> B{是否需要<br/>AI 代理审批?}
  B -- 是 --> F[farmer]
  B -- 否 --> C[wheat<br/>声明 + 七轮编译]
  C --> D{需要复用<br/>历史声明?}
  D -- 是 --> S[silo]
  D -- 否 --> E[mill<br/>导出 PDF / 简报]
  E --> H[harvest<br/>跨速写复盘]
  C -. 多速写并行 .-> O[orchard]

三、仓库结构与架构原则

CONTRIBUTING.md 公开了仓库的核心目录约定,强调这是一份"无 npm install 即可运行"的纯 Node 项目 资料来源:[CONTRIBUTING.md:1-60]。关键模块包括:

架构上有一条很明确的指导原则——*the key architectural principle*——即"由路由器串联,每个工具自己负责一个职责,不相互内嵌" 资料来源:[CONTRIBUTING.md:1-60]。这种松耦合的 monorepo 风格让用户可以按需引入工具,而不会被迫拖入多余的运行时。

站点层面同样贯彻了"零样式重复"的设计:所有生态站点共享 grainulation-tokens.css(设计令牌)与 grainulation-print.css(打印样式),并由 barn 统一通过 barn sync-assets 同步到各站点 资料来源:[site/grainulation-tokens.css:1-40]、site/grainulation-print.css:1-40]。这种"样式集中、主题按 data-tool 切换"的做法与生态的工具化思路一脉相承。

四、安全加固与版本演进

社区证据显示,安全主题在 1.1.0 版本中获得了显式加强。v1.1.0 发布说明披露了三条关键变更 资料来源:[CHANGELOG.md:1-60]:

  1. Shell 注入防护——所有 spawn() 调用统一改用 shell: falseexecSync 被替换为基于参数数组的 execFileSync,覆盖 npm listlsof 调用。
  2. CSP 元标签——落地页增加 Content Security Policy 头,约束脚本与资源来源。
  3. .gitignore 加固——新增 .claude/,避免本地工作目录污染版本库。

随后 v1.1.3 作为自动化发布版本继续推进 资料来源:[CHANGELOG.md:1-60]。从工程实践角度看,这意味着 grainulation 在把"安全默认"作为生态的硬约束——即便只是元包,也以 spawn 边界、CSP 与 gitignore 三道防线兜底。

五、失败模式与上手注意

根据 README.mdCONTRIBUTING.md 的共同提示,使用者应注意以下常见踩坑点:

  • Node 版本不足package.json 强制要求 >=20,否则 lib/server.mjs 内的 ESM 与 fetch 用法可能异常 资料来源:[package.json:1-50]。
  • 依赖误解:生态看起来庞大,但本仓库只通过 @grainulation/barn 引入运行时代码;其余工具以 npx 形式按需拉取,提前 npm install 反而是反模式。
  • 站点样式覆盖:任何对打印或主题令牌的修改都应回写到 barn,而不是在子站点里 fork CSS,否则下一次 barn sync-assets 会将其覆盖 资料来源:[site/grainulation-tokens.css:1-40]。

See Also

  • 小麦 Wheat:研究编译器与七轮编译
  • Barn:共享工具库与同步资产
  • Farmer:权限代理与 SSE 审批
  • 安全策略与发布流程

来源:https://github.com/grainulation/grainulation / 项目说明书

CLI 入口与命令路由

grainulation 是整个 grainulation 生态系统的「总入口」与「路由器」——它本身不实现研究/证据/决策等核心业务,而是把用户敲入的命令解析后分派给 8 个独立的小工具(wheat、farmer、barn、mill、silo、harvest、orchard,以及作为元包自身的 @grainulation/grainulation)。README.md 把...

章节 相关页面

继续阅读本节完整说明和来源证据。

概览与设计目标

grainulation 是整个 grainulation 生态系统的「总入口」与「路由器」——它本身不实现研究/证据/决策等核心业务,而是把用户敲入的命令解析后分派给 8 个独立的小工具(wheat、farmer、barn、mill、silo、harvest、orchard,以及作为元包自身的 @grainulation/grainulation)。README.md 把它定位为「Unified ecosystem CLI aggregating all grainulation tools」README.md

设计上遵循三条原则:

  1. 零依赖(除 barn 外)package.json 中只有 "@grainulation/barn": "^1.3.0" 一条依赖,且 engines.node 限定为 >=20,配合 packageManager: [email protected] 锁定工具链版本 package.json
  2. 直跑可执行bin 字段声明 "grainulation": "bin/grainulation.js",用户 npm install -g 后即可全局调用 package.json
  3. 逐字转发:对子工具的调用基本是「透传 + 注入 npm 包名」,避免在元包里重新实现子工具的语义 CONTRIBUTING.md

目录与模块结构

CONTRIBUTING.md 给出了清晰的模块清单,路由层位于 lib/,执行入口在 bin/,展示层在 public/site/ CONTRIBUTING.md

模块角色
bin/grainulation.jsCLI 入口进程,解析 argv
lib/router.js命令路由表,把 <tool> <cmd> 翻译成 npx <pkg> <cmd>
lib/ecosystem.js工具注册表(8 个工具的元数据)
lib/doctor.js健康检查(版本、路径、依赖)
lib/setup.js首次运行的角色配置
lib/pm.js工具的包管理(安装/更新/卸载)
lib/server.mjs本地仪表盘服务(ESM)
public/生态概览 Web UI
site/grainulation.com 公开站点源码
test/Node 内置测试运行器用例

命令路由机制

CLI 把所有用户输入收敛成两类:无子命令时进入「生态概览」展示;有子命令时按以下顺序匹配 README.md

下面的数据流展示了「入口 → 路由 → 子工具」的串接关系:

graph TD
    A[用户输入<br/>grainulation ...] --> B[bin/grainulation.js<br/>argv 解析]
    B --> C{lib/router.js<br/>命令分派}
    C -->|无子命令| D[生态概览]
    C -->|doctor| E[lib/doctor.js]
    C -->|setup| F[lib/setup.js]
    C -->|&lt;tool&gt;| G[lib/ecosystem.js<br/>查表]
    G --> H[npx @grainulation/wheat]
    G --> I[npx @grainulation/farmer]
    G --> J[npx @grainulation/mill]
    G --> K[npx @grainulation/silo]
    G --> L[npx @grainulation/harvest]
    G --> M[npx @grainulation/orchard]
    G --> N[npx @grainulation/barn]
    E --> O[lib/pm.js<br/>版本校验]
    F --> P[lib/pm.js<br/>按角色安装]

lib/ecosystem.js 中的 TOOLS 数组是这张路由表的唯一事实来源;每个条目至少包含 namepackageiconroledescriptioncategoryportserveCmdentryPoint 等字段 lib/ecosystem.js。其中 entryPoint: true 标记启动入口(wheat),其余工具通过 serveCmd: ['serve']['start'] 拉起 lib/ecosystem.js

安全硬化与依赖约束

v1.1.0 发布说明把「Shell injection prevention」列为头条 CHANGELOG.md:所有 spawn() 调用统一改用 shell: falseexecSync 被替换为 execFileSync,对 npm listlsof 等命令显式传入参数数组。这是路由/包管理链路在 v1.1.0 之后必须遵循的约束——任何新增的子命令分派都要避免字符串拼接到 shell。

版本层面,CHANGELOG 还记录了 v1.0.0 起的「Unified ecosystem CLI」「Tool aggregation dashboard」「Cross-tool health checks」「Sprint overview across all tools」与「Global controls for ecosystem-wide operations」等首批能力 CHANGELOG.md。最新的 v1.1.3 为自动化发布 CHANGELOG.md。对终端用户而言,路由层在 v1.1.3 仍以 lib/ecosystem.js 注册表为权威来源,新增工具只需在该数组追加即可被自动识别 lib/ecosystem.js

常见失效模式

  • 子工具未安装router 透传 npx @grainulation/<tool> 时依赖 npm 临时拉取;若离线环境会失败,应先 grainulation setup README.md
  • 端口冲突:8 个工具分别占用 9090–9097 端口 lib/ecosystem.js;同时启动多个 serve 时需关注宿主端口占用。
  • Node 版本不匹配engines.node >= 20 是硬约束 package.json;低于 20 会因 ESM/内置 API 差异报错。
  • shell 注入回归:自定义 fork 路由逻辑时若重新拼接字符串到 spawn,会破坏 v1.1.0 的安全契约 CHANGELOG.md

See Also

来源:https://github.com/grainulation/grainulation / 项目说明书

工具注册表与本地服务器

grainulation 仓库本身是一个生态路由器(ecosystem router),而非一个单体应用。其核心由两大部分组成:定义所有子工具元数据的「工具注册表」,以及在本地端口上托管统一仪表板的「本地服务器」。整体定位可概括为"轻路由、零依赖、本地优先"。

章节 相关页面

继续阅读本节完整说明和来源证据。

概述

grainulation 仓库本身是一个生态路由器(ecosystem router),而非一个单体应用。其核心由两大部分组成:定义所有子工具元数据的「工具注册表」,以及在本地端口上托管统一仪表板的「本地服务器」。整体定位可概括为"轻路由、零依赖、本地优先"。

关键架构原则:grainulation is a thin router, not a monolith. It delegates to individual tool packages (wheat, barn, farmer, etc.) and provides ecosystem-level concerns: discovery, health checks, scaffolding. —— CONTRIBUTING.md

依赖声明见 package.jsondependencies 字段仅声明了 @grainulation/barn 一个共享工具库,engines.node 要求 >=20,采用 ESM 模块系统(type: module)。

工具注册表结构

lib/ecosystem.js 是工具注册表的实际定义位置。它以数组形式维护了八个工具条目,每个条目包含以下字段(从源码片段归纳):

字段含义示例值
nameCLI 短名wheat / mill / silo / harvest / orchard
packagenpm 包作用域名@grainulation/mill
icon单字母视觉标识M / S / H / O
role一句话角色描述Processes output
description详细功能说明Export and publish. Turn compiled research into PDFs, slides, wikis.
category工具分类research / output / storage / analytics / orchestration
port本地服务器端口9094 / 9095 / 9096 / 9097
serveCmd启动子进程命令['serve']
entryPoint是否为默认入口true / false
资料来源:lib/ecosystem.js:1-90

注册表条目示例(节选自源码):

{
  name: 'mill',
  package: '@grainulation/mill',
  icon: 'M',
  role: 'Processes output',
  description: 'Export and publish. Turn compiled research into PDFs, slides, wikis.',
  category: 'output',
  port: 9094,
  serveCmd: ['serve'],
  entryPoint: false,
}

category 字段把工具分成五大职能域:research(研究)、output(输出)、storage(存储)、analytics(分析)、orchestration(编排)。这一分类在 site/llms.txt 中得到进一步阐释,每个兄弟包都对应一个具体类别。

本地服务器架构

lib/server.mjs 是本地服务器入口,负责托管「统一生态仪表板」(unified ecosystem dashboard)。该文件在 CONTRIBUTING.md 的架构图中有显式列出:

lib/server.mjs            Local server -- unified ecosystem dashboard (ESM)
public/                   Web UI -- ecosystem overview and status

服务器与注册表之间通过端口号耦合:每个非入口工具都分配了独立的 serveCmd 启动方式与固定 port(如 mill=9094、silo=9095、harvest=9096、orchard=9097)。这种设计允许父进程(grainulation 仪表板)通过 HTTP 探测各子工具的存活状态并聚合展示。

graph LR
  A[用户 CLI<br/>grainulation] --> B[bin/grainulation.js]
  B --> C[lib/router.js<br/>命令路由]
  B --> D[lib/doctor.js<br/>健康检查]
  B --> E[lib/server.mjs<br/>本地仪表板]
  E -->|HTTP :9094| F[mill]
  E -->|HTTP :9095| G[silo]
  E -->|HTTP :9096| H[harvest]
  E -->|HTTP :9097| I[orchard]
  D -->|execFileSync npm list| J[npm 注册表]
  D -->|execFileSync lsof| K[本地端口占用]

健康检查、命令路由与安全加固

命令路由层lib/router.js 实现:当用户执行 grainulation <tool> <subcommand> 时,路由器将调用委派给相应的子包(README.md 中的 grainulation wheat initgrainulation farmer start 即典型用法)。

健康检查层lib/doctor.js 提供。grainulation doctor 命令会执行下列诊断动作:

  • 调用 npm list 校验哪些 @grainulation/* 包已安装;
  • 调用 lsof 探测注册表声明的端口是否被占用;
  • 输出每个工具的版本与运行状态。

首次安装lib/setup.js 完成。grainulation setup 命令会根据用户角色安装对应子工具。lib/pm.js(包管理)则承担生态范围内包的安装/卸载。

安全加固在 v1.1.0 引入,对本地服务器与诊断流程均有影响。社区发布说明(v1.1.0 — Security Hardening)明确指出:

  • 所有 spawn() 调用改为 shell: false,防止 Shell 注入;
  • execSync 替换为 execFileSync 并使用参数数组(针对 npm listlsof 调用);
  • 着陆页加入 CSP meta 标签,限制浏览器内嵌脚本来源;
  • .gitignore 增加 .claude/ 条目。

这些修复直接影响 lib/doctor.js(子进程调用入口)与 site/index.html(仪表板前端),因此读者在升级到 v1.1.0 之后,CI 流水线与本地诊断行为可能与旧版略有差异。

资料来源:CHANGELOG.mdv1.1.0 Release Notes

常见失败模式

现象可能根因建议排查入口
grainulation doctor 报告某工具缺失兄弟包未通过 npm 安装运行 grainulation setupnpm i -g @grainulation/<name>
端口 9094-9097 冲突其他进程占用doctor 内部使用 lsof 检测,可在终端手动 lsof -i :9094 复现
grainulation wheat init 报 "command not found"路由器无法解析子命令检查 lib/router.jslib/ecosystem.jsentryPoint 字段是否一致
仪表板加载空白CSP 阻拦内嵌脚本升级到 ≥ v1.1.0 修复后的 site/index.html

参见

来源:https://github.com/grainulation/grainulation / 项目说明书

进程管理与健康诊断

grainulation 是整个研究工具生态的元包入口。围绕进程管理与健康诊断,仓库由一组职责清晰的 Node.js 内置模块组成,共同保证生态中八个工具能被路由、启动、版本校验与状态报告。bin/grainulation.js 是统一入口,lib/router.js 负责命令分发,lib/pm.js、lib/doctor.js 与 lib/ecosystem.js 则承担...

章节 相关页面

继续阅读本节完整说明和来源证据。

概览

grainulation 是整个研究工具生态的元包入口。围绕进程管理健康诊断,仓库由一组职责清晰的 Node.js 内置模块组成,共同保证生态中八个工具能被路由、启动、版本校验与状态报告。bin/grainulation.js 是统一入口,lib/router.js 负责命令分发,lib/pm.jslib/doctor.jslib/ecosystem.js 则承担实际的进程协调与诊断职责。整个仓库保持极简依赖,仅在 package.json 中声明一个直接依赖 @grainulation/barn,并以 engines.node: ">=20" 锁定运行时。资料来源:CONTRIBUTING.md, package.json

健康诊断(`doctor`)架构

grainulation doctor 是面向用户的主要诊断命令。README.md 将其描述为"Health check: which tools, which versions"。其典型工作流可拆解为:

  1. 读取 lib/ecosystem.js 中静态声明的元数据(端口 9093/9094/9095/9096/9097 与对应的 @grainulation/* 包名),枚举出整个生态的工具列表。
  2. 调用子进程执行 npm listlsof 等外部命令,核对包是否已安装、端口是否被占用。
  3. 将结果按工具聚合,向用户报告缺失、过时或端口冲突的工具。

CHANGELOG.md 明确指出:doctor 子进程调用现已加入超时控制,以避免在 Node 22 上挂起 CI。这意味着 lib/doctor.js 历史上曾因 npm list / lsof 在某些环境下不退出而拖垮流水线。该修复属于 v1.1.x 之后的安全与稳定性维护工作。资料来源:CHANGELOG.md, README.md

子进程调用的安全硬化

社区发布说明 v1.1.0 记录了一次系统性的安全硬化,直接关系到进程管理:

  • 所有 spawn() 调用改用 shell: false,关闭 shell 元字符解释路径。
  • 原本的 execSync 全部替换为 execFileSync,并以参数数组形式传入,避免命令字符串拼接。
  • 受影响的命令包括 npm listlsof,这正是 lib/doctor.js 健康诊断依赖的核心外部工具。

硬化后的调用形态等价于:

execFileSync('npm',  ['list', '-g', '--depth=0'], { shell: false, timeout: 30000 });
execFileSync('lsof', ['-i', ':9093'],             { shell: false, timeout: 30000 });

这种形式阻断了诸如包名注入、端口号注入等典型攻击面。同时,超时参数也保障了 doctor 在 CI 上的可预测性。资料来源:CHANGELOG.md, v1.1.0 发布说明

工具发现与版本协调

lib/ecosystem.js 是整个诊断体系的"事实来源",它静态声明了生态中每个工具的元数据(name、package、icon、role、port、serveCmd、category 等)。doctor 读取该清单用于健康检查,pm 依据该清单执行安装,二者共用同一份"事实",避免出现"装了但查不到"或"查到但没装"的不一致状态。资料来源:lib/ecosystem.js

包管理接口(`pm.js`)

lib/pm.js 负责 grainulation 工具的安装与升级,它是 grainulation setup 命令的后端。README.md 中的快速上手示例 grainulation setup 即委托给该模块:按用户角色拉取对应的工具集合。该模块同样遵循 v1.1.0 的安全约束,安装过程避免对网络包管理器进行字符串注入。资料来源:CONTRIBUTING.md, README.md

进程调用流程图

flowchart LR
  User[用户 CLI] --> Bin[bin/grainulation.js]
  Bin --> Router[lib/router.js]
  Router --> Doctor[lib/doctor.js]
  Router --> Pm[lib/pm.js]
  Router --> Eco[lib/ecosystem.js]
  Doctor -- execFileSync shell=false + timeout --> Npm[外部命令 npm list]
  Doctor -- execFileSync shell=false + timeout --> Lsof[外部命令 lsof]
  Eco -- 元数据 --> Doctor
  Eco -- 元数据 --> Pm

常见故障模式

  • CI 在 Node 22 上挂起:通常是 doctor 中的子进程未设超时,升级到 v1.1.3 之后即可。
  • 健康检查报告"工具缺失":通常因为 npm list -g 范围不匹配,需确认安装是全局还是项目级(pnpm 工作区下尤为常见,见 package.jsonpackageManager: [email protected] 字段)。
  • 端口冲突:lsof 报告会指出占用 port 字段所声明端口的进程,可结合 PID 终止。

See Also

来源:https://github.com/grainulation/grainulation / 项目说明书

失败模式与踩坑日记

保留 Doramagic 在发现、验证和编译中沉淀的项目专属风险,不把社区讨论只当作装饰信息。

medium 能力判断依赖假设

假设不成立时,用户拿不到承诺的能力。

medium 维护活跃度未知

新项目、停更项目和活跃项目会被混在一起,推荐信任度下降。

medium 存在评分风险

风险会影响是否适合普通用户安装。

low issue/PR 响应质量未知

用户无法判断遇到问题后是否有人维护。

Pitfall Log / 踩坑日志

项目:grainulation/grainulation

摘要:发现 6 个潜在踩坑项,其中 0 个为 high/blocking;最高优先级:能力坑 - 能力判断依赖假设。

1. 能力坑 · 能力判断依赖假设

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:README/documentation is current enough for a first validation pass.
  • 对用户的影响:假设不成立时,用户拿不到承诺的能力。
  • 证据:capability.assumptions | https://github.com/grainulation/grainulation | README/documentation is current enough for a first validation pass.

2. 维护坑 · 维护活跃度未知

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:未记录 last_activity_observed。
  • 对用户的影响:新项目、停更项目和活跃项目会被混在一起,推荐信任度下降。
  • 证据:evidence.maintainer_signals | https://github.com/grainulation/grainulation | last_activity_observed missing
  • 严重度:medium
  • 证据强度:source_linked
  • 发现:no_demo
  • 证据:downstream_validation.risk_items | https://github.com/grainulation/grainulation | no_demo; severity=medium

4. 安全/权限坑 · 存在评分风险

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:no_demo
  • 对用户的影响:风险会影响是否适合普通用户安装。
  • 证据:risks.scoring_risks | https://github.com/grainulation/grainulation | no_demo; severity=medium

5. 维护坑 · issue/PR 响应质量未知

  • 严重度:low
  • 证据强度:source_linked
  • 发现:issue_or_pr_quality=unknown。
  • 对用户的影响:用户无法判断遇到问题后是否有人维护。
  • 证据:evidence.maintainer_signals | https://github.com/grainulation/grainulation | issue_or_pr_quality=unknown

6. 维护坑 · 发布节奏不明确

  • 严重度:low
  • 证据强度:source_linked
  • 发现:release_recency=unknown。
  • 对用户的影响:安装命令和文档可能落后于代码,用户踩坑概率升高。
  • 证据:evidence.maintainer_signals | https://github.com/grainulation/grainulation | release_recency=unknown

来源:Doramagic 发现、验证与编译记录