@mmerterden/multi-agent-pipeline 12.5.0 → 12.6.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/CHANGELOG.md +130 -0
- package/README.md +1 -1
- package/docs/features.md +20 -0
- package/index.js +7 -1
- package/install/_dev-only-files.mjs +1 -0
- package/package.json +4 -3
- package/pipeline/agents/security-auditor.md +1 -1
- package/pipeline/commands/archive-guard.md +5 -5
- package/pipeline/commands/multi-agent/SKILL.md +2 -0
- package/pipeline/commands/multi-agent/design-check/SKILL.md +287 -0
- package/pipeline/commands/multi-agent/help/SKILL.md +45 -5
- package/pipeline/commands/multi-agent/refactor/SKILL.md +92 -12
- package/pipeline/commands/multi-agent/review/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/sync/SKILL.md +119 -12
- package/pipeline/commands/multi-agent/test/SKILL.md +1 -1
- package/pipeline/commands/sim-test.md +5 -5
- package/pipeline/lib/credential-store.sh +32 -0
- package/pipeline/multi-agent-refs/cross-cli-contract.md +3 -3
- package/pipeline/multi-agent-refs/phases/phase-3-dev.md +2 -2
- package/pipeline/multi-agent-refs/phases/phase-5-test.md +4 -4
- package/pipeline/preferences-template.json +18 -1
- package/pipeline/schemas/agent-state.schema.json +90 -0
- package/pipeline/schemas/design-check-config.schema.json +162 -0
- package/pipeline/schemas/migrations/state-2.0.0-to-2.1.0.mjs +30 -12
- package/pipeline/schemas/prefs.schema.json +161 -5
- package/pipeline/scripts/README.md +7 -5
- package/pipeline/scripts/classify-plan-safety.mjs +8 -3
- package/pipeline/scripts/cost-budget-check.mjs +9 -5
- package/pipeline/scripts/fixtures/install-layout.tsv +6 -6
- package/pipeline/scripts/learnings-ledger.mjs +18 -0
- package/pipeline/scripts/lint-mcp-refs.mjs +207 -0
- package/pipeline/scripts/memory-load.sh +5 -1
- package/pipeline/scripts/render-work-summary.sh +4 -1
- package/pipeline/scripts/smoke-command-inventory.sh +81 -0
- package/pipeline/scripts/smoke-commands-skills-parity.sh +1 -1
- package/pipeline/scripts/smoke-compliance-skills.sh +4 -4
- package/pipeline/scripts/smoke-cross-cli-behavior.sh +12 -2
- package/pipeline/scripts/smoke-generate-issue.sh +6 -5
- package/pipeline/scripts/smoke-per-repo-memory.sh +2 -2
- package/pipeline/scripts/smoke-review-readiness.sh +3 -2
- package/pipeline/scripts/smoke-schema-validation.sh +19 -5
- package/pipeline/scripts/smoke-shadow-git.sh +4 -2
- package/pipeline/scripts/triage-memory.mjs +18 -0
- package/pipeline/scripts/uninstall.mjs +1 -1
- package/pipeline/skills/.skill-manifest.json +24 -8
- package/pipeline/skills/.skills-index.json +39 -3
- package/pipeline/skills/shared/README.md +10 -6
- package/pipeline/skills/shared/core/apple-archive-compliance/SKILL.md +10 -8
- package/pipeline/skills/shared/core/multi-agent-design-check/SKILL.md +248 -0
- package/pipeline/skills/shared/core/multi-agent-help/SKILL.md +22 -0
- package/pipeline/skills/shared/core/multi-agent-refactor/SKILL.md +67 -11
- package/pipeline/skills/shared/core/multi-agent-review/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +51 -9
- package/pipeline/skills/shared/core/multi-agent-test/SKILL.md +1 -1
- package/pipeline/skills/skills-index.md +8 -4
|
@@ -164,7 +164,7 @@ For each task (respecting dependency order):
|
|
|
164
164
|
**Preferred - MCP tool (token-efficient, dev-toolkit-mcp ≥ 2.3.0):**
|
|
165
165
|
```
|
|
166
166
|
acquire_build_lock "$TASK_ID"
|
|
167
|
-
|
|
167
|
+
mcp__dev-toolkit__ios_xcodebuild({
|
|
168
168
|
project: "{projectPath}", // or workspace
|
|
169
169
|
scheme: "{scheme}",
|
|
170
170
|
configuration: "Release",
|
|
@@ -173,7 +173,7 @@ For each task (respecting dependency order):
|
|
|
173
173
|
})
|
|
174
174
|
release_build_lock
|
|
175
175
|
```
|
|
176
|
-
Returns one line: `Build: SUCCESS|FAILURE (E errors, W warnings) [xcresult-<id>]`. On failure, drill in only when needed via `
|
|
176
|
+
Returns one line: `Build: SUCCESS|FAILURE (E errors, W warnings) [xcresult-<id>]`. On failure, drill in only when needed via `mcp__dev-toolkit__ios_xcresult({id, mode: "errors"})`. Saves thousands of tokens per build cycle vs. raw xcodebuild output.
|
|
177
177
|
|
|
178
178
|
**Fallback - raw xcodebuild** (when MCP server is unavailable):
|
|
179
179
|
```bash
|
|
@@ -126,12 +126,12 @@ Before or during user testing, run device-level audits via Bash if user requests
|
|
|
126
126
|
|
|
127
127
|
| Check | When | Command |
|
|
128
128
|
| ------------------- | ----------------- | ----------------------------------------- |
|
|
129
|
-
| Accessibility audit | UI changes | `
|
|
130
|
-
| Biometric test | Auth flow changes | `
|
|
129
|
+
| Accessibility audit | UI changes | `mcp__dev-toolkit__ios_accessibility_audit` (or `swift ui-tree-dumper.swift`) |
|
|
130
|
+
| Biometric test | Auth flow changes | `mcp__dev-toolkit__ios_biometric` (or `xcrun simctl keychain biometric-match`) |
|
|
131
131
|
| Launch time | Android project | `adb shell am start -W` |
|
|
132
132
|
| Visual test | Any UI changes | `/multi-agent test` (sim-test) |
|
|
133
|
-
| Snapshot regression | Component / pixel-stable UI changes | `
|
|
134
|
-
| App Store screenshots | `taskType === screenshot` | `
|
|
133
|
+
| Snapshot regression | Component / pixel-stable UI changes | `mcp__dev-toolkit__ios_visual_diff` (dev-toolkit-mcp ≥ 2.3.0) |
|
|
134
|
+
| App Store screenshots | `taskType === screenshot` | `mcp__dev-toolkit__ios_status_bar({preset: "clean"})` before each capture |
|
|
135
135
|
|
|
136
136
|
Results included in Phase 7 report. MCP tools preferred when available - concise structured output, lower token cost.
|
|
137
137
|
|
|
@@ -73,7 +73,12 @@
|
|
|
73
73
|
"onExceed": "warn",
|
|
74
74
|
"pricingModel": "opus"
|
|
75
75
|
},
|
|
76
|
-
"derivedSkillSources": []
|
|
76
|
+
"derivedSkillSources": [],
|
|
77
|
+
"devToolkit": {
|
|
78
|
+
"enabled": true,
|
|
79
|
+
"mcpServerName": "dev-toolkit",
|
|
80
|
+
"registry": "github-packages"
|
|
81
|
+
}
|
|
77
82
|
},
|
|
78
83
|
"projects": {},
|
|
79
84
|
"_figmaConfigTemplate": {
|
|
@@ -170,5 +175,17 @@
|
|
|
170
175
|
"derivedFromVersion": "0.0.0",
|
|
171
176
|
"upstreamRepoUrl": "https://github.com/<org>/<repo>"
|
|
172
177
|
}
|
|
178
|
+
},
|
|
179
|
+
"_devToolkitTemplate": {
|
|
180
|
+
"_comment": "Optional. global.devToolkit points at the companion MCP server that serves the pipeline's device and browser tools. /multi-agent:refactor Step 0c researches current MCP practice and audits that repo against it (plan band E); /multi-agent:sync Step 3d ships it when it moved (gates, commit, publish). Leave localPath out and both commands auto-detect the repo from your mcpServers registration; set enabled:false to skip both.",
|
|
181
|
+
"_example": {
|
|
182
|
+
"enabled": true,
|
|
183
|
+
"label": "dev-toolkit MCP server",
|
|
184
|
+
"localPath": "$HOME/<repo-dir>",
|
|
185
|
+
"mcpServerName": "dev-toolkit",
|
|
186
|
+
"packageName": "@<scope>/<package>",
|
|
187
|
+
"registry": "github-packages",
|
|
188
|
+
"repoUrl": "https://github.com/<owner>/<repo>"
|
|
189
|
+
}
|
|
173
190
|
}
|
|
174
191
|
}
|
|
@@ -121,6 +121,96 @@
|
|
|
121
121
|
"default": false,
|
|
122
122
|
"description": "A Figma / skill instruction file is steering phases 3-6."
|
|
123
123
|
},
|
|
124
|
+
"mode": {
|
|
125
|
+
"type": ["string", "null"],
|
|
126
|
+
"description": "Pipeline mode for this run (e.g. 'dev', 'local', 'design-check'). Absent = full pipeline."
|
|
127
|
+
},
|
|
128
|
+
"designCheck": {
|
|
129
|
+
"type": ["object", "null"],
|
|
130
|
+
"additionalProperties": true,
|
|
131
|
+
"description": "State for a /multi-agent:design-check run. Populated in Phase 0 (mock feasibility, scenario inventory, scope), Phase 2 (Figma variants) and Phase 3 (captures, skips, findings).",
|
|
132
|
+
"properties": {
|
|
133
|
+
"module": { "type": "string", "description": "Module / submodule path being audited." },
|
|
134
|
+
"platform": { "type": "string", "enum": ["ios", "android"] },
|
|
135
|
+
"mock": {
|
|
136
|
+
"type": "object",
|
|
137
|
+
"additionalProperties": true,
|
|
138
|
+
"description": "design_mock_detect result.",
|
|
139
|
+
"properties": {
|
|
140
|
+
"supported": { "description": "true | false | 'debug-only'" },
|
|
141
|
+
"mechanism": { "type": ["string", "null"] },
|
|
142
|
+
"activation": { "type": ["object", "null"] },
|
|
143
|
+
"variantsHint": { "type": "array", "items": { "type": "string" } }
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
"inventory": {
|
|
147
|
+
"type": ["object", "null"],
|
|
148
|
+
"additionalProperties": true,
|
|
149
|
+
"description": "design_scenario_inventory result, persisted verbatim. THIS is the audit's target set - Phase 3 iterates it and Phase 4 gates on it. Never re-derive it by reading the repo.",
|
|
150
|
+
"properties": {
|
|
151
|
+
"targetCount": { "type": "integer" },
|
|
152
|
+
"targets": {
|
|
153
|
+
"type": "array",
|
|
154
|
+
"items": { "type": "object", "additionalProperties": true },
|
|
155
|
+
"description": "{ id, kind, label, screen, driver, evidence } per state driver (launch-arg / scenario-case / code-scenario / fixture / deep-link)."
|
|
156
|
+
},
|
|
157
|
+
"groups": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
|
|
158
|
+
"byKind": { "type": "object", "additionalProperties": true },
|
|
159
|
+
"truncated": { "type": "boolean" }
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
"scope": {
|
|
163
|
+
"type": ["object", "null"],
|
|
164
|
+
"additionalProperties": true,
|
|
165
|
+
"description": "Resolved run scope: the inventory targets this run must audit. The coverage gate applies to this set, not to the whole inventory - a scoped run is not penalised for out-of-scope targets.",
|
|
166
|
+
"properties": {
|
|
167
|
+
"argument": { "type": ["string", "null"], "description": "Raw $ARGUMENTS as given (empty = whole module, '--resume' = remainder of the last run)." },
|
|
168
|
+
"targetIds": { "type": "array", "items": { "type": "string" } },
|
|
169
|
+
"resumedFrom": { "type": ["string", "null"], "description": "Report dir of the run this scope resumes, when --resume was used." }
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
"figmaUrl": { "type": ["string", "null"] },
|
|
173
|
+
"variants": {
|
|
174
|
+
"type": "array",
|
|
175
|
+
"description": "Mapped variants with their Figma spec, capture, and findings.",
|
|
176
|
+
"items": { "type": "object", "additionalProperties": true }
|
|
177
|
+
},
|
|
178
|
+
"captured": {
|
|
179
|
+
"type": "array",
|
|
180
|
+
"description": "Every capture taken, appended and persisted as it happens so a dying run is resumable. One entry per screenshot, keyed to the target that produced it ('<targetId>', or '<targetId>#<sub-label>' for tap-reachable sub-states).",
|
|
181
|
+
"items": { "type": "object", "additionalProperties": true }
|
|
182
|
+
},
|
|
183
|
+
"skipped": {
|
|
184
|
+
"type": "array",
|
|
185
|
+
"description": "Targets that could not be audited, each with a CONCRETE reason. 'Requires a scenario / prefix / launch-arg' is not a reason - that is the work Phase 3 exists to do. A skip without a reason fails the coverage gate.",
|
|
186
|
+
"items": {
|
|
187
|
+
"type": "object",
|
|
188
|
+
"additionalProperties": true,
|
|
189
|
+
"required": ["id", "reason"],
|
|
190
|
+
"properties": {
|
|
191
|
+
"id": { "type": "string" },
|
|
192
|
+
"group": { "type": ["string", "null"] },
|
|
193
|
+
"reason": { "type": "string", "minLength": 1 }
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
},
|
|
197
|
+
"coverage": {
|
|
198
|
+
"type": ["object", "null"],
|
|
199
|
+
"additionalProperties": true,
|
|
200
|
+
"description": "design_report coverage verdict for this run. gate='fail' means the run is INCOMPLETE and must be reported as such, with the unaccounted ids and the --resume command.",
|
|
201
|
+
"properties": {
|
|
202
|
+
"gate": { "type": "string", "enum": ["pass", "fail"] },
|
|
203
|
+
"audited": { "type": "integer" },
|
|
204
|
+
"target": { "type": "integer" },
|
|
205
|
+
"pct": { "type": "number" },
|
|
206
|
+
"skippedWithReason": { "type": "integer" },
|
|
207
|
+
"unaccounted": { "type": "integer" },
|
|
208
|
+
"unaccountedIds": { "type": "array", "items": { "type": "string" } }
|
|
209
|
+
}
|
|
210
|
+
},
|
|
211
|
+
"reportDir": { "type": ["string", "null"], "description": "Output dir under ~/DesignChecks." }
|
|
212
|
+
}
|
|
213
|
+
},
|
|
124
214
|
"identity": {
|
|
125
215
|
"type": "object",
|
|
126
216
|
"additionalProperties": false,
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://github.com/mmerterden/multi-agent-pipeline/pipeline/schemas/design-check-config.schema.json",
|
|
4
|
+
"title": "Design Check Configuration",
|
|
5
|
+
"description": "Optional per-project config for /multi-agent:design-check. Stored at ~/.claude/projects/{slug}/design-check-config.json. Never committed. Everything here is optional: design_mock_detect auto-detects mock support and design_scenario_inventory auto-enumerates state drivers at run time; this file only overrides or augments that detection (extra mock switch keys, extra launch args / targets no source signal reveals, explicit variant->Figma-node mappings, status-bar crop, coverage floor, Confluence toggle). Keeps the engine generic — project specifics live here, never in shipped code.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": ["schemaVersion"],
|
|
9
|
+
"properties": {
|
|
10
|
+
"schemaVersion": { "type": "string", "const": "1.0.0" },
|
|
11
|
+
"platform": {
|
|
12
|
+
"type": "string",
|
|
13
|
+
"enum": ["ios", "android"],
|
|
14
|
+
"description": "Override auto platform detection."
|
|
15
|
+
},
|
|
16
|
+
"mock": {
|
|
17
|
+
"type": "object",
|
|
18
|
+
"additionalProperties": false,
|
|
19
|
+
"description": "Mock-mode overrides. Omit to rely purely on auto-detection.",
|
|
20
|
+
"properties": {
|
|
21
|
+
"keys": {
|
|
22
|
+
"type": "array",
|
|
23
|
+
"items": { "type": "string" },
|
|
24
|
+
"description": "Extra UserDefaults / launch-arg switch keys to look for (passed as extra_keys to design_mock_detect)."
|
|
25
|
+
},
|
|
26
|
+
"launchArg": {
|
|
27
|
+
"type": "string",
|
|
28
|
+
"description": "Explicit iOS launch argument to force mock mode, e.g. '-debugMockMode YES'. Overrides the detected one."
|
|
29
|
+
},
|
|
30
|
+
"intentExtra": {
|
|
31
|
+
"type": "string",
|
|
32
|
+
"description": "Explicit Android intent extra, e.g. '--ez mockEnabled true'."
|
|
33
|
+
},
|
|
34
|
+
"buildConfig": {
|
|
35
|
+
"type": "string",
|
|
36
|
+
"description": "Build configuration that compiles the mocks (default 'Debug')."
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"inventory": {
|
|
41
|
+
"type": "object",
|
|
42
|
+
"additionalProperties": false,
|
|
43
|
+
"description": "Augments design_scenario_inventory, which decides the audit's target set. Only for states no source signal can reveal — everything detectable is detected.",
|
|
44
|
+
"properties": {
|
|
45
|
+
"extraLaunchArgs": {
|
|
46
|
+
"type": "array",
|
|
47
|
+
"items": { "type": "string" },
|
|
48
|
+
"description": "Launch args (iOS) / boolean intent-extra keys (Android) that drive a distinct state but appear in no scanned literal."
|
|
49
|
+
},
|
|
50
|
+
"extraTargets": {
|
|
51
|
+
"type": "array",
|
|
52
|
+
"description": "Fully hand-declared targets, for states reachable only by a documented manual step.",
|
|
53
|
+
"items": {
|
|
54
|
+
"type": "object",
|
|
55
|
+
"additionalProperties": false,
|
|
56
|
+
"required": ["id"],
|
|
57
|
+
"properties": {
|
|
58
|
+
"id": { "type": "string", "description": "Stable target id, e.g. 'config:seatmap-3d'." },
|
|
59
|
+
"kind": { "type": "string", "description": "Target kind label (default 'config')." },
|
|
60
|
+
"label": { "type": "string" },
|
|
61
|
+
"screen": { "type": "string", "description": "Screen this target belongs to (groups the coverage report)." },
|
|
62
|
+
"driver": {
|
|
63
|
+
"type": "object",
|
|
64
|
+
"additionalProperties": true,
|
|
65
|
+
"description": "How to reach it: { type: 'manual', note } or any driver shape the runner understands."
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
"ignoreTargets": {
|
|
71
|
+
"type": "array",
|
|
72
|
+
"items": { "type": "string" },
|
|
73
|
+
"description": "Target ids to drop from the inventory entirely (dead drivers, states retired in code but still referenced). Unlike a skip, these never enter the coverage gate — use sparingly and prefer a skip with a reason."
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
"coverage": {
|
|
78
|
+
"type": "object",
|
|
79
|
+
"additionalProperties": false,
|
|
80
|
+
"description": "Coverage gate tuning. The gate itself is not optional: a target is audited, or skipped with an explicit reason.",
|
|
81
|
+
"properties": {
|
|
82
|
+
"floor": {
|
|
83
|
+
"type": "number",
|
|
84
|
+
"minimum": 0,
|
|
85
|
+
"maximum": 1,
|
|
86
|
+
"description": "Additional hard floor on audited/target ratio (e.g. 0.9). Below it the gate fails even when every skip carries a reason."
|
|
87
|
+
},
|
|
88
|
+
"confirmAbove": {
|
|
89
|
+
"type": "integer",
|
|
90
|
+
"default": 25,
|
|
91
|
+
"description": "Relaunch count (inventory.relaunchCount for the scoped set, NOT the target count) above which Phase 0 asks for confirmation. Relaunches are the run's real cost: one relaunch serves every in-app target on that screen. Whole-module remains the intended default — this threshold estimates cost, it does not invite shrinking the audit."
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
"figma": {
|
|
96
|
+
"type": "object",
|
|
97
|
+
"additionalProperties": false,
|
|
98
|
+
"description": "Figma frame + variant mapping overrides.",
|
|
99
|
+
"properties": {
|
|
100
|
+
"url": { "type": "string", "description": "Default Figma MCP URL for this module's frame/page." },
|
|
101
|
+
"frameSize": {
|
|
102
|
+
"type": "object",
|
|
103
|
+
"additionalProperties": false,
|
|
104
|
+
"properties": { "w": { "type": "number" }, "h": { "type": "number" } },
|
|
105
|
+
"description": "Figma frame size the spec coordinates are in (usually auto-read)."
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
"variants": {
|
|
110
|
+
"type": "array",
|
|
111
|
+
"description": "Explicit mock-variant -> Figma-node mappings. When present, the picker skips name-similarity guessing for these.",
|
|
112
|
+
"items": {
|
|
113
|
+
"type": "object",
|
|
114
|
+
"additionalProperties": false,
|
|
115
|
+
"required": ["id", "figmaNodeId"],
|
|
116
|
+
"properties": {
|
|
117
|
+
"id": { "type": "string", "description": "Mock variant id (matches a variantsHint / fixture name)." },
|
|
118
|
+
"label": { "type": "string" },
|
|
119
|
+
"figmaNodeId": { "type": "string", "description": "Figma node id for this variant's frame." },
|
|
120
|
+
"activation": {
|
|
121
|
+
"type": "object",
|
|
122
|
+
"additionalProperties": true,
|
|
123
|
+
"description": "How to put the app into this variant (launch arg / UserDefaults values / navigation path)."
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
"capture": {
|
|
129
|
+
"type": "object",
|
|
130
|
+
"additionalProperties": false,
|
|
131
|
+
"description": "Capture / comparison tuning.",
|
|
132
|
+
"properties": {
|
|
133
|
+
"cropTopLive": { "type": "number", "description": "Pixels to crop from the top of the live capture (status bar)." },
|
|
134
|
+
"tolerancePx": { "type": "number", "default": 2 },
|
|
135
|
+
"colorTolerance": { "type": "number", "default": 3 },
|
|
136
|
+
"maxDiffPct": { "type": "number", "default": 1.0 }
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
"report": {
|
|
140
|
+
"type": "object",
|
|
141
|
+
"additionalProperties": false,
|
|
142
|
+
"description": "Report output + export.",
|
|
143
|
+
"properties": {
|
|
144
|
+
"outputRoot": { "type": "string", "description": "Report root dir (default ~/DesignChecks)." },
|
|
145
|
+
"formats": {
|
|
146
|
+
"type": "array",
|
|
147
|
+
"items": { "type": "string", "enum": ["html", "pdf", "confluence"] },
|
|
148
|
+
"default": ["html", "pdf"]
|
|
149
|
+
},
|
|
150
|
+
"confluence": {
|
|
151
|
+
"type": "object",
|
|
152
|
+
"additionalProperties": false,
|
|
153
|
+
"properties": {
|
|
154
|
+
"enabled": { "type": "boolean", "default": false },
|
|
155
|
+
"space": { "type": "string" },
|
|
156
|
+
"parentId": { "type": "string" }
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
@@ -12,22 +12,40 @@ export default function migrate(data) {
|
|
|
12
12
|
|
|
13
13
|
out.schemaVersion = "2.1.0";
|
|
14
14
|
|
|
15
|
-
// If projects[] doesn't exist and scalar
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
15
|
+
// If projects[] doesn't exist and the scalar mirrors do, create projects[0]
|
|
16
|
+
// from them. The item schema sets additionalProperties:false and requires
|
|
17
|
+
// project/projectRoot/branch/baseBranch/identity, so only emit keys the
|
|
18
|
+
// schema declares and only build the entry when every required key is
|
|
19
|
+
// populated - a partial entry would be schema-invalid, which is worse than
|
|
20
|
+
// no entry at all.
|
|
21
|
+
const canMirror =
|
|
22
|
+
!Array.isArray(out.projects) &&
|
|
23
|
+
typeof out.project === "string" &&
|
|
24
|
+
typeof out.projectRoot === "string" &&
|
|
25
|
+
typeof out.branch === "string" &&
|
|
26
|
+
typeof out.baseBranch === "string" &&
|
|
27
|
+
out.identity !== null &&
|
|
28
|
+
typeof out.identity === "object";
|
|
29
|
+
|
|
30
|
+
if (canMirror) {
|
|
31
|
+
const entry = {
|
|
32
|
+
project: out.project,
|
|
33
|
+
projectRoot: out.projectRoot,
|
|
34
|
+
branch: out.branch,
|
|
35
|
+
baseBranch: out.baseBranch,
|
|
36
|
+
identity: out.identity,
|
|
37
|
+
worktreePath: out.worktreePath ?? null,
|
|
26
38
|
commit: null,
|
|
27
39
|
pr: null,
|
|
28
40
|
pushAttempts: 0,
|
|
29
41
|
buildStatus: null,
|
|
30
|
-
}
|
|
42
|
+
};
|
|
43
|
+
// `platform` and `remoteType` are non-nullable enums: omit rather than null.
|
|
44
|
+
if (typeof out.remoteType === "string") {
|
|
45
|
+
entry.remoteType = out.remoteType;
|
|
46
|
+
entry.platform = out.remoteType;
|
|
47
|
+
}
|
|
48
|
+
out.projects = [entry];
|
|
31
49
|
}
|
|
32
50
|
|
|
33
51
|
return out;
|
|
@@ -5,6 +5,11 @@
|
|
|
5
5
|
"description": "User-level preferences. Written to $HOME/.claude/multi-agent-preferences.json. Never committed. Never synced to the open-source repo \u2014 may contain personal data.",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"additionalProperties": false,
|
|
8
|
+
"patternProperties": {
|
|
9
|
+
"^_": {
|
|
10
|
+
"description": "Documentation-only blocks shipped in preferences-template.json (_figmaConfigTemplate, _derivedSkillSourcesTemplate, _devToolkitTemplate). Copy-paste examples, never read by the pipeline."
|
|
11
|
+
}
|
|
12
|
+
},
|
|
8
13
|
"required": [
|
|
9
14
|
"schemaVersion",
|
|
10
15
|
"global",
|
|
@@ -101,7 +106,7 @@
|
|
|
101
106
|
"keychainMapping": {
|
|
102
107
|
"type": "object",
|
|
103
108
|
"additionalProperties": false,
|
|
104
|
-
"description": "Maps logical token names to actual Keychain item names. Pipeline looks up tokens via `security find-generic-password -s <mapped-name>` (or `pipeline/lib/credential-store.sh get` cross-platform).
|
|
109
|
+
"description": "Maps logical token names to actual Keychain item names. Pipeline looks up tokens via `security find-generic-password -s <mapped-name>` (or `pipeline/lib/credential-store.sh get` cross-platform). Covered keys: jira, bitbucket, bitbucket_token, bitbucket_user, github, confluence, figma, figma_pat, figma_user, figma_mcp, fortify, graylog, firebase, jenkins, npm, claude_oauth_token, claude_oauth_token_fallback.",
|
|
105
110
|
"properties": {
|
|
106
111
|
"jira": {
|
|
107
112
|
"type": [
|
|
@@ -164,6 +169,34 @@
|
|
|
164
169
|
"null"
|
|
165
170
|
]
|
|
166
171
|
},
|
|
172
|
+
"figma_pat": {
|
|
173
|
+
"type": [
|
|
174
|
+
"string",
|
|
175
|
+
"null"
|
|
176
|
+
],
|
|
177
|
+
"description": "Figma Personal Access Token. Tier 2 of the Figma access chain (REST API) resolves this key."
|
|
178
|
+
},
|
|
179
|
+
"figma_user": {
|
|
180
|
+
"type": [
|
|
181
|
+
"string",
|
|
182
|
+
"null"
|
|
183
|
+
],
|
|
184
|
+
"description": "Figma account identifier, when the REST flow needs it alongside figma_pat."
|
|
185
|
+
},
|
|
186
|
+
"claude_oauth_token": {
|
|
187
|
+
"type": [
|
|
188
|
+
"string",
|
|
189
|
+
"null"
|
|
190
|
+
],
|
|
191
|
+
"description": "Claude Code OAuth token used by headless / scheduled runs."
|
|
192
|
+
},
|
|
193
|
+
"claude_oauth_token_fallback": {
|
|
194
|
+
"type": [
|
|
195
|
+
"string",
|
|
196
|
+
"null"
|
|
197
|
+
],
|
|
198
|
+
"description": "Secondary OAuth token used when the primary is rate-limited or expired."
|
|
199
|
+
},
|
|
167
200
|
"firebase": {
|
|
168
201
|
"type": [
|
|
169
202
|
"string",
|
|
@@ -499,8 +532,39 @@
|
|
|
499
532
|
}
|
|
500
533
|
},
|
|
501
534
|
"defaultJiraKey": {
|
|
502
|
-
"type":
|
|
503
|
-
|
|
535
|
+
"type": [
|
|
536
|
+
"string",
|
|
537
|
+
"null"
|
|
538
|
+
],
|
|
539
|
+
"description": "Default Jira project key used for placeholder replacement. null until /multi-agent:setup onboards a Jira project."
|
|
540
|
+
},
|
|
541
|
+
"modelFallback": {
|
|
542
|
+
"type": "object",
|
|
543
|
+
"additionalProperties": false,
|
|
544
|
+
"description": "Model-tier fallback policy. When the premium tier is unavailable (quota, dispatch error, or an expired premium window) the pipeline drops to fallbackModel instead of failing the phase.",
|
|
545
|
+
"properties": {
|
|
546
|
+
"enabled": {
|
|
547
|
+
"type": "boolean",
|
|
548
|
+
"default": true,
|
|
549
|
+
"description": "Master switch for tier fallback."
|
|
550
|
+
},
|
|
551
|
+
"premiumTierUntil": {
|
|
552
|
+
"type": [
|
|
553
|
+
"string",
|
|
554
|
+
"null"
|
|
555
|
+
],
|
|
556
|
+
"description": "ISO date after which the premium tier is assumed gone. null = no expiry known."
|
|
557
|
+
},
|
|
558
|
+
"fallbackModel": {
|
|
559
|
+
"type": "string",
|
|
560
|
+
"description": "Model id used when the premium tier is unavailable."
|
|
561
|
+
},
|
|
562
|
+
"onDispatchError": {
|
|
563
|
+
"type": "boolean",
|
|
564
|
+
"default": true,
|
|
565
|
+
"description": "Also fall back when a dispatch call errors, not only on quota."
|
|
566
|
+
}
|
|
567
|
+
}
|
|
504
568
|
},
|
|
505
569
|
"hosts": {
|
|
506
570
|
"type": "object",
|
|
@@ -1130,6 +1194,94 @@
|
|
|
1130
1194
|
"default": false,
|
|
1131
1195
|
"description": "v7.0.0+ \u2014 Dynamic trigger-based skill loading. When enabled, the orchestrator reads `~/.claude/skills/.skills-index.json` after Phase 1 analysis and injects only the top-N matched skills into subagent prompts (via `match-skills.mjs`), instead of relying on eager-loaded SKILL.md bodies. Large token win on small tasks; no visible behavior change on big ones where many skills match. Requires either a full install (index is always shipped) or the `install.js --index-only` mode for users who want skill bodies fetched on demand. Off by default in v7.0 \u2014 flip to `true` to opt in; a future v7.x may flip the default once enough telemetry confirms no regression."
|
|
1132
1196
|
},
|
|
1197
|
+
"derivedSkillSources": {
|
|
1198
|
+
"type": "array",
|
|
1199
|
+
"description": "v11.3.0+. Skills/components in a project that were derived from an upstream marketplace plugin. `/multi-agent:refactor` Step 0b compares each entry's `derivedFromVersion` against the installed upstream version and reports drift (plan band D). Local-only: it may name private marketplaces, so it is never synced into the public repo. Empty array = the drift step is skipped.",
|
|
1200
|
+
"items": {
|
|
1201
|
+
"type": "object",
|
|
1202
|
+
"additionalProperties": false,
|
|
1203
|
+
"required": [
|
|
1204
|
+
"label",
|
|
1205
|
+
"localPath",
|
|
1206
|
+
"upstreamPlugin",
|
|
1207
|
+
"derivedFromVersion"
|
|
1208
|
+
],
|
|
1209
|
+
"properties": {
|
|
1210
|
+
"label": {
|
|
1211
|
+
"type": "string",
|
|
1212
|
+
"description": "Human name for this derivation, shown in the drift table."
|
|
1213
|
+
},
|
|
1214
|
+
"localPath": {
|
|
1215
|
+
"type": "string",
|
|
1216
|
+
"description": "Repo-relative directory holding our derived copy."
|
|
1217
|
+
},
|
|
1218
|
+
"upstreamMarketplace": {
|
|
1219
|
+
"type": "string",
|
|
1220
|
+
"description": "Installed marketplace name, resolved under ~/.claude/plugins/cache/<marketplace>/."
|
|
1221
|
+
},
|
|
1222
|
+
"upstreamPlugin": {
|
|
1223
|
+
"type": "string",
|
|
1224
|
+
"description": "Upstream plugin name inside that marketplace."
|
|
1225
|
+
},
|
|
1226
|
+
"upstreamSkills": {
|
|
1227
|
+
"type": "array",
|
|
1228
|
+
"items": { "type": "string" },
|
|
1229
|
+
"description": "The upstream skill names we took."
|
|
1230
|
+
},
|
|
1231
|
+
"derivedFromVersion": {
|
|
1232
|
+
"type": "string",
|
|
1233
|
+
"description": "Upstream version we last synced from. Bumped after a drift port is applied."
|
|
1234
|
+
},
|
|
1235
|
+
"upstreamRepoUrl": {
|
|
1236
|
+
"type": "string",
|
|
1237
|
+
"description": "Used only when the marketplace is not installed locally (WebFetch fallback)."
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
},
|
|
1242
|
+
"devToolkit": {
|
|
1243
|
+
"type": "object",
|
|
1244
|
+
"additionalProperties": false,
|
|
1245
|
+
"description": "v12.6.0+. The companion MCP server that serves the pipeline's device and browser tools (dev-toolkit-mcp). Two commands read this: `/multi-agent:refactor` Step 0c researches current MCP practice and audits that repo against it (plan band E), and `/multi-agent:sync` Step 3d ships it when it moved (gates, commit, publish). When absent, both commands fall back to auto-detecting the repo from the `mcpServers` registration in ~/.claude.json / ~/.claude/settings.json, and skip silently when that fails. Never a hardcoded path.",
|
|
1246
|
+
"properties": {
|
|
1247
|
+
"enabled": {
|
|
1248
|
+
"type": "boolean",
|
|
1249
|
+
"default": true,
|
|
1250
|
+
"description": "Set false to skip both the refactor band-E research and the sync ship step."
|
|
1251
|
+
},
|
|
1252
|
+
"label": {
|
|
1253
|
+
"type": "string",
|
|
1254
|
+
"description": "Human name used in reports."
|
|
1255
|
+
},
|
|
1256
|
+
"localPath": {
|
|
1257
|
+
"type": "string",
|
|
1258
|
+
"description": "Working copy of the companion repo. `$HOME` and `~` are expanded. When omitted, resolved from the MCP registration (dirname of the stdio server's script)."
|
|
1259
|
+
},
|
|
1260
|
+
"mcpServerName": {
|
|
1261
|
+
"type": "string",
|
|
1262
|
+
"default": "dev-toolkit",
|
|
1263
|
+
"description": "Registered MCP server name, used for the auto-detect fallback and for telling the user whether a restart or a reinstall is needed after a publish."
|
|
1264
|
+
},
|
|
1265
|
+
"packageName": {
|
|
1266
|
+
"type": "string",
|
|
1267
|
+
"description": "Published package name, e.g. @<scope>/<package>. Read from the repo's package.json when omitted."
|
|
1268
|
+
},
|
|
1269
|
+
"registry": {
|
|
1270
|
+
"type": "string",
|
|
1271
|
+
"enum": [
|
|
1272
|
+
"github-packages",
|
|
1273
|
+
"npmjs",
|
|
1274
|
+
"none"
|
|
1275
|
+
],
|
|
1276
|
+
"default": "github-packages",
|
|
1277
|
+
"description": "Publish target for Step 3d. `none` means commit + push only, never publish. The concrete URL comes from the repo's publishConfig; the token comes from the `npm` logical Keychain key through a throwaway --userconfig."
|
|
1278
|
+
},
|
|
1279
|
+
"repoUrl": {
|
|
1280
|
+
"type": "string",
|
|
1281
|
+
"description": "https remote, used in reports and when the working copy has to be cloned by the user."
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
},
|
|
1133
1285
|
"recentAccounts": {
|
|
1134
1286
|
"type": "array",
|
|
1135
1287
|
"description": "v7.3.0+. Last-used-first LRU of account ids (from account-resolver.sh). Used by autopilot to pick the most recent account when multiple are configured.",
|
|
@@ -1217,8 +1369,8 @@
|
|
|
1217
1369
|
"items": {
|
|
1218
1370
|
"type": "string"
|
|
1219
1371
|
},
|
|
1220
|
-
"maxItems":
|
|
1221
|
-
"description": "Bitbucket/generic default reviewers (usernames)."
|
|
1372
|
+
"maxItems": 40,
|
|
1373
|
+
"description": "Bitbucket/generic default reviewers (usernames). Real corporate reviewer groups run well past ten members."
|
|
1222
1374
|
},
|
|
1223
1375
|
"githubDefaultReviewers": {
|
|
1224
1376
|
"type": "array",
|
|
@@ -1290,6 +1442,10 @@
|
|
|
1290
1442
|
"format": "date-time",
|
|
1291
1443
|
"description": "Timestamp of last task start against this project."
|
|
1292
1444
|
},
|
|
1445
|
+
"componentDevWorkflow": {
|
|
1446
|
+
"type": "boolean",
|
|
1447
|
+
"description": "Project follows the component (Configuration / View / Modifiers) development workflow, so Phase 3 dispatches the component skills instead of the standard TDD flow."
|
|
1448
|
+
},
|
|
1293
1449
|
"figmaConfigPath": {
|
|
1294
1450
|
"type": "string",
|
|
1295
1451
|
"description": "Path to per-project figma-config.json (for Figma pipeline projects)."
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Pipeline Scripts - Category Index
|
|
2
2
|
|
|
3
|
-
The `pipeline/scripts/` directory holds
|
|
3
|
+
The `pipeline/scripts/` directory holds 148 shell scripts + 45 Node.js `.mjs` scripts in a flat layout. v6.0.0 evaluated moving them into `smoke/`, `hooks/`, `runtime/` subdirs and decided against it: each path change would need to propagate through `package.json` globs, `install.js` deploy logic, npm scripts, sibling script calls, and CI workflow references - a 40+ file touch radius with high regression risk for minor polish value.
|
|
4
4
|
|
|
5
|
-
Instead, this README is
|
|
5
|
+
Instead, this README is a curated category index of the key scripts, not an exhaustive listing. Use it to navigate.
|
|
6
6
|
|
|
7
|
-
## Smoke scripts (
|
|
7
|
+
## Smoke scripts (118 files - `smoke-*.sh`)
|
|
8
8
|
|
|
9
9
|
Validate contracts. Each emits `══ <name> smoke: N passed, M failed ══` on completion (the `smoke-personal-data.sh` + `smoke-token-budget.sh` suites use `PASS:` / `warnings:` variants). Run via `npm test` (chained) or individually.
|
|
10
10
|
|
|
@@ -57,6 +57,7 @@ Validate contracts. Each emits `══ <name> smoke: N passed, M failed ══`
|
|
|
57
57
|
- `smoke-search.sh` - `/multi-agent:search` log search + smart ranking
|
|
58
58
|
- `smoke-subagent-validators.sh` - Phase 1/2 validator schemas
|
|
59
59
|
- `smoke-telemetry.sh` - opt-in telemetry contract
|
|
60
|
+
- `smoke-learning-curve.sh` - `learning-curve.mjs` metrics-trend contract
|
|
60
61
|
- `smoke-validator-contradiction.sh` - Phase 4 approved/blocking contradiction detection
|
|
61
62
|
- `smoke-pre-commit.sh` - pre-commit hook integration
|
|
62
63
|
|
|
@@ -81,12 +82,13 @@ Shell scripts invoked during pipeline execution.
|
|
|
81
82
|
- `github-ssh-setup.sh` - first-run SSH key setup helper
|
|
82
83
|
- `sync-parity-check.sh` - manual parity verification helper
|
|
83
84
|
|
|
84
|
-
## Node.js helpers (
|
|
85
|
+
## Node.js helpers (45 `.mjs` files)
|
|
85
86
|
|
|
86
87
|
- `aggregate-metrics.mjs` - collects telemetry aggregates
|
|
88
|
+
- `learning-curve.mjs` - time-bucketed trend over `metrics.jsonl` (first-pass clean rate, review cycles, rework/task, tokens/task, cache ratio); `--bucket`, `--since`, `--json`, `--markdown`
|
|
87
89
|
- `eval-triage.mjs` - runs the 10 triage eval fixtures
|
|
88
90
|
- `gen-skills-index.mjs` - regenerates `pipeline/skills/shared/README.md` skill catalog
|
|
89
|
-
- `migrate-prefs.mjs` - preference migration driver (v2.0.0
|
|
91
|
+
- `migrate-prefs.mjs` - preference migration driver (v2.0.0 through v2.4.0)
|
|
90
92
|
- `migrate-state.mjs` - generic migration runner (reads `schemas/migrations/`)
|
|
91
93
|
- `token-budget-report.mjs` - per-phase token usage report
|
|
92
94
|
- `validate-analysis.mjs`, `validate-planning.mjs`, `validate-reviewer.mjs`, `validate-triage.mjs` - per-phase output validators
|