@rosenfan/matrix 0.1.1 → 0.1.2

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.
Files changed (37) hide show
  1. package/.claude/skills/matrix/SKILL.md +62 -21
  2. package/.claude/skills/matrix/agents/openai.yaml +4 -4
  3. package/.claude/skills/matrix/scripts/matrix_claude.py +11 -166
  4. package/.claude/skills/matrix/scripts/matrix_state.py +60 -114
  5. package/.claude/skills/matrix-archive/SKILL.md +33 -26
  6. package/.claude/skills/matrix-build/SKILL.md +26 -39
  7. package/.claude/skills/matrix-claude/SKILL.md +22 -22
  8. package/.claude/skills/matrix-design/SKILL.md +28 -29
  9. package/.claude/skills/matrix-hotfix/SKILL.md +8 -8
  10. package/.claude/skills/matrix-open/SKILL.md +17 -20
  11. package/.claude/skills/matrix-status/SKILL.md +4 -3
  12. package/.claude/skills/matrix-tweak/SKILL.md +8 -8
  13. package/.claude/skills/matrix-verify/SKILL.md +18 -29
  14. package/LICENSE +21 -21
  15. package/README.md +255 -242
  16. package/README.zh-CN.md +254 -242
  17. package/assets/skills-zh-CN/matrix/SKILL.md +57 -5
  18. package/assets/skills-zh-CN/matrix-archive/SKILL.md +23 -2
  19. package/assets/skills-zh-CN/matrix-build/SKILL.md +26 -2
  20. package/assets/skills-zh-CN/matrix-claude/SKILL.md +12 -11
  21. package/assets/skills-zh-CN/matrix-design/SKILL.md +16 -11
  22. package/assets/skills-zh-CN/matrix-hotfix/SKILL.md +8 -8
  23. package/assets/skills-zh-CN/matrix-open/SKILL.md +16 -11
  24. package/assets/skills-zh-CN/matrix-status/SKILL.md +12 -11
  25. package/assets/skills-zh-CN/matrix-tweak/SKILL.md +8 -8
  26. package/assets/skills-zh-CN/matrix-verify/SKILL.md +22 -8
  27. package/bin/matrix.js +15 -15
  28. package/package.json +56 -56
  29. package/src/catalog.js +85 -80
  30. package/src/cli.js +116 -111
  31. package/src/distribution.js +216 -152
  32. package/src/installer.js +45 -45
  33. package/src/matt.js +45 -45
  34. package/src/messages.js +33 -33
  35. package/src/ui.js +89 -89
  36. package/src/workflow-transaction.js +622 -0
  37. package/src/workflow.js +547 -74
@@ -1,11 +1,35 @@
1
1
  ---
2
2
  name: matrix-build
3
- description: 用测试优先的纵向切片实现冻结的 Matrix 计划。
3
+ description: 用测试优先的纵向切片实现冻结的 Matrix 计划。仅在活动 Matrix 阶段为 build 时使用。
4
4
  ---
5
5
 
6
6
  # Matrix Build
7
7
 
8
- 只实现冻结计划中的范围。使用 `implement` 与预先确认的 `tdd` 测试边界;持续记录 `artifacts/verification.md` 的 `## Build evidence`。如发现范围或设计变化,返回设计阶段。
8
+ 读取 `matrix workflow inspect`、`plan.md`、`design.md`、已批准 Contract 与仓库指令,只实现冻结范围。
9
+
10
+ ## 编排
11
+
12
+ - **Prim**:使用 Matrix 自身实现与测试能力。
13
+ - **Arch**:可测试行为变化时调用 `tdd`;真实失败且根因未知时调用 `diagnosing-bugs`;仅在进行中的 merge/rebase 冲突时调用 `resolving-merge-conflicts`。
14
+
15
+ 调用前说明能力与原因。companion 不得 commit、review、transition、archive 或扩大范围。正确安装的能力失败时最多执行一次同能力 Matrix fallback,并记录调用、失败、fallback 与证据;安装完整性问题必须停止并修复。
16
+
17
+ ## 范围纪律
18
+
19
+ 若实现暴露范围或设计变化,停止并执行:
20
+
21
+ ```powershell
22
+ matrix workflow return design --reason design-gap
23
+ ```
24
+
25
+ 回到 Design 会清除既有 Contract 批准并轮换当前验证证据;重新进入 Build 必须生成新的批准与新证据。
26
+
27
+ ## 流程
28
+
29
+ 1. 用 `tdd` 以纵向切片实现。
30
+ 2. 在 `artifacts/verification.md` 的 `## Build evidence` 记录具体命令和结果。
31
+ 3. 运行 Build guard;它同时确认批准的 Contract 仍精确匹配。
32
+ 4. 通过后推进至 Verify,并进入 `$matrix-verify`。
9
33
 
