@mstar-harness/cli 1.5.5 → 1.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/dist/mstar-harness.js +222 -19
- package/package.json +1 -1
package/dist/mstar-harness.js
CHANGED
|
@@ -2344,8 +2344,8 @@ var require_commander = __commonJS((exports) => {
|
|
|
2344
2344
|
});
|
|
2345
2345
|
|
|
2346
2346
|
// src/index.ts
|
|
2347
|
-
import
|
|
2348
|
-
import
|
|
2347
|
+
import fs7 from "fs";
|
|
2348
|
+
import path9 from "path";
|
|
2349
2349
|
import { fileURLToPath } from "url";
|
|
2350
2350
|
|
|
2351
2351
|
// ../../node_modules/@inquirer/core/dist/lib/key.js
|
|
@@ -4070,7 +4070,7 @@ import { execFileSync } from "node:child_process";
|
|
|
4070
4070
|
var REPO_URL = "https://github.com/btspoony/mstar-harness.git";
|
|
4071
4071
|
var PLUGIN_NAME = "morning-star-harness";
|
|
4072
4072
|
var HARNESS_REPO_PATH = path3.join(os.homedir(), ".mstar", "harness");
|
|
4073
|
-
var HARNESS_MARKERS = [".codex-plugin/plugin.json"];
|
|
4073
|
+
var HARNESS_MARKERS = [".codex-plugin/plugin.json", ".zcode-plugin/plugin.json"];
|
|
4074
4074
|
function harnessMarkerPath() {
|
|
4075
4075
|
for (const marker of HARNESS_MARKERS) {
|
|
4076
4076
|
const candidate = path3.join(HARNESS_REPO_PATH, marker);
|
|
@@ -4697,11 +4697,214 @@ var opencodeAdapter = {
|
|
|
4697
4697
|
}
|
|
4698
4698
|
};
|
|
4699
4699
|
|
|
4700
|
+
// src/adapters/zcode.ts
|
|
4701
|
+
import fs5 from "node:fs";
|
|
4702
|
+
import os5 from "node:os";
|
|
4703
|
+
import path7 from "node:path";
|
|
4704
|
+
var MARKETPLACE_ID = "mstar-local";
|
|
4705
|
+
var MARKETPLACE_NAME2 = "mstar-local";
|
|
4706
|
+
var MARKETPLACE_DESCRIPTION = "Morning Star harness marketplace (GitHub source).";
|
|
4707
|
+
var PLUGIN_DESCRIPTION = "Multi-agent code harness framework with unified skills for OpenCode, Cursor, Codex, Kimi Code, and ZCode.";
|
|
4708
|
+
var PLUGIN_VERSION = "1.6.0";
|
|
4709
|
+
var PLUGIN_CATEGORY2 = "Productivity";
|
|
4710
|
+
var GITHUB_REPO = "btspoony/mstar-harness";
|
|
4711
|
+
var GITHUB_REF = "main";
|
|
4712
|
+
var ZCODE_PLUGIN_MARKER = ".zcode-plugin/plugin.json";
|
|
4713
|
+
var ZCODE_PLUGIN_CHECKOUT_PROJECT = ".zcode/plugin-checkout";
|
|
4714
|
+
var ZCODE_AGENT_SMOKE_NAMES = ["fullstack-dev", "qc-specialist"];
|
|
4715
|
+
var ZCODE_PLUGINS_ROOT = path7.join(os5.homedir(), ".zcode", "cli", "plugins");
|
|
4716
|
+
var KNOWN_MARKETPLACES_PATH = path7.join(ZCODE_PLUGINS_ROOT, "known_marketplaces.json");
|
|
4717
|
+
var MARKETPLACE_DIR = path7.join(ZCODE_PLUGINS_ROOT, "marketplaces", MARKETPLACE_ID);
|
|
4718
|
+
var MARKETPLACE_JSON_PATH = path7.join(MARKETPLACE_DIR, "marketplace.json");
|
|
4719
|
+
var GITHUB_SOURCE = { source: "github", repo: GITHUB_REPO, ref: GITHUB_REF };
|
|
4720
|
+
function nowIso() {
|
|
4721
|
+
return new Date().toISOString();
|
|
4722
|
+
}
|
|
4723
|
+
function marketplacePluginEntry() {
|
|
4724
|
+
return {
|
|
4725
|
+
name: PLUGIN_NAME,
|
|
4726
|
+
source: { ...GITHUB_SOURCE },
|
|
4727
|
+
description: PLUGIN_DESCRIPTION,
|
|
4728
|
+
version: PLUGIN_VERSION,
|
|
4729
|
+
category: PLUGIN_CATEGORY2
|
|
4730
|
+
};
|
|
4731
|
+
}
|
|
4732
|
+
function knownMarketplaceEntry(existing) {
|
|
4733
|
+
const previous = existing && typeof existing.addedAt === "string" && existing.addedAt || nowIso();
|
|
4734
|
+
return {
|
|
4735
|
+
id: MARKETPLACE_ID,
|
|
4736
|
+
source: { ...GITHUB_SOURCE },
|
|
4737
|
+
name: MARKETPLACE_NAME2,
|
|
4738
|
+
description: MARKETPLACE_DESCRIPTION,
|
|
4739
|
+
addedAt: previous,
|
|
4740
|
+
pluginCount: 1,
|
|
4741
|
+
lastUpdated: nowIso()
|
|
4742
|
+
};
|
|
4743
|
+
}
|
|
4744
|
+
function upsertKnownMarketplace(raw) {
|
|
4745
|
+
const next = ensureObject(raw);
|
|
4746
|
+
if (typeof next.version !== "number")
|
|
4747
|
+
next.version = 1;
|
|
4748
|
+
if (!Array.isArray(next.marketplaces))
|
|
4749
|
+
next.marketplaces = [];
|
|
4750
|
+
const existing = next.marketplaces.find((entry) => {
|
|
4751
|
+
return entry && typeof entry === "object" && !Array.isArray(entry) && entry.id === MARKETPLACE_ID;
|
|
4752
|
+
});
|
|
4753
|
+
const marketplaces = next.marketplaces.filter((entry) => {
|
|
4754
|
+
return !(entry && typeof entry === "object" && !Array.isArray(entry) && entry.id === MARKETPLACE_ID);
|
|
4755
|
+
});
|
|
4756
|
+
marketplaces.push(knownMarketplaceEntry(existing));
|
|
4757
|
+
next.marketplaces = marketplaces;
|
|
4758
|
+
return next;
|
|
4759
|
+
}
|
|
4760
|
+
function findKnownMarketplace(raw) {
|
|
4761
|
+
const marketplaces = Array.isArray(raw.marketplaces) ? raw.marketplaces : [];
|
|
4762
|
+
return marketplaces.find((entry) => {
|
|
4763
|
+
return entry && typeof entry === "object" && !Array.isArray(entry) && entry.id === MARKETPLACE_ID;
|
|
4764
|
+
});
|
|
4765
|
+
}
|
|
4766
|
+
function findMarketplacePlugin(raw) {
|
|
4767
|
+
const plugins = Array.isArray(raw.plugins) ? raw.plugins : [];
|
|
4768
|
+
return plugins.find((entry) => {
|
|
4769
|
+
return entry && typeof entry === "object" && !Array.isArray(entry) && entry.name === PLUGIN_NAME;
|
|
4770
|
+
});
|
|
4771
|
+
}
|
|
4772
|
+
function validateMarketplaceJson() {
|
|
4773
|
+
const errors2 = [];
|
|
4774
|
+
if (!fs5.existsSync(MARKETPLACE_JSON_PATH)) {
|
|
4775
|
+
errors2.push(`Missing ZCode marketplace: ${MARKETPLACE_JSON_PATH}`);
|
|
4776
|
+
return errors2;
|
|
4777
|
+
}
|
|
4778
|
+
const raw = readJson(MARKETPLACE_JSON_PATH);
|
|
4779
|
+
if (raw.name !== MARKETPLACE_NAME2) {
|
|
4780
|
+
errors2.push(`ZCode marketplace name must be ${MARKETPLACE_NAME2} (in ${MARKETPLACE_JSON_PATH}).`);
|
|
4781
|
+
}
|
|
4782
|
+
const entry = findMarketplacePlugin(raw);
|
|
4783
|
+
if (!entry) {
|
|
4784
|
+
errors2.push(`Missing ${PLUGIN_NAME} plugin entry in ${MARKETPLACE_JSON_PATH}.`);
|
|
4785
|
+
return errors2;
|
|
4786
|
+
}
|
|
4787
|
+
const expected = marketplacePluginEntry();
|
|
4788
|
+
const source = ensureObject(entry.source);
|
|
4789
|
+
if (source.source !== "github") {
|
|
4790
|
+
errors2.push("ZCode marketplace plugin source.source must be `github`.");
|
|
4791
|
+
}
|
|
4792
|
+
if (source.repo !== expected.source.repo) {
|
|
4793
|
+
errors2.push(`ZCode marketplace plugin source.repo must be ${expected.source.repo}.`);
|
|
4794
|
+
}
|
|
4795
|
+
if (entry.version !== PLUGIN_VERSION) {
|
|
4796
|
+
errors2.push(`ZCode marketplace plugin version must be ${PLUGIN_VERSION}.`);
|
|
4797
|
+
}
|
|
4798
|
+
return errors2;
|
|
4799
|
+
}
|
|
4800
|
+
function validateKnownMarketplaces() {
|
|
4801
|
+
const errors2 = [];
|
|
4802
|
+
if (!fs5.existsSync(KNOWN_MARKETPLACES_PATH)) {
|
|
4803
|
+
errors2.push(`Missing ZCode known_marketplaces.json: ${KNOWN_MARKETPLACES_PATH}`);
|
|
4804
|
+
return errors2;
|
|
4805
|
+
}
|
|
4806
|
+
const raw = readJson(KNOWN_MARKETPLACES_PATH);
|
|
4807
|
+
const entry = findKnownMarketplace(raw);
|
|
4808
|
+
if (!entry) {
|
|
4809
|
+
errors2.push(`Missing ${MARKETPLACE_ID} entry in ${KNOWN_MARKETPLACES_PATH}.`);
|
|
4810
|
+
return errors2;
|
|
4811
|
+
}
|
|
4812
|
+
if (entry.id !== MARKETPLACE_ID)
|
|
4813
|
+
errors2.push(`known_marketplaces entry id must be ${MARKETPLACE_ID}.`);
|
|
4814
|
+
const source = ensureObject(entry.source);
|
|
4815
|
+
if (source.source !== "github") {
|
|
4816
|
+
errors2.push(`known_marketplaces entry source.source must be github.`);
|
|
4817
|
+
}
|
|
4818
|
+
if (source.repo !== GITHUB_REPO) {
|
|
4819
|
+
errors2.push(`known_marketplaces entry source.repo must be ${GITHUB_REPO}.`);
|
|
4820
|
+
}
|
|
4821
|
+
return errors2;
|
|
4822
|
+
}
|
|
4823
|
+
function validatePluginAgents2(pluginRoot) {
|
|
4824
|
+
const errors2 = [];
|
|
4825
|
+
const agentsDir = path7.join(pluginRoot, "agents");
|
|
4826
|
+
if (!fs5.existsSync(agentsDir)) {
|
|
4827
|
+
errors2.push(`Missing plugin agents directory: ${agentsDir}`);
|
|
4828
|
+
return errors2;
|
|
4829
|
+
}
|
|
4830
|
+
for (const agentName of ZCODE_AGENT_SMOKE_NAMES) {
|
|
4831
|
+
const agentPath = path7.join(agentsDir, `${agentName}.md`);
|
|
4832
|
+
if (!fs5.existsSync(agentPath)) {
|
|
4833
|
+
errors2.push(`Missing plugin agent file: ${agentPath}`);
|
|
4834
|
+
}
|
|
4835
|
+
}
|
|
4836
|
+
return errors2;
|
|
4837
|
+
}
|
|
4838
|
+
function buildMarketplaceJson() {
|
|
4839
|
+
return {
|
|
4840
|
+
name: MARKETPLACE_NAME2,
|
|
4841
|
+
description: MARKETPLACE_DESCRIPTION,
|
|
4842
|
+
plugins: [marketplacePluginEntry()]
|
|
4843
|
+
};
|
|
4844
|
+
}
|
|
4845
|
+
function runInit2(scope, dryRun) {
|
|
4846
|
+
const notes = ensureLocalHarnessRepo(dryRun);
|
|
4847
|
+
const projectRoot = resolveProjectRoot();
|
|
4848
|
+
if (scope === "project") {
|
|
4849
|
+
const checkoutPath = path7.join(projectRoot, ZCODE_PLUGIN_CHECKOUT_PROJECT);
|
|
4850
|
+
notes.push(...ensureGitCheckout(REPO_URL, checkoutPath, dryRun));
|
|
4851
|
+
notes.push(...appendGitignore(projectRoot, [ZCODE_PLUGIN_CHECKOUT_PROJECT], dryRun));
|
|
4852
|
+
notes.push(...appendHarnessProjectGitignore(projectRoot, dryRun));
|
|
4853
|
+
notes.push(`Materialized local ZCode plugin checkout at ${ZCODE_PLUGIN_CHECKOUT_PROJECT} for smoke checks (the registered marketplace still points at the github repo).`);
|
|
4854
|
+
}
|
|
4855
|
+
if (!dryRun) {
|
|
4856
|
+
if (!fs5.existsSync(MARKETPLACE_DIR))
|
|
4857
|
+
fs5.mkdirSync(MARKETPLACE_DIR, { recursive: true });
|
|
4858
|
+
writeJson(MARKETPLACE_JSON_PATH, buildMarketplaceJson());
|
|
4859
|
+
}
|
|
4860
|
+
notes.push(`Wrote ZCode marketplace: ${MARKETPLACE_JSON_PATH}`);
|
|
4861
|
+
const knownRaw = readJson(KNOWN_MARKETPLACES_PATH);
|
|
4862
|
+
const knownNext = upsertKnownMarketplace(knownRaw);
|
|
4863
|
+
if (!dryRun)
|
|
4864
|
+
writeJson(KNOWN_MARKETPLACES_PATH, knownNext);
|
|
4865
|
+
notes.push(`Registered ${MARKETPLACE_ID} marketplace in ${KNOWN_MARKETPLACES_PATH}`);
|
|
4866
|
+
notes.push(`Then in ZCode: Settings → Plugin Management → Discover → install ${PLUGIN_NAME} from the ${MARKETPLACE_ID} marketplace.`);
|
|
4867
|
+
return {
|
|
4868
|
+
location: KNOWN_MARKETPLACES_PATH,
|
|
4869
|
+
notes
|
|
4870
|
+
};
|
|
4871
|
+
}
|
|
4872
|
+
function runDoctor2(scope) {
|
|
4873
|
+
const errors2 = [];
|
|
4874
|
+
errors2.push(...validateLocalHarnessRepo());
|
|
4875
|
+
if (scope === "project") {
|
|
4876
|
+
const projectRoot = resolveProjectRoot();
|
|
4877
|
+
const checkoutPath = path7.join(projectRoot, ZCODE_PLUGIN_CHECKOUT_PROJECT);
|
|
4878
|
+
errors2.push(...validateGitCheckout(checkoutPath, ZCODE_PLUGIN_MARKER));
|
|
4879
|
+
const gitignorePath = path7.join(projectRoot, ".gitignore");
|
|
4880
|
+
const gitignore = fs5.existsSync(gitignorePath) ? fs5.readFileSync(gitignorePath, "utf8") : "";
|
|
4881
|
+
if (!gitignore.split(/\r?\n/).includes(ZCODE_PLUGIN_CHECKOUT_PROJECT)) {
|
|
4882
|
+
errors2.push(`Missing .gitignore entry: ${ZCODE_PLUGIN_CHECKOUT_PROJECT}`);
|
|
4883
|
+
}
|
|
4884
|
+
for (const entry of missingHarnessProcessGitignoreEntries(gitignore)) {
|
|
4885
|
+
errors2.push(`Missing .gitignore entry: ${entry}`);
|
|
4886
|
+
}
|
|
4887
|
+
errors2.push(...validatePluginAgents2(checkoutPath));
|
|
4888
|
+
} else {
|
|
4889
|
+
errors2.push(...validatePluginAgents2(HARNESS_REPO_PATH));
|
|
4890
|
+
}
|
|
4891
|
+
errors2.push(...validateKnownMarketplaces());
|
|
4892
|
+
errors2.push(...validateMarketplaceJson());
|
|
4893
|
+
return { location: KNOWN_MARKETPLACES_PATH, errors: errors2 };
|
|
4894
|
+
}
|
|
4895
|
+
var zcodeAdapter = {
|
|
4896
|
+
target: "zcode",
|
|
4897
|
+
mode: "install",
|
|
4898
|
+
runInstallInit: (scope, dryRun) => runInit2(scope, dryRun),
|
|
4899
|
+
runInstallDoctor: (scope) => runDoctor2(scope)
|
|
4900
|
+
};
|
|
4901
|
+
|
|
4700
4902
|
// src/adapters/index.ts
|
|
4701
4903
|
var adapters = {
|
|
4702
4904
|
opencode: opencodeAdapter,
|
|
4703
4905
|
cursor: cursorAdapter,
|
|
4704
|
-
codex: codexAdapter
|
|
4906
|
+
codex: codexAdapter,
|
|
4907
|
+
zcode: zcodeAdapter
|
|
4705
4908
|
};
|
|
4706
4909
|
function getAdapter(target) {
|
|
4707
4910
|
const adapter = adapters[target];
|
|
@@ -4711,20 +4914,20 @@ function getAdapter(target) {
|
|
|
4711
4914
|
}
|
|
4712
4915
|
|
|
4713
4916
|
// src/types.ts
|
|
4714
|
-
var SUPPORTED_TARGETS = ["opencode", "cursor", "codex"];
|
|
4917
|
+
var SUPPORTED_TARGETS = ["opencode", "cursor", "codex", "zcode"];
|
|
4715
4918
|
|
|
4716
4919
|
// src/utils.ts
|
|
4717
|
-
import
|
|
4718
|
-
import
|
|
4920
|
+
import fs6 from "node:fs";
|
|
4921
|
+
import path8 from "node:path";
|
|
4719
4922
|
function parseCsv(raw) {
|
|
4720
4923
|
if (!raw)
|
|
4721
4924
|
return;
|
|
4722
4925
|
return raw.split(",").map((item) => item.trim()).filter(Boolean);
|
|
4723
4926
|
}
|
|
4724
4927
|
function readJson2(filePath) {
|
|
4725
|
-
if (!
|
|
4928
|
+
if (!fs6.existsSync(filePath))
|
|
4726
4929
|
return {};
|
|
4727
|
-
const content =
|
|
4930
|
+
const content = fs6.readFileSync(filePath, "utf8").trim();
|
|
4728
4931
|
if (!content)
|
|
4729
4932
|
return {};
|
|
4730
4933
|
try {
|
|
@@ -4734,18 +4937,18 @@ function readJson2(filePath) {
|
|
|
4734
4937
|
}
|
|
4735
4938
|
}
|
|
4736
4939
|
function writeJson2(filePath, value) {
|
|
4737
|
-
const parent =
|
|
4738
|
-
if (!
|
|
4739
|
-
|
|
4740
|
-
|
|
4940
|
+
const parent = path8.dirname(filePath);
|
|
4941
|
+
if (!fs6.existsSync(parent))
|
|
4942
|
+
fs6.mkdirSync(parent, { recursive: true });
|
|
4943
|
+
fs6.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}
|
|
4741
4944
|
`, "utf8");
|
|
4742
4945
|
}
|
|
4743
4946
|
|
|
4744
4947
|
// src/index.ts
|
|
4745
|
-
var packageJsonPath =
|
|
4948
|
+
var packageJsonPath = path9.resolve(path9.dirname(fileURLToPath(import.meta.url)), "../package.json");
|
|
4746
4949
|
var packageVersion = (() => {
|
|
4747
4950
|
try {
|
|
4748
|
-
const parsed = JSON.parse(
|
|
4951
|
+
const parsed = JSON.parse(fs7.readFileSync(packageJsonPath, "utf8"));
|
|
4749
4952
|
return parsed.version || "0.0.0";
|
|
4750
4953
|
} catch {
|
|
4751
4954
|
return "0.0.0";
|
|
@@ -4783,7 +4986,7 @@ function resolveExplicitModelAssignments(options) {
|
|
|
4783
4986
|
others: allow("other-models", parseCsv(options.otherModels), 3, true)
|
|
4784
4987
|
});
|
|
4785
4988
|
}
|
|
4786
|
-
async function
|
|
4989
|
+
async function runInit3(options) {
|
|
4787
4990
|
const target = options.target || (options.yes ? "opencode" : await pickTargetInteractive());
|
|
4788
4991
|
const scope = options.scope || "project";
|
|
4789
4992
|
const adapter = getAdapter(target);
|
|
@@ -4846,7 +5049,7 @@ async function runInit2(options) {
|
|
|
4846
5049
|
}
|
|
4847
5050
|
}
|
|
4848
5051
|
}
|
|
4849
|
-
function
|
|
5052
|
+
function runDoctor3(options) {
|
|
4850
5053
|
const target = options.target || "opencode";
|
|
4851
5054
|
const adapter = getAdapter(target);
|
|
4852
5055
|
const scope = options.scope || "project";
|
|
@@ -4891,10 +5094,10 @@ function runDoctor2(options) {
|
|
|
4891
5094
|
}
|
|
4892
5095
|
program2.name("mstar-harness").description("Morning Star harness CLI for target-based agent bootstrap").version(packageVersion);
|
|
4893
5096
|
program2.command("init").description("Interactive/non-interactive setup for target agent bootstrap").option("-y, --yes", "Non-interactive mode").option("--target <target>", "Install target", "opencode").option("--scope <scope>", "Config scope: global|project (default: project)").option("--output <path>", "Config file path override, relative to project root").option("--dry-run", "Preview result without writing config").option("--pm-model <model>", "Optional: model for project-manager (advanced override)").option("--strategic-models <a,b,c>", "Optional: models for architect/product-manager/prompt-engineer").option("--dev-models <a,b,c>", "Optional: models for fullstack-dev/fullstack-dev-2/frontend-dev").option("--qc-models <a,b,c>", "Optional: models for qc trio").option("--other-models <a,b,c>", "Optional: models for remaining roles").action(async (options) => {
|
|
4894
|
-
await
|
|
5097
|
+
await runInit3(options);
|
|
4895
5098
|
});
|
|
4896
5099
|
program2.command("doctor").description("Validate Morning Star setup for a target agent config").option("--target <target>", "Target agent for doctor checks", "opencode").option("--scope <scope>", "Config scope: global|project", "project").option("--output <path>", "Config file path override, relative to project root").action((options) => {
|
|
4897
|
-
|
|
5100
|
+
runDoctor3(options);
|
|
4898
5101
|
});
|
|
4899
5102
|
program2.parseAsync(process.argv).catch((error) => {
|
|
4900
5103
|
console.error(import_picocolors.default.red(`Setup failed: ${error.message}`));
|