@starlein/paperclip-plugin-company-wizard 0.3.19 → 0.3.21
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 +7 -1
- package/dist/manifest.js +6 -1
- package/dist/manifest.js.map +2 -2
- package/dist/worker.js +60 -6
- package/dist/worker.js.map +2 -2
- package/package.json +1 -1
- package/templates/modules/accessibility/skills/accessibility-audit.bar.md +11 -0
- package/templates/modules/architecture-plan/agents/ui-designer/skills/design-system.bar.md +11 -0
- package/templates/modules/architecture-plan/skills/architecture-plan.bar.md +11 -0
- package/templates/modules/backlog/skills/backlog-health.bar.md +11 -0
- package/templates/modules/brand-identity/skills/brand-identity.bar.md +11 -0
- package/templates/modules/build-api/skills/api-design.bar.md +11 -0
- package/templates/modules/ci-cd/skills/ci-cd.bar.md +11 -0
- package/templates/modules/codebase-onboarding/skills/codebase-audit.bar.md +11 -0
- package/templates/modules/github-repo/docs/git-workflow.md +12 -0
- package/templates/modules/github-repo/module.meta.json +1 -1
- package/templates/modules/market-analysis/skills/market-analysis.bar.md +11 -0
- package/templates/modules/monitoring/skills/monitoring.bar.md +11 -0
- package/templates/modules/pr-review/agents/engineer/skills/pr-workflow.md +6 -4
- package/templates/modules/pr-review/docs/pr-conventions.md +3 -2
- package/templates/modules/pr-review/module.meta.json +3 -2
- package/templates/modules/security-audit/skills/security-review.bar.md +11 -0
- package/templates/modules/security-audit/skills/threat-model.bar.md +11 -0
- package/templates/modules/tech-stack/skills/tech-stack.bar.md +11 -0
- package/templates/modules/user-testing/skills/user-testing.bar.md +11 -0
- package/templates/roles/code-reviewer/DONE.md +10 -0
- package/templates/roles/code-reviewer/LENSES.md +11 -0
- package/templates/roles/devops/DONE.md +10 -0
- package/templates/roles/devops/LENSES.md +12 -0
- package/templates/roles/engineer/DONE.md +10 -0
- package/templates/roles/product-owner/DONE.md +10 -0
- package/templates/roles/product-owner/LENSES.md +11 -0
- package/templates/roles/qa/DONE.md +10 -0
- package/templates/roles/security-engineer/DONE.md +10 -0
- package/templates/roles/security-engineer/LENSES.md +16 -0
- package/templates/roles/ui-designer/DONE.md +10 -0
- package/templates/roles/ui-designer/LENSES.md +13 -0
- package/templates/roles/ux-researcher/DONE.md +10 -0
- package/templates/roles/ux-researcher/LENSES.md +14 -0
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>
|
|
@@ -139,6 +139,8 @@ Every company starts with just the **CEO** — and that's already a functional t
|
|
|
139
139
|
|
|
140
140
|
No role is ever truly missing. When a specialist isn't present, the next best available person steps in. The CEO is always the final fallback.
|
|
141
141
|
|
|
142
|
+
> **Enriched personas (opt-in):** set `enableEnrichedPersonas` to give expert roles named **domain lenses** (e.g. STRIDE, Nielsen's 10, RICE) in their `SOUL.md`, add **output/review bars** to module skills, and append **done-criteria** to `HEARTBEAT.md`. Off by default — the baseline personas stay lean.
|
|
143
|
+
|
|
142
144
|
<details>
|
|
143
145
|
<summary><strong>Full capability ownership table</strong></summary>
|
|
144
146
|
|
|
@@ -334,6 +336,8 @@ Git workflow and commit conventions.
|
|
|
334
336
|
|
|
335
337
|
PR-based review workflow. Requires `github-repo`. Activates with `code-reviewer`, `product-owner`, `ui-designer`, `ux-researcher`, `qa`, or `devops`.
|
|
336
338
|
|
|
339
|
+
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.
|
|
340
|
+
|
|
337
341
|
- **Task:** Engineer sets up branch protection
|
|
338
342
|
- **Doc:** `docs/pr-conventions.md`
|
|
339
343
|
|
|
@@ -587,6 +591,8 @@ Configure the plugin via **Settings → Plugins → Company Wizard** in the Pape
|
|
|
587
591
|
| `paperclipPassword` | No | Board login password. Stored as a secret ref. |
|
|
588
592
|
| `anthropicApiKey` | No | Anthropic API key for AI wizard mode. Stored as a secret ref. Required to use the AI-powered setup path. |
|
|
589
593
|
| `disableBoardApprovalOnNewCompanies` | No | If `true`, the wizard PATCHes new companies to set `requireBoardApprovalForNewAgents=false` during provisioning. Leave `false` to preserve approval-gated hiring. Defaults to `false`. |
|
|
594
|
+
| `enableEnrichedPersonas` | No | If `true`, expert roles get domain lenses (named mental models) in `SOUL.md`, module skills get concrete output/review bars, and `HEARTBEAT.md` gets explicit done-criteria. Leave `false` (default) for the lean baseline personas. |
|
|
595
|
+
|
|
590
596
|
For isolated worktrees: there is no plugin setting. The policy is controlled by Paperclip instance settings under **Settings → Instance → Experimental → enableIsolatedWorkspaces** and is consumed by the plugin during provisioning.
|
|
591
597
|
|
|
592
598
|
<br>
|
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.21",
|
|
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>",
|
|
@@ -59,6 +59,11 @@ var manifest = {
|
|
|
59
59
|
type: "boolean",
|
|
60
60
|
default: false,
|
|
61
61
|
description: "Optional. If true, the wizard will PATCH new companies to set requireBoardApprovalForNewAgents=false during provisioning. Leave false to preserve approval-gated hiring policies."
|
|
62
|
+
},
|
|
63
|
+
enableEnrichedPersonas: {
|
|
64
|
+
type: "boolean",
|
|
65
|
+
default: false,
|
|
66
|
+
description: "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."
|
|
62
67
|
}
|
|
63
68
|
}
|
|
64
69
|
},
|
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.
|
|
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,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;",
|
|
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.21',\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
|
+
"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
|
@@ -9366,6 +9366,9 @@ async function appendToFile(filePath, content) {
|
|
|
9366
9366
|
await appendFile(filePath, content);
|
|
9367
9367
|
}
|
|
9368
9368
|
}
|
|
9369
|
+
function isEnrichmentFragment(name) {
|
|
9370
|
+
return name === "LENSES.md" || name === "DONE.md" || name.endsWith(".bar.md");
|
|
9371
|
+
}
|
|
9369
9372
|
async function readJson(p) {
|
|
9370
9373
|
if (!await exists(p)) return null;
|
|
9371
9374
|
return JSON.parse(await readFile(p, "utf-8"));
|
|
@@ -9397,6 +9400,7 @@ async function assembleCompany({
|
|
|
9397
9400
|
presetRoutines = [],
|
|
9398
9401
|
presetLabels = [],
|
|
9399
9402
|
enableIsolatedWorktrees = false,
|
|
9403
|
+
enableEnrichedPersonas = false,
|
|
9400
9404
|
outputDir,
|
|
9401
9405
|
templatesDir,
|
|
9402
9406
|
onProgress = () => {
|
|
@@ -9480,7 +9484,7 @@ async function assembleCompany({
|
|
|
9480
9484
|
await copyDir(join(roleSrc, entry.name), join(roleDest, entry.name), {
|
|
9481
9485
|
skipExt: ".meta.json"
|
|
9482
9486
|
});
|
|
9483
|
-
} else if (!entry.name.endsWith(".meta.json")) {
|
|
9487
|
+
} else if (!entry.name.endsWith(".meta.json") && !isEnrichmentFragment(entry.name)) {
|
|
9484
9488
|
await copyFile(join(roleSrc, entry.name), join(roleDest, entry.name));
|
|
9485
9489
|
}
|
|
9486
9490
|
}
|
|
@@ -9497,6 +9501,7 @@ async function assembleCompany({
|
|
|
9497
9501
|
const entries = await readdir(roleDir, { withFileTypes: true });
|
|
9498
9502
|
for (const entry of entries) {
|
|
9499
9503
|
if (entry.isDirectory() || !entry.name.endsWith(".md")) continue;
|
|
9504
|
+
if (isEnrichmentFragment(entry.name)) continue;
|
|
9500
9505
|
await copyFile(join(roleDir, entry.name), join(destDir, entry.name));
|
|
9501
9506
|
}
|
|
9502
9507
|
onProgress(`+ agents/${roleName}/ (role)`);
|
|
@@ -9538,12 +9543,13 @@ async function assembleCompany({
|
|
|
9538
9543
|
reviewers.push(role);
|
|
9539
9544
|
}
|
|
9540
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;
|
|
9541
9547
|
if (approver) {
|
|
9542
9548
|
const idx = reviewers.indexOf(approver);
|
|
9543
9549
|
if (idx !== -1) reviewers.splice(idx, 1);
|
|
9544
9550
|
}
|
|
9545
|
-
if (reviewers.length === 0 && !approver) return null;
|
|
9546
|
-
return { reviewers, approver };
|
|
9551
|
+
if (reviewers.length === 0 && !approver && !mergeGate) return null;
|
|
9552
|
+
return { reviewers, approver, mergeGate };
|
|
9547
9553
|
};
|
|
9548
9554
|
const renderReviewGate = (gate) => {
|
|
9549
9555
|
const stages = [];
|
|
@@ -9555,6 +9561,11 @@ async function assembleCompany({
|
|
|
9555
9561
|
` - stage ${stages.length + 1} (approval) \u2192 assign ${JSON.stringify(gate.approver)}`
|
|
9556
9562
|
);
|
|
9557
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
|
+
}
|
|
9558
9569
|
return `- **executionPolicy** (set when creating this issue; resolve each role to its agentId):
|
|
9559
9570
|
${stages.join("\n")}
|
|
9560
9571
|
|
|
@@ -9671,7 +9682,18 @@ ${stages.join("\n")}
|
|
|
9671
9682
|
if (!resolved) return false;
|
|
9672
9683
|
const destSkillsDir = join(companyDir, "agents", roleName, "skills");
|
|
9673
9684
|
await mkdir(destSkillsDir, { recursive: true });
|
|
9674
|
-
|
|
9685
|
+
const destFile = join(destSkillsDir, fileName);
|
|
9686
|
+
await copyFile(resolved.path, destFile);
|
|
9687
|
+
let barApplied = false;
|
|
9688
|
+
if (enableEnrichedPersonas && label === "primary") {
|
|
9689
|
+
const barFileName = fileName.replace(/\.md$/, ".bar.md");
|
|
9690
|
+
const bar = await resolveSkillFile(roleName, barFileName);
|
|
9691
|
+
if (bar) {
|
|
9692
|
+
const barContent = await readFile(bar.path, "utf-8");
|
|
9693
|
+
await appendToFile(destFile, "\n" + barContent.trim() + "\n");
|
|
9694
|
+
barApplied = true;
|
|
9695
|
+
}
|
|
9696
|
+
}
|
|
9675
9697
|
await appendToFile(
|
|
9676
9698
|
join(companyDir, "agents", roleName, "AGENTS.md"),
|
|
9677
9699
|
`
|
|
@@ -9679,7 +9701,10 @@ Read and follow: \`$AGENT_HOME/skills/${fileName}\`
|
|
|
9679
9701
|
`
|
|
9680
9702
|
);
|
|
9681
9703
|
const sourceTag = resolved.source === "shared" ? ", shared" : "";
|
|
9682
|
-
|
|
9704
|
+
const barTag = barApplied ? ", output bar" : "";
|
|
9705
|
+
onProgress(
|
|
9706
|
+
`+ agents/${roleName}/skills/${fileName} (${moduleName}, ${label}${sourceTag}${barTag})`
|
|
9707
|
+
);
|
|
9683
9708
|
return true;
|
|
9684
9709
|
}
|
|
9685
9710
|
for (const [skillName, { primary, cap }] of capabilityOwners) {
|
|
@@ -9701,6 +9726,7 @@ Read and follow: \`$AGENT_HOME/skills/${fileName}\`
|
|
|
9701
9726
|
if (!await exists(skillsDir)) continue;
|
|
9702
9727
|
const skills = await readdir(skillsDir);
|
|
9703
9728
|
for (const skillFile of skills) {
|
|
9729
|
+
if (skillFile.endsWith(".bar.md")) continue;
|
|
9704
9730
|
const skillName = skillFile.replace(/\.md$/, "");
|
|
9705
9731
|
const skillBaseName = skillName.replace(/\.fallback$/, "");
|
|
9706
9732
|
if (capabilityOwners.has(skillBaseName)) continue;
|
|
@@ -9744,6 +9770,24 @@ Read and follow: \`$AGENT_HOME/skills/${skillFile}\`
|
|
|
9744
9770
|
onProgress(`+ agents/${modRole.name}/HEARTBEAT.md (${moduleName}, heartbeat section)`);
|
|
9745
9771
|
}
|
|
9746
9772
|
}
|
|
9773
|
+
if (enableEnrichedPersonas) {
|
|
9774
|
+
for (const roleName of allRoles) {
|
|
9775
|
+
const lensesSrc = join(rolesDir, roleName, "LENSES.md");
|
|
9776
|
+
const soulPath = join(companyDir, "agents", roleName, "SOUL.md");
|
|
9777
|
+
if (await exists(lensesSrc) && await exists(soulPath)) {
|
|
9778
|
+
const lenses = await readFile(lensesSrc, "utf-8");
|
|
9779
|
+
await appendToFile(soulPath, "\n" + lenses.trim() + "\n");
|
|
9780
|
+
onProgress(`+ agents/${roleName}/SOUL.md (domain lenses)`);
|
|
9781
|
+
}
|
|
9782
|
+
const doneSrc = join(rolesDir, roleName, "DONE.md");
|
|
9783
|
+
const heartbeatPath = join(companyDir, "agents", roleName, "HEARTBEAT.md");
|
|
9784
|
+
if (await exists(doneSrc) && await exists(heartbeatPath)) {
|
|
9785
|
+
const done = await readFile(doneSrc, "utf-8");
|
|
9786
|
+
await appendToFile(heartbeatPath, "\n" + done.trim() + "\n");
|
|
9787
|
+
onProgress(`+ agents/${roleName}/HEARTBEAT.md (done criteria)`);
|
|
9788
|
+
}
|
|
9789
|
+
}
|
|
9790
|
+
}
|
|
9747
9791
|
const finalDocsDir = join(companyDir, "docs");
|
|
9748
9792
|
if (await exists(finalDocsDir)) {
|
|
9749
9793
|
const docs = (await readdir(finalDocsDir)).sort();
|
|
@@ -10064,6 +10108,12 @@ Read: \`docs/${doc}\`
|
|
|
10064
10108
|
}
|
|
10065
10109
|
return rows;
|
|
10066
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
|
+
};
|
|
10067
10117
|
const mainProject = resolvedProjects[0];
|
|
10068
10118
|
const mainProjectName = mainProject?.name || companyName;
|
|
10069
10119
|
if (resolvedProjects.length > 0) {
|
|
@@ -10088,6 +10138,7 @@ Read: \`docs/${doc}\`
|
|
|
10088
10138
|
|
|
10089
10139
|
`;
|
|
10090
10140
|
}
|
|
10141
|
+
bootstrap += renderDeferredIsolationNote(workspace);
|
|
10091
10142
|
}
|
|
10092
10143
|
}
|
|
10093
10144
|
if (bootstrapLabels.length > 0) {
|
|
@@ -10212,7 +10263,7 @@ Read: \`docs/${doc}\`
|
|
|
10212
10263
|
bootstrap += `- Do not reuse parent workspaces for subissues unless explicitly requested.
|
|
10213
10264
|
`;
|
|
10214
10265
|
if (moduleNames.includes("pr-review")) {
|
|
10215
|
-
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
|
|
10266
|
+
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.
|
|
10216
10267
|
`;
|
|
10217
10268
|
}
|
|
10218
10269
|
bootstrap += `
|
|
@@ -11150,6 +11201,7 @@ var plugin = definePlugin({
|
|
|
11150
11201
|
presetRoutines: presetBootstrapData.routines,
|
|
11151
11202
|
presetLabels: presetBootstrapData.labels,
|
|
11152
11203
|
enableIsolatedWorktrees: await resolveEnableIsolatedWorkspacesFromInstance(cfg),
|
|
11204
|
+
enableEnrichedPersonas: cfgBool(cfg, "enableEnrichedPersonas"),
|
|
11153
11205
|
outputDir: tmpDir,
|
|
11154
11206
|
templatesDir
|
|
11155
11207
|
});
|
|
@@ -11255,6 +11307,7 @@ var plugin = definePlugin({
|
|
|
11255
11307
|
"disableBoardApprovalOnNewCompanies"
|
|
11256
11308
|
);
|
|
11257
11309
|
const enableIsolatedWorktrees = await resolveEnableIsolatedWorkspacesFromInstance(cfg, log);
|
|
11310
|
+
const enableEnrichedPersonas = cfgBool(cfg, "enableEnrichedPersonas");
|
|
11258
11311
|
const companyName = typeof params.companyName === "string" ? params.companyName.trim() : "";
|
|
11259
11312
|
const existingCompanyId = typeof params.existingCompanyId === "string" && params.existingCompanyId.trim() ? params.existingCompanyId.trim() : "";
|
|
11260
11313
|
if (!companyName) return { error: "companyName is required", logs };
|
|
@@ -11295,6 +11348,7 @@ var plugin = definePlugin({
|
|
|
11295
11348
|
presetRoutines: presetBootstrapData.routines,
|
|
11296
11349
|
presetLabels: presetBootstrapData.labels,
|
|
11297
11350
|
enableIsolatedWorktrees,
|
|
11351
|
+
enableEnrichedPersonas,
|
|
11298
11352
|
outputDir,
|
|
11299
11353
|
templatesDir,
|
|
11300
11354
|
onProgress: log
|