@meltstudio/meltctl 4.158.0 → 4.160.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 +80 -14
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -14,7 +14,7 @@ var CLI_VERSION;
14
14
  var init_version = __esm({
15
15
  "src/utils/version.ts"() {
16
16
  "use strict";
17
- CLI_VERSION = "4.158.0";
17
+ CLI_VERSION = "4.160.0";
18
18
  }
19
19
  });
20
20
 
@@ -1062,6 +1062,15 @@ function createPmResource(config) {
1062
1062
  const res = await apiFetch(config, `/pm/phases/${phaseId}/features/${featureId}`, { method: "DELETE" });
1063
1063
  unwrap("unassign feature", res);
1064
1064
  },
1065
+ /**
1066
+ * Patch the per-phase intent for a feature in a phase (#446 stage 2).
1067
+ * Edits the through-table row's `targetStage`, `phaseDescription`, and/or
1068
+ * `linearEpicUrl`. Server returns the updated membership row.
1069
+ */
1070
+ async updatePhaseFeature(phaseId, featureId, patch) {
1071
+ const res = await apiFetch(config, `/pm/phases/${phaseId}/features/${featureId}`, { method: "PATCH", body: JSON.stringify(patch) });
1072
+ return unwrap("update phase feature", res);
1073
+ },
1065
1074
  // ─── Roadmap ──────────────────────────────────────────────────────────
