@mmerterden/multi-agent-pipeline 13.5.0 → 14.0.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.
Files changed (119) hide show
  1. package/CHANGELOG.md +243 -0
  2. package/README.md +3 -3
  3. package/docs/features.md +1 -1
  4. package/install/_common.mjs +73 -0
  5. package/install/_mcp-register.mjs +70 -31
  6. package/install/_plugin-skills.mjs +73 -14
  7. package/install/claude.mjs +28 -4
  8. package/install/codex.mjs +33 -2
  9. package/install/copilot.mjs +145 -9
  10. package/install/index.mjs +10 -6
  11. package/install/templates/copilot-instructions.md +1 -1
  12. package/package.json +1 -1
  13. package/pipeline/agents/code-reviewer.md +58 -1
  14. package/pipeline/commands/multi-agent/SKILL.md +7 -5
  15. package/pipeline/commands/multi-agent/analysis/SKILL.md +7 -7
  16. package/pipeline/commands/multi-agent/analysis-resolve/SKILL.md +1 -1
  17. package/pipeline/commands/multi-agent/build-optimize/SKILL.md +7 -7
  18. package/pipeline/commands/multi-agent/channels/SKILL.md +5 -5
  19. package/pipeline/commands/multi-agent/dev/SKILL.md +23 -18
  20. package/pipeline/commands/multi-agent/dev-autopilot/SKILL.md +19 -13
  21. package/pipeline/commands/multi-agent/dev-local/SKILL.md +14 -12
  22. package/pipeline/commands/multi-agent/dev-local-autopilot/SKILL.md +17 -12
  23. package/pipeline/commands/multi-agent/garbage-collect/SKILL.md +1 -1
  24. package/pipeline/commands/multi-agent/help/SKILL.md +4 -4
  25. package/pipeline/commands/multi-agent/ios-coding-standard/SKILL.md +2 -2
  26. package/pipeline/commands/multi-agent/local-autopilot/SKILL.md +4 -4
  27. package/pipeline/commands/multi-agent/resume/SKILL.md +1 -1
  28. package/pipeline/commands/multi-agent/review/SKILL.md +5 -5
  29. package/pipeline/commands/multi-agent/scan/SKILL.md +1 -1
  30. package/pipeline/commands/multi-agent/search/SKILL.md +1 -1
  31. package/pipeline/commands/multi-agent/setup/SKILL.md +6 -6
  32. package/pipeline/commands/multi-agent/{finish → ship}/SKILL.md +12 -12
  33. package/pipeline/commands/multi-agent/testflight-validation/SKILL.md +1 -1
  34. package/pipeline/commands/multi-agent/update/SKILL.md +5 -2
  35. package/pipeline/commands/sim-test.md +2 -2
  36. package/pipeline/lib/credential-store-resolver.sh +16 -0
  37. package/pipeline/lib/credential-store.sh +47 -4
  38. package/pipeline/lib/fetch-figma-annotations.sh +26 -28
  39. package/pipeline/lib/figma-screenshot.sh +28 -39
  40. package/pipeline/lib/figma-token.sh +63 -0
  41. package/pipeline/multi-agent-refs/analysis-template.md +1 -1
  42. package/pipeline/multi-agent-refs/android-guide.md +1 -1
  43. package/pipeline/multi-agent-refs/channels/issue-comment.md +1 -1
  44. package/pipeline/multi-agent-refs/component-dispatch.md +2 -2
  45. package/pipeline/multi-agent-refs/cross-cli-contract.md +4 -4
  46. package/pipeline/multi-agent-refs/features/dev-critic.md +2 -2
  47. package/pipeline/multi-agent-refs/features/model-fallback.md +35 -2
  48. package/pipeline/multi-agent-refs/features/plan-todos.md +1 -1
  49. package/pipeline/multi-agent-refs/features/repo-map.md +1 -1
  50. package/pipeline/multi-agent-refs/features/review-multi-repo.md +3 -3
  51. package/pipeline/multi-agent-refs/features/shadow-git.md +1 -1
  52. package/pipeline/multi-agent-refs/features/skill-conformance.md +116 -0
  53. package/pipeline/multi-agent-refs/features/verify-by-test.md +1 -1
  54. package/pipeline/multi-agent-refs/generate-issue.md +1 -1
  55. package/pipeline/multi-agent-refs/multi-repo-integration-build.md +1 -1
  56. package/pipeline/multi-agent-refs/phases/log-format.md +4 -4
  57. package/pipeline/multi-agent-refs/phases/modes.md +7 -7
  58. package/pipeline/multi-agent-refs/phases/phase-0-init.md +13 -11
  59. package/pipeline/multi-agent-refs/phases/phase-1-analysis.md +17 -15
  60. package/pipeline/multi-agent-refs/phases/phase-2-planning.md +7 -7
  61. package/pipeline/multi-agent-refs/phases/phase-3-dev.md +28 -13
  62. package/pipeline/multi-agent-refs/phases/phase-4-review.md +90 -58
  63. package/pipeline/multi-agent-refs/phases/phase-5-test.md +7 -7
  64. package/pipeline/multi-agent-refs/phases/phase-6-commit.md +8 -8
  65. package/pipeline/multi-agent-refs/phases/phase-7-report.md +8 -8
  66. package/pipeline/multi-agent-refs/phases.md +13 -13
  67. package/pipeline/multi-agent-refs/progress-contract.md +2 -2
  68. package/pipeline/multi-agent-refs/rules.md +7 -5
  69. package/pipeline/multi-agent-refs/swiftui-guide.md +1 -1
  70. package/pipeline/multi-agent-refs/tracker-contract.md +16 -15
  71. package/pipeline/preferences-template.json +7 -1
  72. package/pipeline/rules/figma-pipeline.md +2 -2
  73. package/pipeline/schemas/agent-state.schema.json +333 -79
  74. package/pipeline/schemas/criteria-manifest.schema.json +228 -0
  75. package/pipeline/schemas/migrations/prefs-2.4.0-to-2.5.0.mjs +64 -0
  76. package/pipeline/schemas/prefs.schema.json +118 -262
  77. package/pipeline/schemas/reviewer-output.schema.json +48 -3
  78. package/pipeline/schemas/token-budget.json +34 -10
  79. package/pipeline/schemas/triage-output.schema.json +112 -27
  80. package/pipeline/scripts/cost-table.json +7 -4
  81. package/pipeline/scripts/gc-worktrees.sh +1 -1
  82. package/pipeline/scripts/gen-mode-dispatch.mjs +6 -6
  83. package/pipeline/scripts/match-skills.mjs +37 -4
  84. package/pipeline/scripts/migrate-prefs.mjs +88 -17
  85. package/pipeline/scripts/phase-tracker.sh +14 -3
  86. package/pipeline/scripts/pre-commit-check.sh +49 -2
  87. package/pipeline/scripts/skill-conformance.mjs +960 -0
  88. package/pipeline/scripts/smoke-schema-validation.sh +17 -4
  89. package/pipeline/scripts/uninstall.mjs +35 -9
  90. package/pipeline/scripts/validate-reviewer.mjs +108 -1
  91. package/pipeline/skills/.skill-manifest.json +1 -1
  92. package/pipeline/skills/.skills-index.json +36 -9
  93. package/pipeline/skills/shared/README.md +15 -12
  94. package/pipeline/skills/shared/core/apple-archive-compliance/SKILL.md +1 -0
  95. package/pipeline/skills/shared/core/apple-archive-compliance/references/rules.yml +167 -0
  96. package/pipeline/skills/shared/core/google-play-compliance/SKILL.md +1 -0
  97. package/pipeline/skills/shared/core/google-play-compliance/references/rules.yml +184 -0
  98. package/pipeline/skills/shared/core/multi-agent/SKILL.md +10 -10
  99. package/pipeline/skills/shared/core/multi-agent-analysis/SKILL.md +4 -4
  100. package/pipeline/skills/shared/core/multi-agent-analysis-resolve/SKILL.md +3 -3
  101. package/pipeline/skills/shared/core/multi-agent-build-optimize/SKILL.md +2 -2
  102. package/pipeline/skills/shared/core/multi-agent-create-jira/SKILL.md +1 -1
  103. package/pipeline/skills/shared/core/multi-agent-dev/SKILL.md +6 -5
  104. package/pipeline/skills/shared/core/multi-agent-dev-autopilot/SKILL.md +7 -6
  105. package/pipeline/skills/shared/core/multi-agent-dev-local/SKILL.md +4 -3
  106. package/pipeline/skills/shared/core/multi-agent-dev-local-autopilot/SKILL.md +2 -1
  107. package/pipeline/skills/shared/core/multi-agent-help/SKILL.md +2 -2
  108. package/pipeline/skills/shared/core/multi-agent-ios-coding-standard/SKILL.md +1 -1
  109. package/pipeline/skills/shared/core/multi-agent-local-autopilot/SKILL.md +4 -4
  110. package/pipeline/skills/shared/core/multi-agent-review/SKILL.md +5 -5
  111. package/pipeline/skills/shared/core/multi-agent-scan/SKILL.md +1 -1
  112. package/pipeline/skills/shared/core/multi-agent-search/SKILL.md +1 -1
  113. package/pipeline/skills/shared/core/{multi-agent-finish → multi-agent-ship}/SKILL.md +8 -8
  114. package/pipeline/skills/shared/external/ios-coding-standard/SKILL.md +44 -5
  115. package/pipeline/skills/shared/external/ios-coding-standard/modules/_TEMPLATE.yml +82 -0
  116. package/pipeline/skills/shared/external/ios-coding-standard/references/STANDARD.md +169 -10
  117. package/pipeline/skills/shared/external/ios-coding-standard/references/lint-local.sh +13 -1
  118. package/pipeline/skills/shared/external/ios-coding-standard/references/rules.yml +335 -16
  119. package/pipeline/skills/skills-index.md +11 -8
