@meltstudio/meltctl 4.159.0 → 4.161.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 +67 -24
  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.159.0";
17
+ CLI_VERSION = "4.161.0";
18
18
  }
19
19
  });
20
20
 
@@ -954,8 +954,6 @@ function createPmResource(config) {
954
954
  params.set("category", filters.category);
955
955
  if (filters?.currentStage)
956
956
  params.set("currentStage", filters.currentStage);
957
- if (filters?.targetStage)
958
- params.set("targetStage", filters.targetStage);
959
957
  const res = await apiFetch(config, `/pm/features?${params}`);
960
958
  return unwrap("list features", res);
961
959
  },
@@ -1062,6 +1060,15 @@ function createPmResource(config) {
1062
1060
  const res = await apiFetch(config, `/pm/phases/${phaseId}/features/${featureId}`, { method: "DELETE" });
1063
1061
  unwrap("unassign feature", res);
1064
1062
  },
1063
+ /**
1064
+ * Patch the per-phase intent for a feature in a phase (#446 stage 2).
1065
+ * Edits the through-table row's `targetStage`, `phaseDescription`, and/or
1066
+ * `linearEpicUrl`. Server returns the updated membership row.
1067
+ */
1068
+ async updatePhaseFeature(phaseId, featureId, patch) {
1069
+ const res = await apiFetch(config, `/pm/phases/${phaseId}/features/${featureId}`, { method: "PATCH", body: JSON.stringify(patch) });
1070
+ return unwrap("update phase feature", res);
1071
+ },
1065
1072
  // ─── Roadmap ──────────────────────────────────────────────────────────