10
34
  ```powershell
11
35
  matrix workflow guard build
@@ -1,30 +1,31 @@
1
1
  ---
2
2
  name: matrix-claude
3
- description: 将冻结的 Matrix 设计导出为受边界约束的 Claude Code 任务包,不改变 Matrix 工作流状态。
3
+ description: 将已批准的 Matrix Contract 导出为受边界约束的 Claude Code 任务包,不改变 Matrix 工作流状态。
4
4
  ---
5
5
 
6
6
  # Matrix Claude Handoff
7
7
 
8
- 这是可选的旁路操作,而不是 Matrix phase。它不得执行 `transition`、`archive`,也不得写入 `matrix.yaml`、`run-state.json` 或 `events.jsonl`。
8
+ 这是可选旁路,不是 Matrix phase。它不得执行 `transition`、`archive`,也不得写入 `matrix.yaml` 或 `events.jsonl`。
9
9
 
10
- 仅当设计阶段守卫已通过,并且用户明确选择由 Claude Code 实现时使用。先检查:
10
+ 仅当变更已进入 Build、`design -> build` 已批准精确 Contract,并且用户明确选择 Claude Code 实现时使用。先检查:
11
11
 
12
12
  ```powershell
13
- matrix workflow guard design
13
+ matrix workflow guard build
14
14
  ```
15
15
 
16
- 如果主命令确实不在 PATH 中,才使用已安装根 Matrix Skill 中的 bundled runtime;主命令已启动但返回业务错误时不得回退。
17
-
18
- 导出通用任务包:
16
+ 若结果为 `CONTRACT_CHANGED`、`CONTRACT_UNAPPROVED` 或 `CONTRACT_READ_FAILED`,回到 `$matrix-design`,修订后重新进入 Build 取得新批准。导出只读取批准快照中的 `proposal.md`、`design.md` 与 `plan.md`。
19
17
 
20
18
  ```powershell
19
+ # 通用项目:只导出 Matrix 产物
21
20
  matrix workflow export --task-id <ID> --target generic
21
+
22
+ # FnSec:仅在 active.md 含有 NO_ACTIVE_OBJECTIVE 时更新看板
23
+ matrix workflow export --task-id <ID> --target fnsec --apply-fnsec-board
22
24
  ```
23
25
 
24
- 导出 FnSec 任务包时,只有在 `docs/tasks/active.md` 包含 `NO_ACTIVE_OBJECTIVE` 时才可使用 `--apply-fnsec-board`;现有任务绝不覆盖:
26
+ 任务包包含批准的 Contract hash 与 revision,以及同一快照的 proposal、design、plan。导出本身不改变 Build 阶段;Claude 完成后,补齐 `## Build evidence`,然后继续:
25
27
 
26
28
  ```powershell
27
- matrix workflow export --task-id <ID> --target fnsec --apply-fnsec-board
29
+ matrix workflow guard build
30
+ matrix workflow transition verify
28
31
  ```
29
-
30
- 任务包会包含冻结的 proposal、design、plan,以及 Claude Code 回执所需的改动、验证、边界确认和 `NEEDS_DECISION` 项目。
@@ -1,13 +1,18 @@
1
- ---
2
- name: matrix-design
3
- description: 在实现前设计并冻结活动 Matrix 变更。
4
- ---
1
+ ---
2
+ name: matrix-design
3
+ description: 在实现前设计并冻结活动 Matrix 变更。
4
+ ---
5
+
6
+ # Matrix Design
7
+
8
+ 读取 `matrix workflow inspect`、proposal 与冻结 `orchestration`,写入 `design.md`(`## Decisions`、`## Boundaries`、`## Test seams`、`## Risks`)与 `plan.md`(`## Steps`、`## Validation`、`## Stop conditions`)。
5
9
 
6
- # Matrix Design
10
+ - **Prim**:使用 Matrix 自身能力调查并设计。
11
+ - **Arch**:仅按事实触发 `domain-modeling`、`research`、`wayfinder`、`prototype`、`codebase-design`,不得机械执行固定序列。每次调用前说明能力与原因。
7
12
 
