@inixiative /配置
创新生态系统的共享工具链:tsconfig/biome/ tup预设,版本清单(BOM)和 sync/check 执行这两者的CLI。
预设
| 出口 | 使用 |
|---|---|
@inixiative/config/tsconfig/base.json | 包库(打包器解析,veratimmodulesyntax; types: ["bun"]) |
@inixiative/config/tsconfig/node.json | 基地+ types: ["node"] |
@inixiative/config/tsconfig/react.json | base + DOM lib + jsx: react-jsx |
@inixiative/config/biome/base.json | formatter + linter核心(单引号,lineWidth 100,建议+ strict块) |
@inixiative/config/biome/react.json | 覆盖:钩子依赖限制 |
@inixiative/config/tsup | node(options) / react(options) 建立预设 |
@inixiative/config/lefthook/base.yml | 预提交钩子:typecheck + biome上的分级文件 |
采用三个存根文件加上devDependency:
// tsconfig.json
{ "extends": "@inixiative/config/tsconfig/base.json", "exclude": ["dist"] }
// biome.json
{ "extends": ["@inixiative/config/biome/base.json"] }
// tsup.config.ts
import { node } from '@inixiative/config/tsup';
export default node();
存根保存 extends 加上最小的审查覆盖。这个包从不生成配置体。
版本。json (BOM)
一个版本的 @inixiative/config 列出一个连贯的生态系统状态:
bun-祝福运行时,写入.bun-version和packageManagertoolchain-精确引脚@biomejs/biome,typescript,tsup,@types/bunrequired-每个repo必须携带的工具链包ecosystem——原始人的幸福,相互印证@inixiative/*套装,再加上这个包裹agentic-代理lane的祝福集consumers-私有仓库遵循祝福集,但从未发布,由GitHub关键owner/repo:lanes说出每个人走过的小巷,upstream与之同步的回购candidates-发布比他们的祝福版本更新的车道版本,等待每个依赖的人采用它们(见train); 在不需要的时候缺席
"consumers": {
"inixiative/template": { "lanes": ["primitives"] },
"inixiative/kingdom": { "lanes": ["primitives", "agentic"], "upstream": "inixiative/template" },
"inixiative/oracle": { "lanes": ["agentic"] }
}
一条小路是一个释放的瀑布,有它自己的祝福。 primitives (json-rules, permissions, transitions, rules-builder, prisma-map, atlas, gloss)首先发布; agentic (signet→archive, agent-session→foundry-core→foundry→foundry-acp)建立在原语的祝福集上,而不是相反。 check 将每个回购保留到所有通道的并集,所以一个回购混合了这两种答案。
TypeScript 6.0注意事项,由这个repo的fixture套件发现:
- TS 6.0不再自动包含
node_modules/@types,所以base.json集合types: ["bun"]和@types/bun是必需的。 - tup的dts构建优于TS 6.0
baseUrl弃用;tsup预设范围ignoreDeprecations: "6.0"仅针对DTS构建。
命令行界面
bunx @inixiative/config check [dir] [--preset=base|node|react]
bunx @inixiative/config sync [dir] [--preset=...] [--force] [--no-install]
bunx @inixiative/config scan [root] [--lane=primitives|agentic]
bunx @inixiative/config train [root] [--lane=primitives|agentic] [--push] [--dry-run]
bunx @inixiative/config ports [project]
ports 打印每个项目的本地端口 ports.json (也输出为 @inixiative/config/ports.json). 服务的项目端口通常是服务的默认值加上项目块的100倍,这样就不会有两个项目发生冲突。Zealot单独位于block 0,默认值(Aron, 2026-10-20:它已经在那里运行了);所有其他项目都是默认的:Archive (block 7)在4700上提供HTTP, Postgres在6132上提供HTTP;王国(block 2)有web 3200, API 8200, Postgres 5632, Redis 6579。保留端口(5000和7000上的macOS AirPlay)从未分配。 给一个新项目下一个空闲块(永远不要为0),给一个新类型的服务默认值;在任何碰撞中测试都失败。
check 是只读的,并且在漂移时退出非零状态-在安装冻结锁定文件后在CI中运行它。它验证工具链pin——在根声明一次,准确地固定:工作区成员声明一个是错误的,并且 bun.lock 必须解析每个只到它的pin(没有第二个副本)-工具链对等范围(他们必须承认pin而不是旧的major; sync 写 >=<pin major>.<pin minor>.0), "latest" 范围, packageManager/.bun-version、遗留 bun.lockb提交的(跟踪的,不被忽略的) bun.lock,他被忽视了 tmp/ (抓空间; sync 增加了 /tmp/*,它可以跟踪重新包含的文件),所需的脚本(check/typecheck/lint/test),左撇(深+ lefthook.yml 扩展共享钩子+ prepare 脚本;仅Git repos)、存根 extends对于每个生态系统依赖项(在根或任何工作区成员中,任何一个通道),声明的范围允许祝福版本,并且lockfile实际上解析到它(stale-lockfile类)。具有候选对象的包也接受候选对象和介于两者之间的任何对象:允许任何一方通过的范围都可以通过,从指定的版本到候选对象的锁也可以通过。不允许祝福版本的范围将被重写为 ^<blessed>,除了一个精确的大头针,它保持精确并移动到被祝福的版本。一个npm别名("@inixiative/session-archive": "npm:@inixiative/archive@^0.2.1")保持其目标的祝福版本,并被重写为别名; workspace:, file: 和 link: range是一个自身链接的repo,不受影响。
sync 应用每个修复(删除成员工具链项及其失效的成员链接),通过重新锁定 bun install (--force 当第二个工具链副本存活时),并运行 bun update 在声明它们的目录中的陈旧生态系统条目上。它拒绝在脏树上运行,没有 --force. 反应预设是从 react 依赖;覆盖与 --preset. 缺失的脚本被默认值填充;不会触及现有的脚本体。
scan 运行 check 在根目录下检查每个生态系统,检查每个通道或只检查一个 --lane 的名字。目标是从BOM中派生出来的:通道包通过包名匹配——根包或任何工作区成员,所以像foundry这样的单线程包是通过它发布的包找到的——而消费者通过它们的 origin GitHub回购。目录名和本地布局不需要声明:scan查看根目录的每一个子目录和一个子目录 package.json (工作空间文件夹,例如 team-workspace/). 链接的git工作树是其他会话的分支,而不是目标;当几个克隆声明一个包或repo时,只有那些具有 origin 远程计数,直接在根目录下的克隆优于工作空间文件夹中嵌套的克隆,如果仍然留下多个目标,则报告目标不明确,而不是猜测。Origin是事实,而不是签出:扫描每个repo获取,在签出Origin后失败(他们的发现描述了一个陈旧的树),当BOM条目根本没有签出时失败,当签出位于非默认分支时发出警告(其发现描述了分支,而不是交付的内容),并且未合并 claude/* 会话分支。
train 是发布级联,从git签出这个repo运行;它拒绝从非副本(bunx或NPM缓存)进行训练。每台机器一次一列火车:它需要一个机器范围的锁, ~/.inixiative/train.lock,由每个克隆、工作树和车道共享,并且在另一列火车持有它时拒绝启动,并命名持有人和锁定路径。锁是自动创建的,并记录持有者的pid、主机名和进程启动时间。锁是过期的,当它的进程消失时,它的pid现在属于另一个进程,或者无法解析文件。来自另一个主机的锁永远不会被判断为过期;如果它的列车真的消失了,就删除这个文件。 锁在exit和SIGINT、SIGTERM或SIGHUP时被释放。 --dry-run 不需要锁。它按顺序遍历每个车道(原语,然后是代理),或者只遍历车道 --lane 的名字。Origin是事实:它拒绝从Origin后面的配置签出运行,并且在工作之前将干净的签出快速转发到Origin(脏的或分散的repos仍然跳过)。它只提供默认的分支:在一个特性分支上的签出被完全跳过——从不重新锁定、提交或发布。
车道是独立的。如果一个包裹缺少结帐,或者有不明确的结帐,则不会运行;如果一个lane自己的检查(下面不是针对候选项的检查)、commit或publish失败,那么它就会停止:它已经发布的内容仍然是候选项,并且它的候选项都不会运行。谁也挡不住另一条路。 在一个通道内,它会按照依赖顺序进行结账;每次签出,它会将生态系统范围提升到合适的候选集→重新锁定→运行repo check →只提交自己的更改(package.json 文件+ bun.lock)→按依赖顺序发布本地版本领先于npm的每个lane包,并等待注册中心为其提供服务(最多15分钟,因为npm会保留新版本进行处理)→将其记录为BOM中的候选包。
祝福是两阶段的,所以需要工作的依赖项永远不会使释放死锁:
- 候选人。 已出版的版本载于
candidates,并且配置释放结束列车承载它,所以check从那时起,任何回购的CI都接受它。 - 采用。 如果一个回购(lane checkout或consumer)对被移动到的候选对象的检查失败,则不会使列车停止。收银台被放回原来的位置,火车打开了
train/adopt-<pkg>-<version>在工作树中(repo自己的)worktree:create <base> <branch>当它声明一个时,基于模板的repo就会获得它所在槽的数据库,并与它一起发布worktree:destroy;否则为临时链接工作树;不管怎样,回购都被忽略了.env*文件复制在哪里丢失):相同的碰撞和重新锁定,然后回购的train:adopt脚本,如果它的包。json声明了一个(Foundry的重记录磁带)bun run test:live),全部提交,并重新锁定到新的配置版本,以便PR的CI对候选版本进行判断。采用的lane checkout在此运行中不发布任何内容。传递候选分支的消费者将获得相同的分支名称:在分支合并之前,其默认分支仍在以前的版本上。如果采纳的提交被拒绝(它的钩子类型检查),分支将被删除,摘要将指示手工采纳。 - 促进。 在每次运行结束时,候选对象将被祝福(移动到其车道的部分),除非有东西阻止它:它的车道停止;一个repo有一个尚未在其默认分支上的采用分支(在运行时打开,未合并,或提交但从未推送);或者一个声明这次运行没有走到结果的回购——另一个通道的签出,跳过或失败的签出,没有签出的消费者。 后来的一列火车发现了一个等待收养的分支机构,没有打开任何新的;一旦合并,回购就在候选对象上,列车就会推动它。每个依赖者都已经接受的候选人在发布它的运行中受到祝福。未合并而关闭的收养PR保留其候选对象,直到其分支被删除。
摘要列出了被祝福的内容,每个候选人持有的内容,以及每个等待采用的分支及其PR时间 gh 我能找到一个。
根包发布 npm publish;工作空间成员包含 bun pm pack,它改写了 workspace: 范围到要发布的版本,并且tarball被发布 npm publish,因此OTP提示可以通过任何一种方式传递。一个包已经在本地版本的npm上了,但既没有被祝福,也没有成为候选包——由人工发布,或者由后来车道故障的火车发布——在下一次运行时成为候选包。同样,一个 @inixiative/config 在NPM之前提交的版本(发布失败的版本)在下一次运行时发布,即使它没有添加任何新版本。
消费者跑一次,在每个选定的车道之后,首先逆流而上,对抗完整的祝福集:两条车道的消费者结束时与所跑的车道一致。它们得到相同的碰撞→重新锁定→ check,而不是发布,并且它们的更改要经过审查:列车将它们提交到 train/ecosystem-sync-<date> 分支,并将签出放回到其默认分支上。
列车永远不会在结帐时弄脏或离开默认的分支。它只在它发现干净的签出中起作用,因此签出失败的签出将重置为HEAD(跟踪和未跟踪的文件;忽略诸如node_modules和 .env 停留),然后从它的锁文件中重新安装。它创建的每个分支都在一个临时工作树中提交,在列车退出时删除。
当任何东西被记录或祝福时,它会最后发布这个包,所以BOM命名新状态:如果npm已经有当前的补丁版本,那么它会碰撞自己的补丁版本,在BOM中祝福那个版本,带来 test/fixtures 消费者上了福套,跑了 check提交、发布。然后,每次检出列车被重新锁定(lane包在其默认分支上,在其工作树中的消费者和采用分支上)都被重新锁定到新的分支上 @inixiative/config 并且已提交,因此没有任何东西会固定在之前的版本上。除非被要求,否则它从不推 --push 推动其承诺的每个回购,并为每个消费者和采用分支机构开设PR;否则,它将打印命令。 --dry-run 执行相同的计划并打印它将执行的每个步骤(范围重写、重新锁定和检查、提交、审查分支、发布、BOM祝福、推送),而不运行其中任何一个步骤;它只获取和读取git状态和 npm view.
每个命令只接受自己的标志。未知或放错位置的旗帜(--dryrun, --push 在 sync)是一个使用错误,并且在任何运行之前退出。
分工:这个CLI拥有工具链集、生态系统一致性、存根和lockfile格式。Renovate拥有其他所有东西,加上碰撞 @inixiative/config 本身,并且必须与工具链包隔离。
CI
每个lib repo都有一个两行调用者工作流:
name: ci
on:
push:
branches: [main]
pull_request:
jobs:
ci:
uses: inixiative/config/.github/workflows/lib-ci.yml@main
lib-ci.yml 别针发髻 .bun-version,安装 --frozen-lockfile (杀死stale-lockfile类),运行 inixiative-config check .然后是回购 bun run check.
发布流程
两个通道,每个通道按依赖顺序发布,最后一个是config:
- 原语 -例如json-rules→permissions→transitions→rules-builder,加上prisma-map、atlas和gloss。消费者:模板,王国。
- agentic - archive和agent-session,然后foundry-core→foundry (foundry依赖于archive),建立在原语的祝福集上。铸造厂核心和铸造厂发布从铸造厂的单
packages/core和packages/foundry. 消费者:oracle(私有叶),王国。
释放是 train (或 train --lane=agentic (不使用原语):将包的版本放在其默认分支上,然后运行列车。 train 自动化整个过程,这个包和消费者pr包括在内。下游回购通过获取工具链更改 sync.