@mmerterden/multi-agent-pipeline 12.5.0 → 12.7.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 +213 -0
- package/README.md +19 -19
- package/docs/FIGMA_PIPELINE.md +34 -34
- package/docs/adr/0001-three-model-triage.md +12 -12
- package/docs/adr/0002-instruction-driven-flag.md +5 -5
- package/docs/adr/0003-unified-shared-skills.md +5 -5
- package/docs/adr/0004-zero-dependency-philosophy.md +5 -5
- package/docs/adr/0005-lazy-phase-docs.md +2 -2
- package/docs/adr/0006-skills-core-external-split.md +6 -6
- package/docs/adr/0007-multi-tool-adapter-framework.md +19 -19
- package/docs/adr/0008-installer-modularization-and-secret-leak-defense.md +19 -19
- package/docs/adr/README.md +1 -1
- package/docs/best-practices.md +3 -3
- package/docs/features.md +48 -28
- package/docs/performance.md +16 -16
- package/docs/recovery-guide.md +39 -39
- package/index.js +11 -5
- package/install/_common.mjs +5 -11
- package/install/_copilot-instructions.mjs +2 -2
- package/install/_dev-only-files.mjs +2 -1
- package/install/_platform-filter.mjs +1 -1
- package/install/_telemetry.mjs +1 -1
- package/install/claude.mjs +10 -9
- package/install/copilot.mjs +10 -19
- package/install/index.mjs +7 -15
- package/install/templates/copilot-instructions.md +54 -54
- package/install.js +1 -1
- package/package.json +15 -11
- package/pipeline/agents/security-auditor.md +1 -1
- package/pipeline/commands/archive-guard.md +5 -5
- package/pipeline/commands/multi-agent/SKILL.md +3 -1
- package/pipeline/commands/multi-agent/analysis/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/analysis-resolve/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/autopilot/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/build-optimize/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/create-jira/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/design-check/SKILL.md +287 -0
- package/pipeline/commands/multi-agent/dev/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/dev-autopilot/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/dev-local/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/dev-local-autopilot/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/diff-explain/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/finish/SKILL.md +6 -6
- package/pipeline/commands/multi-agent/forget/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/garbage-collect/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/help/SKILL.md +46 -6
- package/pipeline/commands/multi-agent/issue/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/jira/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/kill/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/language/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/local/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/local-autopilot/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/log/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/manual-test/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/prune-logs/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/purge/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/refactor/SKILL.md +107 -19
- package/pipeline/commands/multi-agent/resume/SKILL.md +2 -2
- package/pipeline/commands/multi-agent/review/SKILL.md +2 -2
- package/pipeline/commands/multi-agent/review-issue/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/review-jira/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/routines/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/save/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/scan/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/search/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/setup/SKILL.md +2 -2
- package/pipeline/commands/multi-agent/stack/SKILL.md +3 -3
- package/pipeline/commands/multi-agent/status/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/sync/SKILL.md +123 -16
- package/pipeline/commands/multi-agent/test/SKILL.md +2 -2
- package/pipeline/commands/multi-agent/uninstall/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/update/SKILL.md +3 -3
- package/pipeline/commands/sim-test.md +5 -5
- package/pipeline/eval/run-metrics-fixture.json +60 -13
- package/pipeline/lib/account-resolver.sh +1 -1
- package/pipeline/lib/channels-multi-repo.sh +1 -1
- package/pipeline/lib/context-link-extractor.sh +1 -1
- package/pipeline/lib/credential-store.sh +33 -1
- package/pipeline/lib/fetch-confluence.sh +1 -1
- package/pipeline/lib/fetch-crashlytics.sh +1 -1
- package/pipeline/lib/fetch-fortify.sh +1 -1
- package/pipeline/lib/fetch-graylog.sh +1 -1
- package/pipeline/lib/fetch-swagger.sh +1 -1
- package/pipeline/lib/issue-fetcher.sh +1 -1
- package/pipeline/lib/multi-repo-pipeline.sh +1 -1
- package/pipeline/lib/repo-cache.sh +1 -1
- package/pipeline/lib/submodule-detector.sh +1 -1
- package/pipeline/multi-agent-refs/component-dispatch.md +1 -1
- package/pipeline/multi-agent-refs/component-generation.md +121 -0
- package/pipeline/multi-agent-refs/cross-cli-contract.md +4 -4
- package/pipeline/multi-agent-refs/features/model-fallback.md +2 -2
- package/pipeline/multi-agent-refs/phases/phase-3-dev.md +2 -2
- package/pipeline/multi-agent-refs/phases/phase-4-review.md +1 -1
- package/pipeline/multi-agent-refs/phases/phase-5-test.md +4 -4
- package/pipeline/preferences-template.json +23 -12
- package/pipeline/schemas/agent-state.schema.json +125 -5
- package/pipeline/schemas/analysis-output.schema.json +18 -4
- package/pipeline/schemas/analysis-spec.schema.json +120 -32
- package/pipeline/schemas/clarify-output.schema.json +15 -5
- package/pipeline/schemas/design-check-config.schema.json +183 -0
- package/pipeline/schemas/dev-critic-output.schema.json +20 -5
- package/pipeline/schemas/figma-project-config.schema.json +42 -10
- package/pipeline/schemas/learnings-ledger.schema.json +10 -2
- package/pipeline/schemas/migrations/figma-config-1.0.0-to-2.0.0.mjs +1 -4
- package/pipeline/schemas/migrations/prefs-2.0.0-to-2.1.0.mjs +24 -7
- package/pipeline/schemas/migrations/state-2.0.0-to-2.1.0.mjs +30 -12
- package/pipeline/schemas/plan-todos.schema.json +6 -3
- package/pipeline/schemas/planning-output.schema.json +5 -1
- package/pipeline/schemas/prefs.schema.json +215 -197
- package/pipeline/schemas/test-gap.schema.json +5 -5
- package/pipeline/schemas/token-budget.json +8 -8
- package/pipeline/schemas/triage-corpus.schema.json +1 -1
- package/pipeline/scripts/README.md +7 -5
- package/pipeline/scripts/aggregate-metrics.mjs +18 -6
- package/pipeline/scripts/build-skills-index.mjs +6 -2
- package/pipeline/scripts/build-stack-plugins.mjs +142 -39
- package/pipeline/scripts/check-derived-drift.mjs +196 -0
- package/pipeline/scripts/check-md-links.mjs +6 -2
- package/pipeline/scripts/classify-plan-safety.mjs +26 -8
- package/pipeline/scripts/cost-budget-check.mjs +11 -6
- package/pipeline/scripts/cost-table.json +1 -1
- package/pipeline/scripts/diff-explain.mjs +7 -3
- package/pipeline/scripts/diff-risk-score.mjs +13 -3
- package/pipeline/scripts/eval-golden-tasks-live.mjs +8 -3
- package/pipeline/scripts/eval-golden-tasks.mjs +21 -9
- package/pipeline/scripts/eval-intent.mjs +8 -4
- package/pipeline/scripts/eval-mine-corpus.mjs +14 -4
- package/pipeline/scripts/evidence-gate.mjs +7 -2
- package/pipeline/scripts/fixtures/install-layout.tsv +7 -7
- package/pipeline/scripts/gen-mode-dispatch.mjs +38 -21
- package/pipeline/scripts/gen-skills-index.mjs +18 -3
- package/pipeline/scripts/learning-curve.mjs +13 -3
- package/pipeline/scripts/learnings-ledger.mjs +119 -34
- package/pipeline/scripts/lint-mcp-refs.mjs +218 -0
- package/pipeline/scripts/lint-skills.mjs +20 -9
- package/pipeline/scripts/localize-commands.mjs +6 -1
- package/pipeline/scripts/match-skills.mjs +15 -4
- package/pipeline/scripts/memory-load.sh +5 -1
- package/pipeline/scripts/migrate-prefs.mjs +33 -16
- package/pipeline/scripts/phase-tracker.sh +3 -1
- package/pipeline/scripts/render-work-summary.sh +4 -1
- package/pipeline/scripts/repo-map.mjs +110 -64
- package/pipeline/scripts/review-scope.mjs +7 -1
- package/pipeline/scripts/routine-registry.mjs +4 -9
- package/pipeline/scripts/run-aggregator.mjs +11 -5
- package/pipeline/scripts/run-metrics.mjs +13 -8
- package/pipeline/scripts/run-smokes.mjs +57 -3
- package/pipeline/scripts/scorecard.mjs +258 -0
- 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-context-budget.sh +72 -0
- package/pipeline/scripts/smoke-cross-cli-behavior.sh +12 -2
- package/pipeline/scripts/smoke-generate-issue.sh +6 -5
- package/pipeline/scripts/smoke-model-fallback.sh +1 -1
- package/pipeline/scripts/smoke-no-mcp-in-dev-phases.sh +86 -7
- package/pipeline/scripts/smoke-own-punctuation.sh +103 -0
- 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/smoke-workflow-audit.sh +43 -11
- package/pipeline/scripts/smoke-write-state.sh +49 -5
- package/pipeline/scripts/test-gap-rules/android.json +11 -11
- package/pipeline/scripts/test-gap-rules/ios.json +16 -11
- package/pipeline/scripts/test-gap-rules/node.json +19 -7
- package/pipeline/scripts/test-gap-rules/python.json +10 -4
- package/pipeline/scripts/test-gap-scan.mjs +44 -12
- package/pipeline/scripts/test-integrity-gate.mjs +5 -1
- package/pipeline/scripts/token-budget-report.mjs +44 -21
- package/pipeline/scripts/triage-memory.mjs +142 -32
- package/pipeline/scripts/uninstall.mjs +75 -31
- package/pipeline/scripts/validate-analysis-doc.mjs +15 -5
- package/pipeline/scripts/validate-diff-risk.mjs +32 -18
- package/pipeline/scripts/validate-test-gap.mjs +17 -7
- package/pipeline/scripts/validate-triage.mjs +17 -5
- package/pipeline/scripts/write-state.mjs +32 -9
- package/pipeline/skills/.skill-manifest.json +24 -8
- package/pipeline/skills/.skills-index.json +125 -89
- package/pipeline/skills/shared/README.md +65 -61
- package/pipeline/skills/shared/core/apple-archive-compliance/SKILL.md +10 -8
- package/pipeline/skills/shared/core/google-play-compliance/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent/SKILL.md +26 -279
- package/pipeline/skills/shared/core/multi-agent-analysis/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-analysis-resolve/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-autopilot/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-build-optimize/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-create-jira/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-design-check/SKILL.md +248 -0
- package/pipeline/skills/shared/core/multi-agent-dev/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-dev-autopilot/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-dev-local/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-dev-local-autopilot/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-diff-explain/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-finish/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-forget/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-garbage-collect/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-help/SKILL.md +23 -1
- package/pipeline/skills/shared/core/multi-agent-issue/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-jira/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-kill/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-language/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-local/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-local-autopilot/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-log/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-manual-test/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-prune-logs/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-purge/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-refactor/SKILL.md +82 -18
- package/pipeline/skills/shared/core/multi-agent-resume/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-review/SKILL.md +2 -2
- package/pipeline/skills/shared/core/multi-agent-review-issue/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-review-jira/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-routines/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-save/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-scan/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-search/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-setup/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-stack/SKILL.md +3 -3
- package/pipeline/skills/shared/core/multi-agent-status/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 +2 -2
- package/pipeline/skills/shared/core/multi-agent-uninstall/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-update/SKILL.md +1 -1
- package/pipeline/skills/shared/external/accessibility-compliance-accessibility-audit/SKILL.md +1 -1
- package/pipeline/skills/shared/external/agent-introspection-debugging/SKILL.md +4 -4
- package/pipeline/skills/shared/external/agentflow/SKILL.md +1 -1
- package/pipeline/skills/shared/external/android-jetpack-compose-expert/SKILL.md +1 -1
- package/pipeline/skills/shared/external/android_ui_verification/SKILL.md +1 -1
- package/pipeline/skills/shared/external/api-patterns/SKILL.md +1 -1
- package/pipeline/skills/shared/external/api-security-best-practices/SKILL.md +1 -1
- package/pipeline/skills/shared/external/app-store-changelog/SKILL.md +1 -1
- package/pipeline/skills/shared/external/backlog/BACKLOG.md +1 -1
- package/pipeline/skills/shared/external/backlog/SKILL.md +12 -12
- package/pipeline/skills/shared/external/ci-cd-pipelines/SKILL.md +1 -1
- package/pipeline/skills/shared/external/context-compression/SKILL.md +1 -1
- package/pipeline/skills/shared/external/council/SKILL.md +3 -3
- package/pipeline/skills/shared/external/css-modern/SKILL.md +1 -1
- package/pipeline/skills/shared/external/database-patterns/SKILL.md +1 -1
- package/pipeline/skills/shared/external/debugging-strategies/SKILL.md +1 -1
- package/pipeline/skills/shared/external/docker-expert/SKILL.md +1 -1
- package/pipeline/skills/shared/external/fastapi-pro/SKILL.md +1 -1
- package/pipeline/skills/shared/external/firebase/SKILL.md +1 -1
- package/pipeline/skills/shared/external/github-actions-templates/SKILL.md +1 -1
- package/pipeline/skills/shared/external/help-skills/SKILL.md +1 -1
- package/pipeline/skills/shared/external/hig-components-content/SKILL.md +1 -1
- package/pipeline/skills/shared/external/hig-components-layout/SKILL.md +1 -1
- package/pipeline/skills/shared/external/hig-components-status/SKILL.md +1 -1
- package/pipeline/skills/shared/external/hig-components-system/SKILL.md +1 -1
- package/pipeline/skills/shared/external/hig-foundations/SKILL.md +1 -1
- package/pipeline/skills/shared/external/hig-inputs/SKILL.md +1 -1
- package/pipeline/skills/shared/external/hig-patterns/SKILL.md +1 -1
- package/pipeline/skills/shared/external/hig-platforms/SKILL.md +1 -1
- package/pipeline/skills/shared/external/hig-technologies/SKILL.md +1 -1
- package/pipeline/skills/shared/external/html-semantic/SKILL.md +1 -1
- package/pipeline/skills/shared/external/humanizer/SKILL.md +1 -1
- package/pipeline/skills/shared/external/ios-debugger-agent/SKILL.md +1 -1
- package/pipeline/skills/shared/external/ios-developer/SKILL.md +1 -1
- package/pipeline/skills/shared/external/kotlin-coroutines-expert/SKILL.md +1 -1
- package/pipeline/skills/shared/external/macos-menubar-tuist-app/SKILL.md +1 -1
- package/pipeline/skills/shared/external/macos-spm-app-packaging/SKILL.md +1 -1
- package/pipeline/skills/shared/external/monorepo-architect/SKILL.md +1 -1
- package/pipeline/skills/shared/external/nextjs-app-router/SKILL.md +1 -1
- package/pipeline/skills/shared/external/nodejs-backend-patterns/SKILL.md +1 -1
- package/pipeline/skills/shared/external/observability-engineer/SKILL.md +1 -1
- package/pipeline/skills/shared/external/python-patterns/SKILL.md +1 -1
- package/pipeline/skills/shared/external/react-best-practices/SKILL.md +1 -1
- package/pipeline/skills/shared/external/rest-api-design/SKILL.md +1 -1
- package/pipeline/skills/shared/external/search-first/SKILL.md +2 -2
- package/pipeline/skills/shared/external/skill-creator/SKILL.md +12 -12
- package/pipeline/skills/shared/external/skill-creator/audit.md +21 -21
- package/pipeline/skills/shared/external/skill-creator/checklist.md +3 -3
- package/pipeline/skills/shared/external/skill-creator/examples.md +10 -10
- package/pipeline/skills/shared/external/skill-creator/label-check.md +17 -17
- package/pipeline/skills/shared/external/skill-creator/scripts/audit-panel.js +86 -50
- package/pipeline/skills/shared/external/skill-creator/template.md +9 -9
- package/pipeline/skills/shared/external/swift-concurrency-expert/SKILL.md +1 -1
- package/pipeline/skills/shared/external/swiftui-performance-audit/SKILL.md +1 -1
- package/pipeline/skills/shared/external/swiftui-ui-patterns/SKILL.md +1 -1
- package/pipeline/skills/shared/external/swiftui-view-refactor/SKILL.md +1 -1
- package/pipeline/skills/shared/external/tailwind-css/SKILL.md +1 -1
- package/pipeline/skills/shared/external/testing-backend/SKILL.md +1 -1
- package/pipeline/skills/shared/external/typescript-patterns/SKILL.md +1 -1
- package/pipeline/skills/shared/external/vue-composition/SKILL.md +1 -1
- package/pipeline/skills/shared/external/web-accessibility/SKILL.md +1 -1
- package/pipeline/skills/shared/external/web-performance/SKILL.md +1 -1
- package/pipeline/skills/shared/external/web-testing/SKILL.md +1 -1
- package/pipeline/skills/shared/external/xcode-build-benchmark/schemas/build-benchmark.schema.json +9 -49
- package/pipeline/skills/skills-index.md +63 -59
- package/pipeline/scripts/smoke-plugin-validate.sh +0 -64
|
@@ -64,10 +64,7 @@ export const PIPELINE_AGENT_FILES = [
|
|
|
64
64
|
* Non-multi-agent core skills the installer ships from
|
|
65
65
|
* pipeline/skills/shared/core/ (the multi-agent* dirs are matched by prefix).
|
|
66
66
|
*/
|
|
67
|
-
export const PIPELINE_CORE_SKILL_DIRS = [
|
|
68
|
-
"apple-archive-compliance",
|
|
69
|
-
"google-play-compliance",
|
|
70
|
-
];
|
|
67
|
+
export const PIPELINE_CORE_SKILL_DIRS = ["apple-archive-compliance", "google-play-compliance"];
|
|
71
68
|
|
|
72
69
|
const flags = process.argv.slice(2).filter((a) => a !== "uninstall");
|
|
73
70
|
|
|
@@ -79,14 +76,15 @@ const TOOL_FLAGS = [
|
|
|
79
76
|
"--antigravity",
|
|
80
77
|
"--codex",
|
|
81
78
|
];
|
|
82
|
-
const explicitlyTargeted =
|
|
83
|
-
flags.some((f) => TOOL_FLAGS.includes(f)) || flags.includes("--all");
|
|
79
|
+
const explicitlyTargeted = flags.some((f) => TOOL_FLAGS.includes(f)) || flags.includes("--all");
|
|
84
80
|
|
|
85
81
|
const forClaude = flags.includes("--claude") || flags.includes("--all") || !explicitlyTargeted;
|
|
86
82
|
const forCopilot = flags.includes("--copilot") || flags.includes("--all") || !explicitlyTargeted;
|
|
87
83
|
const forCursor = flags.includes("--cursor") || flags.includes("--all") || !explicitlyTargeted;
|
|
88
|
-
const forCopilotChat =
|
|
89
|
-
|
|
84
|
+
const forCopilotChat =
|
|
85
|
+
flags.includes("--copilot-chat") || flags.includes("--all") || !explicitlyTargeted;
|
|
86
|
+
const forAntigravity =
|
|
87
|
+
flags.includes("--antigravity") || flags.includes("--all") || !explicitlyTargeted;
|
|
90
88
|
const forCodex = flags.includes("--codex") || flags.includes("--all") || !explicitlyTargeted;
|
|
91
89
|
|
|
92
90
|
const dryRun = flags.includes("--dry-run");
|
|
@@ -194,8 +192,7 @@ function legacyTrailingContent(section) {
|
|
|
194
192
|
function stripManagedBlock(filePath) {
|
|
195
193
|
if (!existsSync(filePath)) return false;
|
|
196
194
|
const content = readFileSync(filePath, "utf-8");
|
|
197
|
-
const re =
|
|
198
|
-
/\s*<!-- multi-agent-pipeline:begin -->[\s\S]*?<!-- multi-agent-pipeline:end -->\s*/m;
|
|
195
|
+
const re = /\s*<!-- multi-agent-pipeline:begin -->[\s\S]*?<!-- multi-agent-pipeline:end -->\s*/m;
|
|
199
196
|
if (!re.test(content)) {
|
|
200
197
|
// Copilot's install (install/copilot.mjs) does not wrap the block in
|
|
201
198
|
// begin/end markers. v11.4.1+ writes an explicit end marker after the
|
|
@@ -276,8 +273,10 @@ function cleanClaudeSettings(settingsPath) {
|
|
|
276
273
|
// entry as ours either way.
|
|
277
274
|
settings.hooks.PreToolUse = settings.hooks.PreToolUse.filter(
|
|
278
275
|
(h) =>
|
|
279
|
-
!(
|
|
280
|
-
h.
|
|
276
|
+
!(
|
|
277
|
+
(h.matcher === "Bash" || h.matcher === "Bash(git commit:*)") &&
|
|
278
|
+
h.hooks?.some((sub) => sub.command?.includes("pre-commit-check.sh"))
|
|
279
|
+
),
|
|
281
280
|
);
|
|
282
281
|
if (settings.hooks.PreToolUse.length < before) touched = true;
|
|
283
282
|
if (settings.hooks.PreToolUse.length === 0) delete settings.hooks.PreToolUse;
|
|
@@ -305,7 +304,7 @@ async function confirm(question) {
|
|
|
305
304
|
});
|
|
306
305
|
}
|
|
307
306
|
|
|
308
|
-
async function main() {
|
|
307
|
+
export async function main() {
|
|
309
308
|
console.log("");
|
|
310
309
|
console.log(" multi-agent-pipeline uninstaller");
|
|
311
310
|
console.log(" ================================");
|
|
@@ -313,12 +312,28 @@ async function main() {
|
|
|
313
312
|
if (dryRun) console.log(" [DRY-RUN] Nothing will be modified.");
|
|
314
313
|
console.log("");
|
|
315
314
|
console.log(" Targets:");
|
|
316
|
-
if (forClaude)
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
if (
|
|
321
|
-
|
|
315
|
+
if (forClaude)
|
|
316
|
+
console.log(
|
|
317
|
+
" - Claude Code (~/.claude/{commands/multi-agent, scripts, multi-agent-refs, schemas, lib} + pipeline skills + pipeline agent files)",
|
|
318
|
+
);
|
|
319
|
+
if (forCopilot)
|
|
320
|
+
console.log(
|
|
321
|
+
" - Copilot CLI (~/.copilot/{scripts, schemas, lib} + pipeline skills + pipeline agent files + copilot-instructions.md section)",
|
|
322
|
+
);
|
|
323
|
+
if (forCursor)
|
|
324
|
+
console.log(` - Cursor (${adapterTarget}/.cursor/rules/multi-agent-* + .cursorrules)`);
|
|
325
|
+
if (forCopilotChat)
|
|
326
|
+
console.log(
|
|
327
|
+
` - GitHub Copilot Chat (${adapterTarget}/.github/copilot-instructions.md block + .github/instructions/multi-agent-*)`,
|
|
328
|
+
);
|
|
329
|
+
if (forAntigravity)
|
|
330
|
+
console.log(
|
|
331
|
+
` - Antigravity (${adapterTarget}/.agent/rules + .agent/workflows + AGENTS.md block + .agent/mcp_config.json)`,
|
|
332
|
+
);
|
|
333
|
+
if (forCodex)
|
|
334
|
+
console.log(
|
|
335
|
+
" - OpenAI Codex CLI (~/.codex/prompts/multi-agent.md + AGENTS.md block + config.toml mcp block)",
|
|
336
|
+
);
|
|
322
337
|
console.log("");
|
|
323
338
|
if (allData) {
|
|
324
339
|
console.log(" FULL CLEANUP (--all-data) also removes:");
|
|
@@ -327,7 +342,9 @@ async function main() {
|
|
|
327
342
|
console.log("");
|
|
328
343
|
}
|
|
329
344
|
console.log(" PRESERVED (never touched):");
|
|
330
|
-
console.log(
|
|
345
|
+
console.log(
|
|
346
|
+
" - Personal access tokens in OS credential store (Keychain / Credential Manager / libsecret)",
|
|
347
|
+
);
|
|
331
348
|
console.log(" - ~/.claude/CLAUDE.md (your customizations)");
|
|
332
349
|
console.log(" - ~/.claude/rules/ (user-owned; installed write-if-missing, never overwritten)");
|
|
333
350
|
if (!allData) console.log(" - ~/.claude/multi-agent-preferences.json (your settings)");
|
|
@@ -357,8 +374,18 @@ async function main() {
|
|
|
357
374
|
// (e.g. the git-attribution rule) -- asymmetric data loss. Leave rules
|
|
358
375
|
// in place on uninstall, exactly like CLAUDE.md and preferences.
|
|
359
376
|
const skills = join(CLAUDE, "skills");
|
|
360
|
-
let n = rmMatchingDirs(
|
|
361
|
-
|
|
377
|
+
let n = rmMatchingDirs(
|
|
378
|
+
skills,
|
|
379
|
+
(name) => name === "multi-agent" || name.startsWith("multi-agent-"),
|
|
380
|
+
);
|
|
381
|
+
n += rmMatchingDirs(
|
|
382
|
+
skills,
|
|
383
|
+
(name) =>
|
|
384
|
+
name === "figma-ios" ||
|
|
385
|
+
name === "figma-android" ||
|
|
386
|
+
name === "figma-common" ||
|
|
387
|
+
name === "figma-to-component",
|
|
388
|
+
);
|
|
362
389
|
n += rmMatchingDirs(skills, (name) => PIPELINE_CORE_SKILL_DIRS.includes(name));
|
|
363
390
|
if (n > 0) console.log(` removed ${n} skill dir(s) under ${skills}`);
|
|
364
391
|
rmIfExists(join(skills, ".skills-index.json"));
|
|
@@ -380,8 +407,18 @@ async function main() {
|
|
|
380
407
|
rmIfExists(join(COP, "lib"));
|
|
381
408
|
rmIfExists(join(COP, ".pipeline-version"));
|
|
382
409
|
const skills = join(COP, "skills");
|
|
383
|
-
let n = rmMatchingDirs(
|
|
384
|
-
|
|
410
|
+
let n = rmMatchingDirs(
|
|
411
|
+
skills,
|
|
412
|
+
(name) => name === "multi-agent" || name.startsWith("multi-agent-"),
|
|
413
|
+
);
|
|
414
|
+
n += rmMatchingDirs(
|
|
415
|
+
skills,
|
|
416
|
+
(name) =>
|
|
417
|
+
name === "figma-ios" ||
|
|
418
|
+
name === "figma-android" ||
|
|
419
|
+
name === "figma-common" ||
|
|
420
|
+
name === "figma-to-component",
|
|
421
|
+
);
|
|
385
422
|
n += rmMatchingDirs(skills, (name) => PIPELINE_CORE_SKILL_DIRS.includes(name));
|
|
386
423
|
if (n > 0) console.log(` removed ${n} skill dir(s) under ${skills}`);
|
|
387
424
|
rmIfExists(join(skills, ".skills-index.json"));
|
|
@@ -434,7 +471,9 @@ async function main() {
|
|
|
434
471
|
if (n > 0) console.log(` removed ${n} .agent file(s)`);
|
|
435
472
|
stripManagedBlock(join(adapterTarget, "AGENTS.md"));
|
|
436
473
|
if (existsSync(join(adapterTarget, ".agent", "mcp_config.json")))
|
|
437
|
-
console.log(
|
|
474
|
+
console.log(
|
|
475
|
+
" note: .agent/mcp_config.json left untouched (may hold user servers) - remove pipeline entries manually if present",
|
|
476
|
+
);
|
|
438
477
|
}
|
|
439
478
|
|
|
440
479
|
if (forCodex && HOME) {
|
|
@@ -444,23 +483,29 @@ async function main() {
|
|
|
444
483
|
rmIfExists(join(CODEX, "prompts", "multi-agent.md"));
|
|
445
484
|
stripManagedBlock(join(CODEX, "AGENTS.md"));
|
|
446
485
|
if (existsSync(join(CODEX, "config.toml")))
|
|
447
|
-
console.log(
|
|
486
|
+
console.log(
|
|
487
|
+
" note: ~/.codex/config.toml left untouched (may hold user MCP servers) - remove pipeline entries manually if present",
|
|
488
|
+
);
|
|
448
489
|
}
|
|
449
490
|
|
|
450
491
|
console.log("");
|
|
451
492
|
console.log(" ✓ Pipeline removed.");
|
|
452
493
|
if (!allData) {
|
|
453
494
|
console.log("");
|
|
454
|
-
console.log(
|
|
495
|
+
console.log(
|
|
496
|
+
" Kept your pipeline settings + logs. To remove those too, re-run with --all-data.",
|
|
497
|
+
);
|
|
455
498
|
} else {
|
|
456
499
|
console.log("");
|
|
457
|
-
console.log(
|
|
500
|
+
console.log(
|
|
501
|
+
" Full cleanup done. Still on disk (user-owned, remove by hand if you want a bare system):",
|
|
502
|
+
);
|
|
458
503
|
console.log(" - ~/.claude/CLAUDE.md");
|
|
459
504
|
console.log(" - ~/.claude/rules/");
|
|
460
505
|
}
|
|
461
506
|
console.log("");
|
|
462
507
|
console.log(" Personal access tokens were NOT touched. Inspect with:");
|
|
463
|
-
console.log(
|
|
508
|
+
console.log(' macOS: security find-generic-password -s "<service>" -w');
|
|
464
509
|
console.log(" Windows: cmdkey /list:<target>");
|
|
465
510
|
console.log(" Linux: secret-tool search service <service>");
|
|
466
511
|
console.log("");
|
|
@@ -470,8 +515,7 @@ async function main() {
|
|
|
470
515
|
|
|
471
516
|
// Run only when executed directly (node uninstall.mjs). Guard lets tests
|
|
472
517
|
// import the exported constants without triggering the uninstall.
|
|
473
|
-
const isMainModule =
|
|
474
|
-
process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href;
|
|
518
|
+
const isMainModule = process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href;
|
|
475
519
|
if (isMainModule) {
|
|
476
520
|
main().catch((e) => {
|
|
477
521
|
console.error("uninstall failed:", e.message);
|
|
@@ -131,7 +131,9 @@ function main() {
|
|
|
131
131
|
headingBlobLower.includes("ui test") ||
|
|
132
132
|
headingBlobLower.includes("ui-test");
|
|
133
133
|
if (!hasUi) {
|
|
134
|
-
errors.push(
|
|
134
|
+
errors.push(
|
|
135
|
+
"front-matter ui_tests: true but no Section 15.6 UI test scenarios found (Locked 31)",
|
|
136
|
+
);
|
|
135
137
|
}
|
|
136
138
|
}
|
|
137
139
|
if (a11yDepth === "full") {
|
|
@@ -140,7 +142,9 @@ function main() {
|
|
|
140
142
|
headingBlobLower.includes("walkthrough") ||
|
|
141
143
|
headingBlobLower.includes("gezinme");
|
|
142
144
|
if (!hasWalkthrough) {
|
|
143
|
-
errors.push(
|
|
145
|
+
errors.push(
|
|
146
|
+
"front-matter a11y_depth: full but no Section 16.2 screen-reader walkthrough found",
|
|
147
|
+
);
|
|
144
148
|
}
|
|
145
149
|
}
|
|
146
150
|
|
|
@@ -156,7 +160,9 @@ function main() {
|
|
|
156
160
|
|
|
157
161
|
// 4. Placeholder whole-section bodies (Locked 2)
|
|
158
162
|
if (/^\s*(TBD|Not applicable|N\/A)\s*$/im.test(text)) {
|
|
159
|
-
warns.push(
|
|
163
|
+
warns.push(
|
|
164
|
+
'a line is a bare "TBD"/"Not applicable"/"N/A" body; omit the section instead (Locked 2)',
|
|
165
|
+
);
|
|
160
166
|
}
|
|
161
167
|
|
|
162
168
|
// 5. Traceability (Full mode only, Locked 31)
|
|
@@ -173,7 +179,9 @@ function main() {
|
|
|
173
179
|
}
|
|
174
180
|
for (const [id, n] of counts) {
|
|
175
181
|
if (n < 2) {
|
|
176
|
-
warns.push(
|
|
182
|
+
warns.push(
|
|
183
|
+
`business rule ${id} is defined but never referenced downstream (test/acceptance/analytics) - Locked 31 traceability`,
|
|
184
|
+
);
|
|
177
185
|
}
|
|
178
186
|
}
|
|
179
187
|
}
|
|
@@ -182,7 +190,9 @@ function main() {
|
|
|
182
190
|
for (const w of warns) console.error(`WARN: ${w}`);
|
|
183
191
|
for (const e of errors) console.error(`ERROR: ${e}`);
|
|
184
192
|
if (errors.length > 0) {
|
|
185
|
-
console.error(
|
|
193
|
+
console.error(
|
|
194
|
+
`validate-analysis-doc: FAIL (${errors.length} error(s), ${warns.length} warning(s))`,
|
|
195
|
+
);
|
|
186
196
|
process.exit(1);
|
|
187
197
|
}
|
|
188
198
|
if (strict && warns.length > 0) {
|
|
@@ -49,22 +49,27 @@ function validate(obj) {
|
|
|
49
49
|
if (typeof obj !== "object" || obj === null || Array.isArray(obj)) {
|
|
50
50
|
return ["root must be an object"];
|
|
51
51
|
}
|
|
52
|
-
if (obj.schemaVersion !== "1.1.0")
|
|
52
|
+
if (obj.schemaVersion !== "1.1.0")
|
|
53
|
+
errors.push(`schemaVersion must be "1.1.0", got ${JSON.stringify(obj.schemaVersion)}`);
|
|
53
54
|
|
|
54
55
|
if (typeof obj.task !== "object" || obj.task === null) {
|
|
55
56
|
errors.push("task must be an object");
|
|
56
57
|
} else {
|
|
57
|
-
if (typeof obj.task.base !== "string" || !obj.task.base.length)
|
|
58
|
-
|
|
58
|
+
if (typeof obj.task.base !== "string" || !obj.task.base.length)
|
|
59
|
+
errors.push("task.base must be a non-empty string");
|
|
60
|
+
if (typeof obj.task.head !== "string" || !obj.task.head.length)
|
|
61
|
+
errors.push("task.head must be a non-empty string");
|
|
59
62
|
}
|
|
60
63
|
|
|
61
64
|
if (typeof obj.totals !== "object" || obj.totals === null) {
|
|
62
65
|
errors.push("totals must be an object");
|
|
63
66
|
} else {
|
|
64
67
|
for (const k of ["files", "loc_added", "loc_removed"]) {
|
|
65
|
-
if (!Number.isInteger(obj.totals[k]) || obj.totals[k] < 0)
|
|
68
|
+
if (!Number.isInteger(obj.totals[k]) || obj.totals[k] < 0)
|
|
69
|
+
errors.push(`totals.${k} must be a non-negative integer`);
|
|
66
70
|
}
|
|
67
|
-
if (typeof obj.totals.max_score !== "number" || obj.totals.max_score < 0)
|
|
71
|
+
if (typeof obj.totals.max_score !== "number" || obj.totals.max_score < 0)
|
|
72
|
+
errors.push("totals.max_score must be a non-negative number");
|
|
68
73
|
}
|
|
69
74
|
|
|
70
75
|
if (!Array.isArray(obj.files)) {
|
|
@@ -73,25 +78,33 @@ function validate(obj) {
|
|
|
73
78
|
obj.files.forEach((row, i) => {
|
|
74
79
|
const p = `files[${i}]`;
|
|
75
80
|
if (typeof row !== "object" || row === null) {
|
|
76
|
-
errors.push(`${p} must be an object`);
|
|
81
|
+
errors.push(`${p} must be an object`);
|
|
82
|
+
return;
|
|
77
83
|
}
|
|
78
|
-
if (typeof row.path !== "string" || !row.path.length)
|
|
79
|
-
|
|
84
|
+
if (typeof row.path !== "string" || !row.path.length)
|
|
85
|
+
errors.push(`${p}.path must be a non-empty string`);
|
|
86
|
+
if (typeof row.score !== "number" || row.score < 0)
|
|
87
|
+
errors.push(`${p}.score must be a non-negative number`);
|
|
80
88
|
for (const k of ["loc_added", "loc_removed"]) {
|
|
81
|
-
if (!Number.isInteger(row[k]) || row[k] < 0)
|
|
89
|
+
if (!Number.isInteger(row[k]) || row[k] < 0)
|
|
90
|
+
errors.push(`${p}.${k} must be a non-negative integer`);
|
|
82
91
|
}
|
|
83
92
|
if (!Array.isArray(row.signals)) errors.push(`${p}.signals must be an array`);
|
|
84
|
-
else
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
93
|
+
else
|
|
94
|
+
row.signals.forEach((s, j) => {
|
|
95
|
+
const sp = `${p}.signals[${j}]`;
|
|
96
|
+
if (!ALLOWED_SIGNALS.has(s.name))
|
|
97
|
+
errors.push(`${sp}.name "${s.name}" not in allowed set`);
|
|
98
|
+
if (typeof s.weight !== "number") errors.push(`${sp}.weight must be a number`);
|
|
99
|
+
if (typeof s.value !== "number") errors.push(`${sp}.value must be a number`);
|
|
100
|
+
});
|
|
90
101
|
});
|
|
91
102
|
// Sort invariant
|
|
92
103
|
for (let i = 1; i < obj.files.length; i++) {
|
|
93
104
|
if (obj.files[i].score > obj.files[i - 1].score) {
|
|
94
|
-
errors.push(
|
|
105
|
+
errors.push(
|
|
106
|
+
`files[] must be sorted by score descending (row ${i} score ${obj.files[i].score} > row ${i - 1} score ${obj.files[i - 1].score})`,
|
|
107
|
+
);
|
|
95
108
|
break;
|
|
96
109
|
}
|
|
97
110
|
}
|
|
@@ -103,8 +116,9 @@ function validate(obj) {
|
|
|
103
116
|
(async () => {
|
|
104
117
|
const raw = await readInput();
|
|
105
118
|
let obj;
|
|
106
|
-
try {
|
|
107
|
-
|
|
119
|
+
try {
|
|
120
|
+
obj = JSON.parse(raw);
|
|
121
|
+
} catch (e) {
|
|
108
122
|
console.log(JSON.stringify({ ok: false, errors: [`JSON parse error: ${e.message}`] }));
|
|
109
123
|
process.exit(1);
|
|
110
124
|
}
|
|
@@ -34,15 +34,18 @@ function readInput() {
|
|
|
34
34
|
|
|
35
35
|
function validate(obj) {
|
|
36
36
|
const errors = [];
|
|
37
|
-
if (typeof obj !== "object" || obj === null || Array.isArray(obj))
|
|
37
|
+
if (typeof obj !== "object" || obj === null || Array.isArray(obj))
|
|
38
|
+
return ["root must be an object"];
|
|
38
39
|
if (obj.schemaVersion !== "1.0.0") errors.push(`schemaVersion must be "1.0.0"`);
|
|
39
|
-
if (!ALLOWED_STACK.has(obj.stack))
|
|
40
|
+
if (!ALLOWED_STACK.has(obj.stack))
|
|
41
|
+
errors.push(`stack must be one of ${Array.from(ALLOWED_STACK).join(",")}`);
|
|
40
42
|
|
|
41
43
|
if (typeof obj.totals !== "object" || obj.totals === null) {
|
|
42
44
|
errors.push("totals must be an object");
|
|
43
45
|
} else {
|
|
44
46
|
for (const k of ["sourcesScanned", "testsScanned", "gapCount"]) {
|
|
45
|
-
if (!Number.isInteger(obj.totals[k]) || obj.totals[k] < 0)
|
|
47
|
+
if (!Number.isInteger(obj.totals[k]) || obj.totals[k] < 0)
|
|
48
|
+
errors.push(`totals.${k} must be a non-negative integer`);
|
|
46
49
|
}
|
|
47
50
|
if (typeof obj.totals.gapBySeverity !== "object" || obj.totals.gapBySeverity === null) {
|
|
48
51
|
errors.push("totals.gapBySeverity must be an object");
|
|
@@ -60,12 +63,17 @@ function validate(obj) {
|
|
|
60
63
|
} else {
|
|
61
64
|
obj.gaps.forEach((g, i) => {
|
|
62
65
|
const p = `gaps[${i}]`;
|
|
63
|
-
if (typeof g !== "object" || g === null) {
|
|
64
|
-
|
|
66
|
+
if (typeof g !== "object" || g === null) {
|
|
67
|
+
errors.push(`${p} must be object`);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (typeof g.sourcePath !== "string" || !g.sourcePath.length)
|
|
71
|
+
errors.push(`${p}.sourcePath required`);
|
|
65
72
|
if (typeof g.symbol !== "string" || !g.symbol.length) errors.push(`${p}.symbol required`);
|
|
66
73
|
if (typeof g.kind !== "string" || !g.kind.length) errors.push(`${p}.kind required`);
|
|
67
74
|
if (!ALLOWED_SEVERITY.has(g.severity)) errors.push(`${p}.severity invalid: ${g.severity}`);
|
|
68
|
-
if (!Array.isArray(g.expectedTestPaths) || g.expectedTestPaths.length === 0)
|
|
75
|
+
if (!Array.isArray(g.expectedTestPaths) || g.expectedTestPaths.length === 0)
|
|
76
|
+
errors.push(`${p}.expectedTestPaths must be a non-empty array`);
|
|
69
77
|
if (typeof g.hint !== "string") errors.push(`${p}.hint must be a string`);
|
|
70
78
|
});
|
|
71
79
|
}
|
|
@@ -76,7 +84,9 @@ function validate(obj) {
|
|
|
76
84
|
(async () => {
|
|
77
85
|
const raw = await readInput();
|
|
78
86
|
let obj;
|
|
79
|
-
try {
|
|
87
|
+
try {
|
|
88
|
+
obj = JSON.parse(raw);
|
|
89
|
+
} catch (e) {
|
|
80
90
|
console.log(JSON.stringify({ ok: false, errors: [`JSON parse error: ${e.message}`] }));
|
|
81
91
|
process.exit(1);
|
|
82
92
|
}
|
|
@@ -25,7 +25,12 @@ import { readFileSync } from "node:fs";
|
|
|
25
25
|
|
|
26
26
|
const ALLOWED_REVIEWERS = new Set(["fable", "opus", "sonnet", "gpt"]);
|
|
27
27
|
const ALLOWED_SEVERITIES = new Set(["blocking", "important", "suggestion"]);
|
|
28
|
-
const ALLOWED_CONSENSUS_VERDICTS = new Set([
|
|
28
|
+
const ALLOWED_CONSENSUS_VERDICTS = new Set([
|
|
29
|
+
"unanimous-pass",
|
|
30
|
+
"unanimous-block",
|
|
31
|
+
"split",
|
|
32
|
+
"unverified",
|
|
33
|
+
]);
|
|
29
34
|
const ALLOWED_VERIFICATION_RESULTS = new Set(["confirmed", "not-reproduced", "inconclusive"]);
|
|
30
35
|
const OVER_REJECT_THRESHOLD = 0.8;
|
|
31
36
|
const OVER_REJECT_MIN_FINDINGS = 5;
|
|
@@ -79,7 +84,9 @@ function validateVerification(v, label, errors) {
|
|
|
79
84
|
return;
|
|
80
85
|
}
|
|
81
86
|
if (!ALLOWED_VERIFICATION_RESULTS.has(v.result)) {
|
|
82
|
-
errors.push(
|
|
87
|
+
errors.push(
|
|
88
|
+
`${label}: bad result "${v.result}" (allowed: confirmed|not-reproduced|inconclusive)`,
|
|
89
|
+
);
|
|
83
90
|
return;
|
|
84
91
|
}
|
|
85
92
|
if (v.result === "confirmed" || v.result === "not-reproduced") {
|
|
@@ -115,10 +122,14 @@ function validateConsensus(c, errors) {
|
|
|
115
122
|
return;
|
|
116
123
|
}
|
|
117
124
|
if (!Number.isInteger(c.reviewerCount) || c.reviewerCount < 1) {
|
|
118
|
-
errors.push(
|
|
125
|
+
errors.push(
|
|
126
|
+
`consensus: reviewerCount must be an integer >= 1 (got ${JSON.stringify(c.reviewerCount)})`,
|
|
127
|
+
);
|
|
119
128
|
}
|
|
120
129
|
if (!ALLOWED_CONSENSUS_VERDICTS.has(c.verdict)) {
|
|
121
|
-
errors.push(
|
|
130
|
+
errors.push(
|
|
131
|
+
`consensus: bad verdict "${c.verdict}" (allowed: unanimous-pass|unanimous-block|split|unverified)`,
|
|
132
|
+
);
|
|
122
133
|
}
|
|
123
134
|
if (c.disagreements !== undefined) {
|
|
124
135
|
if (!Array.isArray(c.disagreements)) {
|
|
@@ -211,7 +222,8 @@ function validate(raw) {
|
|
|
211
222
|
errors.push('consensus.verdict "unanimous-pass" contradicts an accepted blocking finding');
|
|
212
223
|
}
|
|
213
224
|
if (
|
|
214
|
-
typeof c.reviewerCount === "number" &&
|
|
225
|
+
typeof c.reviewerCount === "number" &&
|
|
226
|
+
c.reviewerCount < 2 &&
|
|
215
227
|
(c.verdict === "unanimous-pass" || c.verdict === "unanimous-block")
|
|
216
228
|
) {
|
|
217
229
|
errors.push(
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Why this exists:
|
|
6
6
|
* Multiple worktrees can run the pipeline concurrently against the same
|
|
7
7
|
* task id. Two CLI instances writing agent-state.json in the usual
|
|
8
|
-
* fs.writeFileSync('path', JSON.stringify(...)) pattern is racy -
|
|
8
|
+
* fs.writeFileSync('path', JSON.stringify(...)) pattern is racy -
|
|
9
9
|
* second write wipes the first. This helper uses tmpfile + rename, which
|
|
10
10
|
* is atomic on POSIX, combined with an advisory .lock file for the tiny
|
|
11
11
|
* window between "read current state" and "write new state".
|
|
@@ -35,8 +35,7 @@ import {
|
|
|
35
35
|
renameSync,
|
|
36
36
|
existsSync,
|
|
37
37
|
unlinkSync,
|
|
38
|
-
|
|
39
|
-
closeSync,
|
|
38
|
+
linkSync,
|
|
40
39
|
statSync,
|
|
41
40
|
} from "fs";
|
|
42
41
|
import { dirname, basename } from "path";
|
|
@@ -70,17 +69,36 @@ function parseArgs() {
|
|
|
70
69
|
* @param {number} timeoutMs
|
|
71
70
|
* @returns {Promise<void>}
|
|
72
71
|
*/
|
|
73
|
-
async function acquireLock(
|
|
72
|
+
async function acquireLock(
|
|
73
|
+
path,
|
|
74
|
+
timeoutMs = Number(process.env.WRITE_STATE_LOCK_TIMEOUT_MS) || 15_000,
|
|
75
|
+
) {
|
|
74
76
|
const lockPath = `${path}.lock`;
|
|
75
77
|
const staleMs = Number(process.env.WRITE_STATE_LOCK_STALE_MS) || 30_000;
|
|
76
78
|
const deadline = Date.now() + timeoutMs;
|
|
79
|
+
// The lock file must never be observable without its owning PID inside it.
|
|
80
|
+
// It used to be created with openSync(wx) and filled on the next line, so
|
|
81
|
+
// between those two calls it existed and was empty. A writer arriving in
|
|
82
|
+
// that window read an unparseable PID, concluded the lock was stale, and
|
|
83
|
+
// deleted a live one - after which two writers held it and one write was
|
|
84
|
+
// lost. Under CPU load that reproduced 3 times in 15 runs.
|
|
85
|
+
//
|
|
86
|
+
// Writing the PID into a private temp file and hard-linking it into place
|
|
87
|
+
// closes the window: link() fails with EEXIST if the lock is held, and the
|
|
88
|
+
// instant the lock exists it already has its contents.
|
|
89
|
+
const stagePath = `${lockPath}.${process.pid}.stage`;
|
|
77
90
|
while (Date.now() < deadline) {
|
|
78
91
|
try {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
92
|
+
writeFileSync(stagePath, String(process.pid));
|
|
93
|
+
linkSync(stagePath, lockPath); // fails EEXIST if another writer holds it
|
|
94
|
+
unlinkSync(stagePath);
|
|
82
95
|
return;
|
|
83
96
|
} catch (err) {
|
|
97
|
+
try {
|
|
98
|
+
unlinkSync(stagePath);
|
|
99
|
+
} catch {
|
|
100
|
+
/* already gone */
|
|
101
|
+
}
|
|
84
102
|
if (err.code !== "EEXIST") throw err;
|
|
85
103
|
if (isLockStale(lockPath, staleMs)) {
|
|
86
104
|
// Holder crashed or the lock outlived any plausible writer - reclaim it.
|
|
@@ -105,7 +123,7 @@ async function acquireLock(path, timeoutMs = Number(process.env.WRITE_STATE_LOCK
|
|
|
105
123
|
|
|
106
124
|
/**
|
|
107
125
|
* A lock is stale when its owning PID is no longer alive, or when the lock
|
|
108
|
-
* file is older than `staleMs` (covers PID reuse
|
|
126
|
+
* file is older than `staleMs` (which also covers PID reuse).
|
|
109
127
|
* @param {string} lockPath
|
|
110
128
|
* @param {number} staleMs
|
|
111
129
|
* @returns {boolean}
|
|
@@ -121,7 +139,12 @@ function isLockStale(lockPath, staleMs) {
|
|
|
121
139
|
return false;
|
|
122
140
|
}
|
|
123
141
|
if (Date.now() - mtimeMs > staleMs) return true;
|
|
124
|
-
|
|
142
|
+
// An unreadable PID is NOT proof of staleness. Treating it as such is what
|
|
143
|
+
// let a writer delete a live lock and lose another writer's update. With the
|
|
144
|
+
// link-based acquire above a lock is never observable without its PID, so
|
|
145
|
+
// this can only be genuine corruption - which the staleMs check reclaims
|
|
146
|
+
// anyway, without racing a writer that is merely mid-flight.
|
|
147
|
+
if (!Number.isInteger(pid) || pid <= 0) return false;
|
|
125
148
|
try {
|
|
126
149
|
process.kill(pid, 0); // probe liveness without signalling
|
|
127
150
|
return false; // holder alive
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": "1.0.0",
|
|
3
|
-
"generatedAt": "2026-07-
|
|
4
|
-
"skillCount":
|
|
3
|
+
"generatedAt": "2026-07-25T10:41:38Z",
|
|
4
|
+
"skillCount": 193,
|
|
5
5
|
"entries": [
|
|
6
6
|
{
|
|
7
7
|
"path": "shared/core/apple-archive-compliance/SKILL.md",
|
|
8
|
-
"sha256": "
|
|
8
|
+
"sha256": "d3826905606b6ec7d86d3434b03bfdbbd52a424f7108e58ca12a8cb490f1e4ad"
|
|
9
9
|
},
|
|
10
10
|
{
|
|
11
11
|
"path": "shared/core/google-play-compliance/SKILL.md",
|
|
@@ -35,6 +35,10 @@
|
|
|
35
35
|
"path": "shared/core/multi-agent-create-jira/SKILL.md",
|
|
36
36
|
"sha256": "40caf0489ad8322cd00d792a244e772d4ddb6ccfd7c3807729d6b17590e7f81c"
|
|
37
37
|
},
|
|
38
|
+
{
|
|
39
|
+
"path": "shared/core/multi-agent-design-check/SKILL.md",
|
|
40
|
+
"sha256": "a004cf24661789d2a3595c5246dfebe00b76aaee6ece057b458748f502a8cd5c"
|
|
41
|
+
},
|
|
38
42
|
{
|
|
39
43
|
"path": "shared/core/multi-agent-dev-autopilot/SKILL.md",
|
|
40
44
|
"sha256": "82b1cf4a4bbd84fcfef54fcdbcdefa27f2747df6d4fac5c86b42e861013c6d58"
|
|
@@ -59,13 +63,17 @@
|
|
|
59
63
|
"path": "shared/core/multi-agent-finish/SKILL.md",
|
|
60
64
|
"sha256": "3e8e430f7aee626be96129a9d0ae6c9ac5ef0dbf80cbe580dde2d7fb5fccfed1"
|
|
61
65
|
},
|
|
66
|
+
{
|
|
67
|
+
"path": "shared/core/multi-agent-forget/SKILL.md",
|
|
68
|
+
"sha256": "68f6a92a00844ed34c336548888d3e623534c12b5e85afe5762e7a9c8d41aae4"
|
|
69
|
+
},
|
|
62
70
|
{
|
|
63
71
|
"path": "shared/core/multi-agent-garbage-collect/SKILL.md",
|
|
64
72
|
"sha256": "24736f163e645e2bee7d552e555ae6e32cd3fc3d15c844813a75b908a58d52fd"
|
|
65
73
|
},
|
|
66
74
|
{
|
|
67
75
|
"path": "shared/core/multi-agent-help/SKILL.md",
|
|
68
|
-
"sha256": "
|
|
76
|
+
"sha256": "330780854ab3b48f788e34f918ecad585bd46ffbb44f14fd38de7b48a4b568aa"
|
|
69
77
|
},
|
|
70
78
|
{
|
|
71
79
|
"path": "shared/core/multi-agent-issue/SKILL.md",
|
|
@@ -109,7 +117,7 @@
|
|
|
109
117
|
},
|
|
110
118
|
{
|
|
111
119
|
"path": "shared/core/multi-agent-refactor/SKILL.md",
|
|
112
|
-
"sha256": "
|
|
120
|
+
"sha256": "60766ee3a6b974b3872417db5c40d1fc03bfddd99daf4aca11d7a59b57a41b57"
|
|
113
121
|
},
|
|
114
122
|
{
|
|
115
123
|
"path": "shared/core/multi-agent-resume/SKILL.md",
|
|
@@ -127,6 +135,14 @@
|
|
|
127
135
|
"path": "shared/core/multi-agent-review/SKILL.md",
|
|
128
136
|
"sha256": "b1fd57d2b80ee0fe2490439d9f2688fcf415857c2aab60549c5456e27693b9a9"
|
|
129
137
|
},
|
|
138
|
+
{
|
|
139
|
+
"path": "shared/core/multi-agent-routines/SKILL.md",
|
|
140
|
+
"sha256": "91d3bdb15da7addadd1afd0b170057daf3d3fc335da3f6e1feb4feff1af0881e"
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"path": "shared/core/multi-agent-save/SKILL.md",
|
|
144
|
+
"sha256": "f9c6e2ba1dd1b224b80cabe35f4327b5bcc0b1e05868b378547bec616193ef1b"
|
|
145
|
+
},
|
|
130
146
|
{
|
|
131
147
|
"path": "shared/core/multi-agent-scan/SKILL.md",
|
|
132
148
|
"sha256": "266e4e7c9b702bc3205b7d926455c5863e144cddb1e4b883aa81e570a362fd3f"
|
|
@@ -149,11 +165,11 @@
|
|
|
149
165
|
},
|
|
150
166
|
{
|
|
151
167
|
"path": "shared/core/multi-agent-sync/SKILL.md",
|
|
152
|
-
"sha256": "
|
|
168
|
+
"sha256": "3a9f7d8caa47d41d1a4759ce6673bfb94a1ef9f62f7113a4cd3b1e9451464601"
|
|
153
169
|
},
|
|
154
170
|
{
|
|
155
171
|
"path": "shared/core/multi-agent-test/SKILL.md",
|
|
156
|
-
"sha256": "
|
|
172
|
+
"sha256": "2b662ecd9497149c4c2e87cc79e906cc1cab7ea4a7d0efe300b0b018559960c4"
|
|
157
173
|
},
|
|
158
174
|
{
|
|
159
175
|
"path": "shared/core/multi-agent-uninstall/SKILL.md",
|
|
@@ -425,7 +441,7 @@
|
|
|
425
441
|
},
|
|
426
442
|
{
|
|
427
443
|
"path": "shared/external/humanizer/SKILL.md",
|
|
428
|
-
"sha256": "
|
|
444
|
+
"sha256": "2fc8fe79a5832b9e1316f515c73f0545023153e85aba4645ba42060a0afdd049"
|
|
429
445
|
},
|
|
430
446
|
{
|
|
431
447
|
"path": "shared/external/ios-accessibility/SKILL.md",
|