@arvoretech/hub 0.1.2 → 0.3.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 (2) hide show
  1. package/dist/index.js +178 -3
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
- import { Command as Command16 } from "commander";
4
+ import { Command as Command17 } from "commander";
5
5
 
6
6
  // src/commands/init.ts
7
7
  import { Command } from "commander";
@@ -679,6 +679,7 @@ function buildKiroOrchestratorRule(config) {
679
679
  const taskFolder = config.workflow?.task_folder || "./tasks/<TASK_ID>/";
680
680
  const steps = config.workflow?.pipeline || [];
681
681
  const prompt = config.workflow?.prompt;
682
+ const enforce = config.workflow?.enforce_workflow ?? false;
682
683
  const sections = [];
683
684
  sections.push(`# Orchestrator
684
685
 
@@ -687,6 +688,22 @@ function buildKiroOrchestratorRule(config) {
687
688
  You are the development orchestrator. Your job is to ensure that any feature or task requested by the user is completed end-to-end by following a structured pipeline. You work as a single agent but follow specialized instructions from steering files for each phase of development.
688
689
 
689
690
  > **Note:** This workspace uses steering files in \`.kiro/steering/\` to provide role-specific instructions for each pipeline step. When a step says "follow the instructions from steering file X", read that file and apply its guidelines to the current task.`);
691
+ if (enforce) {
692
+ sections.push(`
693
+ ## STRICT WORKFLOW ENFORCEMENT
694
+
695
+ **YOU MUST FOLLOW THE PIPELINE DEFINED BELOW. NO EXCEPTIONS.**
696
+
697
+ - NEVER skip a pipeline step, even if the task seems simple or obvious.
698
+ - ALWAYS execute steps in the exact order defined. Do not reorder, merge, or parallelize steps unless the pipeline explicitly allows it.
699
+ - ALWAYS follow the designated steering file for each step. Do not improvise if a steering file is assigned.
700
+ - ALWAYS wait for a step to complete and validate its output before moving to the next step.
701
+ - If a step produces a document, READ the document and confirm it is complete before proceeding.
702
+ - If a step has unanswered questions or validation issues, RESOLVE them before advancing.
703
+ - NEVER jump directly to coding without completing refinement first.
704
+ - NEVER skip review or QA steps, even for small changes.
705
+ - If the user asks you to skip a step, explain why the pipeline exists and ask for explicit confirmation before proceeding.`);
706
+ }
690
707
  if (prompt?.prepend) {
691
708
  sections.push(`
692
709
  ${prompt.prepend.trim()}`);
@@ -786,6 +803,10 @@ Follow each step sequentially, applying the role-specific instructions from the
786
803
  }
787
804
  const stepTitle = step.step.charAt(0).toUpperCase() + step.step.slice(1);
788
805
  parts.push(`### ${stepTitle}`);
806
+ if (step.mode === "plan") {
807
+ parts.push(`**This step is a planning phase.** Do NOT make any code changes. Focus on reading, analyzing, and collaborating with the user to define requirements before proceeding.`);
808
+ parts.push(``);
809
+ }
789
810
  if (step.agent) {
790
811
  parts.push(`Follow the instructions from the \`agent-${step.agent}.md\` steering file.${step.output ? ` Write output to \`${step.output}\`.` : ""}`);
791
812
  if (step.step === "refinement") {
@@ -825,6 +846,7 @@ function buildOrchestratorRule(config) {
825
846
  const taskFolder = config.workflow?.task_folder || "./tasks/<TASK_ID>/";
826
847
  const steps = config.workflow?.pipeline || [];
827
848
  const prompt = config.workflow?.prompt;
849
+ const enforce = config.workflow?.enforce_workflow ?? false;
828
850
  const sections = [];
829
851
  sections.push(`---
830
852
  description: "Orchestrator agent \u2014 coordinates sub-agents through the development pipeline"
@@ -836,6 +858,22 @@ alwaysApply: true
836
858
  ## Your Main Responsibility
837
859
 
838
860
  You are an agent orchestrator. Your job is to ensure that any feature or task requested by the user is completed end-to-end using specialized sub-agents.`);
861
+ if (enforce) {
862
+ sections.push(`
863
+ ## STRICT WORKFLOW ENFORCEMENT
864
+
865
+ **YOU MUST FOLLOW THE PIPELINE DEFINED BELOW. NO EXCEPTIONS.**
866
+
867
+ - NEVER skip a pipeline step, even if the task seems simple or obvious.
868
+ - ALWAYS execute steps in the exact order defined. Do not reorder, merge, or parallelize steps unless the pipeline explicitly allows it.
869
+ - ALWAYS call the designated sub-agent for each step. Do not attempt to perform a step yourself if an agent is assigned to it.
870
+ - ALWAYS wait for a step to complete and validate its output before moving to the next step.
871
+ - If a step produces a document, READ the document and confirm it is complete before proceeding.
872
+ - If a step has unanswered questions or validation issues, RESOLVE them before advancing.
873
+ - NEVER jump directly to coding without completing refinement first.
874
+ - NEVER skip review or QA steps, even for small changes.
875
+ - If the user asks you to skip a step, explain why the pipeline exists and ask for explicit confirmation before proceeding.`);
876
+ }
839
877
  if (prompt?.prepend) {
840
878
  sections.push(`
841
879
  ${prompt.prepend.trim()}`);
@@ -963,6 +1001,10 @@ function buildPipelineSection(steps) {
963
1001
  }
964
1002
  const stepTitle = step.step.charAt(0).toUpperCase() + step.step.slice(1);
965
1003
  parts.push(`### ${stepTitle}`);
1004
+ if (step.mode === "plan") {
1005
+ parts.push(`**Before starting this step, switch to Plan Mode** by calling \`SwitchMode\` with \`target_mode_id: "plan"\`. This ensures collaborative planning with the user in a read-only context before any implementation begins.`);
1006
+ parts.push(``);
1007
+ }
966
1008
  if (step.agent) {
967
1009
  parts.push(`Call the \`${step.agent}\` agent.${step.output ? ` It writes to \`${step.output}\`.` : ""}`);
968
1010
  if (step.step === "refinement") {
@@ -998,6 +1040,10 @@ If any coding agent has doubts, they will write questions in their document. App
998
1040
  If any validation agent leaves comments requiring fixes, call the relevant coding agents again to address them.`);
999
1041
  }
1000
1042
  }