8
- 阅读 proposal,写入 `design.md`(`## Decisions`、`## Boundaries`、`## Test seams`、`## Risks`)与 `plan.md`(`## Steps`、`## Validation`、`## Stop conditions`)。重大范围或架构决策须先由用户确认。
9
-
10
- ```powershell
11
- matrix workflow guard design
12
- matrix workflow transition build
13
- ```
13
+ 长期有效的领域、ADR 或研究产物遵循仓库约定,关键结论必须同步进入 Matrix design/plan。prototype 默认写入系统临时目录。companion 不得拥有 Matrix 状态或创建竞争计划。重大范围或架构决策须先由用户确认。
14
+
15
+ ```powershell
16
+ matrix workflow guard design
17
+ matrix workflow transition build
18
+ ```
@@ -1,8 +1,8 @@
1
- ---
2
- name: matrix-hotfix
3
- description: 为可复现的小型缺陷运行受约束的 Matrix 工作流。
4
- ---
5
-
6
- # Matrix Hotfix
7
-
8
- 从 `$matrix` 以 `hotfix` 工作流启动。使用 `diagnosing-bugs` 建立可复现的红色反馈循环;如果问题影响架构、公开 API、数据模式或多模块协调,要求升级为完整工作流。
1
+ ---
2
+ name: matrix-hotfix
3
+ description: 为可复现的小型缺陷运行受约束的 Matrix 工作流。
4
+ ---
5
+
6
+ # Matrix Hotfix
7
+
8
+ 从 `$matrix` 以 `hotfix` 工作流启动并保持冻结的 Prim/Arch 编排。Prim 自行诊断;Arch 仅在真实失败存在且根因未知时调用 `diagnosing-bugs`。companion 输出必须回到 Matrix 产物与状态。若问题影响架构、公开 API、数据模式或多模块协调,受控 Return 后升级为完整工作流。
@@ -1,13 +1,18 @@
1
- ---
2
- name: matrix-open
3
- description: 将开发请求澄清为有证据的 Matrix 提案。
4
- ---
1
+ ---
2
+ name: matrix-open
3
+ description: 将开发请求澄清为有证据的 Matrix 提案。
4
+ ---
5
+
6
+ # Matrix Open
7
+
8
+ 读取 `matrix workflow inspect` 的活动变更与冻结 `orchestration`;写入 `artifacts/proposal.md`,必须包含 `## Goal`、`## Scope`、`## Non-goals`、`## Acceptance`、`## Risks`。
5
9
 
6
- # Matrix Open
10
+ - **Prim**:使用 Matrix 自身能力澄清并编写提案。
11
+ - **Arch**:仅在存在重大歧义或用户要求压力测试时调用 `grilling`;仅在领域词汇、不变量或架构决定不清晰时调用 `domain-modeling`。调用前说明能力与原因。
7
12
 
8
- 读取 `matrix workflow inspect` 的活动变更。使用 `grill-with-docs` 澄清完整工作流请求;写入 `artifacts/proposal.md`,必须包含 `## Goal`、`## Scope`、`## Non-goals`、`## Acceptance`、`## Risks`。
9
-
10
- ```powershell
11
- matrix workflow guard open
12
- matrix workflow transition design
13
- ```
13
+ companion 输出只能作为当前 proposal 的证据,不得创建第二套工作流、提案、确认状态或阶段转换。正确安装的能力失败时最多执行一次同能力 Matrix fallback;安装完整性问题必须修复。
14
+
15
+ ```powershell
16
+ matrix workflow guard open
17
+ matrix workflow transition design
18
+ ```
@@ -1,14 +1,15 @@
1
- ---
2
- name: matrix-status
3
- description: 检查活动 Matrix 工作流的磁盘状态、守卫与恢复命令。
4
- ---
5
-
6
- # Matrix Status
7
-
8
- 执行:
9
-
10
- ```powershell
1
+ ---
2
+ name: matrix-status
3
+ description: 检查活动 Matrix 工作流的磁盘状态、守卫与恢复命令。
4
+ ---
5
+
6
+ # Matrix Status
7
+
8
+ 执行:
9
+
10
+ ```powershell
11
11
  matrix workflow inspect
