@kontextmind/kxm 0.7.118 → 0.7.120
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/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +20 -0
- package/docs/contributing/assignment-runner.md +1 -1
- package/docs/guides/agent-skills.md +1 -1
- package/docs/reference/cli-reference.md +68 -13
- package/package.json +1 -1
- package/plugins/kxm/.claude-plugin/plugin.json +1 -1
- package/plugins/kxm/dist/cli.js +33570 -32476
- package/plugins/kxm/dist/extension.js +24 -8
- package/plugins/kxm/dist/mcp-server.js +1 -1
- package/plugins/kxm/package.json +1 -1
- package/plugins/kxm/skills/kxm/SKILL.md +1 -1
- package/plugins/kxm/skills/kxm-runs/SKILL.md +17 -6
- package/plugins/kxm/src/cli/lanes.ts +540 -0
- package/plugins/kxm/src/cli/project.ts +22 -9
- package/plugins/kxm/src/cli.ts +75 -11
- package/plugins/kxm/src/mcp-server.ts +1 -1
- package/plugins/kxm/src/providers/claude-bridge/register.ts +25 -9
- package/schemas/README.md +1 -0
- package/schemas/lanes.schema.json +61 -0
|
@@ -415,28 +415,31 @@ export function resolveKxmRunTarget(
|
|
|
415
415
|
runtime: Runtime,
|
|
416
416
|
workflow: string | undefined,
|
|
417
417
|
forTask = false,
|
|
418
|
+
envelope: Record<string, unknown> = {},
|
|
419
|
+
allowDefaultWorkflow = false,
|
|
418
420
|
): { projectRoot: string; workflowId: string; configRevision: string; defaultHarness: string; prerequisites: KxmRunHandoff[] } | number {
|
|
419
421
|
if (runtime.workspaceFlag !== undefined) {
|
|
420
422
|
print(runtime.io, runtime.json, {
|
|
421
423
|
ok: false,
|
|
422
424
|
command: "run",
|
|
423
425
|
error: "workspace_option_unsupported",
|
|
426
|
+
...envelope,
|
|
424
427
|
}, "kxm run discovers the authoritative project from the current directory; --workspace is not supported");
|
|
425
428
|
return 2;
|
|
426
429
|
}
|
|
427
|
-
if (!workflow && !forTask) {
|
|
428
|
-
print(runtime.io, runtime.json, { ok: false, command: "run", error: "workflow_required" }, "usage: kxm run <workflow> [prompt]");
|
|
430
|
+
if (!workflow && !forTask && !allowDefaultWorkflow) {
|
|
431
|
+
print(runtime.io, runtime.json, { ok: false, command: "run", error: "workflow_required", ...envelope }, "usage: kxm run <workflow> [prompt]");
|
|
429
432
|
return 2;
|
|
430
433
|
}
|
|
431
434
|
const projectRoot = discoverKxmProjectRoot(runtime.cwd);
|
|
432
435
|
if (!projectRoot) {
|
|
433
|
-
print(runtime.io, runtime.json, { ok: false, command: "run", error: "project_required" }, "kxm run requires a KXM project (run kxm init first)");
|
|
436
|
+
print(runtime.io, runtime.json, { ok: false, command: "run", error: "project_required", ...envelope }, "kxm run requires a KXM project (run kxm init first)");
|
|
434
437
|
return 1;
|
|
435
438
|
}
|
|
436
439
|
const bundle = loadKxmProject(projectRoot, {});
|
|
437
440
|
const workflowId = workflow ?? String(bundle.project.value.defaultWorkflow ?? "default");
|
|
438
441
|
if (!bundle.workflows.has(workflowId)) {
|
|
439
|
-
print(runtime.io, runtime.json, { ok: false, command: "run", error: "run_workflow_unknown", workflow: workflowId }, `workflow ${workflowId} does not exist in this project`);
|
|
442
|
+
print(runtime.io, runtime.json, { ok: false, command: "run", error: "run_workflow_unknown", workflow: workflowId, ...envelope }, `workflow ${workflowId} does not exist in this project`);
|
|
440
443
|
return 1;
|
|
441
444
|
}
|
|
442
445
|
const defaultHarness = String(bundle.project.value.defaultHarness ?? "pi");
|
|
@@ -451,9 +454,16 @@ export function resolveKxmRunTarget(
|
|
|
451
454
|
return { projectRoot, workflowId, configRevision: bundle.configRevision, defaultHarness, prerequisites };
|
|
452
455
|
}
|
|
453
456
|
|
|
454
|
-
export async function cmdKxmRun(
|
|
457
|
+
export async function cmdKxmRun(
|
|
458
|
+
runtime: Runtime,
|
|
459
|
+
workflow: string | undefined,
|
|
460
|
+
promptParts: string[],
|
|
461
|
+
forTask = false,
|
|
462
|
+
call?: { brief?: string; prompt?: string; runIdOut?: { runId?: string }; allowDefaultWorkflow?: boolean },
|
|
463
|
+
): Promise<number> {
|
|
464
|
+
const envelope = call?.brief !== undefined ? { brief: call.brief } : {};
|
|
455
465
|
try {
|
|
456
|
-
const target = resolveKxmRunTarget(runtime, workflow, forTask);
|
|
466
|
+
const target = resolveKxmRunTarget(runtime, workflow, forTask, envelope, call?.allowDefaultWorkflow === true);
|
|
457
467
|
if (typeof target === "number") return target;
|
|
458
468
|
const { projectRoot } = target;
|
|
459
469
|
if (runtime.dryRun) {
|
|
@@ -461,21 +471,24 @@ export async function cmdKxmRun(runtime: Runtime, workflow: string | undefined,
|
|
|
461
471
|
ok: true,
|
|
462
472
|
command: "run",
|
|
463
473
|
dryRun: true,
|
|
474
|
+
...envelope,
|
|
464
475
|
...target,
|
|
465
476
|
}, `run plan: workflow ${target.workflowId} at ${target.configRevision.slice(0, 19)}… (no run created)`);
|
|
466
477
|
return 0;
|
|
467
478
|
}
|
|
468
479
|
const supervisor = await (kxmDriveCliSeams.ensureSupervisor ?? ensureKxmSupervisor)({ env: runtime.env });
|
|
469
|
-
const prompt = promptParts.join(" ").trim();
|
|
480
|
+
const prompt = call?.prompt !== undefined ? call.prompt : promptParts.join(" ").trim();
|
|
470
481
|
const acceptance = await (kxmDriveCliSeams.runtimeRequest ?? kxmRuntimeRequest)(supervisor, "POST", "/v1/runs", {
|
|
471
482
|
projectRoot,
|
|
472
483
|
workflowId: target.workflowId,
|
|
473
484
|
prompt,
|
|
474
485
|
});
|
|
475
486
|
const run = acceptance.run as { runId: string; homeRuntimeId: string; status: string; configRevision: string };
|
|
487
|
+
if (call?.runIdOut) call.runIdOut.runId = run.runId;
|
|
476
488
|
print(runtime.io, runtime.json, {
|
|
477
489
|
ok: true,
|
|
478
490
|
command: "run",
|
|
491
|
+
...envelope,
|
|
479
492
|
execution: {
|
|
480
493
|
status: "not_started",
|
|
481
494
|
mode: "live",
|
|
@@ -496,10 +509,10 @@ export async function cmdKxmRun(runtime: Runtime, workflow: string | undefined,
|
|
|
496
509
|
return 0;
|
|
497
510
|
} catch (error) {
|
|
498
511
|
if (error instanceof KxmConfigError) {
|
|
499
|
-
print(runtime.io, runtime.json, { ok: false, command: "run", error: "run_failed", issues: error.issues }, `run failed: ${error.message}`);
|
|
512
|
+
print(runtime.io, runtime.json, { ok: false, command: "run", error: "run_failed", issues: error.issues, ...envelope }, `run failed: ${error.message}`);
|
|
500
513
|
return 1;
|
|
501
514
|
}
|
|
502
|
-
print(runtime.io, runtime.json, { ok: false, command: "run", error: "run_io_failed" }, "run failed because a local operation did not complete");
|
|
515
|
+
print(runtime.io, runtime.json, { ok: false, command: "run", error: "run_io_failed", ...envelope }, "run failed because a local operation did not complete");
|
|
503
516
|
return 1;
|
|
504
517
|
}
|
|
505
518
|
}
|
package/plugins/kxm/src/cli.ts
CHANGED
|
@@ -104,7 +104,6 @@ import {
|
|
|
104
104
|
cmdBackup,
|
|
105
105
|
cmdRestore,
|
|
106
106
|
cmdKxmTrust,
|
|
107
|
-
cmdKxmRun,
|
|
108
107
|
cmdKxmRunStatus,
|
|
109
108
|
cmdKxmRunDrive,
|
|
110
109
|
cmdKxmRunReceipt,
|
|
@@ -122,6 +121,16 @@ cmdBackup,
|
|
|
122
121
|
|
|
123
122
|
import { cmdPluginInstall } from "./cli/plugins.ts";
|
|
124
123
|
|
|
124
|
+
import {
|
|
125
|
+
applyLane,
|
|
126
|
+
cmdKxmRunCli,
|
|
127
|
+
cmdLaneCreate,
|
|
128
|
+
cmdLaneDrop,
|
|
129
|
+
cmdLaneList,
|
|
130
|
+
cmdLaneRun,
|
|
131
|
+
cmdLaneStatus,
|
|
132
|
+
} from "./cli/lanes.ts";
|
|
133
|
+
|
|
125
134
|
import {
|
|
126
135
|
cmdStatus,
|
|
127
136
|
cmdDash,
|
|
@@ -187,6 +196,7 @@ const USAGE_ERROR_CODES = new Set([
|
|
|
187
196
|
*/
|
|
188
197
|
const DRY_RUN_COMMANDS: ReadonlySet<string> = new Set([
|
|
189
198
|
"init", "backup", "restore", "run", "explain", "suggest", "update", "dash", "completion", "completion install",
|
|
199
|
+
"lane create", "lane list", "lane status", "lane drop", "lane run",
|
|
190
200
|
"plugin install", "plugin",
|
|
191
201
|
"runs status", "runs drive", "runs receipt", "runs cancel", "runs list",
|
|
192
202
|
"tenant status", "models inventory-refresh", "harness list", "auth token",
|
|
@@ -435,26 +445,76 @@ function createProgram(ctx: CliContext, result: { code: number }): Command {
|
|
|
435
445
|
result.code = await cmdRestore(runtimeFrom(ctx, this), manifest, options);
|
|
436
446
|
});
|
|
437
447
|
|
|
448
|
+
const laneCmd = addGlobalOptions(program.command("lane").description("Manage one git worktree per unit of work"));
|
|
449
|
+
laneCmd.helpCommand("help", "Show lane help");
|
|
450
|
+
addGlobalOptions(laneCmd.command("create").description("Create a worktree lane from a base ref (default origin/main)"))
|
|
451
|
+
.argument("<unit>", "Lane unit name")
|
|
452
|
+
.option("--base <ref>", "Base ref to resolve before adding the worktree (default origin/main)")
|
|
453
|
+
.action(async function laneCreateAction(this: Command, unit: string, options: { base?: string }) {
|
|
454
|
+
result.code = await cmdLaneCreate(runtimeFrom(ctx, this), unit, options);
|
|
455
|
+
});
|
|
456
|
+
addGlobalOptions(laneCmd.command("list").description("List lanes with dirty, ahead, and behind counts"))
|
|
457
|
+
.action(async function laneListAction(this: Command) {
|
|
458
|
+
result.code = await cmdLaneList(runtimeFrom(ctx, this));
|
|
459
|
+
});
|
|
460
|
+
addGlobalOptions(laneCmd.command("status").description("Show one lane and the projected status of its last run"))
|
|
461
|
+
.argument("<unit>", "Lane unit name")
|
|
462
|
+
.action(async function laneStatusAction(this: Command, unit: string) {
|
|
463
|
+
result.code = await cmdLaneStatus(runtimeFrom(ctx, this), unit);
|
|
464
|
+
});
|
|
465
|
+
addGlobalOptions(laneCmd.command("drop").description("Remove a lane worktree and its record without deleting the branch"))
|
|
466
|
+
.argument("<unit>", "Lane unit name")
|
|
467
|
+
.option("--force", "Remove a dirty lane or one whose last run is still open")
|
|
468
|
+
.action(async function laneDropAction(this: Command, unit: string, options: { force?: boolean }) {
|
|
469
|
+
result.code = await cmdLaneDrop(runtimeFrom(ctx, this), unit, { force: options.force === true });
|
|
470
|
+
});
|
|
471
|
+
addGlobalOptions(laneCmd.command("run").description("Create the lane if needed, start a run from a brief, and drive it"))
|
|
472
|
+
.argument("<unit>", "Lane unit name")
|
|
473
|
+
.requiredOption("--brief <file>", "Read the run prompt from a file")
|
|
474
|
+
.option("--workflow <id>", "Workflow id (default: the project default)")
|
|
475
|
+
.option("--base <ref>", "Base ref when the lane does not exist yet (default origin/main)")
|
|
476
|
+
.option("--wait", "Wait until a drive receipt is recorded")
|
|
477
|
+
.option("--timeout-ms <n>", "Wait timeout in milliseconds (default 60000, max 600000)")
|
|
478
|
+
.action(async function laneRunAction(this: Command, unit: string, options: { brief?: string; workflow?: string; base?: string; wait?: boolean; timeoutMs?: string }) {
|
|
479
|
+
result.code = await cmdLaneRun(runtimeFrom(ctx, this), unit, {
|
|
480
|
+
...(options.brief !== undefined ? { brief: options.brief } : {}),
|
|
481
|
+
...(options.workflow !== undefined ? { workflow: options.workflow } : {}),
|
|
482
|
+
...(options.base !== undefined ? { base: options.base } : {}),
|
|
483
|
+
wait: options.wait === true,
|
|
484
|
+
...(options.timeoutMs !== undefined ? { timeoutMs: options.timeoutMs } : {}),
|
|
485
|
+
});
|
|
486
|
+
});
|
|
487
|
+
|
|
438
488
|
addGlobalOptions(program.command("run").description("Create a KXM run without executing steps; follow its prerequisites, then kxm runs drive <runId> --wait")
|
|
439
489
|
.argument("[workflow]", "Workflow id to run")
|
|
440
490
|
.argument("[prompt...]", "Run prompt (events keep its hash; the full text is kept in a local 0600 sidecar file)")
|
|
441
|
-
.
|
|
442
|
-
|
|
491
|
+
.option("--brief <file>", "Read the run prompt from a file instead of the positional prompt")
|
|
492
|
+
.option("--lane <unit>", "Discover the project from this lane's worktree")
|
|
493
|
+
.action(async function runAction(this: Command, workflow: string | undefined, promptParts: string[], options: { brief?: string; lane?: string }) {
|
|
494
|
+
result.code = await cmdKxmRunCli(runtimeFrom(ctx, this), workflow, promptParts, options);
|
|
443
495
|
}));
|
|
444
496
|
const runCmd = addGlobalOptions(program.command("runs").description("Inspect KXM runs"));
|
|
445
497
|
runCmd.helpCommand("help", "Show runs help");
|
|
446
498
|
addGlobalOptions(runCmd.command("status").description("Show the projected status of a run, including durable drive receipt state (open / receipt verified / unsettled / orphaned)"))
|
|
447
499
|
.argument("<runId>", "Run id")
|
|
448
|
-
.
|
|
449
|
-
|
|
500
|
+
.option("--lane <unit>", "Discover the project from this lane's worktree")
|
|
501
|
+
.action(async function runStatusAction(this: Command, runId: string, options: { lane?: string }) {
|
|
502
|
+
const runtime = applyLane(runtimeFrom(ctx, this), options.lane, "runs status");
|
|
503
|
+
result.code = typeof runtime === "number" ? runtime : await cmdKxmRunStatus(runtime, runId);
|
|
450
504
|
});
|
|
451
505
|
addGlobalOptions(runCmd.command("drive").description("Drive a run with live harness calls, or with the model-free simulation when --simulated is passed"))
|
|
452
506
|
.argument("<runId>", "Run id")
|
|
453
507
|
.option("--simulated", "Use the model-free simulation producer instead of a live model")
|
|
454
508
|
.option("--wait", "Wait until a drive receipt is recorded; exits 0 only for a VERIFIED COMPLETED settlement")
|
|
455
509
|
.option("--timeout-ms <n>", "Wait timeout in milliseconds (default 60000, max 600000)")
|
|
456
|
-
.
|
|
457
|
-
|
|
510
|
+
.option("--lane <unit>", "Discover the project from this lane's worktree")
|
|
511
|
+
.action(async function runDriveAction(this: Command, runId: string, options: { simulated?: boolean; wait?: boolean; timeoutMs?: string; lane?: string }) {
|
|
512
|
+
const runtime = applyLane(runtimeFrom(ctx, this), options.lane, "runs drive");
|
|
513
|
+
if (typeof runtime === "number") {
|
|
514
|
+
result.code = runtime;
|
|
515
|
+
return;
|
|
516
|
+
}
|
|
517
|
+
result.code = await cmdKxmRunDrive(runtime, runId, options.simulated === true, {
|
|
458
518
|
wait: options.wait === true,
|
|
459
519
|
...(options.timeoutMs !== undefined ? { timeoutMs: options.timeoutMs } : {}),
|
|
460
520
|
});
|
|
@@ -462,13 +522,17 @@ function createProgram(ctx: CliContext, result: { code: number }): Command {
|
|
|
462
522
|
addGlobalOptions(runCmd.command("receipt").description("Print the newest drive receipt for a run"))
|
|
463
523
|
.argument("<runId>", "Run id")
|
|
464
524
|
.option("--all", "Print the capped receipt list for the run")
|
|
465
|
-
.
|
|
466
|
-
|
|
525
|
+
.option("--lane <unit>", "Discover the project from this lane's worktree")
|
|
526
|
+
.action(async function runReceiptAction(this: Command, runId: string, options: { all?: boolean; lane?: string }) {
|
|
527
|
+
const runtime = applyLane(runtimeFrom(ctx, this), options.lane, "runs receipt");
|
|
528
|
+
result.code = typeof runtime === "number" ? runtime : await cmdKxmRunReceipt(runtime, runId, { all: options.all === true });
|
|
467
529
|
});
|
|
468
530
|
addGlobalOptions(runCmd.command("cancel").description("Durably request cancellation of a run"))
|
|
469
531
|
.argument("<runId>", "Run id")
|
|
470
|
-
.
|
|
471
|
-
|
|
532
|
+
.option("--lane <unit>", "Discover the project from this lane's worktree")
|
|
533
|
+
.action(async function runCancelAction(this: Command, runId: string, options: { lane?: string }) {
|
|
534
|
+
const runtime = applyLane(runtimeFrom(ctx, this), options.lane, "runs cancel");
|
|
535
|
+
result.code = typeof runtime === "number" ? runtime : await cmdKxmRunCancel(runtime, runId);
|
|
472
536
|
});
|
|
473
537
|
addGlobalOptions(runCmd.command("list").description("List recent runs for the current project"))
|
|
474
538
|
.action(async function runListAction(this: Command) {
|
|
@@ -11,7 +11,7 @@ import { deliverInboxNotification } from "./inbox.ts";
|
|
|
11
11
|
import type { HubEvent, MessageRecord } from "./protocol.ts";
|
|
12
12
|
import { sessionTokenFixHint } from "./session-token-hint.ts";
|
|
13
13
|
|
|
14
|
-
const VERSION = "0.7.
|
|
14
|
+
const VERSION = "0.7.120";
|
|
15
15
|
const CONFIGURE_PLUGIN = "/plugin configure kxm@kxm";
|
|
16
16
|
const inbox = new Map<string, MessageRecord>();
|
|
17
17
|
const notifiedInbox = new Set<string>();
|
|
@@ -92,6 +92,12 @@ export function claudeBridgeRegistrationNotice(
|
|
|
92
92
|
report: ClaudeBridgeRegistration | undefined,
|
|
93
93
|
pi?: object,
|
|
94
94
|
): { message: string; type: "warning" } | undefined {
|
|
95
|
+
if (report?.warning) {
|
|
96
|
+
return {
|
|
97
|
+
message: boundedRegistrationWarning(report.warning),
|
|
98
|
+
type: "warning",
|
|
99
|
+
};
|
|
100
|
+
}
|
|
95
101
|
const conflict = Boolean(report?.conflict) || (pi ? claudeBridgeStandaloneToolsPresent(pi) : false);
|
|
96
102
|
if (!conflict) return undefined;
|
|
97
103
|
return {
|
|
@@ -112,13 +118,23 @@ export function registerClaudeBridgeProvider(pi: ExtensionAPI): ClaudeBridgeRegi
|
|
|
112
118
|
return { registered: false, conflict: false };
|
|
113
119
|
}
|
|
114
120
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
121
|
+
try {
|
|
122
|
+
pi.registerProvider(PROVIDER_ID, {
|
|
123
|
+
name: PROVIDER_NAME,
|
|
124
|
+
baseUrl: PROVIDER_ID,
|
|
125
|
+
apiKey: PROVIDER_ID,
|
|
126
|
+
api: CLAUDE_BRIDGE_API,
|
|
127
|
+
models: registeredClaudeBridgeModels(),
|
|
128
|
+
streamSimple: streamClaudeBridge,
|
|
129
|
+
} as unknown as Parameters<ExtensionAPI["registerProvider"]>[1]);
|
|
130
|
+
|
|
131
|
+
return { registered: true, conflict: false };
|
|
132
|
+
} catch (error) {
|
|
133
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
134
|
+
return {
|
|
135
|
+
registered: false,
|
|
136
|
+
conflict: false,
|
|
137
|
+
warning: `kxm: claude-bridge provider registration failed (${reason}). Configure apiKey or ensure provider auth is valid.`,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
124
140
|
}
|
package/schemas/README.md
CHANGED
|
@@ -13,6 +13,7 @@ Runtime-local records, and JSON events/results for the planned KXM contract.
|
|
|
13
13
|
| `workflow.schema.json` | `kxm.workflow.v1` |
|
|
14
14
|
| `template-provenance.schema.json` | `kxm.template-provenance.v1` |
|
|
15
15
|
| `local-repository-bindings.schema.json` | `kxm.local-repository-bindings.v1` |
|
|
16
|
+
| `lanes.schema.json` | `kxm.lanes.v1` |
|
|
16
17
|
| `init-operation.schema.json` | `kxm.init-operation.v1` |
|
|
17
18
|
| `permission-diff.schema.json` | `kxm.permission-diff.v1` |
|
|
18
19
|
| `run-event.schema.json` | `kxm.run-event.v1` |
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://schemas.kxm.dev/lanes.schema.json",
|
|
4
|
+
"title": "KXM worktree lanes",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"required": ["schema", "lanes"],
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"properties": {
|
|
9
|
+
"schema": {
|
|
10
|
+
"const": "kxm.lanes.v1"
|
|
11
|
+
},
|
|
12
|
+
"lanes": {
|
|
13
|
+
"type": "object",
|
|
14
|
+
"propertyNames": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"minLength": 1,
|
|
17
|
+
"maxLength": 64,
|
|
18
|
+
"pattern": "^[a-z][a-z0-9]*(?:[-_][a-z0-9]+)*$"
|
|
19
|
+
},
|
|
20
|
+
"patternProperties": {
|
|
21
|
+
"^[a-z][a-z0-9]*(?:[-_][a-z0-9]+)*$": {
|
|
22
|
+
"$ref": "#/$defs/lane"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"additionalProperties": false
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"$defs": {
|
|
29
|
+
"lane": {
|
|
30
|
+
"type": "object",
|
|
31
|
+
"required": ["path", "branch", "baseRef", "baseSha", "createdAt"],
|
|
32
|
+
"additionalProperties": false,
|
|
33
|
+
"properties": {
|
|
34
|
+
"path": {
|
|
35
|
+
"type": "string",
|
|
36
|
+
"minLength": 1
|
|
37
|
+
},
|
|
38
|
+
"branch": {
|
|
39
|
+
"type": "string",
|
|
40
|
+
"minLength": 1
|
|
41
|
+
},
|
|
42
|
+
"baseRef": {
|
|
43
|
+
"type": "string",
|
|
44
|
+
"minLength": 1
|
|
45
|
+
},
|
|
46
|
+
"baseSha": {
|
|
47
|
+
"type": "string",
|
|
48
|
+
"pattern": "^[a-f0-9]{40,64}$"
|
|
49
|
+
},
|
|
50
|
+
"createdAt": {
|
|
51
|
+
"type": "string",
|
|
52
|
+
"pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(?:\\.[0-9]{1,9})?Z$"
|
|
53
|
+
},
|
|
54
|
+
"lastRunId": {
|
|
55
|
+
"type": "string",
|
|
56
|
+
"minLength": 1
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|