@rosenfan/matrix 0.1.1 → 0.1.3
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 +60 -17
- package/.claude/skills/matrix/agents/openai.yaml +4 -4
- package/.claude/skills/matrix/scripts/matrix_claude.py +3 -158
- package/.claude/skills/matrix/scripts/matrix_state.py +53 -107
- package/.claude/skills/matrix-archive/SKILL.md +23 -13
- package/.claude/skills/matrix-build/SKILL.md +24 -35
- package/.claude/skills/matrix-claude/SKILL.md +26 -24
- package/.claude/skills/matrix-design/SKILL.md +29 -26
- package/.claude/skills/matrix-hotfix/SKILL.md +8 -8
- package/.claude/skills/matrix-open/SKILL.md +25 -18
- package/.claude/skills/matrix-status/SKILL.md +3 -2
- package/.claude/skills/matrix-tweak/SKILL.md +8 -8
- package/.claude/skills/matrix-verify/SKILL.md +21 -30
- package/LICENSE +21 -21
- package/README.md +294 -255
- package/README.zh-CN.md +293 -255
- package/assets/skills-zh-CN/matrix/SKILL.md +80 -25
- package/assets/skills-zh-CN/matrix-archive/SKILL.md +33 -9
- package/assets/skills-zh-CN/matrix-build/SKILL.md +36 -10
- package/assets/skills-zh-CN/matrix-claude/SKILL.md +31 -28
- package/assets/skills-zh-CN/matrix-design/SKILL.md +19 -10
- package/assets/skills-zh-CN/matrix-hotfix/SKILL.md +8 -8
- package/assets/skills-zh-CN/matrix-open/SKILL.md +22 -7
- package/assets/skills-zh-CN/matrix-status/SKILL.md +15 -14
- package/assets/skills-zh-CN/matrix-tweak/SKILL.md +8 -8
- package/assets/skills-zh-CN/matrix-verify/SKILL.md +26 -10
- package/bin/matrix.js +15 -15
- package/package.json +56 -56
- package/src/catalog.js +92 -87
- package/src/cli.js +159 -101
- package/src/distribution.js +281 -186
- package/src/installer.js +45 -45
- package/src/matt.js +45 -45
- package/src/messages.js +33 -33
- package/src/self-update.js +81 -0
- package/src/ui.js +89 -89
- package/src/workflow-transaction.js +622 -0
- package/src/workflow.js +787 -82
|
@@ -3,38 +3,77 @@ name: matrix
|
|
|
3
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
4
|
---
|
|
5
5
|
|
|
6
|
-
# Matrix
|
|
7
|
-
|
|
6
|
+
# Matrix
|
|
7
|
+
|
|
8
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
|
+
Read `artifact_language` from `matrix workflow inspect`. Keep required Markdown heading tokens unchanged, but write every user-facing artifact body, explanation, and handoff in that language: English for `en`, Chinese for `zh-CN`.
|
|
9
11
|
|
|
10
12
|
## Route
|
|
11
13
|
|
|
12
|
-
First run:
|
|
14
|
+
First run:
|
|
13
15
|
|
|
14
16
|
```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
|
-
```
|
|
17
|
+
matrix workflow inspect
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
If and only if the `matrix` executable is reported as absent, run the bundled fallback from this Skill directory instead:
|
|
23
21
|
|
|
24
|
-
|
|
22
|
+
```powershell
|
|
23
|
+
node <matrix-skill-directory>/scripts/matrix-runtime.mjs inspect
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
- If an active change exists, show its phase and frozen `orchestration`, report any Arch installation-integrity failure, and enter the returned `next_skill` only when the Runtime permits continuation.
|
|
25
27
|
- 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
28
|
- Do not create Matrix state for questions, read-only investigation, or requests outside software development.
|
|
27
29
|
- Before `init`, derive a short kebab-case change id and an accurate title. Start with `full` unless a shortcut clearly applies.
|
|
28
30
|
|
|
29
31
|
```powershell
|
|
30
|
-
matrix workflow init <change-id> --workflow <full|hotfix|tweak> --title "<title>"
|
|
32
|
+
matrix workflow init <change-id> --workflow <full|hotfix|tweak> --orchestration <prim|arch> --title "<title>"
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
An explicit mode wins; otherwise Runtime uses the project `default_orchestration`. The resolved value is immutable for the change and is shown in init, inspect, and the initialized Event. Then enter `$matrix-open`.
|
|
36
|
+
|
|
37
|
+
## Orchestration
|
|
38
|
+
|
|
39
|
+
- **Prim** uses Matrix's own capability in every phase and never requires Matt Skills.
|
|
40
|
+
- **Arch** conditionally invokes the initialization-verified ten-Skill cohort when documented task-fact triggers are present.
|
|
41
|
+
|
|
42
|
+
Both orchestration modes use the same selected workflow profile. `full` uses `open → design → build → verify → archive`; `hotfix` and `tweak` share one internal `lightweight` profile, `open → build → verify → archive`, with different evidence policies. Companion Skills never write Matrix state, transition, commit, archive, or create competing workflow artifacts.
|
|
43
|
+
|
|
44
|
+
A correctly installed Arch capability that fails gets at most one Matrix-owned fallback for the same bounded capability, with failure and evidence recorded. A missing, modified, or incomplete Arch installation must be repaired with `matrix init --with-mattpocock`; never switch the active change to Prim.
|
|
45
|
+
|
|
46
|
+
## Recovery
|
|
47
|
+
|
|
48
|
+
Use Runtime commands instead of editing Matrix state:
|
|
49
|
+
|
|
50
|
+
```powershell
|
|
51
|
+
matrix workflow return design --reason design-gap
|
|
52
|
+
matrix workflow return build --reason verification-failed
|
|
53
|
+
matrix workflow return design --reason acceptance-or-design-gap
|
|
54
|
+
matrix workflow return design --reason acceptance-or-design-gap # from Archive, before terminal archive
|
|
55
|
+
matrix workflow abort --reason <requirement-cancelled|superseded|no-longer-valuable|blocked|other>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Return preserves the change but moves the current `verification.md` into revisioned evidence history, so the returned phase must produce fresh current evidence. Abort preserves the last phase and moves the terminal change into `.matrix/archive/`; it never undoes worktree changes.
|
|
59
|
+
|
|
60
|
+
If any mutation reports `WORKFLOW_RECOVERY_REQUIRED`, stop normal phase work and run the read-only diagnosis:
|
|
61
|
+
|
|
62
|
+
```powershell
|
|
63
|
+
matrix workflow doctor
|
|
31
64
|
```
|
|
32
65
|
|
|
33
|
-
|
|
66
|
+
Never infer a repair target or strategy. Use only the exact command returned by doctor:
|
|
67
|
+
|
|
68
|
+
```powershell
|
|
69
|
+
matrix workflow doctor --repair --transaction <id> --strategy <continue|rollback>
|
|
70
|
+
matrix workflow doctor --repair --lock <id>
|
|
71
|
+
```
|
|
34
72
|
|
|
35
73
|
## Optional Claude handoff
|
|
36
74
|
|
|
37
|
-
`$matrix-claude` is an optional sidecar command
|
|
75
|
+
`$matrix-claude` is an optional sidecar command used after the approved Design -> Build transition. It exports the matching approved contract to a Claude Code task package. It never changes the Matrix phase, workflow, guard result, or runtime state.
|
|
76
|
+
Use it only when the user explicitly chooses Codex design with Claude Code implementation; never inject it into the standard path.
|
|
38
77
|
|
|
39
78
|
## Cross-Cutting Skills
|
|
40
79
|
|
|
@@ -43,7 +82,11 @@ When context is running low and work needs to continue in a fresh session, use `
|
|
|
43
82
|
|
|
44
83
|
## Rules
|
|
45
84
|
|
|
46
|
-
- A phase can advance only through `matrix workflow transition`; run its guard first.
|
|
85
|
+
- A phase can advance only through `matrix workflow transition`; run its guard first.
|
|
86
|
+
- A phase can move backward only through one of the documented `matrix workflow return` intents.
|
|
87
|
+
- Full Build approval binds proposal, design, and plan. Lightweight Build approval binds its compact proposal, requires `transition build --confirmed`, and rejects project implementation changes made after initialization but before approval.
|
|
88
|
+
- A successful Archive is always a two-step optimistic commit: run `matrix workflow archive --dry-run`, then pass its exact hash to `matrix workflow archive --expect-preflight <sha256>`. Never bypass the preflight.
|
|
89
|
+
- `matrix workflow doctor` is read-only. Every transaction or stale-lock repair must explicitly bind the identity reported by doctor; do not edit or delete `.matrix/transactions/` or `.matrix/workflow.lock`.
|
|
47
90
|
- Do not replace required evidence with an assertion that work is complete.
|
|
48
91
|
- Pause for user confirmation at material architecture/scope decisions and before archive/commit.
|
|
49
|
-
- On scope expansion, return
|
|
92
|
+
- On shortcut scope expansion, run `matrix workflow return design --reason design-gap`; Runtime upgrades the change to `full`. Never silently continue the old contract.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
interface:
|
|
2
|
-
display_name: "Matrix"
|
|
3
|
-
short_description: "Route, resume, and govern development changes"
|
|
4
|
-
default_prompt: "Use $matrix to start or resume a development change."
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "Matrix"
|
|
3
|
+
short_description: "Route, resume, and govern development changes"
|
|
4
|
+
default_prompt: "Use $matrix to start or resume a development change."
|
|
@@ -1,166 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
2
|
+
"""Compatibility adapter for the authoritative Node workflow exporter."""
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
import argparse
|
|
6
|
-
import re
|
|
7
5
|
import sys
|
|
8
|
-
from pathlib import Path
|
|
9
6
|
|
|
10
|
-
from matrix_state import
|
|
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)
|
|
7
|
+
from matrix_state import run_runtime
|
|
163
8
|
|
|
164
9
|
|
|
165
10
|
if __name__ == "__main__":
|
|
166
|
-
|
|
11
|
+
raise SystemExit(run_runtime(sys.argv[1:]))
|
|
@@ -1,114 +1,60 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
2
|
+
"""Compatibility adapter for the authoritative Node Workflow Runtime."""
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
import
|
|
6
|
-
import json
|
|
7
|
-
import re
|
|
5
|
+
import os
|
|
8
6
|
import shutil
|
|
7
|
+
import subprocess
|
|
9
8
|
import sys
|
|
10
|
-
from datetime import datetime, timezone
|
|
11
9
|
from pathlib import Path
|
|
12
10
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
if
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
return
|
|
54
|
-
return
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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()
|
|
11
|
+
|
|
12
|
+
def development_runtime() -> Path | None:
|
|
13
|
+
"""Return an explicitly selected source runtime for repository tests only."""
|
|
14
|
+
configured = os.environ.get("MATRIX_DEVELOPMENT_RUNTIME")
|
|
15
|
+
return Path(configured).resolve() if configured else None
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def primary_runtime() -> str | None:
|
|
19
|
+
if os.name == "nt":
|
|
20
|
+
return shutil.which("matrix.cmd") or shutil.which("matrix.exe")
|
|
21
|
+
return shutil.which("matrix")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def runtime_command(args: list[str]) -> list[str]:
|
|
25
|
+
primary = primary_runtime()
|
|
26
|
+
if primary is not None:
|
|
27
|
+
return [primary, "workflow", *args, "--json"]
|
|
28
|
+
|
|
29
|
+
development = development_runtime()
|
|
30
|
+
if development is not None:
|
|
31
|
+
if not development.is_file():
|
|
32
|
+
raise RuntimeError(f"Configured Matrix development runtime was not found: {development}")
|
|
33
|
+
node = shutil.which("node")
|
|
34
|
+
if node is None:
|
|
35
|
+
raise RuntimeError("Node.js is required to run the Matrix workflow.")
|
|
36
|
+
return [node, str(development), *args]
|
|
37
|
+
|
|
38
|
+
bundled = Path(__file__).with_name("matrix-runtime.mjs")
|
|
39
|
+
node = shutil.which("node")
|
|
40
|
+
if node is not None and bundled.exists():
|
|
41
|
+
return [node, str(bundled), *args]
|
|
42
|
+
|
|
43
|
+
raise RuntimeError("Matrix CLI is absent and the bundled workflow runtime was not found.")
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def run_runtime(args: list[str]) -> int:
|
|
47
|
+
try:
|
|
48
|
+
completed = subprocess.run(runtime_command(args), cwd=Path.cwd(), check=False)
|
|
49
|
+
except (OSError, RuntimeError) as error:
|
|
50
|
+
print(f"MATRIX ERROR [RUNTIME_UNAVAILABLE]: {error}", file=sys.stderr)
|
|
51
|
+
return 2
|
|
52
|
+
return completed.returncode
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def main() -> int:
|
|
56
|
+
return run_runtime(sys.argv[1:])
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
if __name__ == "__main__":
|
|
60
|
+
raise SystemExit(main())
|
|
@@ -3,24 +3,34 @@ name: matrix-archive
|
|
|
3
3
|
description: Close and archive a verified Matrix change. Use when the active Matrix phase is archive.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Matrix Archive
|
|
6
|
+
# Matrix Archive
|
|
7
|
+
|
|
8
|
+
This is the final Matrix phase. Read the proposal, plan, and verification evidence; summarize changed behavior, verification, residual risks, and follow-up work. Ask for explicit confirmation before committing or archiving.
|
|
9
|
+
|
|
10
|
+
Write archive summaries and handoff prose in `artifact_language`; keep Runtime-required English heading tokens unchanged.
|
|
7
11
|
|
|
8
|
-
|
|
12
|
+
Archive is Matrix-owned in both Prim and Arch. Do not invoke companion implementation, review, or architecture capabilities here.
|
|
9
13
|
|
|
10
|
-
##
|
|
14
|
+
## Mandatory two-step Archive
|
|
11
15
|
|
|
12
|
-
|
|
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
|
|
16
|
+
Run the read-only preflight and review its bounded effect summary. Then submit exactly the hash returned by that preflight:
|
|
17
17
|
|
|
18
18
|
```powershell
|
|
19
|
-
matrix workflow archive
|
|
20
|
-
|
|
19
|
+
matrix workflow archive --dry-run
|
|
20
|
+
matrix workflow archive --expect-preflight <sha256-returned-by-dry-run>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Bare Archive is rejected. Runtime reacquires the project Archive boundary and recomputes the entire protected change-directory manifest before committing.
|
|
24
|
+
For hotfix/tweak, ask for explicit confirmation after reviewing the preflight, then use the returned command with `--confirmed`. Runtime rejects a shortcut Archive without it.
|
|
25
|
+
|
|
26
|
+
- `ARCHIVE_PREFLIGHT_CHANGED`: run dry-run again and review the new summary.
|
|
27
|
+
- `ARCHIVE_BUSY`: retry later. Do not remove or take over the lock; stale-lock recovery belongs to the later doctor/repair change.
|
|
28
|
+
- Guard or Contract failure: use the returned recovery command and do not submit.
|
|
21
29
|
|
|
22
|
-
|
|
30
|
+
If acceptance criteria or design must change while awaiting confirmation, use the sole Archive recovery path:
|
|
23
31
|
|
|
24
|
-
|
|
32
|
+
```powershell
|
|
33
|
+
matrix workflow return design --reason acceptance-or-design-gap
|
|
34
|
+
```
|
|
25
35
|
|
|
26
|
-
|
|
36
|
+
After successful commit, the change is under `.matrix/archive/` and the workflow is complete.
|
|
@@ -3,53 +3,42 @@ name: matrix-build
|
|
|
3
3
|
description: Implement the frozen active Matrix plan with test-first vertical slices. Use when the active Matrix phase is build.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Matrix Build
|
|
6
|
+
# Matrix Build
|
|
7
|
+
|
|
8
|
+
Run `matrix workflow inspect` and implement only its approved Contract. Full and `legacy-full` read proposal/design/plan. `lightweight` reads the approved compact proposal and must not backfill Design artifacts.
|
|
9
|
+
|
|
10
|
+
Write build evidence and user-facing explanations in `artifact_language`; preserve any Runtime-required English heading tokens.
|
|
7
11
|
|
|
8
|
-
|
|
12
|
+
## Prim
|
|
9
13
|
|
|
10
|
-
|
|
14
|
+
Use Matrix's own implementation and test discipline.
|
|
11
15
|
|
|
12
|
-
|
|
16
|
+
## Arch
|
|
13
17
|
|
|
14
|
-
|
|
18
|
+
- invoke `tdd` when the change modifies observable behavior at a testable seam;
|
|
19
|
+
- invoke `diagnosing-bugs` only when an actual failure exists and root cause is not established;
|
|
20
|
+
- invoke `resolving-merge-conflicts` only for an in-progress merge or rebase conflict.
|
|
15
21
|
|
|
16
|
-
|
|
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
|
+
Announce each triggered capability and reason. No companion may commit, review, transition, archive, or broaden scope. A correctly installed capability gets at most one Matrix-owned fallback for that same capability; record the Skill, failure, fallback, and evidence. Installation-integrity failure stops the phase.
|
|
22
23
|
|
|
23
|
-
|
|
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`
|
|
24
|
+
## Scope Discipline
|
|
34
25
|
|
|
35
|
-
If
|
|
26
|
+
If implementation exposes a scope or design change, **stop and run**; a lightweight change is upgraded to full by this Return:
|
|
36
27
|
|
|
37
|
-
|
|
28
|
+
```powershell
|
|
29
|
+
matrix workflow return design --reason design-gap
|
|
30
|
+
```
|
|
38
31
|
|
|
39
|
-
|
|
32
|
+
Then enter `$matrix-design`; do not amend the plan silently. The Runtime preserves old verification evidence in revision history and requires fresh evidence after the redesigned plan returns to Build.
|
|
40
33
|
|
|
41
34
|
## Process
|
|
42
35
|
|
|
43
|
-
1.
|
|
44
|
-
2.
|
|
45
|
-
3.
|
|
46
|
-
4.
|
|
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**
|
|
36
|
+
1. Implement the approved plan in bounded vertical slices.
|
|
37
|
+
2. Use only triggered Arch capabilities.
|
|
38
|
+
3. Record common facts under `## Build evidence`. Hotfix also requires `## Reproduction evidence` and `## Root cause`; tweak also requires `## Scope evidence`.
|
|
39
|
+
4. Run the guard and transition, then enter `$matrix-verify`.
|
|
51
40
|
|
|
52
41
|
```powershell
|
|
53
|
-
matrix workflow guard build
|
|
54
|
-
matrix workflow transition verify
|
|
42
|
+
matrix workflow guard build
|
|
43
|
+
matrix workflow transition verify
|
|
55
44
|
```
|