12
+ matrix workflow doctor
12
13
  ```
13
14
 
14
- 报告变更 ID、工作流、阶段、守卫结果和 `next_skill`;不得修改状态。
15
+ 报告变更 ID、工作流、冻结 `orchestration`、阶段、守卫结果、`next_skill`、Workflow health、未完成 transaction、可用策略和精确恢复命令。Arch 完整性失败时列出平台/Skill 事实并报告 `matrix init --with-mattpocock`,不得把 change 解释为 Prim。两条命令都只读;不得推断恢复策略、运行 `--repair` 或修改状态。
@@ -1,8 +1,8 @@
1
- ---
2
- name: matrix-tweak
3
- description: 为边界清晰的小改动运行轻量 Matrix 工作流。
4
- ---
5
-
6
- # Matrix Tweak
7
-
8
- 从 `$matrix` 以 `tweak` 工作流启动。保持提案和设计简洁,但仍定义验收条件与测试边界。若涉及 API、模式、架构或跨模块协调,升级为完整工作流。
1
+ ---
2
+ name: matrix-tweak
3
+ description: 为边界清晰的小改动运行轻量 Matrix 工作流。
4
+ ---
5
+
6
+ # Matrix Tweak
7
+
8
+ 从 `$matrix` 以 `tweak` 工作流启动并保持冻结的 Prim/Arch 编排。保持提案和设计简洁,但仍定义验收条件与测试边界。Arch 只调用满足正常事实触发条件的能力,轻量流程不会获得固定 companion 序列或更弱的证据要求。若涉及 API、模式、架构或跨模块协调,受控 Return 后升级为完整工作流。
@@ -1,13 +1,27 @@
1
- ---
2
- name: matrix-verify
3
- description: 依据计划验证 Matrix 变更并审查差异。
4
- ---
1
+ ---
2
+ name: matrix-verify
3
+ description: 依据计划验证 Matrix 变更并审查差异。
4
+ ---
5
+
6
+ # Matrix Verify
7
+
8
+ 运行计划的验证命令,在 `verification.md` 写入 `## Test evidence`。读取冻结 `orchestration`:
5
9
 
6
- # Matrix Verify
10
+ - **Prim**:Matrix 自行完成 Standards 与 Spec 双轴审查。
11
+ - **Arch**:调用 `code-review` 产生双轴证据,并说明调用原因。
7
12
 
8
- 运行计划的验证命令,在 `verification.md` 写入 `## Test evidence`。使用 `code-review` 完成标准与规格双轴审查,并在 `## Review evidence` 记录结论。失败时回到产生问题的阶段。
13
+ 审查结果只是 Matrix Verify 的输入;companion 不得决定阶段结果、扩大已批准架构、推进或归档。不得调用事后架构改进 wrapper。正确安装的审查能力失败时最多执行一次同能力 Matrix fallback;安装完整性问题必须停止。
14
+
15
+ 失败时使用受控 Return:
9
16
 
10
17
  ```powershell
11
- matrix workflow guard verify
12
- matrix workflow transition archive
18
+ matrix workflow return build --reason verification-failed
19
+ matrix workflow return design --reason acceptance-or-design-gap
13
20
  ```