@@ -0,0 +1,228 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/mmerterden/multi-agent-pipeline/pipeline/schemas/criteria-manifest.schema.json",
4
+ "title": "Criteria manifest",
5
+ "description": "What the changed code was supposed to honour, resolved deterministically by skill-conformance.mjs BEFORE any reviewer runs. Produced in Phase 4 Step 1.78, consumed by the reviewer prompt assembly (the ${CRITERIA} block) and by the triage merge. Written to disk so the denominator of 'was this done completely' is fixed in advance and cannot be renegotiated by a reviewer after the fact.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": [
9
+ "schemaVersion",
10
+ "ledger",
11
+ "languages",
12
+ "registries",
13
+ "selectedRules",
14
+ "selectedRuleCount",
15
+ "coverage",
16
+ "findings"
17
+ ],
18
+ "properties": {
19
+ "schemaVersion": { "type": "string", "const": "1.0.0" },
20
+ "generatedFor": {
21
+ "type": "object",
22
+ "additionalProperties": true,
23
+ "properties": {
24
+ "repoRoot": { "type": "string" },
25
+ "changedFileCount": { "type": "integer", "minimum": 0 }
26
+ }
27
+ },
28
+ "ledger": {
29
+ "type": "object",
30
+ "description": "Phase 3's self-report about which skills it consulted, and how much of it the resolver could corroborate. Never the source of coverage: an unrecorded consultation and no consultation are byte-identical in state, so a percentage computed from self-report reads green over an empty set.",
31
+ "additionalProperties": false,
32
+ "required": ["source", "selfReport", "entryCount"],
33
+ "properties": {
34
+ "source": {
35
+ "type": "string",
36
+ "enum": ["derived", "mixed", "declared"],
37
+ "description": "derived = resolver only, no usable self-report (the default and the fail-safe). mixed = a self-report existed and was cross-checked against the resolver. declared = reserved; no consumer may treat self-report as sufficient on its own."
38
+ },
39
+ "selfReport": {
40
+ "type": "string",
41
+ "enum": ["absent", "empty", "declared"],
42
+ "description": "Three distinct states, deliberately not collapsed. absent = no telemetry.skillCalls[] key at all. empty = the key exists and is []. declared = at least one entry. Rendering absent as 'nothing was applied' would make the completeness claim unfalsifiable."
43
+ },
44
+ "entryCount": { "type": "integer", "minimum": 0 },
45
+ "entriesMissingTargetFiles": {
46
+ "type": "integer",
47
+ "minimum": 0,
48
+ "description": "Entries with no targetFiles[]. A skill applied to the wrong files still counts as 'applied' without this, so coverage cannot be attributed and the entry is corroborating nothing."
49
+ },
50
+ "declaredButNotResolved": {
51
+ "type": "array",
52
+ "items": { "type": "string" },
53
+ "description": "Skills Phase 3 claims it used that the resolver could not bind to any changed file. Flagged, not trusted."
54
+ },
55
+ "note": { "type": "string" }
56
+ }
57
+ },
58
+ "languages": {
59
+ "type": "object",
60
+ "description": "Language census of the diff by file extension, the deterministic substitute for Phase 1 detectedStack (which does not exist in the dev modes). Describes what the diff CONTAINS rather than what the repo is nominally built in.",
61
+ "additionalProperties": { "type": "integer", "minimum": 1 }
62
+ },
63
+ "registries": {
64
+ "type": "array",
65
+ "items": {
66
+ "type": "object",
67
+ "additionalProperties": true,
68
+ "required": ["name", "totalRules", "selectedRules", "droppedRules", "loadedAs"],
69
+ "properties": {
70
+ "name": { "type": "string" },
71
+ "rulesPath": { "type": "string" },
72
+ "version": { "type": ["string", "null"] },
73
+ "totalRules": { "type": "integer", "minimum": 0 },
74
+ "selectedRules": { "type": "integer", "minimum": 0 },
75
+ "droppedRules": { "type": "integer", "minimum": 0 },
76
+ "droppedReasons": {
77
+ "type": "object",
78
+ "additionalProperties": { "type": "integer", "minimum": 1 },
79
+ "description": "Reason to count. A dropped rule is reported, never silent: silently narrowing the rule set is indistinguishable from the code passing it."
80
+ },
81
+ "scopeDeclared": {
82
+ "type": "boolean",
83
+ "description": "False means the registry did not declare languages or paths. Such a registry loads as reference-only and contributes no rule IDs, because applying an undeclared rule set to an unknown language manufactures findings and buries the real ones."
84
+ },
85
+ "scopeLanguages": { "type": "array", "items": { "type": "string" } },
86
+ "languagesMatched": { "type": "array", "items": { "type": "string" } },
87
+ "inScopeFileCount": { "type": "integer", "minimum": 0 },
88
+ "notCovered": {
89
+ "type": "object",
90
+ "additionalProperties": { "type": "string" },
91
+ "description": "Languages the registry explicitly disclaims. Quoted into the coverage gap so the report names WHY nothing applied."
92
+ },
93
+ "loadedAs": {
94
+ "type": "string",
95
+ "enum": ["rule-checklist", "reference-only", "not-applicable"],
96
+ "description": "rule-checklist = its rule IDs entered the denominator. reference-only = readable context, no IDs (undeclared scope). not-applicable = in scope by language but no changed file matched its paths."
97
+ },
98
+ "referenceOnlyReason": { "type": "string" },
99
+ "toolchains": {
100
+ "type": "array",
101
+ "items": {
102
+ "type": "object",
103
+ "additionalProperties": false,
104
+ "properties": {
105
+ "tool": { "type": "string" },
106
+ "wired": { "type": "boolean" },
107
+ "configCandidates": { "type": "array", "items": { "type": "string" } }
108
+ }
109
+ },
110
+ "description": "Linters the registry delegates its mechanical rules to. An unwired toolchain is itself a finding: those rules are unverified, and a review reporting no violations for them is reporting that nothing was measured."
111
+ },
112
+ "exceptionMarker": { "type": ["string", "null"] }
113
+ }
114
+ }
115
+ },
116
+ "unparseableRegistries": {
117
+ "type": "array",
118
+ "description": "Declared registries that could not be read. Non-empty makes the gate exit 2 (fail closed): continuing would drop a whole rule set from the denominator and report a clean review over criteria never loaded.",
119
+ "items": {
120
+ "type": "object",
121
+ "additionalProperties": false,
122
+ "properties": {
123
+ "name": { "type": "string" },
124
+ "path": { "type": "string" },
125
+ "reason": { "type": "string" }
126
+ }
127
+ }
128
+ },
129
+ "selectedRules": {
130
+ "type": "array",
131
+ "description": "The denominator. Every entry must come back from the reviewers with a verdict or an explicit waiver; an ID that is neither checked nor waived fails the stage.",
132
+ "items": {
133
+ "type": "object",
134
+ "additionalProperties": false,
135
+ "required": ["ruleId", "registry", "severity", "enforcement", "files"],
136
+ "properties": {
137
+ "ruleId": { "type": "string", "minLength": 1 },
138
+ "registry": { "type": "string" },
139
+ "severity": { "type": "string", "enum": ["blocking", "important", "suggestion"] },
140
+ "enforcement": { "type": "string", "enum": ["format", "lint", "scan", "judgement"] },
141
+ "files": { "type": "array", "items": { "type": "string" }, "minItems": 1 },
142
+ "statusDeclared": {
143
+ "type": "boolean",
144
+ "description": "Whether the rule carried an explicit status. No shipped registry populates status today, so a missing one means active and is recorded rather than assumed."
145
+ }
146
+ }
147
+ }
148
+ },
149
+ "selectedRuleCount": { "type": "integer", "minimum": 0 },
150
+ "coverage": {
151
+ "type": "object",
152
+ "additionalProperties": false,
153
+ "required": [
154
+ "changedFiles",
155
+ "filesWithRuleCriteria",
156
+ "filesWithoutRuleCriteria",
157
+ "declaredGaps"
158
+ ],
159
+ "properties": {
160
+ "changedFiles": { "type": "integer", "minimum": 0 },
161
+ "filesWithRuleCriteria": { "type": "integer", "minimum": 0 },
162
+ "filesWithoutRuleCriteria": { "type": "integer", "minimum": 0 },
163
+ "uncoveredFiles": { "type": "array", "items": { "type": "string" } },
164
+ "declaredGaps": {
165
+ "type": "array",
166
+ "description": "A language in the diff that no registry covers. Declared explicitly so 'no rule applied' is distinguishable from 'every rule passed'.",
167
+ "items": {
168
+ "type": "object",
169
+ "additionalProperties": false,
170
+ "required": ["language", "fileCount", "reason"],
171
+ "properties": {
172
+ "language": { "type": "string" },
173
+ "fileCount": { "type": "integer", "minimum": 1 },
174
+ "files": { "type": "array", "items": { "type": "string" } },
175
+ "reason": { "type": "string" },
176
+ "consequence": { "type": "string" }
177
+ }
178
+ }
179
+ }
180
+ }
181
+ },
182
+ "moduleGuides": {
183
+ "type": "object",
184
+ "additionalProperties": false,
185
+ "properties": {
186
+ "guides": { "type": "array", "items": { "type": "string" } },
187
+ "dropped": { "type": "array", "items": { "type": "string" } },
188
+ "cap": { "type": "integer", "minimum": 1 }
189
+ },
190
+ "description": "In-repo convention guides on the changed files' directory chains. One criteria source inside this manifest, not a parallel list."
191
+ },
192
+ "findings": {
193
+ "type": "array",
194
+ "description": "Deterministic findings, reviewer-shaped so Step 3.0 merges them alongside the test-integrity set and triage adjudicates them instead of never seeing them.",
195
+ "items": {
196
+ "type": "object",
197
+ "additionalProperties": false,
198
+ "required": ["severity", "file", "line", "issue", "fix"],
199
+ "properties": {
200
+ "severity": { "type": "string", "enum": ["blocking", "important", "suggestion"] },
201
+ "file": { "type": "string", "minLength": 1 },
202
+ "line": { "type": "integer", "minimum": 0 },
203
+ "issue": { "type": "string", "minLength": 4 },
204
+ "fix": { "type": "string", "minLength": 4 },
205
+ "ruleId": { "type": "string" },
206
+ "criteriaSource": { "type": "string" }
207
+ }
208
+ }
209
+ },
210
+ "skillsRootsSearched": {
211
+ "type": "array",
212
+ "description": "Every candidate root that was PROBED, each flagged with whether it existed. Recorded because the skills root differs per host and scripts/ is installed without path rewriting, so an empty result must be attributable to a root rather than to an absence of registries. Earlier this listed only the roots that existed, which made it empty in exactly the case it exists to explain: zero roots produced [], leaving 'no registries installed' and 'wrong root' indistinguishable.",
213
+ "items": {
214
+ "type": "object",
215
+ "additionalProperties": false,
216
+ "required": ["path", "existed"],
217
+ "properties": {
218
+ "path": { "type": "string" },
219
+ "existed": { "type": "boolean" }
220
+ }
221
+ }
222
+ },
223
+ "resolutionFailure": {
224
+ "type": ["string", "null"],
225
+ "description": "Non-null when criteria could not be resolved at all (no skills root existed). The gate exits 2 in that case: a manifest with zero selected rules makes validate-reviewer.mjs skip the conformance check, so the review would read as clean over criteria that were never loaded. An empty registry set inside a root that DOES exist is the different, legitimate case and stays exit 0 with a declared coverage gap."
226
+ }
227
+ }
228
+ }
@@ -0,0 +1,64 @@
1
+ /**
2
+ * prefs-2.4.0-to-2.5.0.mjs - preference schema upgrade 2.4.0 -> 2.5.0
3
+ *
4
+ * v14.0.0 put Phase 4 Review into the four `--dev` mode phase sets and added the
5
+ * criteria-resolution stage (Phase 4 Step 1.78). Two preference keys follow:
6
+ *
7
+ * - global.skillConformance.blockOnCoverageGap (default FALSE)
8
+ * Whether a declared coverage gap - a language in the diff that no rule
9
+ * registry covers - halts the run. Default false on purpose: today only
10
+ * Swift, plus the two store-compliance catalogs, ship a scoped registry, so
11
+ * defaulting this true would block every Kotlin, Python, Node and
12
+ * Objective-C run from the moment it lands. The gap is always REPORTED
13
+ * either way; this only controls whether it stops the pipeline.
14
+ *
15
+ * There is deliberately no key for the stage itself, and none for the
16
+ * exception-expiry check, on the same grounds as Phase 4 Step 1.76: a run
17
+ * that can switch off its own anti-reward-hacking control cannot be
18
+ * trusted to report a pass.
19
+ *
20
+ * - global.ship.autoFix (default FALSE)
21
+ * Already referenced by the tail command's spec as `prefs.global.finish
22
+ * .autoFix` but never declared in the schema, so it could not validate and
23
+ * a user setting it got no protection from `additionalProperties: false`.
24
+ * Declared here under the command's new name (`finish` -> `ship`), and any
25
+ * value the user had under the old key is carried over rather than dropped.
26
+ *
27
+ * Idempotent: safe on already-2.5.0 input. Non-destructive: an existing explicit
28
+ * value for either key is preserved.
29
+ *
30
+ * @param {object} data - parsed JSON content of the preferences file
31
+ * @returns {object} - same data with schemaVersion = "2.5.0"
32
+ */
33
+ export default function migrate(data) {
34
+ const out = JSON.parse(JSON.stringify(data));
35
+
36
+ out.schemaVersion = "2.5.0";
37
+
38
+ if (!out.global) out.global = {};
39
+
40
+ if (typeof out.global.skillConformance !== "object" || out.global.skillConformance === null) {
41
+ out.global.skillConformance = {};
42
+ }
43
+ if (typeof out.global.skillConformance.blockOnCoverageGap !== "boolean") {
44
+ out.global.skillConformance.blockOnCoverageGap = false;
45
+ }
46
+
47
+ if (typeof out.global.ship !== "object" || out.global.ship === null) {
48
+ out.global.ship = {};
49
+ }
50
+ if (typeof out.global.ship.autoFix !== "boolean") {
51
+ // Carry the value across the finish -> ship rename instead of resetting it:
52
+ // a user who opted into auto-fix did so deliberately.
53
+ const legacy = out.global.finish?.autoFix;
54
+ out.global.ship.autoFix = typeof legacy === "boolean" ? legacy : false;
55
+ }
56
+ // The old key is not a declared property, so leaving it behind would fail
57
+ // validation against a closed `global`.
58
+ if (out.global.finish && typeof out.global.finish === "object") {
59
+ delete out.global.finish.autoFix;
60
+ if (Object.keys(out.global.finish).length === 0) delete out.global.finish;
61
+ }
62
+
63
+ return out;
64
+ }