@starlein/paperclip-plugin-company-wizard 0.3.20 → 0.3.22
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/README.md +5 -2
- package/dist/manifest.js +1 -1
- package/dist/manifest.js.map +1 -1
- package/dist/worker.js +64 -7
- package/dist/worker.js.map +2 -2
- package/package.json +15 -13
- package/templates/modules/github-repo/docs/git-workflow.md +12 -0
- package/templates/modules/github-repo/module.meta.json +1 -1
- package/templates/modules/pr-review/agents/code-reviewer/skills/code-review.md +1 -1
- package/templates/modules/pr-review/agents/devops/skills/infra-review.md +1 -1
- package/templates/modules/pr-review/agents/engineer/skills/pr-workflow.md +7 -5
- package/templates/modules/pr-review/agents/product-owner/skills/product-review.md +1 -1
- package/templates/modules/pr-review/agents/qa/skills/qa-review.md +1 -1
- package/templates/modules/pr-review/agents/ui-designer/skills/design-review.md +1 -1
- package/templates/modules/pr-review/agents/ux-researcher/skills/ux-review.md +1 -1
- package/templates/modules/pr-review/docs/pr-conventions.md +22 -3
- package/templates/modules/pr-review/module.meta.json +3 -2
- package/templates/roles/code-reviewer/AGENTS.md +1 -1
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<strong>Bootstrap AI agent teams from modular templates.</strong>
|
|
6
6
|
</p>
|
|
7
7
|
<p align="center">
|
|
8
|
-
<a href="https://
|
|
8
|
+
<a href="https://www.npmjs.com/package/@starlein/paperclip-plugin-company-wizard"><img src="https://img.shields.io/npm/v/@starlein/paperclip-plugin-company-wizard?color=cb3837&label=npm" alt="npm version"></a>
|
|
9
9
|
<a href="https://github.com/starlein/paperclip-plugin-company-wizard/actions/workflows/ci.yml"><img src="https://github.com/starlein/paperclip-plugin-company-wizard/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
|
|
10
10
|
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue" alt="License"></a>
|
|
11
11
|
<a href="https://nodejs.org"><img src="https://img.shields.io/badge/node-%3E%3D20-brightgreen" alt="Node.js"></a>
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
#### Bootstrap reliability
|
|
30
30
|
|
|
31
31
|
- **Agents provisioned with complete instructions** — every non-CEO agent is now created by the plugin directly with its full `instructionsBundle` (AGENTS.md + HEARTBEAT/SOUL/TOOLS + skills). Previously the CEO created these agents during bootstrap with only an `instructionsFilePath`, leaving each agent with a bare AGENTS.md and fragile external path references
|
|
32
|
-
- **Routines created directly during provisioning** — Paperclip only allows an agent to create routines assigned to itself, so the CEO could not create routines owned by the Product Owner. The plugin now creates all routines with board authority at provisioning time; BOOTSTRAP.md tells the CEO they already exist
|
|
32
|
+
- **Routines created directly during provisioning** — Paperclip only allows an agent to create routines assigned to itself, so the CEO could not create routines owned by the Product Owner. The plugin now creates all routines with board authority at provisioning time and pre-creates the main project so every routine — including those owned by non-CEO agents — is linked to it; BOOTSTRAP.md tells the CEO they already exist
|
|
33
33
|
- **Worker agents no longer run always-on heartbeats** — enabling heartbeats on every provisioned agent caused bursts of concurrent runs that crashed the dev server. Only the CEO keeps an always-on heartbeat; all other agents are woken on assignment
|
|
34
34
|
- **Fresh local repos no longer bootstrap with isolated git worktrees** — provisioning a brand-new `local_path` project with an `isolated_workspace` / `git_worktree` policy made worker agents try to branch off `main` before the repo existed, so early runs failed and agents flipped to `error`. The isolated policy is now suppressed for fresh local repos (agents work in the shared project workspace during bootstrap); existing external repos keep it. Guarded in `assemble.js` and removed at the source in `StepRepository` and the AI wizard prompts
|
|
35
35
|
- **Workspace isolation follows Paperclip instance settings** — `enableIsolatedWorktrees` is no longer a plugin setting. The wizard reads `enableIsolatedWorkspaces` from the Paperclip instance experimental settings and only applies `isolated_workspace` / `git_worktree` for external repositories when that setting is enabled.
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
- **Doc references use relative paths** (`docs/<file>`) instead of absolute paths that baked in the collision-suffixed company directory name
|
|
43
43
|
- Duplicate bootstrap issues (same title from module + preset) are now deduplicated; preset issue wins
|
|
44
44
|
- CFO role removed — was orphaned (no preset, no capability, never activated)
|
|
45
|
+
- **PR bodies and comments use `--body-file`** — review skills posted GitHub PR bodies and comments with inline `gh pr … --body "..."`, where a double-quoted shell string keeps `\n` literal, so multi-line Markdown rendered as literal `text\ntext`. All PR-review guidance now writes Markdown to a file and uses `--body-file`, with a verdict-heading comment template documented in `pr-conventions.md`
|
|
45
46
|
|
|
46
47
|
#### AI wizard
|
|
47
48
|
|
|
@@ -336,6 +337,8 @@ Git workflow and commit conventions.
|
|
|
336
337
|
|
|
337
338
|
PR-based review workflow. Requires `github-repo`. Activates with `code-reviewer`, `product-owner`, `ui-designer`, `ux-researcher`, `qa`, or `devops`.
|
|
338
339
|
|
|
340
|
+
Reviews run through the issue's native `executionPolicy` (stages), not child issues: a `review` stage for the Code Reviewer (plus relevant domain reviewers), an `approval` stage for the Product Owner, then a final `approval` **merge gate** owned by the Engineer — who is woken last to merge the PR before recording the verdict that closes the issue. The merge gate is deliberately the last stage so the Product Owner's approval does not auto-close the issue with the PR still open.
|
|
341
|
+
|
|
339
342
|
- **Task:** Engineer sets up branch protection
|
|
340
343
|
- **Doc:** `docs/pr-conventions.md`
|
|
341
344
|
|
package/dist/manifest.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
var manifest = {
|
|
3
3
|
id: "starlein.paperclip-plugin-company-wizard",
|
|
4
4
|
apiVersion: 1,
|
|
5
|
-
version: "0.3.
|
|
5
|
+
version: "0.3.22",
|
|
6
6
|
displayName: "Company Wizard",
|
|
7
7
|
description: "AI-powered wizard to bootstrap agent companies from composable templates",
|
|
8
8
|
author: "Sascha Pietrowski <sp@speednetwork.de>",
|
package/dist/manifest.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/manifest.ts"],
|
|
4
|
-
"sourcesContent": ["import type { PaperclipPluginManifestV1 } from '@paperclipai/plugin-sdk';\n\nconst manifest: PaperclipPluginManifestV1 = {\n id: 'starlein.paperclip-plugin-company-wizard',\n apiVersion: 1,\n version: '0.3.
|
|
4
|
+
"sourcesContent": ["import type { PaperclipPluginManifestV1 } from '@paperclipai/plugin-sdk';\n\nconst manifest: PaperclipPluginManifestV1 = {\n id: 'starlein.paperclip-plugin-company-wizard',\n apiVersion: 1,\n version: '0.3.22',\n displayName: 'Company Wizard',\n description: 'AI-powered wizard to bootstrap agent companies from composable templates',\n author: 'Sascha Pietrowski <sp@speednetwork.de>',\n categories: ['workspace', 'ui'],\n capabilities: [\n 'companies.read',\n 'issues.create',\n 'issues.read',\n 'issues.update',\n 'goals.create',\n 'goals.read',\n 'agents.read',\n 'projects.read',\n 'plugin.state.read',\n 'plugin.state.write',\n 'secrets.read-ref',\n 'events.subscribe',\n 'ui.page.register',\n 'ui.sidebar.register',\n ],\n instanceConfigSchema: {\n type: 'object',\n properties: {\n companiesDir: {\n type: 'string',\n description:\n 'Directory where assembled company workspaces are written. Defaults to ~/.paperclip/instances/default/companies. Override for Docker setups (e.g. /paperclip/instances/default/companies).',\n },\n templatesPath: {\n type: 'string',\n description:\n 'Path to the templates directory. Defaults to ~/.paperclip/plugin-templates (auto-downloaded from templatesRepoUrl if missing). Override for Docker setups (e.g. /paperclip/plugin-templates).',\n },\n templatesRepoUrl: {\n type: 'string',\n default: 'https://github.com/starlein/paperclip-plugin-company-wizard/tree/main/templates',\n description:\n 'GitHub tree URL to pull templates from when the templates directory does not exist.',\n },\n anthropicApiKey: {\n type: 'string',\n description:\n 'Anthropic API key for the AI wizard (e.g. sk-ant-...). Required to use the AI-powered company setup path.',\n },\n paperclipUrl: {\n type: 'string',\n description:\n 'Paperclip instance URL. Defaults to http://localhost:3100 or the PAPERCLIP_PUBLIC_URL env var.',\n },\n paperclipEmail: {\n type: 'string',\n description: 'Board login email (for authenticated instances).',\n },\n paperclipPassword: {\n type: 'string',\n description: 'Board login password (for authenticated instances).',\n },\n disableBoardApprovalOnNewCompanies: {\n type: 'boolean',\n default: false,\n description:\n 'Optional. If true, the wizard will PATCH new companies to set requireBoardApprovalForNewAgents=false during provisioning. Leave false to preserve approval-gated hiring policies.',\n },\n enableEnrichedPersonas: {\n type: 'boolean',\n default: false,\n description:\n 'Optional. If true, expert roles are enriched with domain lenses (named mental models), module skills gain concrete output/review bars with negative examples, and HEARTBEAT.md gains explicit done-criteria. Leave false (default) for the lean baseline personas.',\n },\n },\n },\n entrypoints: {\n worker: './dist/worker.js',\n ui: './dist/ui',\n },\n ui: {\n slots: [\n {\n type: 'page',\n id: 'company-wizard',\n displayName: 'Company Wizard',\n exportName: 'WizardPage',\n routePath: 'company-creator',\n },\n {\n type: 'sidebar',\n id: 'company-wizard-link',\n displayName: 'Create Company',\n exportName: 'SidebarLink',\n },\n ],\n },\n};\n\nexport default manifest;\n"],
|
|
5
5
|
"mappings": ";AAEA,IAAM,WAAsC;AAAA,EAC1C,IAAI;AAAA,EACJ,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,aAAa;AAAA,EACb,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,YAAY,CAAC,aAAa,IAAI;AAAA,EAC9B,cAAc;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,sBAAsB;AAAA,IACpB,MAAM;AAAA,IACN,YAAY;AAAA,MACV,cAAc;AAAA,QACZ,MAAM;AAAA,QACN,aACE;AAAA,MACJ;AAAA,MACA,eAAe;AAAA,QACb,MAAM;AAAA,QACN,aACE;AAAA,MACJ;AAAA,MACA,kBAAkB;AAAA,QAChB,MAAM;AAAA,QACN,SAAS;AAAA,QACT,aACE;AAAA,MACJ;AAAA,MACA,iBAAiB;AAAA,QACf,MAAM;AAAA,QACN,aACE;AAAA,MACJ;AAAA,MACA,cAAc;AAAA,QACZ,MAAM;AAAA,QACN,aACE;AAAA,MACJ;AAAA,MACA,gBAAgB;AAAA,QACd,MAAM;AAAA,QACN,aAAa;AAAA,MACf;AAAA,MACA,mBAAmB;AAAA,QACjB,MAAM;AAAA,QACN,aAAa;AAAA,MACf;AAAA,MACA,oCAAoC;AAAA,QAClC,MAAM;AAAA,QACN,SAAS;AAAA,QACT,aACE;AAAA,MACJ;AAAA,MACA,wBAAwB;AAAA,QACtB,MAAM;AAAA,QACN,SAAS;AAAA,QACT,aACE;AAAA,MACJ;AAAA,IACF;AAAA,EACF;AAAA,EACA,aAAa;AAAA,IACX,QAAQ;AAAA,IACR,IAAI;AAAA,EACN;AAAA,EACA,IAAI;AAAA,IACF,OAAO;AAAA,MACL;AAAA,QACE,MAAM;AAAA,QACN,IAAI;AAAA,QACJ,aAAa;AAAA,QACb,YAAY;AAAA,QACZ,WAAW;AAAA,MACb;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,IAAI;AAAA,QACJ,aAAa;AAAA,QACb,YAAY;AAAA,MACd;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAO,mBAAQ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/worker.js
CHANGED
|
@@ -9543,12 +9543,13 @@ async function assembleCompany({
|
|
|
9543
9543
|
reviewers.push(role);
|
|
9544
9544
|
}
|
|
9545
9545
|
const approver = typeof reviewGate.approver === "string" && allRoles.has(reviewGate.approver) ? reviewGate.approver : void 0;
|
|
9546
|
+
const mergeGate = typeof reviewGate.mergeGate === "string" && allRoles.has(reviewGate.mergeGate) ? reviewGate.mergeGate : void 0;
|
|
9546
9547
|
if (approver) {
|
|
9547
9548
|
const idx = reviewers.indexOf(approver);
|
|
9548
9549
|
if (idx !== -1) reviewers.splice(idx, 1);
|
|
9549
9550
|
}
|
|
9550
|
-
if (reviewers.length === 0 && !approver) return null;
|
|
9551
|
-
return { reviewers, approver };
|
|
9551
|
+
if (reviewers.length === 0 && !approver && !mergeGate) return null;
|
|
9552
|
+
return { reviewers, approver, mergeGate };
|
|
9552
9553
|
};
|
|
9553
9554
|
const renderReviewGate = (gate) => {
|
|
9554
9555
|
const stages = [];
|
|
@@ -9560,6 +9561,11 @@ async function assembleCompany({
|
|
|
9560
9561
|
` - stage ${stages.length + 1} (approval) \u2192 assign ${JSON.stringify(gate.approver)}`
|
|
9561
9562
|
);
|
|
9562
9563
|
}
|
|
9564
|
+
if (gate.mergeGate) {
|
|
9565
|
+
stages.push(
|
|
9566
|
+
` - stage ${stages.length + 1} (approval) \u2192 assign ${JSON.stringify(gate.mergeGate)} \u2014 merge gate: merge the PR, then record approved to close`
|
|
9567
|
+
);
|
|
9568
|
+
}
|
|
9563
9569
|
return `- **executionPolicy** (set when creating this issue; resolve each role to its agentId):
|
|
9564
9570
|
${stages.join("\n")}
|
|
9565
9571
|
|
|
@@ -10102,12 +10108,29 @@ Read: \`docs/${doc}\`
|
|
|
10102
10108
|
}
|
|
10103
10109
|
return rows;
|
|
10104
10110
|
};
|
|
10111
|
+
const renderDeferredIsolationNote = (workspace) => {
|
|
10112
|
+
if (!enableIsolatedWorktrees || !isFreshLocalRepo(workspace)) return "";
|
|
10113
|
+
return `> **Enable isolated worktrees once the repo exists.** This instance has isolated worktrees enabled, but this project starts as a fresh local repository, so the \`executionWorkspacePolicy\` is intentionally omitted now \u2014 worktrees need an existing base ref and would fail on the first run. As the final step of **"Prepare GitHub repository"**, after the initial commit is pushed to \`main\`, switch this project to isolated worktrees (Project settings \u2192 isolated workspaces, or set \`executionWorkspacePolicy: { defaultMode: "isolated_workspace", workspaceStrategy: { type: "git_worktree", baseRef: "main" } }\` on the project). Until then agents share the project workspace; do not flip it before the repo has its first commit.
|
|
10114
|
+
|
|
10115
|
+
`;
|
|
10116
|
+
};
|
|
10105
10117
|
const mainProject = resolvedProjects[0];
|
|
10106
10118
|
const mainProjectName = mainProject?.name || companyName;
|
|
10119
|
+
const mainProjectInfo = mainProject ? {
|
|
10120
|
+
name: mainProjectName,
|
|
10121
|
+
description: mainProject.description || "",
|
|
10122
|
+
workspace: normalizeProjectWorkspace(mainProject)
|
|
10123
|
+
} : null;
|
|
10124
|
+
const mainProjectPreCreated = initialRoutines.length > 0 && mainProjectInfo !== null;
|
|
10107
10125
|
if (resolvedProjects.length > 0) {
|
|
10108
10126
|
bootstrap += `## Projects
|
|
10109
10127
|
|
|
10110
10128
|
`;
|
|
10129
|
+
if (mainProjectPreCreated) {
|
|
10130
|
+
bootstrap += `> **The Company Wizard has already created the main project "${mainProjectName}"** (with board authority) so the scheduled routines could be linked to it. Do NOT recreate it \u2014 create issues against it, and link the goals above to it.
|
|
10131
|
+
|
|
10132
|
+
`;
|
|
10133
|
+
}
|
|
10111
10134
|
for (const proj of resolvedProjects) {
|
|
10112
10135
|
const workspace = normalizeProjectWorkspace(proj);
|
|
10113
10136
|
bootstrap += `### ${proj.name}
|
|
@@ -10126,6 +10149,7 @@ Read: \`docs/${doc}\`
|
|
|
10126
10149
|
|
|
10127
10150
|
`;
|
|
10128
10151
|
}
|
|
10152
|
+
bootstrap += renderDeferredIsolationNote(workspace);
|
|
10129
10153
|
}
|
|
10130
10154
|
}
|
|
10131
10155
|
if (bootstrapLabels.length > 0) {
|
|
@@ -10250,7 +10274,7 @@ Read: \`docs/${doc}\`
|
|
|
10250
10274
|
bootstrap += `- Do not reuse parent workspaces for subissues unless explicitly requested.
|
|
10251
10275
|
`;
|
|
10252
10276
|
if (moduleNames.includes("pr-review")) {
|
|
10253
|
-
bootstrap += `- Required PR reviews use the issue's \`executionPolicy\`: a \`review\` stage for the Code Reviewer (plus any relevant domain reviewer \u2014 QA/UI/UX/DevOps), then a final \`approval\` stage for the Product Owner. Resolve each
|
|
10277
|
+
bootstrap += `- Required PR reviews use the issue's \`executionPolicy\`: a \`review\` stage for the Code Reviewer (plus any relevant domain reviewer \u2014 QA/UI/UX/DevOps), an \`approval\` stage for the Product Owner, then a final \`approval\` merge-gate stage for the Engineer (who merges the PR before recording approval, which closes the issue). The merge gate must be last so the Product Owner's approval does not auto-close the issue with the PR still open. Resolve each role to its agentId. Do not create separate child review issues and do not use @-mentions.
|
|
10254
10278
|
`;
|
|
10255
10279
|
}
|
|
10256
10280
|
bootstrap += `
|
|
@@ -10299,14 +10323,20 @@ Read: \`docs/${doc}\`
|
|
|
10299
10323
|
bootstrap += `${stepN++}. **Create goal** "${g.title}" (level: ${level}${parentNote})
|
|
10300
10324
|
`;
|
|
10301
10325
|
}
|
|
10302
|
-
|
|
10326
|
+
resolvedProjects.forEach((proj, idx) => {
|
|
10303
10327
|
const workspace = normalizeProjectWorkspace(proj);
|
|
10304
10328
|
const goalLinks = proj.goals?.length > 0 ? `, goalIds \u2192 [${proj.goals.map((g) => `"${g}"`).join(", ")}]` : "";
|
|
10305
10329
|
const activePolicy = effectiveExecutionPolicy(proj, workspace);
|
|
10306
10330
|
const policy = activePolicy?.defaultMode ? `, executionWorkspacePolicy.defaultMode: "${activePolicy.defaultMode}"` : "";
|
|
10307
|
-
|
|
10331
|
+
if (idx === 0 && mainProjectPreCreated) {
|
|
10332
|
+
const goalLinkInstruction = goalLinks ? ` After creating the goals above, link them to it (${goalLinks.replace(/^, /, "")}).` : "";
|
|
10333
|
+
bootstrap += `${stepN++}. **Main project already created** \u2014 the Company Wizard provisioned project "${proj.name}" (with board authority) so the scheduled routines could be linked to it. Do NOT recreate it.${goalLinkInstruction}
|
|
10308
10334
|
`;
|
|
10309
|
-
|
|
10335
|
+
} else {
|
|
10336
|
+
bootstrap += `${stepN++}. **Create project** "${proj.name}" (workspace: ${formatWorkspaceObject(workspace)}${policy}${goalLinks})
|
|
10337
|
+
`;
|
|
10338
|
+
}
|
|
10339
|
+
});
|
|
10310
10340
|
if (bootstrapLabels.length > 0) {
|
|
10311
10341
|
bootstrap += `${stepN++}. **Create labels** \u2014 create each label exactly as listed in the Labels section before creating issues
|
|
10312
10342
|
`;
|
|
@@ -10325,7 +10355,14 @@ Read: \`docs/${doc}\`
|
|
|
10325
10355
|
`;
|
|
10326
10356
|
await writeFile(join(companyDir, "BOOTSTRAP.md"), bootstrap);
|
|
10327
10357
|
onProgress("+ BOOTSTRAP.md");
|
|
10328
|
-
return {
|
|
10358
|
+
return {
|
|
10359
|
+
companyDir,
|
|
10360
|
+
allRoles,
|
|
10361
|
+
initialIssues,
|
|
10362
|
+
initialRoutines,
|
|
10363
|
+
roleAdapterOverrides,
|
|
10364
|
+
mainProject: mainProjectInfo
|
|
10365
|
+
};
|
|
10329
10366
|
}
|
|
10330
10367
|
|
|
10331
10368
|
// src/api/client.js
|
|
@@ -11586,6 +11623,25 @@ var plugin = definePlugin({
|
|
|
11586
11623
|
}
|
|
11587
11624
|
if (!existingCompanyId) {
|
|
11588
11625
|
const routines = Array.isArray(assembleResult.initialRoutines) ? assembleResult.initialRoutines : [];
|
|
11626
|
+
let mainProjectId;
|
|
11627
|
+
const mainProject = assembleResult.mainProject;
|
|
11628
|
+
if (routines.length > 0 && mainProject?.name) {
|
|
11629
|
+
try {
|
|
11630
|
+
const createdProject = await client.createProject(companyId, {
|
|
11631
|
+
name: mainProject.name,
|
|
11632
|
+
description: mainProject.description,
|
|
11633
|
+
workspace: mainProject.workspace
|
|
11634
|
+
});
|
|
11635
|
+
mainProjectId = createdProject?.id;
|
|
11636
|
+
log(
|
|
11637
|
+
`\u2713 Main project "${mainProject.name}" created${mainProjectId ? ` (${mainProjectId})` : " (no id returned)"}`
|
|
11638
|
+
);
|
|
11639
|
+
} catch (err) {
|
|
11640
|
+
log(
|
|
11641
|
+
`\u26A0 Could not create main project "${mainProject.name}": ${err instanceof Error ? err.message : String(err)}. Routines will be created without a project.`
|
|
11642
|
+
);
|
|
11643
|
+
}
|
|
11644
|
+
}
|
|
11589
11645
|
for (const routine of routines) {
|
|
11590
11646
|
const title = typeof routine.title === "string" && routine.title.trim() ? routine.title.trim() : typeof routine.name === "string" ? routine.name.trim() : "";
|
|
11591
11647
|
if (!title) continue;
|
|
@@ -11596,6 +11652,7 @@ var plugin = definePlugin({
|
|
|
11596
11652
|
title,
|
|
11597
11653
|
description: routine.description,
|
|
11598
11654
|
assigneeAgentId,
|
|
11655
|
+
projectId: mainProjectId,
|
|
11599
11656
|
priority: routine.priority || "medium",
|
|
11600
11657
|
concurrencyPolicy: routine.concurrencyPolicy || "skip_if_active"
|
|
11601
11658
|
});
|