@rosenfan/matrix 0.1.0
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.
- package/.claude/skills/matrix/SKILL.md +49 -0
- package/.claude/skills/matrix/agents/openai.yaml +4 -0
- package/.claude/skills/matrix/scripts/matrix_claude.py +166 -0
- package/.claude/skills/matrix/scripts/matrix_state.py +114 -0
- package/.claude/skills/matrix-archive/SKILL.md +26 -0
- package/.claude/skills/matrix-archive/agents/openai.yaml +4 -0
- package/.claude/skills/matrix-build/SKILL.md +55 -0
- package/.claude/skills/matrix-build/agents/openai.yaml +4 -0
- package/.claude/skills/matrix-claude/SKILL.md +96 -0
- package/.claude/skills/matrix-claude/agents/openai.yaml +4 -0
- package/.claude/skills/matrix-design/SKILL.md +68 -0
- package/.claude/skills/matrix-design/agents/openai.yaml +4 -0
- package/.claude/skills/matrix-hotfix/SKILL.md +8 -0
- package/.claude/skills/matrix-hotfix/agents/openai.yaml +4 -0
- package/.claude/skills/matrix-open/SKILL.md +33 -0
- package/.claude/skills/matrix-open/agents/openai.yaml +4 -0
- package/.claude/skills/matrix-status/SKILL.md +14 -0
- package/.claude/skills/matrix-status/agents/openai.yaml +4 -0
- package/.claude/skills/matrix-tweak/SKILL.md +8 -0
- package/.claude/skills/matrix-tweak/agents/openai.yaml +4 -0
- package/.claude/skills/matrix-verify/SKILL.md +82 -0
- package/.claude/skills/matrix-verify/agents/openai.yaml +4 -0
- package/LICENSE +21 -0
- package/README.md +273 -0
- package/README.zh-CN.md +271 -0
- package/assets/skills-zh-CN/matrix/SKILL.md +28 -0
- package/assets/skills-zh-CN/matrix-archive/SKILL.md +12 -0
- package/assets/skills-zh-CN/matrix-build/SKILL.md +13 -0
- package/assets/skills-zh-CN/matrix-claude/SKILL.md +30 -0
- package/assets/skills-zh-CN/matrix-design/SKILL.md +13 -0
- package/assets/skills-zh-CN/matrix-hotfix/SKILL.md +8 -0
- package/assets/skills-zh-CN/matrix-open/SKILL.md +13 -0
- package/assets/skills-zh-CN/matrix-status/SKILL.md +14 -0
- package/assets/skills-zh-CN/matrix-tweak/SKILL.md +8 -0
- package/assets/skills-zh-CN/matrix-verify/SKILL.md +13 -0
- package/bin/matrix.js +15 -0
- package/package.json +56 -0
- package/src/catalog.js +87 -0
- package/src/cli.js +117 -0
- package/src/distribution.js +192 -0
- package/src/installer.js +45 -0
- package/src/matt.js +34 -0
- package/src/messages.js +33 -0
- package/src/ui.js +89 -0
- package/src/workflow.js +95 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: matrix
|
|
3
|
+
description: Route, initialize, resume, and govern a persistent Matrix development workflow. Use when the user starts a feature, change, bug fix, or asks to resume managed development.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Matrix
|
|
7
|
+
|
|
8
|
+
Use Matrix as the development-workflow entrypoint. Its source of truth is the current repository's `.matrix/`; never infer a phase from chat history.
|
|
9
|
+
|
|
10
|
+
## Route
|
|
11
|
+
|
|
12
|
+
First run:
|
|
13
|
+
|
|
14
|
+
```powershell
|
|
15
|
+
matrix workflow inspect
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
If and only if the `matrix` executable is reported as absent, run the bundled fallback from this Skill directory instead:
|
|
19
|
+
|
|
20
|
+
```powershell
|
|
21
|
+
node <matrix-skill-directory>/scripts/matrix-runtime.mjs inspect
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
- If an active change exists, show its phase and enter the returned `next_skill`.
|
|
25
|
+
- If no active change exists, classify the request: reproducible small bug → `$matrix-hotfix` with workflow `hotfix`; bounded small change with no public API/schema/architecture impact → `$matrix-tweak` with workflow `tweak`; otherwise full Matrix with workflow `full`.
|
|
26
|
+
- Do not create Matrix state for questions, read-only investigation, or requests outside software development.
|
|
27
|
+
- Before `init`, derive a short kebab-case change id and an accurate title. Start with `full` unless a shortcut clearly applies.
|
|
28
|
+
|
|
29
|
+
```powershell
|
|
30
|
+
matrix workflow init <change-id> --workflow <full|hotfix|tweak> --title "<title>"
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Then enter `$matrix-open`. State initialization creates tracked design artifacts and ignores machine-only state without changing the repository's existing `.gitignore`.
|
|
34
|
+
|
|
35
|
+
## Optional Claude handoff
|
|
36
|
+
|
|
37
|
+
`$matrix-claude` is an optional sidecar command that exports a frozen Matrix design to a Claude Code task package. It never changes the Matrix phase, workflow, guard result, or runtime state.
|
|
38
|
+
|
|
39
|
+
## Cross-Cutting Skills
|
|
40
|
+
|
|
41
|
+
### Handoff (`handoff`)
|
|
42
|
+
When context is running low and work needs to continue in a fresh session, use `handoff` at any stage boundary. It compacts the conversation into a handoff document with suggested skills for the next agent. Save to the OS temp directory, not the workspace.
|
|
43
|
+
|
|
44
|
+
## Rules
|
|
45
|
+
|
|
46
|
+
- A phase can advance only through `matrix workflow transition`; run its guard first.
|
|
47
|
+
- Do not replace required evidence with an assertion that work is complete.
|
|
48
|
+
- Pause for user confirmation at material architecture/scope decisions and before archive/commit.
|
|
49
|
+
- On scope expansion, return to `$matrix-design`; never silently continue the old plan.
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Export a frozen Matrix design to a Claude Code task package without changing Matrix state."""
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
import re
|
|
7
|
+
import sys
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
from matrix_state import active_path, artifact, get_active, guard, parse_flow, root
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def fail(message: str) -> None:
|
|
14
|
+
print(f"MATRIX CLAUDE ERROR: {message}", file=sys.stderr)
|
|
15
|
+
raise SystemExit(2)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def read_artifact(change: str, name: str) -> str:
|
|
19
|
+
path = artifact(change, name)
|
|
20
|
+
if not path.exists():
|
|
21
|
+
fail(f"Required Matrix artifact is missing: {path}")
|
|
22
|
+
return path.read_text(encoding="utf-8").strip()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def task_content(change: str, task_id: str, proposal: str, design: str, plan: str, result_path: str) -> str:
|
|
26
|
+
return f"""# Claude Code 执行任务包:{task_id}
|
|
27
|
+
|
|
28
|
+
## 元数据
|
|
29
|
+
|
|
30
|
+
| 字段 | 内容 |
|
|
31
|
+
| --- | --- |
|
|
32
|
+
| 状态 | CLAUDE_QUEUED |
|
|
33
|
+
| Codex 决策人 | Codex |
|
|
34
|
+
| Claude Code 执行人 | Claude Code |
|
|
35
|
+
| Matrix Change | `{change}` |
|
|
36
|
+
| 回执 | `{result_path}` |
|
|
37
|
+
|
|
38
|
+
## 目标
|
|
39
|
+
|
|
40
|
+
以下目标来自已冻结的 Matrix proposal,不得扩展:
|
|
41
|
+
|
|
42
|
+
{proposal}
|
|
43
|
+
|
|
44
|
+
## 范围
|
|
45
|
+
|
|
46
|
+
### 允许修改
|
|
47
|
+
|
|
48
|
+
- 仅修改为完成下列 Matrix 设计与计划所必需的文件。
|
|
49
|
+
- 先阅读仓库级指令与现有测试,再开始实施。
|
|
50
|
+
|
|
51
|
+
### 禁止修改
|
|
52
|
+
|
|
53
|
+
- 不得修改 Matrix 状态文件或推进 Matrix phase。
|
|
54
|
+
- 不得自行改变架构、公开接口、数据模型、依赖或任务范围。
|
|
55
|
+
- 不得执行未获授权的网络、部署、破坏性或外部副作用动作。
|
|
56
|
+
|
|
57
|
+
## 禁止事项
|
|
58
|
+
|
|
59
|
+
- 不得把设计外的发现直接实现为额外功能。
|
|
60
|
+
- 遇到范围扩大、设计冲突或验收不清时必须停止并写 `NEEDS_DECISION`。
|
|
61
|
+
|
|
62
|
+
## 已冻结的设计决定
|
|
63
|
+
|
|
64
|
+
{design}
|
|
65
|
+
|
|
66
|
+
## 执行步骤
|
|
67
|
+
|
|
68
|
+
{plan}
|
|
69
|
+
|
|
70
|
+
## 验收
|
|
71
|
+
|
|
72
|
+
- 执行 `plan.md` 中的全部验证命令。
|
|
73
|
+
- 为每项行为变化提供测试或可复现验证证据。
|
|
74
|
+
- 完成后保留可供 Codex 固定基线审查的 diff。
|
|
75
|
+
|
|
76
|
+
## 停止并上报的条件
|
|
77
|
+
|
|
78
|
+
- 需要修改范围外文件或改变冻结设计。
|
|
79
|
+
- 验收失败且不能在既定范围内修复。
|
|
80
|
+
- 发现安全、授权或项目指令冲突。
|
|
81
|
+
|
|
82
|
+
## 回执路径
|
|
83
|
+
|
|
84
|
+
在 `{result_path}` 创建结构化回执,至少包含:
|
|
85
|
+
|
|
86
|
+
- `## 元数据`:执行状态与任务 ID。
|
|
87
|
+
- `## 改动清单`:实际改动文件和理由。
|
|
88
|
+
- `## 测试结果`:命令与输出摘要。
|
|
89
|
+
- `## 边界确认`:未越界声明,或 `NEEDS_DECISION`。
|
|
90
|
+
- `## 未解决项`:如有。
|
|
91
|
+
|
|
92
|
+
Codex 才能验收;Claude Code 不得自行宣告任务已接受或完成。
|
|
93
|
+
"""
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def active_board(task_id: str, task_path: str, result_path: str, change: str) -> str:
|
|
97
|
+
return f"""# 活跃任务看板
|
|
98
|
+
|
|
99
|
+
> 这里是唯一实时任务面板:只放当前任务的状态、执行主体、范围、完成条件和下一步。
|
|
100
|
+
|
|
101
|
+
## 当前状态
|
|
102
|
+
|
|
103
|
+
| 字段 | 内容 |
|
|
104
|
+
| --- | --- |
|
|
105
|
+
| ID | {task_id} |
|
|
106
|
+
| 状态 | CLAUDE_QUEUED |
|
|
107
|
+
| 执行主体 | Claude Code(由用户通过 `$matrix-claude` 明确选择) |
|
|
108
|
+
| 目标 | 执行 Matrix Change `{change}` 的冻结任务包。 |
|
|
109
|
+
| 冻结设计 | `.matrix/changes/{change}/artifacts/{{proposal,design,plan}}.md` |
|
|
110
|
+
| 任务包 | `{task_path}` |
|
|
111
|
+
| 回执 | `{result_path}` |
|
|
112
|
+
| 完成条件 | 任务包验收命令通过、Claude 回执齐全,并经 Codex 审查实际 diff 和证据。 |
|
|
113
|
+
| 下一步 | Claude Code 按冻结任务包实施;范围冲突时写 `NEEDS_DECISION`。 |
|
|
114
|
+
"""
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def export(args: argparse.Namespace) -> None:
|
|
118
|
+
change = get_active()
|
|
119
|
+
flow = parse_flow(root() / "changes" / change / "matrix.yaml")
|
|
120
|
+
if flow.get("phase") != "design":
|
|
121
|
+
fail(f"Matrix change '{change}' is in phase '{flow.get('phase')}', not design.")
|
|
122
|
+
if not guard(change, "design", output=True):
|
|
123
|
+
fail("Design guard failed; no Claude task package was written.")
|
|
124
|
+
if not re.fullmatch(r"[A-Za-z0-9][A-Za-z0-9-]*", args.task_id):
|
|
125
|
+
fail("Task id must use letters, digits, and hyphens.")
|
|
126
|
+
proposal, design, plan = (read_artifact(change, n) for n in ("proposal.md", "design.md", "plan.md"))
|
|
127
|
+
|
|
128
|
+
if args.target == "generic":
|
|
129
|
+
output = artifact(change, "claude-task.md")
|
|
130
|
+
result = artifact(change, "claude-result.md")
|
|
131
|
+
output.write_text(task_content(change, args.task_id, proposal, design, plan, str(result.relative_to(Path.cwd())).replace("\\", "/")), encoding="utf-8")
|
|
132
|
+
print(output)
|
|
133
|
+
return
|
|
134
|
+
|
|
135
|
+
tasks = Path.cwd() / "docs" / "tasks"
|
|
136
|
+
if not tasks.is_dir() or not (tasks / "active.md").is_file():
|
|
137
|
+
fail("FnSec target requires docs/tasks/active.md in the current project.")
|
|
138
|
+
output = tasks / f"claude-task-{args.task_id}.md"
|
|
139
|
+
result = tasks / f"claude-result-{args.task_id}.md"
|
|
140
|
+
if output.exists() or result.exists():
|
|
141
|
+
fail(f"FnSec task or result path already exists for {args.task_id}.")
|
|
142
|
+
output.write_text(task_content(change, args.task_id, proposal, design, plan, str(result.relative_to(Path.cwd())).replace("\\", "/")), encoding="utf-8")
|
|
143
|
+
if args.apply_fnsec_board:
|
|
144
|
+
board = tasks / "active.md"
|
|
145
|
+
current = board.read_text(encoding="utf-8")
|
|
146
|
+
if "NO_ACTIVE_OBJECTIVE" not in current:
|
|
147
|
+
output.unlink()
|
|
148
|
+
fail("FnSec active.md already has an objective; refused to overwrite it.")
|
|
149
|
+
board.write_text(active_board(args.task_id, str(output.relative_to(Path.cwd())).replace("\\", "/"), str(result.relative_to(Path.cwd())).replace("\\", "/"), change), encoding="utf-8")
|
|
150
|
+
print(output)
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def main() -> None:
|
|
154
|
+
parser = argparse.ArgumentParser()
|
|
155
|
+
subs = parser.add_subparsers(dest="command", required=True)
|
|
156
|
+
command = subs.add_parser("export")
|
|
157
|
+
command.add_argument("--task-id", required=True)
|
|
158
|
+
command.add_argument("--target", choices=("generic", "fnsec"), default="generic")
|
|
159
|
+
command.add_argument("--apply-fnsec-board", action="store_true")
|
|
160
|
+
command.set_defaults(func=export)
|
|
161
|
+
args = parser.parse_args()
|
|
162
|
+
args.func(args)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
if __name__ == "__main__":
|
|
166
|
+
main()
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Deterministic state and guard kernel shared by every Matrix Skill."""
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
import json
|
|
7
|
+
import re
|
|
8
|
+
import shutil
|
|
9
|
+
import sys
|
|
10
|
+
from datetime import datetime, timezone
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
PHASES = ("open", "design", "build", "verify", "archive")
|
|
14
|
+
NEXT = {"open": "design", "design": "build", "build": "verify", "verify": "archive"}
|
|
15
|
+
SKILLS = {phase: f"$matrix-{phase}" for phase in PHASES}
|
|
16
|
+
|
|
17
|
+
def now(): return datetime.now(timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
|
|
18
|
+
def root(): return Path.cwd() / ".matrix"
|
|
19
|
+
def active_path(): return root() / "active.json"
|
|
20
|
+
def fail(message): print(f"MATRIX ERROR: {message}", file=sys.stderr); raise SystemExit(2)
|
|
21
|
+
def write_json(path, value): path.write_text(json.dumps(value, indent=2, ensure_ascii=False) + "\n", encoding="utf-8")
|
|
22
|
+
def load_json(path): return json.loads(path.read_text(encoding="utf-8"))
|
|
23
|
+
def flow_path(change): return root() / "changes" / change / "matrix.yaml"
|
|
24
|
+
def parse_flow(path):
|
|
25
|
+
values = {}
|
|
26
|
+
for line in path.read_text(encoding="utf-8").splitlines():
|
|
27
|
+
if ":" in line and not line.startswith(" "):
|
|
28
|
+
key, value = line.split(":", 1); values[key.strip()] = value.strip().strip('"')
|
|
29
|
+
return values
|
|
30
|
+
def write_flow(path, values):
|
|
31
|
+
order = ("schema", "id", "workflow", "status", "phase", "title", "created_at", "updated_at", "acceptance", "scope")
|
|
32
|
+
path.write_text("\n".join(f"{key}: {values.get(key, '')}" for key in order) + "\n", encoding="utf-8")
|
|
33
|
+
def get_active():
|
|
34
|
+
if not active_path().exists(): fail("No active Matrix change. Start with $matrix <request>.")
|
|
35
|
+
change = load_json(active_path()).get("change_id")
|
|
36
|
+
if not isinstance(change, str) or not flow_path(change).exists(): fail("active.json does not reference a valid Matrix change.")
|
|
37
|
+
return change
|
|
38
|
+
def artifact(change, name): return root() / "changes" / change / "artifacts" / name
|
|
39
|
+
def meaningful(path, headings=()):
|
|
40
|
+
if not path.exists(): return False
|
|
41
|
+
text = path.read_text(encoding="utf-8").strip()
|
|
42
|
+
if len(text) < 40: return False
|
|
43
|
+
return all(h in text for h in headings)
|
|
44
|
+
def checks(change, phase):
|
|
45
|
+
base = root() / "changes" / change / "artifacts"
|
|
46
|
+
if phase == "open":
|
|
47
|
+
return [("proposal.md has goal, scope, and acceptance", meaningful(base / "proposal.md", ("## Goal", "## Scope", "## Acceptance")))]
|
|
48
|
+
if phase == "design":
|
|
49
|
+
return [("design.md has decisions and test seams", meaningful(base / "design.md", ("## Decisions", "## Test seams"))), ("plan.md has ordered implementation steps", meaningful(base / "plan.md", ("## Steps", "## Validation")))]
|
|
50
|
+
if phase == "build":
|
|
51
|
+
return [("plan.md exists", meaningful(base / "plan.md", ("## Steps",))), ("verification.md has build evidence", meaningful(base / "verification.md", ("## Build evidence",)))]
|
|
52
|
+
if phase == "verify":
|
|
53
|
+
return [("verification.md has test evidence", meaningful(base / "verification.md", ("## Test evidence",))), ("verification.md has review evidence", meaningful(base / "verification.md", ("## Review evidence",)))]
|
|
54
|
+
return [("verify guard passed before archive", meaningful(base / "verification.md", ("## Test evidence", "## Review evidence")))]
|
|
55
|
+
def guard(change, phase, output=True):
|
|
56
|
+
results = checks(change, phase)
|
|
57
|
+
ok = all(result for _, result in results)
|
|
58
|
+
if output:
|
|
59
|
+
print(f"Matrix guard: {change} / {phase}")
|
|
60
|
+
for label, result in results: print(f"[{'PASS' if result else 'FAIL'}] {label}")
|
|
61
|
+
return ok
|
|
62
|
+
def event(change, event_name, before, after):
|
|
63
|
+
p = root() / "changes" / change / "events.jsonl"
|
|
64
|
+
with p.open("a", encoding="utf-8") as handle: handle.write(json.dumps({"at": now(), "event": event_name, "from": before, "to": after}, ensure_ascii=False) + "\n")
|
|
65
|
+
def init(args):
|
|
66
|
+
change = re.sub(r"[^a-z0-9]+", "-", args.change.lower()).strip("-")
|
|
67
|
+
if not change: fail("Change id must contain letters or digits.")
|
|
68
|
+
if active_path().exists(): fail(f"Active Matrix change already exists: {get_active()}.")
|
|
69
|
+
directory = root() / "changes" / change
|
|
70
|
+
if directory.exists() or (root() / "archive" / change).exists(): fail(f"Matrix change already exists: {change}.")
|
|
71
|
+
(directory / "artifacts").mkdir(parents=True)
|
|
72
|
+
root().mkdir(exist_ok=True); (root() / "archive").mkdir(exist_ok=True)
|
|
73
|
+
(root() / "config.yaml").write_text("schema: matrix/config/v1\nauto_transition: true\n", encoding="utf-8") if not (root() / "config.yaml").exists() else None
|
|
74
|
+
gitignore = root() / ".gitignore"
|
|
75
|
+
ignored = "active.json\ninstallation.json\nchanges/*/run-state.json\nchanges/*/events.jsonl\nchanges/*/artifacts/handoff.md\n"
|
|
76
|
+
gitignore.write_text(ignored, encoding="utf-8") if not gitignore.exists() else None
|
|
77
|
+
values = {"schema":"matrix/change/v1", "id":change, "workflow":args.workflow, "status":"active", "phase":"open", "title":args.title, "created_at":now(), "updated_at":now(), "acceptance":"pending", "scope":"pending"}
|
|
78
|
+
write_flow(directory / "matrix.yaml", values)
|
|
79
|
+
write_json(directory / "run-state.json", {"schema":"matrix/run/v1", "current_step":"open", "iteration":0, "pending_gate":None, "updated_at":now()})
|
|
80
|
+
write_json(active_path(), {"change_id":change})
|
|
81
|
+
event(change, "initialized", None, "open")
|
|
82
|
+
print(f"Initialized Matrix change '{change}'. Next: {SKILLS['open']}")
|
|
83
|
+
def inspect(_):
|
|
84
|
+
change = get_active(); flow = parse_flow(flow_path(change)); phase = flow.get("phase", "invalid")
|
|
85
|
+
if phase not in PHASES: fail(f"Invalid phase '{phase}'.")
|
|
86
|
+
print(json.dumps({"change_id":change, "workflow":flow.get("workflow"), "phase":phase, "next_skill":SKILLS[phase], "guard_pass":guard(change, phase, False)}, ensure_ascii=False, indent=2))
|
|
87
|
+
def transition(args):
|
|
88
|
+
change = get_active(); flow = parse_flow(flow_path(change)); before = flow.get("phase")
|
|
89
|
+
expected = NEXT.get(before)
|
|
90
|
+
if args.to != expected: fail(f"Illegal transition {before} -> {args.to}; expected {expected or 'archive command' }.")
|
|
91
|
+
if not guard(change, before): fail("Current phase guard failed; state was not changed.")
|
|
92
|
+
flow["phase"] = args.to; flow["updated_at"] = now(); write_flow(flow_path(change), flow); event(change, "transition", before, args.to)
|
|
93
|
+
print(f"Transitioned {change}: {before} -> {args.to}. Next: {SKILLS[args.to]}")
|
|
94
|
+
def archive(_):
|
|
95
|
+
change = get_active(); flow = parse_flow(flow_path(change))
|
|
96
|
+
if flow.get("phase") != "archive": fail("Only an archive-phase change can be archived.")
|
|
97
|
+
if not guard(change, "archive"): fail("Archive guard failed; state was not changed.")
|
|
98
|
+
flow["status"] = "archived"; flow["updated_at"] = now(); write_flow(flow_path(change), flow); event(change, "archived", "archive", "archived")
|
|
99
|
+
source = root() / "changes" / change; target = root() / "archive" / change; shutil.move(str(source), str(target)); active_path().unlink()
|
|
100
|
+
print(f"Archived Matrix change '{change}'.")
|
|
101
|
+
def handoff(_):
|
|
102
|
+
change = get_active(); flow = parse_flow(flow_path(change)); phase = flow["phase"]
|
|
103
|
+
p = artifact(change, "handoff.md")
|
|
104
|
+
p.write_text(f"# Matrix handoff: {change}\n\n- Workflow: {flow['workflow']}\n- Current phase: {phase}\n- Resume with: `{SKILLS[phase]}`\n- Guard passes: {guard(change, phase, False)}\n", encoding="utf-8")
|
|
105
|
+
print(p)
|
|
106
|
+
def main():
|
|
107
|
+
parser = argparse.ArgumentParser(); subs = parser.add_subparsers(dest="command", required=True)
|
|
108
|
+
p = subs.add_parser("init"); p.add_argument("change"); p.add_argument("--workflow", choices=("full","hotfix","tweak"), default="full"); p.add_argument("--title", required=True); p.set_defaults(func=init)
|
|
109
|
+
subs.add_parser("inspect").set_defaults(func=inspect)
|
|
110
|
+
p = subs.add_parser("guard"); p.add_argument("phase", choices=PHASES); p.set_defaults(func=lambda a: sys.exit(0 if guard(get_active(), a.phase) else 1))
|
|
111
|
+
p = subs.add_parser("transition"); p.add_argument("to", choices=PHASES[1:]); p.set_defaults(func=transition)
|
|
112
|
+
subs.add_parser("archive").set_defaults(func=archive); subs.add_parser("handoff").set_defaults(func=handoff)
|
|
113
|
+
args = parser.parse_args(); args.func(args)
|
|
114
|
+
if __name__ == "__main__": main()
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: matrix-archive
|
|
3
|
+
description: Close and archive a verified Matrix change. Use when the active Matrix phase is archive.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Matrix Archive
|
|
7
|
+
|
|
8
|
+
This is the **final phase** of the Matrix workflow. After archiving, the workflow is complete.
|
|
9
|
+
|
|
10
|
+
## Process
|
|
11
|
+
|
|
12
|
+
1. Read the proposal, plan, and verification evidence
|
|
13
|
+
2. Summarize changed behavior, verification, residual risks, and follow-up work in `artifacts/verification.md` or the project's normal delivery document
|
|
14
|
+
3. Ask for explicit confirmation before committing or archiving
|
|
15
|
+
4. Run the archive command (this also runs the verify guard)
|
|
16
|
+
5. **Workflow complete** — no further phase transitions needed
|
|
17
|
+
|
|
18
|
+
```powershell
|
|
19
|
+
matrix workflow archive
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Do not archive if the verify guard fails.
|
|
23
|
+
|
|
24
|
+
## After Archive
|
|
25
|
+
|
|
26
|
+
The change is moved to `.matrix/archive/`. To start a new change, run `$matrix` again.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: matrix-build
|
|
3
|
+
description: Implement the frozen active Matrix plan with test-first vertical slices. Use when the active Matrix phase is build.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Matrix Build
|
|
7
|
+
|
|
8
|
+
Read `plan.md`, `design.md`, and repository instructions. Implement only the frozen scope.
|
|
9
|
+
|
|
10
|
+
## Skills to Use
|
|
11
|
+
|
|
12
|
+
### Primary: `implement`
|
|
13
|
+
|
|
14
|
+
Use the `implement` skill to execute the plan. It automatically:
|
|
15
|
+
|
|
16
|
+
1. Uses `/tdd` at pre-agreed seams for red-green-refactor cycles
|
|
17
|
+
2. Runs typechecking regularly
|
|
18
|
+
3. Runs single test files regularly during development
|
|
19
|
+
4. Runs the full test suite once at the end
|
|
20
|
+
5. Uses `/code-review` to review the work when done
|
|
21
|
+
6. Commits work to the current branch
|
|
22
|
+
|
|
23
|
+
### On Failure: `diagnosing-bugs`
|
|
24
|
+
|
|
25
|
+
When encountering crashes, test failures, or build failures:
|
|
26
|
+
|
|
27
|
+
1. **Stop** — do not propose source code fixes before root cause is located
|
|
28
|
+
2. Load the `diagnosing-bugs` skill
|
|
29
|
+
3. Follow its feedback-loop discipline: build a tight red/pass signal first
|
|
30
|
+
4. Only after root cause is identified, implement the fix through `implement` + `tdd`
|
|
31
|
+
5. Record the diagnosis and fix in `artifacts/verification.md` under `## Build evidence`
|
|
32
|
+
|
|
33
|
+
### On Merge Conflicts: `resolving-merge-conflicts`
|
|
34
|
+
|
|
35
|
+
If merge conflicts occur during implementation, use the `resolving-merge-conflicts` skill to resolve them systematically.
|
|
36
|
+
|
|
37
|
+
## Scope Discipline
|
|
38
|
+
|
|
39
|
+
If implementation exposes a scope or design change, **stop and return to `$matrix-design`**; do not amend the plan silently.
|
|
40
|
+
|
|
41
|
+
## Process
|
|
42
|
+
|
|
43
|
+
1. Load `implement` skill
|
|
44
|
+
2. Implement through vertical slices with TDD
|
|
45
|
+
3. On failure: load `diagnosing-bugs` skill
|
|
46
|
+
4. On merge conflicts: load `resolving-merge-conflicts` skill
|
|
47
|
+
5. Record concrete commands and outcomes under `## Build evidence` in `artifacts/verification.md`
|
|
48
|
+
6. Run the guard
|
|
49
|
+
7. If guard passes, run transition to advance to verify phase
|
|
50
|
+
8. **Then enter `$matrix-verify` to continue the workflow**
|
|
51
|
+
|
|
52
|
+
```powershell
|
|
53
|
+
matrix workflow guard build
|
|
54
|
+
matrix workflow transition verify
|
|
55
|
+
```
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: matrix-claude
|
|
3
|
+
description: Export a frozen Matrix design as a bounded Claude Code task package without changing Matrix workflow state. Use when Codex should design and Claude Code should implement.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Matrix Claude Handoff
|
|
7
|
+
|
|
8
|
+
This is an optional Matrix sidecar, not a Matrix phase. It must not call `transition`, `archive`, or write `matrix.yaml`, `run-state.json`, or `events.jsonl`.
|
|
9
|
+
|
|
10
|
+
## When to Use
|
|
11
|
+
|
|
12
|
+
Use `$matrix-claude` when:
|
|
13
|
+
- The design phase guard has passed (design is frozen)
|
|
14
|
+
- You want Claude Code (instead of Codex) to implement the design
|
|
15
|
+
- You need a bounded task package with all implementation details
|
|
16
|
+
|
|
17
|
+
## Preconditions
|
|
18
|
+
|
|
19
|
+
The exporter performs this read-only check before writing anything:
|
|
20
|
+
|
|
21
|
+
```powershell
|
|
22
|
+
matrix workflow guard design
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
If `matrix` is genuinely absent from PATH, use the bundled runtime from the installed root Matrix Skill. Do not fall back when the primary command starts and returns an error.
|
|
26
|
+
|
|
27
|
+
If the design guard fails, stop and return to `$matrix-design`. The exporter reads the active change's `proposal.md`, `design.md`, and `plan.md`; it does not invent missing facts.
|
|
28
|
+
|
|
29
|
+
## Export
|
|
30
|
+
|
|
31
|
+
Treat explicit invocation of `$matrix-claude` as the user's choice of Claude Code as the implementation actor. Generate the package with the deterministic exporter; it refuses a missing design guard and does not alter Matrix state.
|
|
32
|
+
|
|
33
|
+
```powershell
|
|
34
|
+
# Generic project: only exports a Matrix artifact.
|
|
35
|
+
matrix workflow export --task-id <ID> --target generic
|
|
36
|
+
|
|
37
|
+
# FnSec: exports its formal task package. Add --apply-fnsec-board only when
|
|
38
|
+
# active.md is NO_ACTIVE_OBJECTIVE; an existing task is never overwritten.
|
|
39
|
+
matrix workflow export --task-id <ID> --target fnsec --apply-fnsec-board
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Task Package Contents
|
|
43
|
+
|
|
44
|
+
The exported package (`artifacts/claude-task.md`) contains everything Claude Code needs to implement and produce evidence for `$matrix-verify`:
|
|
45
|
+
|
|
46
|
+
1. **Task ID and execution actor**: Claude Code
|
|
47
|
+
2. **Objective and acceptance criteria** — copied from `proposal.md`
|
|
48
|
+
3. **In-scope and out-of-scope boundaries** — from `proposal.md`
|
|
49
|
+
4. **Frozen design decisions** — from `design.md` (Decisions, Boundaries, Test seams)
|
|
50
|
+
5. **Ordered implementation plan** — from `plan.md` (Steps, Validation)
|
|
51
|
+
6. **Allowed and prohibited files/actions** — to prevent scope creep
|
|
52
|
+
7. **Required commands** — test, lint, typecheck, build commands to run
|
|
53
|
+
8. **Stop conditions** — ambiguity, scope expansion, failing acceptance, design conflict
|
|
54
|
+
9. **Required evidence for verify**:
|
|
55
|
+
- Changed files list
|
|
56
|
+
- Commands and their outputs
|
|
57
|
+
- Test results (pass/fail)
|
|
58
|
+
- Build evidence
|
|
59
|
+
- Residual risks
|
|
60
|
+
- `NEEDS_DECISION` items (if any)
|
|
61
|
+
|
|
62
|
+
## After Claude Code Completes
|
|
63
|
+
|
|
64
|
+
When Claude Code returns results, verify that the following evidence is present before proceeding to `$matrix-verify`:
|
|
65
|
+
|
|
66
|
+
- [ ] `artifacts/verification.md` exists with `## Build evidence` section
|
|
67
|
+
- [ ] Build evidence includes concrete commands and outcomes
|
|
68
|
+
- [ ] All tests in the plan's validation section have been run
|
|
69
|
+
- [ ] Any `NEEDS_DECISION` items have been resolved or documented
|
|
70
|
+
|
|
71
|
+
If evidence is missing, ask Claude Code to补充 before proceeding.
|
|
72
|
+
|
|
73
|
+
## Resuming Matrix Workflow
|
|
74
|
+
|
|
75
|
+
After Claude Code completes and evidence is present:
|
|
76
|
+
|
|
77
|
+
1. Run build guard to verify evidence:
|
|
78
|
+
```powershell
|
|
79
|
+
matrix workflow guard build
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
2. If guard passes, transition to verify:
|
|
83
|
+
```powershell
|
|
84
|
+
matrix workflow transition verify
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
3. Enter `$matrix-verify` to继续验证流程
|
|
88
|
+
|
|
89
|
+
If the build guard fails, return to Claude Code to补充 missing evidence.
|
|
90
|
+
|
|
91
|
+
## Important Notes
|
|
92
|
+
|
|
93
|
+
- This sidecar does NOT change Matrix phase, workflow, or guard result
|
|
94
|
+
- The Matrix state remains in `design` phase until explicitly transitioned
|
|
95
|
+
- Claude Code must produce evidence that satisfies the build guard conditions
|
|
96
|
+
- After successful transition to verify, the normal verify流程 continues
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: matrix-design
|
|
3
|
+
description: Design and freeze the active Matrix change before implementation. Use when the active Matrix phase is design or when build scope requires redesign.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Matrix Design
|
|
7
|
+
|
|
8
|
+
Read the active proposal. Write `artifacts/design.md` with `## Decisions`, `## Boundaries`, `## Test seams`, and `## Risks`; write `artifacts/plan.md` with `## Steps`, `## Validation`, and `## Stop conditions`.
|
|
9
|
+
|
|
10
|
+
## Skills to Use (Recommended Order)
|
|
11
|
+
|
|
12
|
+
1. **`domain-modeling`** — First, establish or refine the domain vocabulary. Update `CONTEXT.md` with any new terms from the proposal. This ensures all subsequent design work uses consistent language.
|
|
13
|
+
|
|
14
|
+
2. **`research`** — If the design requires investigating external APIs, documentation, or specifications, spawn a background research agent. It will investigate primary sources and write findings to a Markdown file.
|
|
15
|
+
|
|
16
|
+
3. **`wayfinder`** — For complex codebases, use this to explore and understand existing module structure, seams, and dependencies before making design decisions.
|
|
17
|
+
|
|
18
|
+
4. **`prototype`** — When a design question needs empirical validation (e.g., "does this state model feel right?" or "what should this UI look like?"), build a throwaway prototype. Two modes:
|
|
19
|
+
- **Logic prototype**: interactive terminal app to test state machines
|
|
20
|
+
- **UI prototype**: multiple UI variations on a single route
|
|
21
|
+
|
|
22
|
+
5. **`codebase-design`** — Finally, define module boundaries, interfaces, and test seams. Use its "design-it-twice" pattern to explore alternative approaches before committing.
|
|
23
|
+
|
|
24
|
+
## Process
|
|
25
|
+
|
|
26
|
+
1. Start with `domain-modeling` to ground the vocabulary
|
|
27
|
+
2. Use `research` for external dependencies (runs in background)
|
|
28
|
+
3. Use `wayfinder` to explore complex existing code
|
|
29
|
+
4. Use `prototype` to validate key design questions
|
|
30
|
+
5. Use `codebase-design` to finalize module boundaries
|
|
31
|
+
6. Confirm material architecture choices with the user before freezing
|
|
32
|
+
7. Run the guard
|
|
33
|
+
8. If guard passes, ask the user to choose implementation method:
|
|
34
|
+
|
|
35
|
+
```powershell
|
|
36
|
+
matrix workflow guard design
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Implementation Decision Point
|
|
40
|
+
|
|
41
|
+
After the design guard passes, the user chooses:
|
|
42
|
+
|
|
43
|
+
### Option A: Continue with Codex (default)
|
|
44
|
+
|
|
45
|
+
Run transition and enter `$matrix-build`:
|
|
46
|
+
|
|
47
|
+
```powershell
|
|
48
|
+
matrix workflow transition build
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Then enter `$matrix-build` to implement directly in this session.
|
|
52
|
+
|
|
53
|
+
### Option B: Use Claude Code for implementation
|
|
54
|
+
|
|
55
|
+
Run `$matrix-claude` to export the frozen design as a bounded task package. This:
|
|
56
|
+
- Does NOT change Matrix phase or state
|
|
57
|
+
- Creates `artifacts/claude-task.md` with all implementation details
|
|
58
|
+
- Includes acceptance criteria, test seams, and required commands
|
|
59
|
+
|
|
60
|
+
After Claude Code completes and returns results, run the transition and enter `$matrix-verify`:
|
|
61
|
+
|
|
62
|
+
```powershell
|
|
63
|
+
matrix workflow transition build
|
|
64
|
+
matrix workflow guard build
|
|
65
|
+
matrix workflow transition verify
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Then enter `$matrix-verify` to verify the implementation.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: matrix-hotfix
|
|
3
|
+
description: Run a constrained Matrix workflow for a reproducible small bug. Use for a bug fix that has no material architecture, API, schema, or multi-module coordination impact.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Matrix Hotfix
|
|
7
|
+
|
|
8
|
+
Start through `$matrix` with workflow `hotfix`, then use `diagnosing-bugs` to establish a red-capable feedback loop before changing code. Write the compact proposal, then continue through Matrix gates. If the bug requires architecture change, a new public API, schema work, or broad coordination, pause and ask whether to upgrade to full `$matrix`.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: matrix-open
|
|
3
|
+
description: Open or resume the Matrix open phase by clarifying a development request into an evidence-backed proposal. Use after $matrix initializes a change or when the active Matrix phase is open.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Matrix Open
|
|
7
|
+
|
|
8
|
+
Read the active Matrix change with `matrix workflow inspect`. Produce `artifacts/proposal.md` containing exactly these substantive sections: `## Goal`, `## Scope`, `## Non-goals`, `## Acceptance`, and `## Risks`.
|
|
9
|
+
|
|
10
|
+
## Skills to Use
|
|
11
|
+
|
|
12
|
+
For a **full workflow**, use `grill-with-docs` to resolve ambiguity before writing the proposal. This skill automatically:
|
|
13
|
+
|
|
14
|
+
1. Runs a `/grilling` session to stress-test the plan through relentless Q&A
|
|
15
|
+
2. Invokes `/domain-modeling` to establish shared vocabulary
|
|
16
|
+
3. Creates or updates `CONTEXT.md` with domain terms
|
|
17
|
+
4. Creates ADRs (Architecture Decision Records) for significant decisions
|
|
18
|
+
|
|
19
|
+
For **hotfix/tweak**, use `grilling` directly (without docs) — keep it concise but preserve acceptance criteria.
|
|
20
|
+
|
|
21
|
+
## Process
|
|
22
|
+
|
|
23
|
+
1. Run `grill-with-docs` (or `grilling` for hotfix/tweak)
|
|
24
|
+
2. Write `proposal.md` with all required sections
|
|
25
|
+
3. Ask the user to confirm when scope or risk is material
|
|
26
|
+
4. Run the guard
|
|
27
|
+
5. If guard passes, run transition to advance to design phase
|
|
28
|
+
6. **Then enter `$matrix-design` to continue the workflow**
|
|
29
|
+
|
|
30
|
+
```powershell
|
|
31
|
+
matrix workflow guard open
|
|
32
|
+
matrix workflow transition design
|
|
33
|
+
```
|