1043
+ if (step.mode === "plan") {
1044
+ parts.push(`
1045
+ **After this step is complete and approved**, switch back to Agent Mode to proceed with the next step.`);
1046
+ }
1001
1047
  parts.push("");
1002
1048
  }
1003
1049
  return parts.join("\n");
@@ -2291,6 +2337,55 @@ Agent '${name}' not found in ${opts.global ? "global" : "project"}
2291
2337
  Removed agent: ${name}
2292
2338
  `));
2293
2339
  })
2340
+ ).addCommand(
2341
+ new Command9("sync").description("Install all agents referenced in hub.yaml from the registry").option("-g, --global", "Install to global ~/.cursor/agents/").option("-r, --repo <repo>", "Registry repository (owner/repo)").option("-f, --force", "Re-install even if the agent already exists locally").action(async (opts) => {
2342
+ const hubDir = process.cwd();
2343
+ let config;
2344
+ try {
2345
+ config = await loadHubConfig(hubDir);
2346
+ } catch {
2347
+ console.log(chalk9.red("\n Could not load hub.yaml in the current directory.\n"));
2348
+ return;
2349
+ }
2350
+ const steps = config.workflow?.pipeline || [];
2351
+ const agentNames = /* @__PURE__ */ new Set();
2352
+ for (const step of steps) {
2353
+ if (step.agent) agentNames.add(step.agent);
2354
+ if (Array.isArray(step.agents)) {
2355
+ for (const a of step.agents) {
2356
+ agentNames.add(typeof a === "string" ? a : a.agent);
2357
+ }
2358
+ }
2359
+ }
2360
+ if (agentNames.size === 0) {
2361
+ console.log(chalk9.yellow("\n No agents found in hub.yaml workflow pipeline.\n"));
2362
+ return;
2363
+ }
2364
+ console.log(chalk9.blue(`
2365
+ \u2501\u2501\u2501 Syncing ${agentNames.size} agent(s) from hub.yaml \u2501\u2501\u2501
2366
+ `));
2367
+ const targetBase = opts.global ? join10(process.env.HOME || "~", ".cursor", "agents") : join10(hubDir, "agents");
2368
+ let installed = 0;
2369
+ let skipped = 0;
2370
+ for (const name of agentNames) {
2371
+ const fileName = name.endsWith(".md") ? name : `${name}.md`;
2372
+ const targetPath = join10(targetBase, fileName);
2373
+ if (!opts.force && existsSync7(targetPath)) {
2374
+ console.log(chalk9.dim(` \u2713 ${name} (already installed)`));
2375
+ skipped++;
2376
+ continue;
2377
+ }
2378
+ await addFromRegistry2(name, hubDir, { global: opts.global, repo: opts.repo });
2379
+ installed++;
2380
+ }
2381
+ console.log();
2382
+ if (installed > 0) console.log(chalk9.green(` ${installed} agent(s) installed`));
2383
+ if (skipped > 0) console.log(chalk9.dim(` ${skipped} agent(s) already up to date`));
2384
+ if (installed === 0 && skipped > 0) {
2385
+ console.log(chalk9.green(" All agents are already installed. Use --force to re-install."));
2386
+ }
2387
+ console.log();
2388
+ })
2294
2389
  );
2295
2390
 
2296
2391
  // src/commands/hooks.ts
@@ -3246,11 +3341,90 @@ function extractVersion(s) {
3246
3341
  return match?.[1] || s;
3247
3342
  }
3248
3343
 
3344
+ // src/commands/update.ts
3345
+ import { Command as Command16 } from "commander";
3346
+ import { execSync as execSync12 } from "child_process";
3347
+ import { readFileSync } from "fs";
3348
+ import { join as join17, dirname } from "path";
3349
+ import { fileURLToPath } from "url";
3350
+ import chalk16 from "chalk";
3351
+ var PACKAGE_NAME = "@arvoretech/hub";
3352
+ function getCurrentVersion() {
3353
+ const __dirname = dirname(fileURLToPath(import.meta.url));
3354
+ const pkgPath = join17(__dirname, "..", "package.json");
3355
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
3356
+ return pkg.version;
3357
+ }
3358
+ async function getLatestVersion() {
3359
+ const res = await fetch(`https://registry.npmjs.org/${PACKAGE_NAME}/latest`);
3360
+ if (!res.ok) throw new Error(`npm registry returned ${res.status}`);
3361
+ const data = await res.json();
3362
+ return data.version;
3363
+ }
3364
+ function detectPackageManager() {
3365
+ try {
3366
+ execSync12("pnpm --version", { stdio: "pipe" });
3367
+ return "pnpm";
3368
+ } catch {
3369
+ try {
3370
+ execSync12("yarn --version", { stdio: "pipe" });
3371
+ return "yarn";
3372
+ } catch {
3373
+ return "npm";
3374
+ }
3375
+ }
3376
+ }
3377
+ var updateCommand = new Command16("update").description("Update hub CLI to the latest version").option("--check", "Only check for updates without installing").action(async (opts) => {
3378
+ const currentVersion = getCurrentVersion();
3379
+ console.log(chalk16.blue(`
3380
+ Current version: ${currentVersion}`));
3381
+ let latestVersion;
3382
+ try {
3383
+ latestVersion = await getLatestVersion();
3384
+ } catch (err) {
3385
+ console.log(chalk16.red(` Failed to check for updates: ${err.message}
3386
+ `));
3387
+ return;
3388
+ }
3389
+ console.log(chalk16.blue(` Latest version: ${latestVersion}`));
3390
+ if (currentVersion === latestVersion) {
3391
+ console.log(chalk16.green("\n You're already on the latest version.\n"));
3392
+ return;
3393
+ }
3394
+ console.log(chalk16.yellow(`
3395
+ Update available: ${currentVersion} \u2192 ${latestVersion}`));
3396
+ if (opts.check) {
3397
+ const pm2 = detectPackageManager();
3398
+ console.log(chalk16.dim(`
3399
+ Run 'hub update' or '${pm2} install -g ${PACKAGE_NAME}@latest' to update.
3400
+ `));
3401
+ return;
3402
+ }
3403
+ const pm = detectPackageManager();
3404
+ const installCmd = pm === "pnpm" ? `pnpm install -g ${PACKAGE_NAME}@latest` : pm === "yarn" ? `yarn global add ${PACKAGE_NAME}@latest` : `npm install -g ${PACKAGE_NAME}@latest`;
3405
+ console.log(chalk16.cyan(`
3406
+ Updating with ${pm}...
3407
+ `));
3408
+ console.log(chalk16.dim(` $ ${installCmd}
3409
+ `));
3410
+ try {
3411
+ execSync12(installCmd, { stdio: "inherit" });
3412
+ console.log(chalk16.green(`
3413
+ Updated to ${latestVersion} successfully.
3414
+ `));
3415
+ } catch {
3416
+ console.log(chalk16.red(`
3417
+ Update failed. Try running manually:`));
3418
+ console.log(chalk16.dim(` $ ${installCmd}
3419
+ `));
3420
+ }
3421
+ });
3422
+
3249
3423
  // src/index.ts
3250
- var program = new Command16();
3424
+ var program = new Command17();
3251
3425
  program.name("hub").description(
3252
3426
  "Give your AI coding assistant the full picture. Multi-repo context, agent orchestration, and end-to-end workflows."
3253
- ).version("0.1.2").enablePositionalOptions();
3427
+ ).version("0.2.0").enablePositionalOptions();
3254
3428
  program.addCommand(initCommand);
3255
3429
  program.addCommand(addRepoCommand);
3256
3430
  program.addCommand(setupCommand);
@@ -3268,4 +3442,5 @@ program.addCommand(execCommand);
3268
3442
  program.addCommand(worktreeCommand);
3269
3443
  program.addCommand(doctorCommand);
3270
3444
  program.addCommand(toolsCommand);
3445
+ program.addCommand(updateCommand);
3271
3446
  program.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arvoretech/hub",
3
- "version": "0.1.2",
3
+ "version": "0.3.0",
4
4
  "description": "CLI for managing AI-aware multi-repository workspaces",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",