21
+
22
+ Return 会轮换旧 `verification.md`;不得把旧结论直接复制为新的当前证据。
23
+
24
+ ```powershell
25
+ matrix workflow guard verify
26
+ matrix workflow transition archive
27
+ ```
package/bin/matrix.js CHANGED
@@ -1,15 +1,15 @@
1
- #!/usr/bin/env node
2
-
3
- import { main } from "../src/cli.js";
4
-
5
- main(process.argv.slice(2)).then((exitCode) => {
6
- if (Number.isInteger(exitCode) && exitCode !== 0) process.exitCode = exitCode;
7
- }).catch((error) => {
8
- if (error.code === "CANCELLED") {
9
- console.log("\nCancelled.");
10
- process.exitCode = 0;
11
- } else {
12
- console.error(`\nMatrix error: ${error.message}`);
13
- process.exitCode = 1;
14
- }
15
- });
1
+ #!/usr/bin/env node
2
+
3
+ import { main } from "../src/cli.js";
4
+
5
+ main(process.argv.slice(2)).then((exitCode) => {
6
+ if (Number.isInteger(exitCode) && exitCode !== 0) process.exitCode = exitCode;
7
+ }).catch((error) => {
8
+ if (error.code === "CANCELLED") {
9
+ console.log("\nCancelled.");
10
+ process.exitCode = 0;
11
+ } else {
12
+ console.error(`\nMatrix error: ${error.message}`);
13
+ process.exitCode = 1;
14
+ }
15
+ });
package/package.json CHANGED
@@ -1,56 +1,56 @@
1
- {
2
- "name": "@rosenfan/matrix",
3
- "version": "0.1.1",
4
- "description": "Install and manage the Matrix workflow for Matt Pocock's agent skills.",
5
- "license": "MIT",
6
- "type": "module",
7
- "bin": {
8
- "matrix": "bin/matrix.js"
9
- },
10
- "files": [
11
- "bin/",
12
- "src/",
13
- "assets/skills-zh-CN",
14
- ".claude/skills/matrix",
15
- ".claude/skills/matrix-open",
16
- ".claude/skills/matrix-design",
17
- ".claude/skills/matrix-build",
18
- ".claude/skills/matrix-verify",
19
- ".claude/skills/matrix-archive",
20
- ".claude/skills/matrix-hotfix",
21
- ".claude/skills/matrix-tweak",
22
- ".claude/skills/matrix-status",
23
- ".claude/skills/matrix-claude",
24
- "!.claude/skills/**/__pycache__",
25
- "!.claude/skills/**/scripts/test_*.py",
26
- "README.md",
27
- "README.zh-CN.md",
28
- "LICENSE"
29
- ],
30
- "scripts": {
31
- "test": "node --test",
32
- "pack:check": "npm pack --dry-run",
33
- "prepublishOnly": "npm run test && npm run pack:check"
34
- },
35
- "engines": {
36
- "node": ">=18"
37
- },
38
- "repository": {
39
- "type": "git",
40
- "url": "git+https://github.com/Rosenfan/Matrix.git"
41
- },
42
- "bugs": {
43
- "url": "https://github.com/Rosenfan/Matrix/issues"
44
- },
45
- "homepage": "https://github.com/Rosenfan/Matrix#readme",
46
- "publishConfig": {
47
- "access": "public"
48
- },
49
- "keywords": [
50
- "claude-code",
51
- "agent-skills",
52
- "workflow",
53
- "tdd",
54
- "ai"
55
- ]
56
- }
1
+ {
2
+ "name": "@rosenfan/matrix",
3
+ "version": "0.1.2",
4
+ "description": "Evidence-driven development workflow with Prim and Arch agent-skill orchestration.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "bin": {
8
+ "matrix": "bin/matrix.js"
9
+ },
10
+ "files": [
11
+ "bin/",
12
+ "src/",
13
+ "assets/skills-zh-CN",
14
+ ".claude/skills/matrix",
15
+ ".claude/skills/matrix-open",
16
+ ".claude/skills/matrix-design",
17
+ ".claude/skills/matrix-build",
18
+ ".claude/skills/matrix-verify",
19
+ ".claude/skills/matrix-archive",
20
+ ".claude/skills/matrix-hotfix",
21
+ ".claude/skills/matrix-tweak",
22
+ ".claude/skills/matrix-status",
23
+ ".claude/skills/matrix-claude",
24
+ "!.claude/skills/**/__pycache__",
25
+ "!.claude/skills/**/scripts/test_*.py",
26
+ "README.md",
27
+ "README.zh-CN.md",
28
+ "LICENSE"
29
+ ],
30
+ "scripts": {
31
+ "test": "node --test",
32
+ "pack:check": "npm pack --dry-run",
33
+ "prepublishOnly": "npm run test && npm run pack:check"
34
+ },
35
+ "engines": {
36
+ "node": ">=18"
37
+ },
38
+ "repository": {
39
+ "type": "git",
40
+ "url": "git+https://github.com/Rosenfan/Matrix.git"
41
+ },
42
+ "bugs": {
43
+ "url": "https://github.com/Rosenfan/Matrix/issues"
44
+ },
45
+ "homepage": "https://github.com/Rosenfan/Matrix#readme",
46
+ "publishConfig": {
47
+ "access": "public"
48
+ },
49
+ "keywords": [
50
+ "claude-code",
51
+ "agent-skills",
52
+ "workflow",
53
+ "tdd",
54
+ "ai"
55
+ ]
56
+ }
package/src/catalog.js CHANGED
@@ -1,87 +1,92 @@
1
- import crypto from "node:crypto";
2
- import fs from "node:fs";
3
- import os from "node:os";
4
- import path from "node:path";
5
- import { fileURLToPath } from "node:url";
6
-
7
- export const LANGUAGE_IDS = ["en", "zh-CN"];
8
- export const PLATFORM_IDS = ["claude-code", "codex"];
9
- export const MATRIX_SKILLS = [
10
- "matrix", "matrix-open", "matrix-design", "matrix-build", "matrix-verify",
11
- "matrix-archive", "matrix-hotfix", "matrix-tweak", "matrix-status", "matrix-claude"
12
- ];
1
+ import crypto from "node:crypto";
2
+ import fs from "node:fs";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+
7
+ export const LANGUAGE_IDS = ["en", "zh-CN"];
8
+ export const PLATFORM_IDS = ["claude-code", "codex"];
9
+ export const MATRIX_SKILLS = [
10
+ "matrix", "matrix-open", "matrix-design", "matrix-build", "matrix-verify",
11
+ "matrix-archive", "matrix-hotfix", "matrix-tweak", "matrix-status", "matrix-claude"
12
+ ];
13
13
  export const MATT_SKILLS = [
14
- "grill-with-docs", "grilling", "domain-modeling", "research", "wayfinder", "prototype",
15
- "codebase-design", "implement", "tdd", "code-review", "diagnosing-bugs",
16
- "resolving-merge-conflicts", "improve-codebase-architecture"
14
+ "grilling", "domain-modeling", "research", "wayfinder", "prototype",
15
+ "codebase-design", "tdd", "diagnosing-bugs", "resolving-merge-conflicts", "code-review"
17
16
  ];
