@meltstudio/meltctl 5.17.0 → 5.19.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/index.js +42 -15
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7450,7 +7450,7 @@ var CLI_VERSION;
|
|
|
7450
7450
|
var init_version = __esm({
|
|
7451
7451
|
"src/utils/version.ts"() {
|
|
7452
7452
|
"use strict";
|
|
7453
|
-
CLI_VERSION = "5.
|
|
7453
|
+
CLI_VERSION = "5.19.0";
|
|
7454
7454
|
}
|
|
7455
7455
|
});
|
|
7456
7456
|
|
|
@@ -27403,8 +27403,14 @@ function createPmResource(config2) {
|
|
|
27403
27403
|
});
|
|
27404
27404
|
return unwrap("promote scenario", res);
|
|
27405
27405
|
},
|
|
27406
|
-
|
|
27407
|
-
|
|
27406
|
+
/**
|
|
27407
|
+
* Add a feature to a phase, optionally authoring the per-phase intent in
|
|
27408
|
+
* the same call (#611). Omitting `init` keeps the historical behaviour —
|
|
27409
|
+
* the membership takes the schema defaults (target `mv`, placeholder
|
|
27410
|
+
* scope) and the PM refines later via {@link updatePhaseFeature}.
|
|
27411
|
+
*/
|
|
27412
|
+
async assignFeature(phaseId, featureId, init) {
|
|
27413
|
+
const res = await apiFetch(config2, `/pm/phases/${phaseId}/features`, { method: "POST", body: JSON.stringify({ featureId, ...init }) });
|
|
27408
27414
|
return unwrap("assign feature", res, 201);
|
|
27409
27415
|
},
|
|
27410
27416
|
async unassignFeature(phaseId, featureId) {
|
|
@@ -43237,6 +43243,7 @@ function detectAuditType(filename) {
|
|
|
43237
43243
|
const lower = filename.toLowerCase();
|
|
43238
43244
|
if (lower.includes("security-audit")) return "security-audit";
|
|
43239
43245
|
if (lower.includes("ux-audit")) return "ux-audit";
|
|
43246
|
+
if (lower.includes("cost-audit")) return "cost-audit";
|
|
43240
43247
|
return "audit";
|
|
43241
43248
|
}
|
|
43242
43249
|
async function autoDetectAuditFile() {
|
|
@@ -43324,7 +43331,8 @@ async function auditListCommand(options) {
|
|
|
43324
43331
|
const typeLabels = {
|
|
43325
43332
|
audit: "Tech Audit",
|
|
43326
43333
|
"ux-audit": "UX Audit",
|
|
43327
|
-
"security-audit": "Security"
|
|
43334
|
+
"security-audit": "Security",
|
|
43335
|
+
"cost-audit": "Cost Audit"
|
|
43328
43336
|
};
|
|
43329
43337
|
if (options.latest) {
|
|
43330
43338
|
console.log(source_default.bold(`
|
|
@@ -43370,7 +43378,7 @@ function printLatestAuditRow(r, typeLabels) {
|
|
|
43370
43378
|
});
|
|
43371
43379
|
const repo = r.repository ?? r.project;
|
|
43372
43380
|
const label = typeLabels[r.type] ?? r.type;
|
|
43373
|
-
const typeColor = r.type === "ux-audit" ? source_default.yellow : r.type === "security-audit" ? source_default.red : source_default.magenta;
|
|
43381
|
+
const typeColor = r.type === "ux-audit" ? source_default.yellow : r.type === "security-audit" ? source_default.red : r.type === "cost-audit" ? source_default.cyan : source_default.magenta;
|
|
43374
43382
|
const ageText = daysAgo === 0 ? "today" : `${daysAgo}d ago`;
|
|
43375
43383
|
const isSecurityAudit = r.type === "security-audit";
|
|
43376
43384
|
const ageColor = isSecurityAudit ? daysAgo <= 30 ? source_default.green : daysAgo <= 90 ? source_default.yellow : source_default.red : daysAgo <= 7 ? source_default.green : daysAgo <= 30 ? source_default.yellow : source_default.red;
|
|
@@ -43388,7 +43396,7 @@ function printAuditRow(r, typeLabels) {
|
|
|
43388
43396
|
});
|
|
43389
43397
|
const repo = r.repository ?? r.project;
|
|
43390
43398
|
const label = typeLabels[r.type] ?? r.type;
|
|
43391
|
-
const typeColor = r.type === "ux-audit" ? source_default.yellow : r.type === "security-audit" ? source_default.red : source_default.magenta;
|
|
43399
|
+
const typeColor = r.type === "ux-audit" ? source_default.yellow : r.type === "security-audit" ? source_default.red : r.type === "cost-audit" ? source_default.cyan : source_default.magenta;
|
|
43392
43400
|
console.log(
|
|
43393
43401
|
` ${source_default.dim(r.id.slice(0, 8).padEnd(10))} ${typeColor(label.padEnd(12))} ${source_default.white(repo.padEnd(40))} ${source_default.dim(r.author.padEnd(30))} ${source_default.dim(date5)}`
|
|
43394
43402
|
);
|
|
@@ -43413,7 +43421,8 @@ async function auditViewCommand(id, options) {
|
|
|
43413
43421
|
const typeLabels = {
|
|
43414
43422
|
audit: "Tech Audit",
|
|
43415
43423
|
"ux-audit": "UX Audit",
|
|
43416
|
-
"security-audit": "Security Audit"
|
|
43424
|
+
"security-audit": "Security Audit",
|
|
43425
|
+
"cost-audit": "Cost Audit"
|
|
43417
43426
|
};
|
|
43418
43427
|
const label = typeLabels[audit2.type] ?? audit2.type;
|
|
43419
43428
|
const date5 = new Date(audit2.createdAt).toLocaleDateString("en-US", {
|
|
@@ -54052,8 +54061,14 @@ function createPmResource2(config2) {
|
|
|
54052
54061
|
});
|
|
54053
54062
|
return unwrap2("promote scenario", res);
|
|
54054
54063
|
},
|
|
54055
|
-
|
|
54056
|
-
|
|
54064
|
+
/**
|
|
54065
|
+
* Add a feature to a phase, optionally authoring the per-phase intent in
|
|
54066
|
+
* the same call (#611). Omitting `init` keeps the historical behaviour —
|
|
54067
|
+
* the membership takes the schema defaults (target `mv`, placeholder
|
|
54068
|
+
* scope) and the PM refines later via {@link updatePhaseFeature}.
|
|
54069
|
+
*/
|
|
54070
|
+
async assignFeature(phaseId, featureId, init) {
|
|
54071
|
+
const res = await apiFetch2(config2, `/pm/phases/${phaseId}/features`, { method: "POST", body: JSON.stringify({ featureId, ...init }) });
|
|
54057
54072
|
return unwrap2("assign feature", res, 201);
|
|
54058
54073
|
},
|
|
54059
54074
|
async unassignFeature(phaseId, featureId) {
|
|
@@ -55355,7 +55370,8 @@ async function deletePhase(client, input) {
|
|
|
55355
55370
|
});
|
|
55356
55371
|
}
|
|
55357
55372
|
async function assignFeatureToPhase(client, input) {
|
|
55358
|
-
|
|
55373
|
+
const { phaseId, featureId, ...init } = input;
|
|
55374
|
+
return safe(() => client.pm.assignFeature(phaseId, featureId, init));
|
|
55359
55375
|
}
|
|
55360
55376
|
async function unassignFeatureFromPhase(client, input) {
|
|
55361
55377
|
return safe(() => client.pm.unassignFeature(input.phaseId, input.featureId));
|
|
@@ -55471,10 +55487,19 @@ Mandatory caller behavior: present the phase's name + id + active/closed status
|
|
|
55471
55487
|
"assign_feature_to_phase",
|
|
55472
55488
|
{
|
|
55473
55489
|
title: "Assign feature to phase",
|
|
55474
|
-
description: "Adds an existing feature to an existing phase. Captures the feature's current_stage as a stage_snapshot at join time \u2014 closed phases keep the snapshot they ended at, even if the feature later progresses. The feature and phase must belong to the same project. Returns the membership row.",
|
|
55490
|
+
description: "Adds an existing feature to an existing phase, and is where the per-phase INTENT should be authored. A feature can sit in several phases, so what matters is which SLICE of it this phase builds \u2014 set targetStage and phaseDescription here rather than leaving the defaults for a follow-up update_phase_feature call. Left unset they fall back to target 'mv' and the placeholder 'PM to refine', which renders on the roadmap as an unscoped row the PM has to come back and fix. Captures the feature's current_stage as a stage_snapshot at join time \u2014 closed phases keep the snapshot they ended at, even if the feature later progresses. The feature and phase must belong to the same project. Returns the membership row.",
|
|
55475
55491
|
inputSchema: {
|
|
55476
55492
|
phaseId: external_exports.string().uuid().describe("Phase id from list_phases or create_phase."),
|
|
55477
|
-
featureId: external_exports.string().uuid().describe("Feature id from list_features or create_feature.")
|
|
55493
|
+
featureId: external_exports.string().uuid().describe("Feature id from list_features or create_feature."),
|
|
55494
|
+
targetStage: external_exports.enum(STAGE_VALUES).optional().describe(
|
|
55495
|
+
"Per-phase target stage \u2014 what THIS phase brings the feature to, which is usually not its eventual target (e.g. 'pt' in an early phase, 'mv' in a later one). 7-stage enum (idea | poc | pt | mv | mk | ma | mbi). Defaults to 'mv' when omitted."
|
|
55496
|
+
),
|
|
55497
|
+
phaseDescription: external_exports.string().min(1).optional().describe(
|
|
55498
|
+
"Per-phase scope: which part of the feature this phase builds, in PM voice \u2014 e.g. 'Core: email/password auth' in one phase and 'Extended: Google + Apple SSO, magic-link spike' in the next. Shown on the roadmap board and the client portal under the feature name, so write it for the client to read. Defaults to the 'PM to refine' placeholder when omitted."
|
|
55499
|
+
),
|
|
55500
|
+
force: external_exports.boolean().optional().describe(
|
|
55501
|
+
"Required (true) only when setting targetStage on a membership in a LOCKED phase (state active/proposed) \u2014 that moves every downstream planning baseline. Plain assigns never need it."
|
|
55502
|
+
)
|
|
55478
55503
|
}
|
|
55479
55504
|
},
|
|
55480
55505
|
withClientArgs(getClient2, assignFeatureToPhase)
|
|
@@ -55495,7 +55520,7 @@ Mandatory caller behavior: present the phase's name + id + active/closed status
|
|
|
55495
55520
|
"update_phase_feature",
|
|
55496
55521
|
{
|
|
55497
55522
|
title: "Update phase-feature membership",
|
|
55498
|
-
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), status (per-phase status \u2014 a feature can be done in one phase and in_progress in another). The same feature can have different per-phase values across phases. Use
|
|
55523
|
+
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), status (per-phase status \u2014 a feature can be done in one phase and in_progress in another). The same feature can have different per-phase values across phases. Use to REVISE a membership \u2014 the initial targetStage and phaseDescription are better set on assign_feature_to_phase, in one call. 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. Editing a membership in a LOCKED phase (state active/proposed) requires force=true.",
|
|
55499
55524
|
inputSchema: {
|
|
55500
55525
|
phaseId: external_exports.string().uuid().describe("Phase id from list_phases."),
|
|
55501
55526
|
featureId: external_exports.string().uuid().describe("Feature id of the membership to edit."),
|
|
@@ -55503,7 +55528,7 @@ Mandatory caller behavior: present the phase's name + id + active/closed status
|
|
|
55503
55528
|
"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)."
|
|
55504
55529
|
),
|
|
55505
55530
|
phaseDescription: external_exports.string().min(1).optional().describe(
|
|
55506
|
-
"
|
|
55531
|
+
"Per-phase scope in PM voice: which part of the feature this phase builds / what it should be doing once this phase's jump lands. Shown on the roadmap board and the client portal under the feature name. New memberships default to the 'PM to refine' placeholder."
|
|
55507
55532
|
),
|
|
55508
55533
|
linearEpicUrl: external_exports.string().url().nullable().optional().describe(
|
|
55509
55534
|
"Per-phase Linear epic URL. Each phase's work on a feature can be its own epic. Pass null to clear."
|
|
@@ -56053,6 +56078,7 @@ ${source_default.dim(" /melt-dev-debug Systematically investigate an
|
|
|
56053
56078
|
${source_default.dim(" /melt-dev-tech-audit Run a project compliance audit")}
|
|
56054
56079
|
${source_default.dim(" /melt-dev-ux-audit Review UI against usability heuristics")}
|
|
56055
56080
|
${source_default.dim(" /melt-dev-security-audit Run a security posture audit across the platform")}
|
|
56081
|
+
${source_default.dim(" /melt-dev-cost-audit Run an AWS cost optimization audit")}
|
|
56056
56082
|
${source_default.dim(" /melt-dev-help Answer questions about the development playbook")}
|
|
56057
56083
|
|
|
56058
56084
|
${source_default.bold("Setup")}
|
|
@@ -56132,12 +56158,13 @@ ${source_default.dim("Related skills (run in your AI coding tool):")}
|
|
|
56132
56158
|
${source_default.dim(" /melt-dev-tech-audit Run a project compliance audit")}
|
|
56133
56159
|
${source_default.dim(" /melt-dev-ux-audit Review UI against usability heuristics")}
|
|
56134
56160
|
${source_default.dim(" /melt-dev-security-audit Run a security posture audit across the platform")}
|
|
56161
|
+
${source_default.dim(" /melt-dev-cost-audit Run an AWS cost optimization audit")}
|
|
56135
56162
|
`
|
|
56136
56163
|
);
|
|
56137
56164
|
audit.command("submit").description("submit an audit report from a markdown file").argument("[file]", "path to the audit file (auto-detects from .audits/ if omitted)").action(async (file2) => {
|
|
56138
56165
|
await auditSubmitCommand(file2);
|
|
56139
56166
|
});
|
|
56140
|
-
audit.command("list").description("list submitted audits (Team Managers only)").option("--type <type>", "filter by type (audit, ux-audit, security-audit)").option("--repository <repo>", "filter by repository (owner/repo)").option("--latest", "show only the latest audit per project and type").option("--limit <n>", "max results (default 50, max 200)").action(async (options) => {
|
|
56167
|
+
audit.command("list").description("list submitted audits (Team Managers only)").option("--type <type>", "filter by type (audit, ux-audit, security-audit, cost-audit)").option("--repository <repo>", "filter by repository (owner/repo)").option("--latest", "show only the latest audit per project and type").option("--limit <n>", "max results (default 50, max 200)").action(async (options) => {
|
|
56141
56168
|
await auditListCommand(options);
|
|
56142
56169
|
});
|
|
56143
56170
|
audit.command("view").description("view a submitted audit by ID (Team Managers only)").argument("<id>", "audit ID").option("-o, --output <file>", "save to file instead of printing").action(async (id, options) => {
|
package/package.json
CHANGED