1066
1075
  async getRoadmap(projectId) {
1067
1076
  const res = await apiFetch(config, `/pm/projects/${projectId}/roadmap`);
@@ -4011,6 +4020,15 @@ function createPmResource2(config) {
4011
4020
  const res = await apiFetch2(config, `/pm/phases/${phaseId}/features/${featureId}`, { method: "DELETE" });
4012
4021
  unwrap2("unassign feature", res);
4013
4022
  },
4023
+ /**
4024
+ * Patch the per-phase intent for a feature in a phase (#446 stage 2).
4025
+ * Edits the through-table row's `targetStage`, `phaseDescription`, and/or
4026
+ * `linearEpicUrl`. Server returns the updated membership row.
4027
+ */
4028
+ async updatePhaseFeature(phaseId, featureId, patch) {
4029
+ const res = await apiFetch2(config, `/pm/phases/${phaseId}/features/${featureId}`, { method: "PATCH", body: JSON.stringify(patch) });
4030
+ return unwrap2("update phase feature", res);
4031
+ },
4014
4032
  // ─── Roadmap ──────────────────────────────────────────────────────────
4015
4033
  async getRoadmap(projectId) {
4016
4034
  const res = await apiFetch2(config, `/pm/projects/${projectId}/roadmap`);
@@ -4769,7 +4787,7 @@ function registerProjectTools(server, getClient2) {
4769
4787
  "get_project_settings",
4770
4788
  {
4771
4789
  title: "Get project settings",
4772
- description: 'Returns the project\'s PM-skills settings: cadence (weekly/biweekly/monthly), start_day, demo_day, team_size, velocity_override, Linear workspace, Notion URLs, code repo path, tech-support contact, default language, project glossary, project stage. Includes a `warnings` array flagging settings whose absence breaks downstream behavior (e.g., "calculator: missing teamSize"). Returns sensible defaults if no settings row exists yet (cadence=weekly, start_day=Monday, demo_day=Friday, defaultLanguage=English).',
4790
+ description: 'Returns the project\'s PM-skills settings: cadence (weekly/biweekly/monthly), start_day, demo_day, team_size, velocity_override, Linear workspace, Notion URLs, code repo path, tech-support contact, default language, project glossary, project stage, default jump duration weeks. Includes a `warnings` array flagging settings whose absence breaks downstream behavior (e.g., "calculator: missing teamSize"). Returns sensible defaults if no settings row exists yet (cadence=weekly, start_day=Monday, demo_day=Friday, defaultLanguage=English, defaultJumpDurationWeeks=1).',
4773
4791
  inputSchema: {
4774
4792
  projectId: z22.number().int().positive().describe("Strapi project id from list_projects.")
4775
4793
  }
@@ -4805,6 +4823,9 @@ function registerProjectTools(server, getClient2) {
4805
4823
  projectGlossary: z22.string().nullable().optional().describe(
4806
4824
  "Free-text project glossary surfaced to skills as context. Pass null to clear."
4807
4825
  ),
4826
+ defaultJumpDurationWeeks: z22.number().positive().optional().describe(
4827
+ "Project-wide default weeks per maturity jump. New phases inherit this on insert; PMs override per phase via update_phase. Used by the maturity-jumps calculator: total_jumps \xD7 jumpDurationWeeks \xD7 teamSize = total_weeks. Tighter values (0.25-0.5) model fast iteration; longer values (2-3) model robust hardening. NOT NULL with default 1; omit to leave the existing value in place."
4828
+ ),
4808
4829
  projectStage: z22.enum(PROJECT_STAGE_VALUES).nullable().optional().describe(
4809
4830
  "Canonical PM-owned project stage that drives audit calibration: prototype | early_revenue | growth | scale. The server stamps projectStageSetBy + projectStageSetAt automatically. Pass null to clear."
4810
4831
  )
@@ -4826,6 +4847,7 @@ function registerProjectTools(server, getClient2) {
4826
4847
  }
4827
4848
  var SHAPE_VALUES = ["crawling", "walking", "running"];
4828
4849
  var SHAPE_DESC = "crawling | walking | running. Target shape is intent (PM sets when creating); current shape is computed from feature stages.";
4850
+ var STAGE_VALUES = ["idea", "poc", "pt", "mv", "mk", "ma", "mbi"];
4829
4851
  async function listPhases(client, input3) {
4830
4852
  return safe(() => client.pm.listPhases(input3.projectId, input3.includeClosed ?? false));
4831
4853
  }
@@ -4851,13 +4873,18 @@ async function assignFeatureToPhase(client, input3) {
4851
4873
  async function unassignFeatureFromPhase(client, input3) {
4852
4874
  return safe(() => client.pm.unassignFeature(input3.phaseId, input3.featureId));
4853
4875
  }
4876
+ async function updatePhaseFeature(client, input3) {
4877
+ const { phaseId, featureId, ...patch } = input3;
4878
+ return safe(() => client.pm.updatePhaseFeature(phaseId, featureId, patch));
4879
+ }
4854
4880
  var createPhaseInputSchema = z3.object({
4855
4881
  projectId: z3.number().int().positive(),
4856
4882
  name: z3.string().min(1),
4857
4883
  targetShape: z3.enum(SHAPE_VALUES).default("walking"),
4858
4884
  isPrimary: z3.boolean().optional(),
4859
4885
  createdAt: z3.string().datetime().optional(),
4860
- closedAt: z3.string().datetime().nullable().optional()
4886
+ closedAt: z3.string().datetime().nullable().optional(),
4887
+ jumpDurationWeeks: z3.number().positive().optional()
4861
4888
  });
4862
4889
  function registerPhaseTools(server, getClient2) {
4863
4890
  server.registerTool(
@@ -4889,6 +4916,9 @@ function registerPhaseTools(server, getClient2) {
4889
4916
  ),
4890
4917
  closedAt: z3.string().datetime().nullable().optional().describe(
4891
4918
  "ISO 8601 timestamp. When set, the phase is created as historical (isActive=false, isPrimary=false). Use to backfill phases that closed months ago."
4919
+ ),
4920
+ jumpDurationWeeks: z3.number().positive().optional().describe(
4921
+ "Override the project default jump duration for this phase, in weeks. Tighter (0.25-0.5) for fast iteration / proof-of-concept; longer (2-3) for hardening. Omit to inherit pm_project_settings.defaultJumpDurationWeeks."
4892
4922
  )
4893
4923
  }
4894
4924
  },
@@ -4926,6 +4956,9 @@ function registerPhaseTools(server, getClient2) {
4926
4956
  ),
4927
4957
  closedAt: z3.string().datetime().nullable().optional().describe(
4928
4958
  "ISO 8601 timestamp or null. When set non-null, forces isActive=false + isPrimary=false. When null, clears the closed-at stamp."
4959
+ ),
4960
+ jumpDurationWeeks: z3.number().positive().optional().describe(
4961
+ "Override the project default jump duration for this phase, in weeks. Tighter (0.25-0.5) for fast iteration / proof-of-concept; longer (2-3) for hardening. The audit will eventually flag mismatches between jump duration and per-feature target stages."
4929
4962
  )
4930
4963
  }
4931
4964
  },
@@ -4968,9 +5001,38 @@ Mandatory caller behavior: present the phase's name + id + active/closed status
4968
5001
  },
4969
5002
  withClientArgs(getClient2, unassignFeatureFromPhase)
4970
5003
  );
5004
+ server.registerTool(
5005
+ "update_phase_feature",
5006
+ {
5007
+ title: "Update phase-feature membership",
5008
+ description: "Edits the per-phase intent for a feature in a phase: targetStage (what this phase aims to bring the feature to), phaseDescription (PM-authored note about what this jump means in this phase), linearEpicUrl (per-phase Linear epic). The same feature can have different per-phase targets \u2014 e.g. 'prototype' in phase 1, 'MVP' in phase 2. Use after assign_feature_to_phase when the PM wants per-membership values different from the feature-row defaults. The PM should review the proposed change before this is called \u2014 this is a write operation. Pass linearEpicUrl=null to clear the per-phase Linear link.",
5009
+ inputSchema: {
5010
+ phaseId: z3.string().uuid().describe("Phase id from list_phases."),
5011
+ featureId: z3.string().uuid().describe("Feature id of the membership to edit."),
5012
+ targetStage: z3.enum(STAGE_VALUES).optional().describe(
5013
+ "Per-phase target stage. What this phase aims to bring the feature to \u2014 e.g. 'pt' for prototype in an early phase, 'mv' for MVP in a later one. 7-stage enum (idea | poc | pt | mv | mk | ma | mbi)."
5014
+ ),
5015
+ phaseDescription: z3.string().min(1).optional().describe(
5016
+ "One-line PM-voice note: what should this feature be doing once this phase's jump lands. New memberships default to 'PM to refine'."
5017
+ ),
5018
+ linearEpicUrl: z3.string().url().nullable().optional().describe(
5019
+ "Per-phase Linear epic URL. Each phase's work on a feature can be its own epic. Pass null to clear."
5020
+ )
5021
+ }
5022
+ },
5023
+ withClientArgs(getClient2, updatePhaseFeature)
5024
+ );
4971
5025
  }
4972
- var STAGE_VALUES = ["idea", "poc", "pt", "mv", "mk", "ma", "mbi"];
5026
+ var STAGE_VALUES2 = ["idea", "poc", "pt", "mv", "mk", "ma", "mbi"];
4973
5027
  var STAGE_DESC = "idea | poc | pt | mv | mk | ma | mbi. The 7 maturity stages from the workflow doc \u2014 pick the one that matches where the work *looks like* it is right now (or where it should land for target).";
5028
+ var STARTING_POINT_VALUES = [
5029
+ "unknown",
5030
+ "starter_kit",
5031
+ "saas",
5032
+ "oss_library",
5033
+ "from_scratch"
5034
+ ];
5035
+ var STARTING_POINT_DESC = "unknown | starter_kit | saas | oss_library | from_scratch. The feature's technical starting point. Drives audit calibration \u2014 a feature backed by SaaS (Stripe, Auth0) gets to MVP in one jump; one built from scratch needs more. starter_kit is called out specially in audits + portal as a Melt differentiator. Default 'unknown' for historical features where the starting point is genuinely not known \u2014 downstream consumers treat 'unknown' as 'skip this dimension', not 'from scratch'.";
4974
5036
  var PRD_PATH_DESC = "http(s) URL pointing to the PRD (Notion, Google Doc, etc.). Omit if there is no PRD yet \u2014 relative paths or plain text are rejected.";
4975
5037
  async function listFeatures(client, input3) {
4976
5038
  const { projectId, ...filters } = input3;
@@ -4998,8 +5060,9 @@ var createFeatureInputSchema = z4.object({
4998
5060
  category: z4.string().min(1),
4999
5061
  description: z4.string().optional(),
5000
5062
  prdPath: z4.string().url().optional(),
5001
- currentStage: z4.enum(STAGE_VALUES).optional(),
5002
- targetStage: z4.enum(STAGE_VALUES).optional(),
5063
+ currentStage: z4.enum(STAGE_VALUES2).optional(),
5064
+ targetStage: z4.enum(STAGE_VALUES2).optional(),
5065
+ startingPoint: z4.enum(STARTING_POINT_VALUES).optional(),
5003
5066
  status: z4.string().optional(),
5004
5067
  clientNotes: z4.string().optional(),
5005
5068
  createdAt: z4.string().datetime().optional(),
@@ -5012,8 +5075,9 @@ var updateFeatureInputSchema = z4.object({
5012
5075
  category: z4.string().min(1).optional(),
5013
5076
  description: z4.string().optional(),
5014
5077
  prdPath: z4.string().url().optional(),
5015
- currentStage: z4.enum(STAGE_VALUES).optional(),
5016
- targetStage: z4.enum(STAGE_VALUES).optional(),
5078
+ currentStage: z4.enum(STAGE_VALUES2).optional(),
5079
+ targetStage: z4.enum(STAGE_VALUES2).optional(),
5080
+ startingPoint: z4.enum(STARTING_POINT_VALUES).optional(),
5017
5081
  status: z4.string().optional(),
5018
5082
  clientNotes: z4.string().optional(),
5019
5083
  linearEpicUrl: z4.string().url().nullable().optional()
@@ -5029,8 +5093,8 @@ function registerFeatureTools(server, getClient2) {
5029
5093
  phaseId: z4.string().uuid().optional().describe("Limit to features assigned to this phase (phase_features join)."),
5030
5094
  status: z4.string().optional().describe("Filter by status \u2014 typically not_started / in_progress / done."),
5031
5095
  category: z4.string().optional().describe("Filter by roadmap category, exact match."),
5032
- currentStage: z4.enum(STAGE_VALUES).optional().describe("Filter by current_stage."),
5033
- targetStage: z4.enum(STAGE_VALUES).optional().describe("Filter by target_stage.")
5096
+ currentStage: z4.enum(STAGE_VALUES2).optional().describe("Filter by current_stage."),
5097
+ targetStage: z4.enum(STAGE_VALUES2).optional().describe("Filter by target_stage.")
5034
5098
  }
5035
5099
  },
5036
5100
  withClientArgs(getClient2, listFeatures)
@@ -5046,8 +5110,9 @@ function registerFeatureTools(server, getClient2) {
5046
5110
  category: z4.string().min(1).describe('Roadmap grouping, e.g. "Frontend & UI", "API & Data", "Ops".'),
5047
5111
  description: z4.string().optional().describe("One-sentence summary for the roadmap row."),
5048
5112
  prdPath: z4.string().url().optional().describe(PRD_PATH_DESC),
5049
- currentStage: z4.enum(STAGE_VALUES).optional().describe(`Default idea. ${STAGE_DESC}`),
5050
- targetStage: z4.enum(STAGE_VALUES).optional().describe(`Default mv. ${STAGE_DESC}`),
5113
+ currentStage: z4.enum(STAGE_VALUES2).optional().describe(`Default idea. ${STAGE_DESC}`),
5114
+ targetStage: z4.enum(STAGE_VALUES2).optional().describe(`Default mv. ${STAGE_DESC}`),
5115
+ startingPoint: z4.enum(STARTING_POINT_VALUES).optional().describe(`Default unknown. ${STARTING_POINT_DESC}`),
5051
5116
  status: z4.string().optional().describe("Default not_started. Common values: not_started, in_progress, done."),
5052
5117
  clientNotes: z4.string().optional().describe("Free-text. What blockers from the client side, if any."),
5053
5118
  createdAt: z4.string().datetime().optional().describe(
@@ -5096,8 +5161,9 @@ Mandatory caller behavior: present the feature's name + id + every phase it curr
5096
5161
  category: z4.string().min(1).optional(),
5097
5162
  description: z4.string().optional(),
5098
5163
  prdPath: z4.string().url().optional().describe(PRD_PATH_DESC),
5099
- currentStage: z4.enum(STAGE_VALUES).optional().describe(STAGE_DESC),
5100
- targetStage: z4.enum(STAGE_VALUES).optional().describe(STAGE_DESC),
5164
+ currentStage: z4.enum(STAGE_VALUES2).optional().describe(STAGE_DESC),
5165
+ targetStage: z4.enum(STAGE_VALUES2).optional().describe(STAGE_DESC),
5166
+ startingPoint: z4.enum(STARTING_POINT_VALUES).optional().describe(STARTING_POINT_DESC),
5101
5167
  status: z4.string().optional().describe("Common values: not_started, in_progress, done."),
5102
5168
  clientNotes: z4.string().optional(),
5103
5169
  linearEpicUrl: z4.string().url().nullable().optional().describe(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meltstudio/meltctl",
3
- "version": "4.158.0",
3
+ "version": "4.160.0",
4
4
  "description": "AI-first development tools for teams - set up AGENTS.md, Claude Code, Cursor, and OpenCode standards",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",