18
-
19
- const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
20
- const packageManifest = JSON.parse(fs.readFileSync(path.join(packageRoot, "package.json"), "utf8"));
21
-
22
- export const PLATFORMS = {
23
- "claude-code": {
24
- id: "claude-code", name: "Claude Code", skillsCliAgent: "claude-code",
25
- skillRoot(base) { return path.join(base, ".claude", "skills"); },
26
- legacyRoots() { return []; }
27
- },
28
- codex: {
29
- id: "codex", name: "Codex", skillsCliAgent: "codex",
30
- skillRoot(base) { return path.join(base, ".agents", "skills"); },
31
- legacyRoots(base) { return [path.join(base, ".codex", "skills")]; }
32
- }
33
- };
34
-
35
- export function sourceSkillsRoot(language = "en") {
36
- const localized = language === "zh-CN"
37
- ? path.join(packageRoot, "assets", "skills-zh-CN")
38
- : path.join(packageRoot, ".claude", "skills");
39
- if (!fs.existsSync(localized)) throw new Error(`Matrix package is incomplete: ${language} assets are missing.`);
40
- return localized;
41
- }
42
-
43
- export function scopeBase(scope, projectRoot, home = os.homedir()) {
44
- return scope === "global" ? home : projectRoot;
45
- }
46
-
47
- export function installationRoot(scope, projectRoot, home) {
48
- return path.join(scopeBase(scope, projectRoot, home), ".matrix");
49
- }
50
-
51
- export function manifestPath(scope, projectRoot, home) {
52
- return path.join(installationRoot(scope, projectRoot, home), "installation.json");
53
- }
54
-
55
- export function hashDirectory(directory, extraFiles = []) {
56
- const hash = crypto.createHash("sha256");
57
- const files = new Map();
58
- const visit = (current, relative = "") => {
59
- for (const entry of fs.readdirSync(current, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
60
- const child = path.join(current, entry.name);
61
- const childRelative = path.join(relative, entry.name).replaceAll("\\", "/");
62
- if (entry.isDirectory()) visit(child, childRelative);
63
- else if (entry.isFile()) {
64
- files.set(childRelative, fs.readFileSync(child));
65
- }
66
- }
67
- };
68
- visit(directory);
69
- for (const extra of extraFiles) files.set(extra.path, Buffer.from(extra.contents));
70
- for (const [relative, contents] of [...files.entries()].sort(([left], [right]) => left.localeCompare(right))) {
71
- hash.update(`${relative}\0`);
72
- hash.update(contents);
73
- }
74
- return hash.digest("hex");
75
- }
76
-
17
+ export const UNMANAGED_MATT_SKILLS = ["grill-with-docs", "implement", "improve-codebase-architecture"];
18
+
19
+ const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
20
+ const packageManifest = JSON.parse(fs.readFileSync(path.join(packageRoot, "package.json"), "utf8"));
21
+
22
+ export const PLATFORMS = {
23
+ "claude-code": {
24
+ id: "claude-code", name: "Claude Code", skillsCliAgent: "claude-code",
25
+ skillRoot(base) { return path.join(base, ".claude", "skills"); },
26
+ legacyRoots() { return []; }
27
+ },
28
+ codex: {
29
+ id: "codex", name: "Codex", skillsCliAgent: "codex",
30
+ skillRoot(base) { return path.join(base, ".agents", "skills"); },
31
+ legacyRoots(base) { return [path.join(base, ".codex", "skills")]; }
32
+ }
33
+ };
34
+
35
+ export function sourceSkillsRoot(language = "en") {
36
+ const localized = language === "zh-CN"
37
+ ? path.join(packageRoot, "assets", "skills-zh-CN")
38
+ : path.join(packageRoot, ".claude", "skills");
39
+ if (!fs.existsSync(localized)) throw new Error(`Matrix package is incomplete: ${language} assets are missing.`);
40
+ return localized;
41
+ }
42
+
43
+ export function scopeBase(scope, projectRoot, home = os.homedir()) {
44
+ return scope === "global" ? home : projectRoot;
45
+ }
46
+
47
+ export function installationRoot(scope, projectRoot, home) {
48
+ return path.join(scopeBase(scope, projectRoot, home), ".matrix");
49
+ }
50
+
51
+ export function manifestPath(scope, projectRoot, home) {
52
+ return path.join(installationRoot(scope, projectRoot, home), "installation.json");
53
+ }
54
+
55
+ export function hashDirectory(directory, extraFiles = []) {
56
+ const hash = crypto.createHash("sha256");
57
+ const files = new Map();
58
+ const visit = (current, relative = "") => {
59
+ for (const entry of fs.readdirSync(current, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
60
+ const child = path.join(current, entry.name);
61
+ const childRelative = path.join(relative, entry.name).replaceAll("\\", "/");
62
+ if (entry.isDirectory()) visit(child, childRelative);
63
+ else if (entry.isFile()) {
64
+ files.set(childRelative, fs.readFileSync(child));
65
+ }
66
+ }
67
+ };
68
+ visit(directory);
69
+ for (const extra of extraFiles) files.set(extra.path, Buffer.from(extra.contents));
70
+ for (const [relative, contents] of [...files.entries()].sort(([left], [right]) => left.localeCompare(right))) {
71
+ hash.update(`${relative}\0`);
72
+ hash.update(contents);
73
+ }
74
+ return hash.digest("hex");
75
+ }
76
+
77
77
  export function workflowRuntimeSource() { return path.join(packageRoot, "src", "workflow.js"); }
78
-
79
- export function releaseCatalog(language = "en") {
80
- if (!LANGUAGE_IDS.includes(language)) throw new Error(`Unsupported language: ${language}`);
78
+ export function workflowTransactionSource() { return path.join(packageRoot, "src", "workflow-transaction.js"); }
79
+
80
+ export function releaseCatalog(language = "en") {
81
+ if (!LANGUAGE_IDS.includes(language)) throw new Error(`Unsupported language: ${language}`);
81
82
  const root = sourceSkillsRoot(language);
82
83
  const missing = MATRIX_SKILLS.filter((skill) => !fs.existsSync(path.join(root, skill, "SKILL.md")));
83
84
  if (missing.length) throw new Error(`Matrix package is incomplete. Missing: ${missing.join(", ")}`);
84
85
  const runtime = fs.readFileSync(workflowRuntimeSource());
85
- const skills = Object.fromEntries(MATRIX_SKILLS.map((skill) => [skill, hashDirectory(path.join(root, skill), [{ path: "scripts/matrix-runtime.mjs", contents: runtime }])]));
86
- return { language, root, version: packageManifest.version, skills, digest: crypto.createHash("sha256").update(JSON.stringify(skills)).digest("hex") };
87
- }
86
+ const transaction = fs.readFileSync(workflowTransactionSource());
87
+ const skills = Object.fromEntries(MATRIX_SKILLS.map((skill) => [skill, hashDirectory(path.join(root, skill), [
88
+ { path: "scripts/matrix-runtime.mjs", contents: runtime },
89
+ { path: "scripts/workflow-transaction.js", contents: transaction }
90
+ ])]));
91
+ return { language, root, version: packageManifest.version, skills, digest: crypto.createHash("sha256").update(JSON.stringify(skills)).digest("hex") };
92
+ }