@elmundi/ship-cli 0.15.3 → 0.15.4
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/lib/commands/run.mjs +32 -3
- package/lib/config/schema.mjs +5 -0
- package/lib/runtime/routines.mjs +5 -0
- package/package.json +1 -1
package/lib/commands/run.mjs
CHANGED
|
@@ -158,7 +158,10 @@ export async function runCommand(ctx, rest) {
|
|
|
158
158
|
if (!roleResolved) {
|
|
159
159
|
die(EXIT_USAGE, `unknown agent role '${specialistSlug}' for this workspace`);
|
|
160
160
|
}
|
|
161
|
-
|
|
161
|
+
// Per-routine FSM stage override takes precedence over the role's
|
|
162
|
+
// default. Lets one role (``ba``) drive both ``ba_requirements`` for
|
|
163
|
+
// SDLC and ``wbs`` for decomposition without per-process role clones.
|
|
164
|
+
const fsmStage = resolved.executable?.fsm_stage || roleResolved.fsm_stage || null;
|
|
162
165
|
const roleBody = roleResolved.prompt || "";
|
|
163
166
|
const systemBody = systemResolved?.prompt || "";
|
|
164
167
|
|
|
@@ -484,6 +487,24 @@ function renderPrompt({ patternBody, baseBody, role, routineSpec, task, fsmStage
|
|
|
484
487
|
out.push("");
|
|
485
488
|
out.push(renderLifecycleHooks());
|
|
486
489
|
if (task) {
|
|
490
|
+
// ELS-86: parent project context (Brief / WBS / Architecture /
|
|
491
|
+
// Test architecture / Tasks). The server lifts and caps it; we
|
|
492
|
+
// render it BEFORE the per-ticket block so the agent sees the
|
|
493
|
+
// surrounding plan first, then narrows to its own scope. Only
|
|
494
|
+
// present when the ticket is part of a decomposed project — the
|
|
495
|
+
// server returns ``project_context: null`` otherwise and we
|
|
496
|
+
// skip the block silently.
|
|
497
|
+
if (typeof task.project_context === "string" && task.project_context.trim()) {
|
|
498
|
+
out.push("");
|
|
499
|
+
out.push("## Project context");
|
|
500
|
+
out.push("");
|
|
501
|
+
out.push(
|
|
502
|
+
"_Excerpt of the parent project body. Read for surrounding plan;",
|
|
503
|
+
"your scope is the per-task block below, not the whole project._",
|
|
504
|
+
);
|
|
505
|
+
out.push("");
|
|
506
|
+
out.push(task.project_context.trim());
|
|
507
|
+
}
|
|
487
508
|
out.push("");
|
|
488
509
|
out.push("## Task");
|
|
489
510
|
out.push(`- **Ticket:** \`${task.ticket_ref}\` (${task.kind})`);
|
|
@@ -637,11 +658,19 @@ as a one-shot credential for this run.
|
|
|
637
658
|
|
|
638
659
|
function makeBranchName(routine, ticketRef) {
|
|
639
660
|
const stamp = Date.now().toString(36);
|
|
661
|
+
// Sanitize ``routine`` too — for pipeline-pick runs ``runHandle`` is
|
|
662
|
+
// ``pipeline:<specialist>`` and the bare ``:`` is in git's reserved
|
|
663
|
+
// character set, which Cursor's ``/v0/agents`` validator rejects
|
|
664
|
+
// with HTTP 400 ("Invalid branch name. Branch names cannot start
|
|
665
|
+
// with '-', contain invalid characters (spaces, ~, ^, :, ?, *, [,
|
|
666
|
+
// ], \\, .., @{, //), end with '/', '.lock', or '.', or be named
|
|
667
|
+
// 'HEAD'."). Same regex as the ticketRef path.
|
|
668
|
+
const safeRoutine = String(routine).replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
640
669
|
if (ticketRef) {
|
|
641
670
|
const safe = String(ticketRef).replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
642
|
-
return `cursor/ship-${
|
|
671
|
+
return `cursor/ship-${safeRoutine}-${safe}-${stamp}`;
|
|
643
672
|
}
|
|
644
|
-
return `cursor/ship-${
|
|
673
|
+
return `cursor/ship-${safeRoutine}-${stamp}`;
|
|
645
674
|
}
|
|
646
675
|
|
|
647
676
|
|
package/lib/config/schema.mjs
CHANGED
|
@@ -558,6 +558,10 @@ function validateProcessRoutines(value, errors, warnings) {
|
|
|
558
558
|
"schedule",
|
|
559
559
|
"window",
|
|
560
560
|
"event",
|
|
561
|
+
// ``fsm_stage`` overrides the role's default stage so one role
|
|
562
|
+
// can drive multiple processes (BA serves both
|
|
563
|
+
// ``ba_requirements`` for SDLC and ``wbs`` for decomposition).
|
|
564
|
+
"fsm_stage",
|
|
561
565
|
]),
|
|
562
566
|
prefix,
|
|
563
567
|
warnings,
|
|
@@ -616,6 +620,7 @@ function validateProcessRoutines(value, errors, warnings) {
|
|
|
616
620
|
);
|
|
617
621
|
}
|
|
618
622
|
validateProcessAgentProfile(routine.agent_profile, `${prefix}.agent_profile`, errors);
|
|
623
|
+
requireOptionalString(routine.fsm_stage, `${prefix}.fsm_stage`, errors, { required: false });
|
|
619
624
|
validateRoutineTrigger(routine.trigger, `${prefix}.trigger`, errors);
|
|
620
625
|
if (routine.schedule !== undefined && routine.schedule !== null) {
|
|
621
626
|
if (typeof routine.schedule !== "string" && !isPlainObject(routine.schedule)) {
|
package/lib/runtime/routines.mjs
CHANGED
|
@@ -64,6 +64,11 @@ export function routineToExecutable(id, routine) {
|
|
|
64
64
|
idempotency: routine.idempotency || null,
|
|
65
65
|
prompt: stringOrNull(routine.prompt) || stringOrNull(routine.instructions),
|
|
66
66
|
agent_profile: stringOrNull(routine.agent_profile) || stringOrNull(routine.specialist?.agent_profile),
|
|
67
|
+
// Per-routine FSM stage override. When set, ``shipctl run`` uses
|
|
68
|
+
// it instead of the role's default ``fsm_stage`` — that's how a
|
|
69
|
+
// single role (e.g. ``ba``) serves both SDLC (``ba_requirements``)
|
|
70
|
+
// and decomposition (``wbs``) without per-process role clones.
|
|
71
|
+
fsm_stage: stringOrNull(routine.fsm_stage),
|
|
67
72
|
};
|
|
68
73
|
}
|
|
69
74
|
|