1066
1073
  async getRoadmap(projectId) {
1067
1074
  const res = await apiFetch(config, `/pm/projects/${projectId}/roadmap`);
@@ -3903,8 +3910,6 @@ function createPmResource2(config) {
3903
3910
  params.set("category", filters.category);
3904
3911
  if (filters?.currentStage)
3905
3912
  params.set("currentStage", filters.currentStage);
3906
- if (filters?.targetStage)
3907
- params.set("targetStage", filters.targetStage);
3908
3913
  const res = await apiFetch2(config, `/pm/features?${params}`);
3909
3914
  return unwrap2("list features", res);
3910
3915
  },
@@ -4011,6 +4016,15 @@ function createPmResource2(config) {
4011
4016
  const res = await apiFetch2(config, `/pm/phases/${phaseId}/features/${featureId}`, { method: "DELETE" });
4012
4017
  unwrap2("unassign feature", res);
4013
4018
  },
4019
+ /**
4020
+ * Patch the per-phase intent for a feature in a phase (#446 stage 2).
4021
+ * Edits the through-table row's `targetStage`, `phaseDescription`, and/or
4022
+ * `linearEpicUrl`. Server returns the updated membership row.
4023
+ */
4024
+ async updatePhaseFeature(phaseId, featureId, patch) {
4025
+ const res = await apiFetch2(config, `/pm/phases/${phaseId}/features/${featureId}`, { method: "PATCH", body: JSON.stringify(patch) });
4026
+ return unwrap2("update phase feature", res);
4027
+ },
4014
4028
  // ─── Roadmap ──────────────────────────────────────────────────────────
4015
4029
  async getRoadmap(projectId) {
4016
4030
  const res = await apiFetch2(config, `/pm/projects/${projectId}/roadmap`);
@@ -4829,6 +4843,7 @@ function registerProjectTools(server, getClient2) {
4829
4843
  }
4830
4844
  var SHAPE_VALUES = ["crawling", "walking", "running"];
4831
4845
  var SHAPE_DESC = "crawling | walking | running. Target shape is intent (PM sets when creating); current shape is computed from feature stages.";
4846
+ var STAGE_VALUES = ["idea", "poc", "pt", "mv", "mk", "ma", "mbi"];
4832
4847
  async function listPhases(client, input3) {
4833
4848
  return safe(() => client.pm.listPhases(input3.projectId, input3.includeClosed ?? false));
4834
4849
  }
@@ -4854,6 +4869,10 @@ async function assignFeatureToPhase(client, input3) {
4854
4869
  async function unassignFeatureFromPhase(client, input3) {
4855
4870
  return safe(() => client.pm.unassignFeature(input3.phaseId, input3.featureId));
4856
4871
  }
4872
+ async function updatePhaseFeature(client, input3) {
4873
+ const { phaseId, featureId, ...patch } = input3;
4874
+ return safe(() => client.pm.updatePhaseFeature(phaseId, featureId, patch));
4875
+ }
4857
4876
  var createPhaseInputSchema = z3.object({
4858
4877
  projectId: z3.number().int().positive(),
4859
4878
  name: z3.string().min(1),
@@ -4978,9 +4997,38 @@ Mandatory caller behavior: present the phase's name + id + active/closed status
4978
4997
  },
4979
4998
  withClientArgs(getClient2, unassignFeatureFromPhase)
4980
4999
  );
5000
+ server.registerTool(
5001
+ "update_phase_feature",
5002
+ {
5003
+ title: "Update phase-feature membership",
5004
+ 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.",
5005
+ inputSchema: {
5006
+ phaseId: z3.string().uuid().describe("Phase id from list_phases."),
5007
+ featureId: z3.string().uuid().describe("Feature id of the membership to edit."),
5008
+ targetStage: z3.enum(STAGE_VALUES).optional().describe(
5009
+ "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)."
5010
+ ),
5011
+ phaseDescription: z3.string().min(1).optional().describe(
5012
+ "One-line PM-voice note: what should this feature be doing once this phase's jump lands. New memberships default to 'PM to refine'."
5013
+ ),
5014
+ linearEpicUrl: z3.string().url().nullable().optional().describe(
5015
+ "Per-phase Linear epic URL. Each phase's work on a feature can be its own epic. Pass null to clear."
5016
+ )
5017
+ }
5018
+ },
5019
+ withClientArgs(getClient2, updatePhaseFeature)
5020
+ );
4981
5021
  }
4982
- var STAGE_VALUES = ["idea", "poc", "pt", "mv", "mk", "ma", "mbi"];
5022
+ var STAGE_VALUES2 = ["idea", "poc", "pt", "mv", "mk", "ma", "mbi"];
4983
5023
  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).";
5024
+ var STARTING_POINT_VALUES = [
5025
+ "unknown",
5026
+ "starter_kit",
5027
+ "saas",
5028
+ "oss_library",
5029
+ "from_scratch"
5030
+ ];
5031
+ 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'.";
4984
5032
  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.";
4985
5033
  async function listFeatures(client, input3) {
4986
5034
  const { projectId, ...filters } = input3;
@@ -5008,8 +5056,8 @@ var createFeatureInputSchema = z4.object({
5008
5056
  category: z4.string().min(1),
5009
5057
  description: z4.string().optional(),
5010
5058
  prdPath: z4.string().url().optional(),
5011
- currentStage: z4.enum(STAGE_VALUES).optional(),
5012
- targetStage: z4.enum(STAGE_VALUES).optional(),
5059
+ currentStage: z4.enum(STAGE_VALUES2).optional(),
5060
+ startingPoint: z4.enum(STARTING_POINT_VALUES).optional(),
5013
5061
  status: z4.string().optional(),
5014
5062
  clientNotes: z4.string().optional(),
5015
5063
  createdAt: z4.string().datetime().optional(),
@@ -5022,25 +5070,23 @@ var updateFeatureInputSchema = z4.object({
5022
5070
  category: z4.string().min(1).optional(),
5023
5071
  description: z4.string().optional(),
5024
5072
  prdPath: z4.string().url().optional(),
5025
- currentStage: z4.enum(STAGE_VALUES).optional(),
5026
- targetStage: z4.enum(STAGE_VALUES).optional(),
5073
+ currentStage: z4.enum(STAGE_VALUES2).optional(),
5074
+ startingPoint: z4.enum(STARTING_POINT_VALUES).optional(),
5027
5075
  status: z4.string().optional(),
5028
- clientNotes: z4.string().optional(),
5029
- linearEpicUrl: z4.string().url().nullable().optional()
5076
+ clientNotes: z4.string().optional()
5030
5077
  });
5031
5078
  function registerFeatureTools(server, getClient2) {
5032
5079
  server.registerTool(
5033
5080
  "list_features",
5034
5081
  {
5035
5082
  title: "List features",
5036
- description: "Lists features on the project. Each entry has id, name, category, description, current_stage, target_stage, status, prd_path, client_notes, and Linear epic url if synced. Optional filters narrow server-side: phaseId returns only features assigned to that phase; status / category / currentStage / targetStage filter on the matching column.",
5083
+ description: "Lists features on the project. Each entry has id, name, category, description, current_stage, status, prd_path, client_notes, and starting_point. Per-phase target stage + Linear epic live on the phase membership (see list_phases), not the feature row. Optional filters narrow server-side: phaseId returns only features assigned to that phase; status / category / currentStage filter on the matching column.",
5037
5084
  inputSchema: {
5038
5085
  projectId: z4.number().int().positive(),
5039
5086
  phaseId: z4.string().uuid().optional().describe("Limit to features assigned to this phase (phase_features join)."),
5040
5087
  status: z4.string().optional().describe("Filter by status \u2014 typically not_started / in_progress / done."),
5041
5088
  category: z4.string().optional().describe("Filter by roadmap category, exact match."),
5042
- currentStage: z4.enum(STAGE_VALUES).optional().describe("Filter by current_stage."),
5043
- targetStage: z4.enum(STAGE_VALUES).optional().describe("Filter by target_stage.")
5089
+ currentStage: z4.enum(STAGE_VALUES2).optional().describe("Filter by current_stage.")
5044
5090
  }
5045
5091
  },
5046
5092
  withClientArgs(getClient2, listFeatures)
@@ -5056,8 +5102,8 @@ function registerFeatureTools(server, getClient2) {
5056
5102
  category: z4.string().min(1).describe('Roadmap grouping, e.g. "Frontend & UI", "API & Data", "Ops".'),
5057
5103
  description: z4.string().optional().describe("One-sentence summary for the roadmap row."),
5058
5104
  prdPath: z4.string().url().optional().describe(PRD_PATH_DESC),
5059
- currentStage: z4.enum(STAGE_VALUES).optional().describe(`Default idea. ${STAGE_DESC}`),
5060
- targetStage: z4.enum(STAGE_VALUES).optional().describe(`Default mv. ${STAGE_DESC}`),
5105
+ currentStage: z4.enum(STAGE_VALUES2).optional().describe(`Default idea. ${STAGE_DESC}`),
5106
+ startingPoint: z4.enum(STARTING_POINT_VALUES).optional().describe(`Default unknown. ${STARTING_POINT_DESC}`),
5061
5107
  status: z4.string().optional().describe("Default not_started. Common values: not_started, in_progress, done."),
5062
5108
  clientNotes: z4.string().optional().describe("Free-text. What blockers from the client side, if any."),
5063
5109
  createdAt: z4.string().datetime().optional().describe(
@@ -5099,20 +5145,17 @@ Mandatory caller behavior: present the feature's name + id + every phase it curr
5099
5145
  "update_feature",
5100
5146
  {
5101
5147
  title: "Update feature",
5102
- description: "Patches fields on an existing feature. Pass only the fields you want to change. Common uses: advancing current_stage as work progresses, flipping status to in_progress/done, wiring linearEpicUrl after the Linear epic exists. The PM should review the proposed change before this is called \u2014 this is a write operation. Pass linearEpicUrl=null to clear the Linear link.",
5148
+ description: "Patches fields on an existing feature. Pass only the fields you want to change. Common uses: advancing current_stage as work progresses, flipping status to in_progress/done, setting starting_point. The PM should review the proposed change before this is called \u2014 this is a write operation. Per-phase target stage + Linear epic are NOT set here \u2014 they live on the phase membership; use update_phase_feature for those.",
5103
5149
  inputSchema: {
5104
5150
  id: z4.string().uuid().describe("Feature id from list_features or create_feature."),
5105
5151
  name: z4.string().min(1).optional(),
5106
5152
  category: z4.string().min(1).optional(),
5107
5153
  description: z4.string().optional(),
5108
5154
  prdPath: z4.string().url().optional().describe(PRD_PATH_DESC),
5109
- currentStage: z4.enum(STAGE_VALUES).optional().describe(STAGE_DESC),
5110
- targetStage: z4.enum(STAGE_VALUES).optional().describe(STAGE_DESC),
5155
+ currentStage: z4.enum(STAGE_VALUES2).optional().describe(STAGE_DESC),
5156
+ startingPoint: z4.enum(STARTING_POINT_VALUES).optional().describe(STARTING_POINT_DESC),
5111
5157
  status: z4.string().optional().describe("Common values: not_started, in_progress, done."),
5112
- clientNotes: z4.string().optional(),
5113
- linearEpicUrl: z4.string().url().nullable().optional().describe(
5114
- "Linear epic URL for the feature. Pass null to clear. Setting this also marks the feature as synced (synced_to_linear_at = now); clearing it also clears that timestamp."
5115
- )
5158
+ clientNotes: z4.string().optional()
5116
5159
  }
5117
5160
  },
5118
5161
  withClientArgs(getClient2, updateFeature)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meltstudio/meltctl",
3
- "version": "4.159.0",
3
+ "version": "4.161.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",