@matthew-cochran/crossmatrix 0.0.0-stage → 0.3.1
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/LICENSE +202 -0
- package/NOTICE +4 -0
- package/README.md +143 -2
- package/bin/crossmatrix-mcp.js +51 -0
- package/lib/install.js +571 -0
- package/lib/postinstall.js +46 -0
- package/lib/sync-skills.js +50 -0
- package/package.json +46 -4
- package/skills/crossmatrix/SKILL.md +120 -0
- package/skills/crossmatrix-competitive/SKILL.md +39 -0
- package/skills/crossmatrix-hoq/SKILL.md +59 -0
- package/skills/crossmatrix-jtbd/SKILL.md +46 -0
- package/skills/crossmatrix-prioritize/SKILL.md +39 -0
- package/skills/crossmatrix-review/SKILL.md +51 -0
- package/skills/crossmatrix-risk/SKILL.md +40 -0
- package/skills/crossmatrix-test-coverage/SKILL.md +39 -0
package/package.json
CHANGED
|
@@ -1,6 +1,48 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@matthew-cochran/crossmatrix",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.3.1",
|
|
4
|
+
"description": "npx launcher for the crossmatrix MCP server (multidimensional House of Quality): downloads the verified release binary for your platform, runs it over stdio, and ships the crossmatrix agent skills.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"mcp",
|
|
7
|
+
"model-context-protocol",
|
|
8
|
+
"crossmatrix",
|
|
9
|
+
"house-of-quality",
|
|
10
|
+
"qfd",
|
|
11
|
+
"crossmatrix-mcp"
|
|
12
|
+
],
|
|
13
|
+
"license": "Apache-2.0",
|
|
14
|
+
"author": "Matthew Cochran <matthew@cochranweb.com>",
|
|
15
|
+
"homepage": "https://github.com/praxec/crossmatrix#readme",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/praxec/crossmatrix.git",
|
|
19
|
+
"directory": "npm"
|
|
20
|
+
},
|
|
21
|
+
"bugs": {
|
|
22
|
+
"url": "https://github.com/praxec/crossmatrix/issues"
|
|
23
|
+
},
|
|
24
|
+
"bin": {
|
|
25
|
+
"crossmatrix-mcp": "bin/crossmatrix-mcp.js"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"bin/crossmatrix-mcp.js",
|
|
29
|
+
"lib/install.js",
|
|
30
|
+
"lib/postinstall.js",
|
|
31
|
+
"lib/sync-skills.js",
|
|
32
|
+
"skills/",
|
|
33
|
+
"README.md",
|
|
34
|
+
"LICENSE",
|
|
35
|
+
"NOTICE"
|
|
36
|
+
],
|
|
37
|
+
"scripts": {
|
|
38
|
+
"postinstall": "node lib/postinstall.js",
|
|
39
|
+
"prepack": "node lib/sync-skills.js",
|
|
40
|
+
"test": "node --test test/*.test.mjs"
|
|
41
|
+
},
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=18"
|
|
44
|
+
},
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: crossmatrix
|
|
3
|
+
description: "Method reference for the crossmatrix-mcp tools (crossmatrix.command and crossmatrix.query): a generic, multidimensional House of Quality / weighted cross-reference matrix. Use when you build, fill or read any crossmatrix model, or when no narrower crossmatrix-* skill fits. Covers the Configuration / Dimensions / State split, observation-only writes (tokens plus evidence, never numbers), the driver loop (gaps.next, observe, analyze), scoped slices, optimistic versions and requestIds, links, and the committed .crossmatrix/ store."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# crossmatrix
|
|
7
|
+
|
|
8
|
+
crossmatrix keeps a sparse, weighted cross-reference between **dimensions** (lists of
|
|
9
|
+
things: needs, characteristics, jobs, tests, risks, deliverables...). You make the
|
|
10
|
+
judgments; the engine does every number. Domain meaning lives in your configuration and
|
|
11
|
+
in these skills, never in the engine.
|
|
12
|
+
|
|
13
|
+
## Three documents, linked by id@version
|
|
14
|
+
|
|
15
|
+
| Layer | Holds | Op family |
|
|
16
|
+
|---|---|---|
|
|
17
|
+
| Configuration | scales, relation declarations, contractions | `scale.declare`, `relation.declare`, `contraction.declare` |
|
|
18
|
+
| Dimensions | dimensions and their members (rosters, weights) | `dimension.register`, `members.sync`, `member.propose` |
|
|
19
|
+
| State | cells: observations on member pairs | `observe`, `evidence.attach`, `deprecate` |
|
|
20
|
+
|
|
21
|
+
Findings are computed on every read and are never stored.
|
|
22
|
+
|
|
23
|
+
## The store: `.crossmatrix/` (commit it)
|
|
24
|
+
|
|
25
|
+
Run `crossmatrix-mcp init` once at the repo root. It creates `.crossmatrix/` with
|
|
26
|
+
`config/<configId>@<version>.json`, `dimensions/<dimensionSetId>@<version>.json`,
|
|
27
|
+
`state/<stateId>.json`, an append-only `audit/<stateId>.jsonl` (union-merged), a README and
|
|
28
|
+
a `.gitattributes`. Files are canonical JSON, so diffs are small. **Commit the folder.** Run
|
|
29
|
+
`crossmatrix-mcp check` after merges and in CI; it exits 1 with path-specific diagnostics.
|
|
30
|
+
|
|
31
|
+
The server picks its store from `CROSSMATRIX_DIR`, else the nearest `.crossmatrix/` above
|
|
32
|
+
its working directory, else a per-user data directory. Confirm `root` in `model.status`
|
|
33
|
+
before you write.
|
|
34
|
+
|
|
35
|
+
## Calling the tools
|
|
36
|
+
|
|
37
|
+
Every write is one `crossmatrix.command`:
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{"request": {"schemaVersion": "0.2.0", "requestId": "obs-0007", "modelId": "checkout",
|
|
41
|
+
"expectedVersion": 6, "actor": {"actorType": "llm", "persona": "observer"},
|
|
42
|
+
"op": {"kind": "observe", "relationId": "rel_need_char", "from": "need_fast",
|
|
43
|
+
"to": "char_latency", "observation": "strong", "provenanceClass": "inferred",
|
|
44
|
+
"evidence": [{"sourceRef": {"sourceRef": "docs/perf.md", "locator": "L10-L24"}}]}}}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
- `requestId` is an idempotency key: resending it replays the first answer.
|
|
48
|
+
- `expectedVersion` is the version you last saw. A `version_conflict` means someone else
|
|
49
|
+
wrote; re-read `model.status` and retry.
|
|
50
|
+
- Every response, including a rejection, carries `links`: the legal next ops. A rejection
|
|
51
|
+
carries `error.code`; fix the cause the code names, then follow a link.
|
|
52
|
+
|
|
53
|
+
Reads are `crossmatrix.query` with `{"request": {"query": {"kind": "...", ...}}}`.
|
|
54
|
+
|
|
55
|
+
## Observation-only
|
|
56
|
+
|
|
57
|
+
- A cell value is a **token** from the relation's scale (`none|weak|moderate|strong` or
|
|
58
|
+
whatever the scale declares), never a number.
|
|
59
|
+
- Member importance is a `weightObservation` token from the dimension's `weightScale`. A
|
|
60
|
+
numeric `weight` is accepted only from a deterministic source with `sourceRef.system`
|
|
61
|
+
(for example an FMECA criticality import).
|
|
62
|
+
- `provenanceClass`: `normative` (a decision), `observed` (measured or seen), `inferred`
|
|
63
|
+
(your judgment; **evidence is required**). A `measuredValue` needs `observed` plus a
|
|
64
|
+
`sourceRef`.
|
|
65
|
+
- Support and opposition are separate relations (`supports` vs `opposes`, `mitigates` vs
|
|
66
|
+
`exposes`), so strong-for and strong-against never cancel; the engine reports net and
|
|
67
|
+
tension.
|
|
68
|
+
|
|
69
|
+
## Build a model
|
|
70
|
+
|
|
71
|
+
1. `model.open` with `stateId` (creates it if absent; reopens it after a restart).
|
|
72
|
+
2. `scale.declare` your relationship scale and an importance scale.
|
|
73
|
+
3. `dimension.register` each axis (`dimensionKind` is any snake_case word; set
|
|
74
|
+
`weightScale` on weighted axes), then `members.sync` its roster.
|
|
75
|
+
4. `relation.declare` each pair of axes (`from == to` is a correlation roof), with a
|
|
76
|
+
`coveragePolicy` (`every_from`, `every_to`, `both`) when gaps must be filled.
|
|
77
|
+
5. `contraction.declare` a chain when you need a derived A→C view through B.
|
|
78
|
+
|
|
79
|
+
## The driver loop
|
|
80
|
+
|
|
81
|
+
Do not fill cells in bulk from memory. Let the engine pick:
|
|
82
|
+
|
|
83
|
+
1. `gaps.next` → the most important uncovered members.
|
|
84
|
+
2. Open the evidence, then `observe` one cell (token + rationale + evidence).
|
|
85
|
+
3. Repeat until `gaps.next` is empty or the remaining gaps are knowingly `none`.
|
|
86
|
+
4. `analyze.findings`, `conflicts`, `coverage`, `analyze.marginalize` for priorities.
|
|
87
|
+
|
|
88
|
+
## Scoped reads
|
|
89
|
+
|
|
90
|
+
Never ask for the whole model when a slice answers the question: `describe` (structure),
|
|
91
|
+
`slice {relationId, from?, to?}`, `trace {member}`, `explain {relationId, from, to}`,
|
|
92
|
+
`coverage`, `gaps.orphans`. Use `export` only to hand the model to another tool, and
|
|
93
|
+
`report` for a human-readable House of Quality.
|
|
94
|
+
|
|
95
|
+
## Large rosters, hierarchies and sources
|
|
96
|
+
|
|
97
|
+
- Sync rosters straight from their source (files, tickets, tests) with a per-member
|
|
98
|
+
`sourceRef {"uri": "file://src/lib.rs", "hash": "sha256:..."}`. `members.sync` handles
|
|
99
|
+
10k+ members; re-sending an unchanged roster is a no-op (no new version).
|
|
100
|
+
- Model nesting (directory contains file, epic contains story) as a `contains`
|
|
101
|
+
self-relation, parent → child. Add `rollup: true` to `trace`, `slice`, `coverage`,
|
|
102
|
+
`gaps.next` or `analyze.*` to roll leaf observations up to ancestors.
|
|
103
|
+
- `trace {"member": "<id or uri>"}` and `slice {"relationId", "from"|"to": "<id or uri>"}`
|
|
104
|
+
work in both directions and page with `limit` / `cursor` (`nextCursor`).
|
|
105
|
+
- `stale {"hashes": {"<uri>": "<hash>"}}` (or `"readFiles": true` for `file://` sources
|
|
106
|
+
inside the project) returns the changed members and every cell that rests on them.
|
|
107
|
+
|
|
108
|
+
## Changing your mind
|
|
109
|
+
|
|
110
|
+
Never delete. `deprecate {targetId, reason, supersededBy?}` retires a member or relation;
|
|
111
|
+
deprecated elements leave analyses but stay in history. A re-synced roster deprecates
|
|
112
|
+
members that disappeared from the source.
|
|
113
|
+
|
|
114
|
+
Narrower skills: [crossmatrix-hoq](../crossmatrix-hoq/SKILL.md),
|
|
115
|
+
[crossmatrix-jtbd](../crossmatrix-jtbd/SKILL.md),
|
|
116
|
+
[crossmatrix-competitive](../crossmatrix-competitive/SKILL.md),
|
|
117
|
+
[crossmatrix-test-coverage](../crossmatrix-test-coverage/SKILL.md),
|
|
118
|
+
[crossmatrix-risk](../crossmatrix-risk/SKILL.md),
|
|
119
|
+
[crossmatrix-prioritize](../crossmatrix-prioritize/SKILL.md),
|
|
120
|
+
[crossmatrix-review](../crossmatrix-review/SKILL.md).
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: crossmatrix-competitive
|
|
3
|
+
description: "Benchmark customer needs against competitors (including your own product) with crossmatrix-mcp and find the gaps worth winning: high-importance needs every competitor serves weakly. Use when the user asks for competitive benchmarking, a competitor matrix, a QFD planning matrix, or where to differentiate."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Needs × competitors
|
|
7
|
+
|
|
8
|
+
Read [crossmatrix](../crossmatrix/SKILL.md) first.
|
|
9
|
+
|
|
10
|
+
## Model
|
|
11
|
+
|
|
12
|
+
- Reuse the weighted needs from a House of Quality ([crossmatrix-hoq](../crossmatrix-hoq/SKILL.md))
|
|
13
|
+
or register `dim_need` with `weightScale: "importance"`.
|
|
14
|
+
- `dimension.register {"dimensionId": "dim_competitor", "dimensionKind": "competitor"}` and
|
|
15
|
+
`members.sync` the competitors **and your own product** (`attributes.self: true`). Give
|
|
16
|
+
each a `sourceRef` to the page, review or teardown you assessed.
|
|
17
|
+
- `scale.declare` a performance scale, e.g. `absent|poor|fair|good|best` (0/1/3/6/9), with
|
|
18
|
+
rubric descriptions a second reviewer could apply the same way.
|
|
19
|
+
- `relation.declare {"relationId": "rel_need_competitor", "from": "dim_need", "to": "dim_competitor", "relationType": "satisfies", "scale": "performance", "coveragePolicy": "both"}`.
|
|
20
|
+
|
|
21
|
+
## Fill
|
|
22
|
+
|
|
23
|
+
For each need and competitor, `observe` the performance token with evidence (screenshot
|
|
24
|
+
path, review URL, test log) and `provenanceClass: "observed"` when you saw it yourself,
|
|
25
|
+
`inferred` when you deduced it. Use `gaps.next` to keep the work in importance order.
|
|
26
|
+
|
|
27
|
+
## Read
|
|
28
|
+
|
|
29
|
+
- `slice {"relationId": "rel_need_competitor", "from": "<need>"}`: one need across all
|
|
30
|
+
competitors.
|
|
31
|
+
- `analyze.marginalize {"relationId": "rel_need_competitor", "axis": "from"}`: competitors
|
|
32
|
+
ranked by importance-weighted performance (your product's rank is your position).
|
|
33
|
+
- Gaps worth winning: needs with high importance where **no** competitor is above `fair`.
|
|
34
|
+
Read them from `report {"relationId": "rel_need_competitor"}` (weights and grid in one
|
|
35
|
+
place) and list them with their evidence. Gaps where only you are weak are catch-up work.
|
|
36
|
+
- `coverage` shows needs or competitors you have not assessed yet.
|
|
37
|
+
|
|
38
|
+
Feed the gaps worth winning into [crossmatrix-prioritize](../crossmatrix-prioritize/SKILL.md)
|
|
39
|
+
as value drivers.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: crossmatrix-hoq
|
|
3
|
+
description: "Build a classic House of Quality (QFD) with crossmatrix-mcp: weighted customer needs (WHATs) against engineering characteristics (HOWs), the correlation roof between characteristics, technical-importance ranking and targets. Use when the user asks for a House of Quality, QFD, needs-to-characteristics matrix, or which engineering characteristics matter most."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# House of Quality with crossmatrix
|
|
7
|
+
|
|
8
|
+
Read [crossmatrix](../crossmatrix/SKILL.md) first for the envelope, observation-only rules
|
|
9
|
+
and the driver loop. Every op below is a `crossmatrix.command` `op`.
|
|
10
|
+
|
|
11
|
+
## 1. Frame
|
|
12
|
+
|
|
13
|
+
- `model.open {"stateId": "<product>-hoq", "aspect": "hoq", "title": "<product> House of Quality"}`
|
|
14
|
+
- `scale.declare` the relationship scale (classic 0/1/3/9):
|
|
15
|
+
|
|
16
|
+
```json
|
|
17
|
+
{"kind": "scale.declare", "scale": {"id": "qfd", "levels": [
|
|
18
|
+
{"observation": "none", "value": 0, "description": "No relationship."},
|
|
19
|
+
{"observation": "weak", "value": 1, "description": "Indirect or minor effect."},
|
|
20
|
+
{"observation": "moderate", "value": 3, "description": "Contributes, not the main lever."},
|
|
21
|
+
{"observation": "strong", "value": 9, "description": "Primary mechanism."}]}}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
- `scale.declare` an importance scale (`low` 1, `medium` 3, `high` 9) with rubric
|
|
25
|
+
descriptions the customer evidence can be checked against.
|
|
26
|
+
|
|
27
|
+
## 2. Rooms
|
|
28
|
+
|
|
29
|
+
- `dimension.register {"dimensionId": "dim_need", "dimensionKind": "customer_requirement", "weightScale": "importance"}`
|
|
30
|
+
- `members.sync` the needs in the customer's words, each with `weightObservation` and a
|
|
31
|
+
`sourceRef` to the interview, survey or ticket it came from.
|
|
32
|
+
- `dimension.register {"dimensionId": "dim_char", "dimensionKind": "engineering_characteristic"}`
|
|
33
|
+
- `members.sync` measurable characteristics. Put the target and unit in `attributes`
|
|
34
|
+
(`{"target": "< 200", "unit": "ms"}`); the report prints a Targets table from them.
|
|
35
|
+
|
|
36
|
+
## 3. Relations
|
|
37
|
+
|
|
38
|
+
- `relation.declare {"relationId": "rel_need_char", "from": "dim_need", "to": "dim_char", "relationType": "satisfies", "scale": "qfd", "coveragePolicy": "every_from"}`
|
|
39
|
+
(every need must be served by something).
|
|
40
|
+
- The roof is a self-relation on the characteristics. Use `supports` for synergies and
|
|
41
|
+
`opposes` for trade-offs, as two separate relations:
|
|
42
|
+
`relation.declare {"relationId": "roof_conflict", "from": "dim_char", "to": "dim_char", "relationType": "opposes", "scale": "qfd"}`.
|
|
43
|
+
|
|
44
|
+
## 4. Fill (driver loop)
|
|
45
|
+
|
|
46
|
+
`gaps.next` → `observe` one cell with rationale and evidence → repeat. Observe the roof
|
|
47
|
+
only for pairs where a real trade-off or synergy exists. Do not fill `none` everywhere.
|
|
48
|
+
|
|
49
|
+
## 5. Read the house
|
|
50
|
+
|
|
51
|
+
- Technical importance: `analyze.marginalize {"relationId": "rel_need_char", "axis": "from"}`
|
|
52
|
+
rolls the needs up into a ranked list of characteristics (weight × strength).
|
|
53
|
+
- Trade-offs: `conflicts` lists characteristics where opposition meets or beats support.
|
|
54
|
+
- Gaps: `coverage` with the `every_from` policy flags needs no characteristic serves.
|
|
55
|
+
- The full house: `report {"relationId": "rel_need_char"}` returns Markdown with weights,
|
|
56
|
+
the matrix, the roof, technical importance, targets, coverage and findings.
|
|
57
|
+
|
|
58
|
+
Hand the ranked characteristics to [crossmatrix-prioritize](../crossmatrix-prioritize/SKILL.md)
|
|
59
|
+
or to a planner, and finish with [crossmatrix-review](../crossmatrix-review/SKILL.md).
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: crossmatrix-jtbd
|
|
3
|
+
description: "Map jobs to be done against user segments and journey steps with crossmatrix-mcp, then contract the axes to see which journey steps carry the most weighted job importance per segment. Use when the user wants a JTBD map, a jobs-by-segment matrix, journey coverage of jobs, or to find under-served jobs and journey steps."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Jobs to be done × segments × journeys
|
|
7
|
+
|
|
8
|
+
Read [crossmatrix](../crossmatrix/SKILL.md) first. This is a three-axis model joined by a
|
|
9
|
+
contraction.
|
|
10
|
+
|
|
11
|
+
## Axes
|
|
12
|
+
|
|
13
|
+
- `dimension.register {"dimensionId": "dim_segment", "dimensionKind": "user_segment", "weightScale": "importance"}`:
|
|
14
|
+
segments weighted by business importance (`weightObservation`), each with a `sourceRef`
|
|
15
|
+
to the research that defines it.
|
|
16
|
+
- `dimension.register {"dimensionId": "dim_job", "dimensionKind": "jtbd_step"}`: jobs
|
|
17
|
+
phrased as "When <situation>, I want to <motivation>, so I can <outcome>" in the
|
|
18
|
+
`label`.
|
|
19
|
+
- `dimension.register {"dimensionId": "dim_journey", "dimensionKind": "journey_step"}`:
|
|
20
|
+
the product's journey steps, in order (`attributes.order`).
|
|
21
|
+
|
|
22
|
+
## Relations
|
|
23
|
+
|
|
24
|
+
- `rel_segment_job` (`dim_segment` → `dim_job`, `relationType: "supports"`, scale
|
|
25
|
+
`importance-of-job`): how much this segment needs this job done. Declare a scale such as
|
|
26
|
+
`none|nice|important|critical` (0/1/3/9) with rubric descriptions.
|
|
27
|
+
- `rel_job_journey` (`dim_job` → `dim_journey`, `relationType: "satisfies"`, scale `qfd`,
|
|
28
|
+
`coveragePolicy: "every_from"`): which journey steps get the job done.
|
|
29
|
+
- `contraction.declare {"contractionId": "ctr_segment_journey", "chain": ["rel_segment_job", "rel_job_journey"], "weightCombination": "product"}`.
|
|
30
|
+
|
|
31
|
+
## Fill
|
|
32
|
+
|
|
33
|
+
Use the driver loop: `gaps.next`, then observe from interview notes or analytics, with
|
|
34
|
+
evidence. Leave a cell empty rather than guessing `none`.
|
|
35
|
+
|
|
36
|
+
## Read
|
|
37
|
+
|
|
38
|
+
- `analyze.contract`: segment → journey-step findings, each with the path through the
|
|
39
|
+
jobs that carries the weight. The top rows are the steps to invest in for each segment.
|
|
40
|
+
- `analyze.marginalize {"relationId": "rel_job_journey", "axis": "from"}`: journey steps
|
|
41
|
+
ranked by how much job importance they serve.
|
|
42
|
+
- `coverage` / `gaps.orphans`: jobs that no journey step serves are the under-served jobs.
|
|
43
|
+
- `report {"relationId": "rel_job_journey"}` for the Markdown matrix.
|
|
44
|
+
|
|
45
|
+
Pairs with [crossmatrix-test-coverage](../crossmatrix-test-coverage/SKILL.md), which reuses
|
|
46
|
+
the journey steps, and with [crossmatrix-prioritize](../crossmatrix-prioritize/SKILL.md).
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: crossmatrix-prioritize
|
|
3
|
+
description: "Rank deliverables against weighted value drivers with crossmatrix-mcp and hand the ranked list to a planner such as cpm-planner. Use when the user asks what to build first, wants a value-weighted backlog, or needs a priority order derived from needs, gaps, risks or competitive gaps rather than gut feel."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Deliverables × value drivers
|
|
7
|
+
|
|
8
|
+
Read [crossmatrix](../crossmatrix/SKILL.md) first.
|
|
9
|
+
|
|
10
|
+
## Model
|
|
11
|
+
|
|
12
|
+
- `dimension.register {"dimensionId": "dim_value", "dimensionKind": "business_metric", "weightScale": "importance"}`:
|
|
13
|
+
the value drivers (customer needs, gaps worth winning, risks to retire, revenue or cost
|
|
14
|
+
goals), each with a `weightObservation` and a `sourceRef` to where its importance comes
|
|
15
|
+
from. Reuse members from other crossmatrix models where they exist.
|
|
16
|
+
- `dimension.register {"dimensionId": "dim_deliverable", "dimensionKind": "deliverable"}`
|
|
17
|
+
and `members.sync` the candidate deliverables (epics, features, fixes). Put effort or
|
|
18
|
+
duration hints in `attributes`; the engine does not use them, the planner does.
|
|
19
|
+
- `scale.declare` a contribution scale (`none|weak|moderate|strong`, 0/1/3/9).
|
|
20
|
+
- `relation.declare {"relationId": "rel_value_deliverable", "from": "dim_value", "to": "dim_deliverable", "relationType": "satisfies", "scale": "contribution", "coveragePolicy": "every_from"}`.
|
|
21
|
+
- If a deliverable works against a driver (it adds risk, slows a goal), record that in a
|
|
22
|
+
separate `opposes` relation. Never lower the support token instead.
|
|
23
|
+
|
|
24
|
+
## Fill
|
|
25
|
+
|
|
26
|
+
Use the driver loop: `gaps.next`, then observe the contribution with rationale.
|
|
27
|
+
|
|
28
|
+
## Rank and hand off
|
|
29
|
+
|
|
30
|
+
1. `analyze.marginalize {"relationId": "rel_value_deliverable", "axis": "from"}`: the
|
|
31
|
+
ranked deliverables (value-weighted score, highest first).
|
|
32
|
+
2. `conflicts`: deliverables with strong opposition; decide or split them before
|
|
33
|
+
planning.
|
|
34
|
+
3. `coverage`: value drivers no deliverable serves (`every_from` makes them violations).
|
|
35
|
+
4. Hand the ranked list to the planner. For cpm-planner, keep the order as the priority,
|
|
36
|
+
carry each deliverable's id, and add durations and dependencies there. Do not invent
|
|
37
|
+
numeric scores for the planner; pass the rank and the engine's score.
|
|
38
|
+
|
|
39
|
+
Record the hand-off in the report: `report {"relationId": "rel_value_deliverable"}`.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: crossmatrix-review
|
|
3
|
+
description: "Review and sign off a crossmatrix model before it is relied on: run crossmatrix-mcp check, validate, conflicts, stale and coverage, produce the Markdown report, and walk a sign-off checklist. Use when the user asks to review, audit, validate or sign off a House of Quality or any crossmatrix model, or before committing .crossmatrix/ changes."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Review and sign-off
|
|
7
|
+
|
|
8
|
+
Read [crossmatrix](../crossmatrix/SKILL.md) first. Review is read-only: it never writes
|
|
9
|
+
except to record fixes the reviewer approves.
|
|
10
|
+
|
|
11
|
+
## 1. Integrity
|
|
12
|
+
|
|
13
|
+
- `crossmatrix-mcp check` at the repo root: exit 0, no diagnostics. Fix any path it names.
|
|
14
|
+
- `model.open {"stateId": "<id>"}`, then `model.status`: right `root` (the repo's
|
|
15
|
+
`.crossmatrix/`), expected version, counts.
|
|
16
|
+
- `validate` returns `validated: true`.
|
|
17
|
+
|
|
18
|
+
## 2. Evidence
|
|
19
|
+
|
|
20
|
+
- `stale {"hashes": {...}}` with the current content hashes of every source you can
|
|
21
|
+
re-hash: each stale entry is a cell or weight whose source changed. Re-observe or
|
|
22
|
+
deprecate it.
|
|
23
|
+
- `slice` the most important rows and confirm each `inferred` observation has evidence
|
|
24
|
+
that still says what the rationale claims.
|
|
25
|
+
|
|
26
|
+
## 3. Findings
|
|
27
|
+
|
|
28
|
+
- `conflicts`: every `conflict` (opposition ≥ support) needs a decision recorded in the
|
|
29
|
+
report or a design change.
|
|
30
|
+
- `analyze.findings`: read the contributors of each finding; they name the cells that
|
|
31
|
+
drive it.
|
|
32
|
+
- `coverage` / `gaps.orphans`: violations of a `coveragePolicy` must be closed or the
|
|
33
|
+
policy consciously relaxed.
|
|
34
|
+
|
|
35
|
+
## 4. Report
|
|
36
|
+
|
|
37
|
+
`report {}` (whole aspect) or `report {"relationId": "..."}`. Attach it to the PR or the
|
|
38
|
+
review record. `export {"format": "model"}` gives the merged JSON for another tool.
|
|
39
|
+
|
|
40
|
+
## Sign-off checklist
|
|
41
|
+
|
|
42
|
+
- [ ] `crossmatrix-mcp check` passes and `.crossmatrix/` is committed.
|
|
43
|
+
- [ ] Every weighted dimension has a weight on every active member, from a token or a
|
|
44
|
+
deterministic import.
|
|
45
|
+
- [ ] No unresolved `conflict` findings, or each has a recorded decision.
|
|
46
|
+
- [ ] No coverage violations, or each is accepted in writing.
|
|
47
|
+
- [ ] No stale references.
|
|
48
|
+
- [ ] Every `inferred` observation has evidence.
|
|
49
|
+
- [ ] The top of the technical-importance or priority ranking matches the team's
|
|
50
|
+
understanding, or the disagreement is explained.
|
|
51
|
+
- [ ] The report is attached to the review.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: crossmatrix-risk
|
|
3
|
+
description: "Cross failure modes against components or requirements with crossmatrix-mcp: import FMECA criticality as deterministic weights, separate exposes from mitigates, and find unmitigated critical exposure. Pairs with fmeca-mcp. Use when the user wants a risk × component matrix, to tie an FMECA to the design, or to see which requirements carry the most failure exposure."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Failure modes × components / requirements
|
|
7
|
+
|
|
8
|
+
Read [crossmatrix](../crossmatrix/SKILL.md) first. Criticality comes from an FMECA (for
|
|
9
|
+
example fmeca-mcp `report.export`), never from you.
|
|
10
|
+
|
|
11
|
+
## Model
|
|
12
|
+
|
|
13
|
+
- `dimension.register {"dimensionId": "dim_fail", "dimensionKind": "failure_mode", "system": "fmeca"}`.
|
|
14
|
+
- `members.sync` the failure modes with their **imported** criticality as `weight` and a
|
|
15
|
+
deterministic `sourceRef` (`{"system": "fmeca", "sourceRef": "<session>/<fm id>", "contentHash": "..."}`).
|
|
16
|
+
A numeric weight without `sourceRef.system` is rejected (`observation_only`).
|
|
17
|
+
- The design axis: components (`implementation_asset`) or requirements
|
|
18
|
+
(`customer_requirement`), synced from the repo or the requirements doc.
|
|
19
|
+
- Two relations, never one signed scale:
|
|
20
|
+
- `rel_comp_exposes_fail` (`relationType: "exposes"`): the component can produce the
|
|
21
|
+
failure mode.
|
|
22
|
+
- `rel_comp_mitigates_fail` (`relationType: "mitigates"`): the component prevents or
|
|
23
|
+
detects it.
|
|
24
|
+
- Optional chain to requirements: `contraction.declare {"contractionId": "ctr_req_exposure", "chain": ["rel_req_comp", "rel_comp_exposes_fail"]}`.
|
|
25
|
+
|
|
26
|
+
## Fill
|
|
27
|
+
|
|
28
|
+
Observe exposure and mitigation separately, with evidence (code path, design doc, test).
|
|
29
|
+
Re-sync `dim_fail` whenever the FMECA changes; `stale` with the new hashes shows which
|
|
30
|
+
cells rest on outdated failure modes.
|
|
31
|
+
|
|
32
|
+
## Read
|
|
33
|
+
|
|
34
|
+
- `analyze.contract`: requirement → failure exposure, with the components on the path.
|
|
35
|
+
- `conflicts` / `analyze.findings`: failure modes where exposure meets or exceeds
|
|
36
|
+
mitigation (`conflict`, severity `block`), most critical first.
|
|
37
|
+
- `analyze.marginalize {"relationId": "rel_comp_exposes_fail", "axis": "to"}`: components
|
|
38
|
+
ranked by criticality-weighted exposure.
|
|
39
|
+
- Send unmitigated critical exposures back to fmeca-mcp as actions, and their components
|
|
40
|
+
to [crossmatrix-prioritize](../crossmatrix-prioritize/SKILL.md).
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: crossmatrix-test-coverage
|
|
3
|
+
description: "Trace requirements or journey steps to tests with crossmatrix-mcp: a requirements × tests matrix whose orphans are untested requirements and orphan tests, weighted so the most important untested requirement comes first. Use when the user asks about test coverage of requirements, a traceability matrix, untested features, or which tests to write next."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Requirements / journeys × tests
|
|
7
|
+
|
|
8
|
+
Read [crossmatrix](../crossmatrix/SKILL.md) first.
|
|
9
|
+
|
|
10
|
+
## Model
|
|
11
|
+
|
|
12
|
+
- The WHAT axis: requirements (`dimensionKind: "customer_requirement"`) or journey steps
|
|
13
|
+
(`journey_step`, reused from [crossmatrix-jtbd](../crossmatrix-jtbd/SKILL.md)), weighted
|
|
14
|
+
with `weightObservation`.
|
|
15
|
+
- `dimension.register {"dimensionId": "dim_test", "dimensionKind": "test_artifact"}`, then
|
|
16
|
+
`members.sync` the tests from the source: one member per test id, `sourceRef` pointing to
|
|
17
|
+
the file and test name (`{"sourceRef": "tests/checkout.rs", "locator": "fn pays_once"}`)
|
|
18
|
+
plus a `contentHash` of the file. Re-sync after test changes; removed tests are
|
|
19
|
+
deprecated, not deleted.
|
|
20
|
+
- `scale.declare` a verification scale, e.g. `none|smoke|partial|full` (0/1/3/9).
|
|
21
|
+
- `relation.declare {"relationId": "rel_req_test", "from": "dim_req", "to": "dim_test", "relationType": "verifies", "scale": "verification", "coveragePolicy": "every_from"}`.
|
|
22
|
+
|
|
23
|
+
## Fill
|
|
24
|
+
|
|
25
|
+
Read each test, then `observe` how fully it verifies each requirement it touches, with
|
|
26
|
+
the assertion lines as evidence. Do not credit a test for a requirement it only executes
|
|
27
|
+
without asserting on.
|
|
28
|
+
|
|
29
|
+
## Read
|
|
30
|
+
|
|
31
|
+
- `coverage`: with `every_from`, every uncovered requirement is a **violation** (untested).
|
|
32
|
+
- `gaps.next`: untested requirements ordered by importance; write tests in that order.
|
|
33
|
+
- `gaps.orphans`: tests that verify no requirement (dead or misfiled tests) and
|
|
34
|
+
requirements no test touches.
|
|
35
|
+
- `stale {"hashes": {"tests/checkout.rs": "<current hash>"}}`: which recorded test
|
|
36
|
+
evidence changed since it was observed; re-observe those cells.
|
|
37
|
+
- `report {"relationId": "rel_req_test"}` for the traceability matrix.
|
|
38
|
+
|
|
39
|
+
Finish with [crossmatrix-review](../crossmatrix-review/SKILL.md) before a release.
|