@starlein/paperclip-plugin-company-wizard 0.2.4 → 0.3.15

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.
Files changed (56) hide show
  1. package/README.md +60 -3
  2. package/dist/manifest.js +4 -5
  3. package/dist/manifest.js.map +2 -2
  4. package/dist/ui/index.css +563 -578
  5. package/dist/ui/index.css.map +2 -2
  6. package/dist/ui/index.js +1143 -559
  7. package/dist/ui/index.js.map +4 -4
  8. package/dist/worker.js +679 -253
  9. package/dist/worker.js.map +4 -4
  10. package/package.json +12 -7
  11. package/templates/ai-wizard/config-format.md +12 -4
  12. package/templates/ai-wizard/interview-system.md +3 -2
  13. package/templates/ai-wizard/messages.json +1 -1
  14. package/templates/ai-wizard/single-shot-system.md +4 -0
  15. package/templates/bootstrap-instructions.md +12 -2
  16. package/templates/modules/auto-assign/agents/ceo/heartbeat-section.md +1 -1
  17. package/templates/modules/auto-assign/agents/ceo/skills/auto-assign.fallback.md +1 -1
  18. package/templates/modules/auto-assign/agents/product-owner/heartbeat-section.md +1 -1
  19. package/templates/modules/auto-assign/module.meta.json +1 -1
  20. package/templates/modules/auto-assign/skills/auto-assign.md +1 -1
  21. package/templates/modules/backlog/module.meta.json +4 -3
  22. package/templates/modules/build-api/module.meta.json +1 -0
  23. package/templates/modules/ci-cd/module.meta.json +2 -1
  24. package/templates/modules/game-design/module.meta.json +18 -0
  25. package/templates/modules/game-design/skills/audio-design.fallback.md +16 -0
  26. package/templates/modules/game-design/skills/audio-design.md +28 -0
  27. package/templates/modules/game-design/skills/level-design.fallback.md +17 -0
  28. package/templates/modules/game-design/skills/level-design.md +29 -0
  29. package/templates/modules/github-repo/README.md +1 -0
  30. package/templates/modules/github-repo/module.meta.json +4 -1
  31. package/templates/modules/pr-review/README.md +5 -5
  32. package/templates/modules/pr-review/agents/code-reviewer/skills/code-review.md +7 -6
  33. package/templates/modules/pr-review/agents/devops/skills/infra-review.md +6 -6
  34. package/templates/modules/pr-review/agents/engineer/skills/pr-workflow.md +11 -6
  35. package/templates/modules/pr-review/agents/product-owner/skills/product-review.md +7 -6
  36. package/templates/modules/pr-review/agents/qa/skills/qa-review.md +6 -6
  37. package/templates/modules/pr-review/agents/ui-designer/skills/design-review.md +6 -6
  38. package/templates/modules/pr-review/agents/ux-researcher/skills/ux-review.md +6 -6
  39. package/templates/modules/pr-review/docs/pr-conventions.md +16 -15
  40. package/templates/modules/pr-review/module.meta.json +8 -3
  41. package/templates/modules/stall-detection/module.meta.json +1 -1
  42. package/templates/modules/website-relaunch/module.meta.json +2 -1
  43. package/templates/presets/build-game/preset.meta.json +2 -1
  44. package/templates/presets/content/preset.meta.json +3 -1
  45. package/templates/presets/full/preset.meta.json +1 -0
  46. package/templates/presets/gtm/preset.meta.json +3 -1
  47. package/templates/presets/launch-pack/preset.meta.json +1 -0
  48. package/templates/presets/quality/preset.meta.json +2 -1
  49. package/templates/presets/repo-maintenance/preset.meta.json +2 -1
  50. package/templates/presets/secure/preset.meta.json +1 -0
  51. package/templates/roles/security-engineer/role.meta.json +1 -1
  52. package/templates/roles/cfo/AGENTS.md +0 -31
  53. package/templates/roles/cfo/HEARTBEAT.md +0 -37
  54. package/templates/roles/cfo/SOUL.md +0 -17
  55. package/templates/roles/cfo/TOOLS.md +0 -3
  56. package/templates/roles/cfo/role.meta.json +0 -17
package/dist/worker.js CHANGED
@@ -4,7 +4,7 @@ var __export = (target, all) => {
4
4
  __defProp(target, name, { get: all[name], enumerable: true });
5
5
  };
6
6
 
7
- // node_modules/.pnpm/@paperclipai+plugin-sdk@file+..+paperclip+packages+plugins+sdk_react@19.2.4/node_modules/@paperclipai/plugin-sdk/dist/define-plugin.js
7
+ // node_modules/.pnpm/@paperclipai+plugin-sdk@2026.529.0_react@19.2.4/node_modules/@paperclipai/plugin-sdk/dist/define-plugin.js
8
8
  function definePlugin(definition) {
9
9
  return Object.freeze({ definition });
10
10
  }
@@ -4050,7 +4050,7 @@ var coerce = {
4050
4050
  };
4051
4051
  var NEVER = INVALID;
4052
4052
 
4053
- // ../paperclip/packages/shared/src/constants.ts
4053
+ // node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/constants.js
4054
4054
  var COMPANY_STATUSES = ["active", "paused", "archived"];
4055
4055
  var DEFAULT_COMPANY_ATTACHMENT_MAX_BYTES = 10 * 1024 * 1024;
4056
4056
  var MAX_COMPANY_ATTACHMENT_MAX_BYTES = 1024 * 1024 * 1024;
@@ -4171,7 +4171,8 @@ var ISSUE_COMMENT_METADATA_ROW_TYPES = [
4171
4171
  "run_link"
4172
4172
  ];
4173
4173
  function clampIssueRequestDepth(value) {
4174
- if (typeof value !== "number" || !Number.isFinite(value)) return 0;
4174
+ if (typeof value !== "number" || !Number.isFinite(value))
4175
+ return 0;
4175
4176
  return Math.min(MAX_ISSUE_REQUEST_DEPTH, Math.max(0, Math.floor(value)));
4176
4177
  }
4177
4178
  var ISSUE_THREAD_INTERACTION_KINDS = [
@@ -4586,11 +4587,11 @@ var PLUGIN_STATE_SCOPE_KINDS = [
4586
4587
  "run"
4587
4588
  ];
4588
4589
 
4589
- // ../paperclip/packages/shared/src/adapter-type.ts
4590
+ // node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/adapter-type.js
4590
4591
  var agentAdapterTypeSchema = external_exports.string().trim().min(1).default("process").describe(`Known built-in adapters: ${AGENT_ADAPTER_TYPES.join(", ")}. External adapters may register additional non-empty string types at runtime.`);
4591
4592
  var optionalAgentAdapterTypeSchema = external_exports.string().trim().min(1).optional();
4592
4593
 
4593
- // ../paperclip/packages/shared/src/network-bind.ts
4594
+ // node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/network-bind.js
4594
4595
  function normalizeHost(host) {
4595
4596
  const trimmed = host?.trim();
4596
4597
  return trimmed ? trimmed : void 0;
@@ -4606,9 +4607,12 @@ function isAllInterfacesHost(host) {
4606
4607
  function inferBindModeFromHost(host, opts) {
4607
4608
  const normalized = normalizeHost(host);
4608
4609
  const tailnetBindHost = normalizeHost(opts?.tailnetBindHost);
4609
- if (!normalized || isLoopbackHost(normalized)) return "loopback";
4610
- if (isAllInterfacesHost(normalized)) return "lan";
4611
- if (tailnetBindHost && normalized === tailnetBindHost) return "tailnet";
4610
+ if (!normalized || isLoopbackHost(normalized))
4611
+ return "loopback";
4612
+ if (isAllInterfacesHost(normalized))
4613
+ return "lan";
4614
+ if (tailnetBindHost && normalized === tailnetBindHost)
4615
+ return "tailnet";
4612
4616
  return "custom";
4613
4617
  }
4614
4618
  function validateConfiguredBindMode(input) {
@@ -4630,7 +4634,7 @@ function validateConfiguredBindMode(input) {
4630
4634
  return errors;
4631
4635
  }
4632
4636
 
4633
- // ../paperclip/packages/shared/src/types/instance.ts
4637
+ // node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/types/instance.js
4634
4638
  var DAILY_RETENTION_PRESETS = [3, 7, 14];
4635
4639
  var WEEKLY_RETENTION_PRESETS = [1, 2, 4];
4636
4640
  var MONTHLY_RETENTION_PRESETS = [1, 3, 6];
@@ -4643,13 +4647,13 @@ var DEFAULT_BACKUP_RETENTION = {
4643
4647
  monthlyMonths: 1
4644
4648
  };
4645
4649
 
4646
- // ../paperclip/packages/shared/src/types/search.ts
4650
+ // node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/types/search.js
4647
4651
  var COMPANY_SEARCH_SCOPES = ["all", "issues", "comments", "documents", "agents", "projects"];
4648
4652
 
4649
- // ../paperclip/packages/shared/src/types/resource-memberships.ts
4653
+ // node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/types/resource-memberships.js
4650
4654
  var RESOURCE_MEMBERSHIP_STATES = ["joined", "left"];
4651
4655
 
4652
- // ../paperclip/packages/shared/src/validators/sidebar-preferences.ts
4656
+ // node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/sidebar-preferences.js
4653
4657
  var sidebarOrderedIdSchema = external_exports.string().uuid();
4654
4658
  var sidebarOrderPreferenceSchema = external_exports.object({
4655
4659
  orderedIds: external_exports.array(sidebarOrderedIdSchema),
@@ -4659,13 +4663,13 @@ var upsertSidebarOrderPreferenceSchema = external_exports.object({
4659
4663
  orderedIds: external_exports.array(sidebarOrderedIdSchema)
4660
4664
  });
4661
4665
 
4662
- // ../paperclip/packages/shared/src/validators/resource-memberships.ts
4666
+ // node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/resource-memberships.js
4663
4667
  var resourceMembershipStateSchema = external_exports.enum(RESOURCE_MEMBERSHIP_STATES);
4664
4668
  var updateResourceMembershipSchema = external_exports.object({
4665
4669
  state: resourceMembershipStateSchema
4666
4670
  });
4667
4671
 
4668
- // ../paperclip/packages/shared/src/validators/execution-workspace.ts
4672
+ // node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/execution-workspace.js
4669
4673
  var executionWorkspaceStatusSchema = external_exports.enum([
4670
4674
  "active",
4671
4675
  "idle",
@@ -4785,14 +4789,14 @@ var updateExecutionWorkspaceSchema = external_exports.object({
4785
4789
  metadata: external_exports.record(external_exports.string(), external_exports.unknown()).optional().nullable()
4786
4790
  }).strict();
4787
4791
 
4788
- // ../paperclip/packages/shared/src/types/feedback.ts
4792
+ // node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/types/feedback.js
4789
4793
  var FEEDBACK_TARGET_TYPES = ["issue_comment", "issue_document_revision"];
4790
4794
  var FEEDBACK_VOTE_VALUES = ["up", "down"];
4791
4795
  var FEEDBACK_DATA_SHARING_PREFERENCES = ["allowed", "not_allowed", "prompt"];
4792
4796
  var DEFAULT_FEEDBACK_DATA_SHARING_PREFERENCE = "prompt";
4793
4797
  var FEEDBACK_TRACE_STATUSES = ["local_only", "pending", "sent", "failed"];
4794
4798
 
4795
- // ../paperclip/packages/shared/src/validators/feedback.ts
4799
+ // node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/feedback.js
4796
4800
  var feedbackTargetTypeSchema = external_exports.enum(FEEDBACK_TARGET_TYPES);
4797
4801
  var feedbackTraceStatusSchema = external_exports.enum(FEEDBACK_TRACE_STATUSES);
4798
4802
  var feedbackVoteValueSchema = external_exports.enum(FEEDBACK_VOTE_VALUES);
@@ -4805,12 +4809,9 @@ var upsertIssueFeedbackVoteSchema = external_exports.object({
4805
4809
  allowSharing: external_exports.boolean().optional()
4806
4810
  });
4807
4811
 
4808
- // ../paperclip/packages/shared/src/validators/instance.ts
4812
+ // node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/instance.js
4809
4813
  function presetSchema(presets, label) {
4810
- return external_exports.number().refine(
4811
- (v) => presets.includes(v),
4812
- { message: `${label} must be one of: ${presets.join(", ")}` }
4813
- );
4814
+ return external_exports.number().refine((v) => presets.includes(v), { message: `${label} must be one of: ${presets.join(", ")}` });
4814
4815
  }
4815
4816
  var backupRetentionPolicySchema = external_exports.object({
4816
4817
  dailyDays: presetSchema(DAILY_RETENTION_PRESETS, "dailyDays").default(DEFAULT_BACKUP_RETENTION.dailyDays),
@@ -4820,9 +4821,7 @@ var backupRetentionPolicySchema = external_exports.object({
4820
4821
  var instanceGeneralSettingsSchema = external_exports.object({
4821
4822
  censorUsernameInLogs: external_exports.boolean().default(false),
4822
4823
  keyboardShortcuts: external_exports.boolean().default(false),
4823
- feedbackDataSharingPreference: feedbackDataSharingPreferenceSchema.default(
4824
- DEFAULT_FEEDBACK_DATA_SHARING_PREFERENCE
4825
- ),
4824
+ feedbackDataSharingPreference: feedbackDataSharingPreferenceSchema.default(DEFAULT_FEEDBACK_DATA_SHARING_PREFERENCE),
4826
4825
  backupRetention: backupRetentionPolicySchema.default(DEFAULT_BACKUP_RETENTION)
4827
4826
  }).strict();
4828
4827
  var patchInstanceGeneralSettingsSchema = instanceGeneralSettingsSchema.partial();
@@ -4840,7 +4839,7 @@ var issueGraphLivenessAutoRecoveryRequestSchema = external_exports.object({
4840
4839
  lookbackHours: external_exports.number().int().min(MIN_ISSUE_GRAPH_LIVENESS_AUTO_RECOVERY_LOOKBACK_HOURS).max(MAX_ISSUE_GRAPH_LIVENESS_AUTO_RECOVERY_LOOKBACK_HOURS).optional()
4841
4840
  }).strict();
4842
4841
 
4843
- // ../paperclip/packages/shared/src/validators/budget.ts
4842
+ // node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/budget.js
4844
4843
  var upsertBudgetPolicySchema = external_exports.object({
4845
4844
  scopeType: external_exports.enum(BUDGET_SCOPE_TYPES),
4846
4845
  scopeId: external_exports.string().uuid(),
@@ -4866,7 +4865,7 @@ var resolveBudgetIncidentSchema = external_exports.object({
4866
4865
  }
4867
4866
  });
4868
4867
 
4869
- // ../paperclip/packages/shared/src/validators/company.ts
4868
+ // node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/company.js
4870
4869
  var logoAssetIdSchema = external_exports.string().uuid().nullable().optional();
4871
4870
  var brandColorSchema = external_exports.string().regex(/^#[0-9a-fA-F]{6}$/).nullable().optional();
4872
4871
  var feedbackDataSharingTermsVersionSchema = external_exports.string().min(1).nullable().optional();
@@ -4894,12 +4893,9 @@ var updateCompanyBrandingSchema = external_exports.object({
4894
4893
  description: external_exports.string().nullable().optional(),
4895
4894
  brandColor: brandColorSchema,
4896
4895
  logoAssetId: logoAssetIdSchema
4897
- }).strict().refine(
4898
- (value) => value.name !== void 0 || value.description !== void 0 || value.brandColor !== void 0 || value.logoAssetId !== void 0,
4899
- "At least one branding field must be provided"
4900
- );
4896
+ }).strict().refine((value) => value.name !== void 0 || value.description !== void 0 || value.brandColor !== void 0 || value.logoAssetId !== void 0, "At least one branding field must be provided");
4901
4897
 
4902
- // ../paperclip/packages/shared/src/validators/environment.ts
4898
+ // node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/environment.js
4903
4899
  var environmentDriverSchema = external_exports.enum(ENVIRONMENT_DRIVERS);
4904
4900
  var environmentStatusSchema = external_exports.enum(ENVIRONMENT_STATUSES);
4905
4901
  var environmentLeaseStatusSchema = external_exports.enum(ENVIRONMENT_LEASE_STATUSES);
@@ -4929,7 +4925,7 @@ var probeEnvironmentConfigSchema = external_exports.object({
4929
4925
  metadata: external_exports.record(external_exports.string(), external_exports.unknown()).optional().nullable()
4930
4926
  }).strict();
4931
4927
 
4932
- // ../paperclip/packages/shared/src/validators/company-skill.ts
4928
+ // node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/company-skill.js
4933
4929
  var companySkillSourceTypeSchema = external_exports.enum(["local_path", "github", "url", "catalog", "skills_sh"]);
4934
4930
  var companySkillTrustLevelSchema = external_exports.enum(["markdown_only", "assets", "scripts_executables"]);
4935
4931
  var companySkillCompatibilitySchema = external_exports.enum(["compatible", "unknown", "invalid"]);
@@ -4973,9 +4969,7 @@ var companySkillUsageAgentSchema = external_exports.object({
4973
4969
  urlKey: external_exports.string().min(1),
4974
4970
  adapterType: external_exports.string().min(1),
4975
4971
  desired: external_exports.boolean(),
4976
- actualState: external_exports.string().nullable().describe(
4977
- "Runtime adapter skill state when explicitly fetched; company skill detail reads return null without probing agent runtimes."
4978
- )
4972
+ actualState: external_exports.string().nullable().describe("Runtime adapter skill state when explicitly fetched; company skill detail reads return null without probing agent runtimes.")
4979
4973
  });
4980
4974
  var companySkillDetailSchema = companySkillSchema.extend({
4981
4975
  attachedAgentCount: external_exports.number().int().nonnegative(),
@@ -5137,7 +5131,7 @@ var companySkillInstallCatalogResultSchema = external_exports.object({
5137
5131
  warnings: external_exports.array(external_exports.string())
5138
5132
  });
5139
5133
 
5140
- // ../paperclip/packages/shared/src/validators/adapter-skills.ts
5134
+ // node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/adapter-skills.js
5141
5135
  var agentSkillStateSchema = external_exports.enum([
5142
5136
  "available",
5143
5137
  "configured",
@@ -5185,13 +5179,13 @@ var agentSkillSyncSchema = external_exports.object({
5185
5179
  desiredSkills: external_exports.array(external_exports.string().min(1))
5186
5180
  });
5187
5181
 
5188
- // ../paperclip/packages/shared/src/validators/text.ts
5182
+ // node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/text.js
5189
5183
  function normalizeEscapedLineBreaks(value) {
5190
5184
  return value.replace(/\\r\\n/g, "\n").replace(/\\n/g, "\n").replace(/\\r/g, "\n");
5191
5185
  }
5192
5186
  var multilineTextSchema = external_exports.string().transform(normalizeEscapedLineBreaks);
5193
5187
 
5194
- // ../paperclip/packages/shared/src/validators/issue.ts
5188
+ // node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/issue.js
5195
5189
  var issueBlockedInboxStateSchema = external_exports.enum([
5196
5190
  "needs_attention",
5197
5191
  "awaiting_decision",
@@ -5462,9 +5456,11 @@ function resolveCreateIssueStatusDefault(input) {
5462
5456
  }
5463
5457
  function withCreateIssueStatusDefault(schema) {
5464
5458
  return external_exports.preprocess((input) => {
5465
- if (!input || typeof input !== "object" || Array.isArray(input)) return input;
5459
+ if (!input || typeof input !== "object" || Array.isArray(input))
5460
+ return input;
5466
5461
  const raw = input;
5467
- if (raw.status !== void 0) return input;
5462
+ if (raw.status !== void 0)
5463
+ return input;
5468
5464
  return {
5469
5465
  ...raw,
5470
5466
  status: resolveCreateIssueStatusDefault(raw).status
@@ -5606,9 +5602,7 @@ var addIssueCommentSchema = external_exports.object({
5606
5602
  });
5607
5603
  var issueThreadInteractionStatusSchema = external_exports.enum(ISSUE_THREAD_INTERACTION_STATUSES);
5608
5604
  var issueThreadInteractionKindSchema = external_exports.enum(ISSUE_THREAD_INTERACTION_KINDS);
5609
- var issueThreadInteractionContinuationPolicySchema = external_exports.enum(
5610
- ISSUE_THREAD_INTERACTION_CONTINUATION_POLICIES
5611
- );
5605
+ var issueThreadInteractionContinuationPolicySchema = external_exports.enum(ISSUE_THREAD_INTERACTION_CONTINUATION_POLICIES);
5612
5606
  var issueDocumentKeySchema = external_exports.string().trim().min(1).max(64).regex(/^[a-z0-9][a-z0-9_-]*$/, "Document key must be lowercase letters, numbers, _ or -");
5613
5607
  var suggestedTaskDraftSchema = external_exports.object({
5614
5608
  clientKey: external_exports.string().trim().min(1).max(120),
@@ -5840,7 +5834,7 @@ var upsertIssueDocumentSchema = external_exports.object({
5840
5834
  });
5841
5835
  var restoreIssueDocumentRevisionSchema = external_exports.object({});
5842
5836
 
5843
- // ../paperclip/packages/shared/src/validators/secret.ts
5837
+ // node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/secret.js
5844
5838
  var envBindingPlainSchema = external_exports.object({
5845
5839
  type: external_exports.literal("plain"),
5846
5840
  value: external_exports.string()
@@ -5923,9 +5917,11 @@ var safeShortText = external_exports.string().trim().min(1).max(160);
5923
5917
  var optionalSafeShortText = safeShortText.optional().nullable();
5924
5918
  var deniedProviderConfigKeyPattern = /^(access[-_]?key([-_]?id)?|secret[-_]?access[-_]?key|secret[-_]?key|token|password|passwd|credential|credentials|private[-_]?key|pem|jwt|session[-_]?token|service[-_]?account([-_]?json)?|client[-_]?secret|secret[-_]?id|unseal[-_]?key|recovery[-_]?key|key[-_]?file([-_]?path)?|token[-_]?file([-_]?path)?)$/i;
5925
5919
  function rejectSensitiveProviderConfigKeys(value, ctx) {
5926
- if (!value || typeof value !== "object" || Array.isArray(value)) return;
5920
+ if (!value || typeof value !== "object" || Array.isArray(value))
5921
+ return;
5927
5922
  for (const key of Object.keys(value)) {
5928
- if (!deniedProviderConfigKeyPattern.test(key)) continue;
5923
+ if (!deniedProviderConfigKeyPattern.test(key))
5924
+ continue;
5929
5925
  ctx.addIssue({
5930
5926
  code: external_exports.ZodIssueCode.custom,
5931
5927
  path: ["config", key],
@@ -5950,28 +5946,27 @@ var gcpSecretManagerProviderConfigSchema = external_exports.object({
5950
5946
  namespace: optionalSafeShortText,
5951
5947
  secretNamePrefix: optionalSafeShortText
5952
5948
  }).strict();
5953
- var vaultAddressSchema = external_exports.preprocess(
5954
- (value) => typeof value === "string" ? value.trim() : value,
5955
- external_exports.string().url().superRefine((value, ctx) => {
5956
- let url;
5957
- try {
5958
- url = new URL(value);
5959
- } catch {
5960
- return;
5961
- }
5962
- const hasPath = url.pathname !== "" && url.pathname !== "/";
5963
- if (url.protocol !== "http:" && url.protocol !== "https:" || url.username || url.password || url.search || url.hash || hasPath) {
5964
- ctx.addIssue({
5965
- code: external_exports.ZodIssueCode.custom,
5966
- message: "Vault address must be an origin-only HTTP(S) URL without credentials, path, query, or fragment"
5967
- });
5968
- }
5969
- }).transform((value) => new URL(value).origin)
5970
- );
5949
+ var vaultAddressSchema = external_exports.preprocess((value) => typeof value === "string" ? value.trim() : value, external_exports.string().url().superRefine((value, ctx) => {
5950
+ let url;
5951
+ try {
5952
+ url = new URL(value);
5953
+ } catch {
5954
+ return;
5955
+ }
5956
+ const hasPath = url.pathname !== "" && url.pathname !== "/";
5957
+ if (url.protocol !== "http:" && url.protocol !== "https:" || url.username || url.password || url.search || url.hash || hasPath) {
5958
+ ctx.addIssue({
5959
+ code: external_exports.ZodIssueCode.custom,
5960
+ message: "Vault address must be an origin-only HTTP(S) URL without credentials, path, query, or fragment"
5961
+ });
5962
+ }
5963
+ }).transform((value) => new URL(value).origin));
5971
5964
  function rejectUnsafeVaultAddress(value, ctx) {
5972
- if (value === void 0 || value === null) return;
5965
+ if (value === void 0 || value === null)
5966
+ return;
5973
5967
  const parsed = vaultAddressSchema.safeParse(value);
5974
- if (parsed.success) return;
5968
+ if (parsed.success)
5969
+ return;
5975
5970
  for (const issue of parsed.error.issues) {
5976
5971
  ctx.addIssue({
5977
5972
  ...issue,
@@ -6085,7 +6080,7 @@ var remoteSecretImportSchema = external_exports.object({
6085
6080
  secrets: external_exports.array(remoteSecretImportSelectionSchema).min(1).max(100)
6086
6081
  });
6087
6082
 
6088
- // ../paperclip/packages/shared/src/validators/routine.ts
6083
+ // node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/routine.js
6089
6084
  var routineVariableValueSchema = external_exports.union([external_exports.string(), external_exports.number().finite(), external_exports.boolean()]);
6090
6085
  var routineVariableSchema = external_exports.object({
6091
6086
  name: external_exports.string().trim().regex(/^[A-Za-z][A-Za-z0-9_]*$/),
@@ -6209,7 +6204,7 @@ var runRoutineSchema = external_exports.object({
6209
6204
  });
6210
6205
  var rotateRoutineTriggerSecretSchema = external_exports.object({});
6211
6206
 
6212
- // ../paperclip/packages/shared/src/validators/company-portability.ts
6207
+ // node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/company-portability.js
6213
6208
  var portabilityIncludeSchema = external_exports.object({
6214
6209
  company: external_exports.boolean().optional(),
6215
6210
  agents: external_exports.boolean().optional(),
@@ -6433,7 +6428,7 @@ var companyPortabilityImportSchema = companyPortabilityPreviewSchema.extend({
6433
6428
  adapterOverrides: external_exports.record(external_exports.string().min(1), portabilityAdapterOverrideSchema).optional()
6434
6429
  });
6435
6430
 
6436
- // ../paperclip/packages/shared/src/validators/agent.ts
6431
+ // node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/agent.js
6437
6432
  var agentPermissionsSchema = external_exports.object({
6438
6433
  canCreateAgents: external_exports.boolean().optional().default(false)
6439
6434
  });
@@ -6451,7 +6446,8 @@ var upsertAgentInstructionsFileSchema = external_exports.object({
6451
6446
  });
6452
6447
  var adapterConfigSchema = external_exports.record(external_exports.string(), external_exports.unknown()).superRefine((value, ctx) => {
6453
6448
  const envValue = value.env;
6454
- if (envValue === void 0) return;
6449
+ if (envValue === void 0)
6450
+ return;
6455
6451
  const parsed = envConfigSchema.safeParse(envValue);
6456
6452
  if (!parsed.success) {
6457
6453
  ctx.addIssue({
@@ -6521,10 +6517,7 @@ var wakeAgentSchema = external_exports.object({
6521
6517
  reason: external_exports.string().optional().nullable(),
6522
6518
  payload: external_exports.record(external_exports.string(), external_exports.unknown()).optional().nullable(),
6523
6519
  idempotencyKey: external_exports.string().optional().nullable(),
6524
- forceFreshSession: external_exports.preprocess(
6525
- (value) => value === null ? void 0 : value,
6526
- external_exports.boolean().optional().default(false)
6527
- )
6520
+ forceFreshSession: external_exports.preprocess((value) => value === null ? void 0 : value, external_exports.boolean().optional().default(false))
6528
6521
  });
6529
6522
  var resetAgentSessionSchema = external_exports.object({
6530
6523
  taskKey: external_exports.string().min(1).optional().nullable()
@@ -6544,7 +6537,7 @@ var updateAgentPermissionsSchema = external_exports.object({
6544
6537
  canAssignTasks: external_exports.boolean()
6545
6538
  });
6546
6539
 
6547
- // ../paperclip/packages/shared/src/validators/project.ts
6540
+ // node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/project.js
6548
6541
  var executionWorkspaceStrategySchema2 = external_exports.object({
6549
6542
  type: external_exports.enum(["project_primary", "git_worktree", "adapter_managed", "cloud_sandbox"]).optional(),
6550
6543
  baseRef: external_exports.string().optional().nullable(),
@@ -6640,7 +6633,7 @@ var createProjectSchema = external_exports.object({
6640
6633
  });
6641
6634
  var updateProjectSchema = external_exports.object(projectFields).partial();
6642
6635
 
6643
- // ../paperclip/packages/shared/src/validators/document-annotation.ts
6636
+ // node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/document-annotation.js
6644
6637
  var documentAnnotationThreadStatusSchema = external_exports.enum(DOCUMENT_ANNOTATION_THREAD_STATUSES);
6645
6638
  var documentAnnotationAnchorStateSchema = external_exports.enum(DOCUMENT_ANNOTATION_ANCHOR_STATES);
6646
6639
  var documentAnnotationAnchorConfidenceSchema = external_exports.enum(DOCUMENT_ANNOTATION_ANCHOR_CONFIDENCES);
@@ -6689,7 +6682,7 @@ var updateDocumentAnnotationThreadSchema = external_exports.object({
6689
6682
  message: "At least one field must be provided"
6690
6683
  });
6691
6684
 
6692
- // ../paperclip/packages/shared/src/validators/search.ts
6685
+ // node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/search.js
6693
6686
  var COMPANY_SEARCH_MAX_QUERY_LENGTH = 200;
6694
6687
  var COMPANY_SEARCH_DEFAULT_LIMIT = 20;
6695
6688
  var COMPANY_SEARCH_MAX_LIMIT = 50;
@@ -6700,7 +6693,8 @@ function firstQueryValue(value) {
6700
6693
  function clampInteger(value, fallback, min, max) {
6701
6694
  const raw = firstQueryValue(value);
6702
6695
  const numeric = typeof raw === "number" ? raw : typeof raw === "string" && raw.trim().length > 0 ? Number.parseInt(raw, 10) : Number.NaN;
6703
- if (!Number.isFinite(numeric)) return fallback;
6696
+ if (!Number.isFinite(numeric))
6697
+ return fallback;
6704
6698
  return Math.min(max, Math.max(min, Math.floor(numeric)));
6705
6699
  }
6706
6700
  var companySearchQuerySchema = external_exports.object({
@@ -6710,7 +6704,7 @@ var companySearchQuerySchema = external_exports.object({
6710
6704
  offset: external_exports.unknown().optional().transform((value) => clampInteger(value, 0, 0, COMPANY_SEARCH_MAX_OFFSET))
6711
6705
  });
6712
6706
 
6713
- // ../paperclip/packages/shared/src/validators/issue-tree-control.ts
6707
+ // node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/issue-tree-control.js
6714
6708
  var issueTreeControlModeSchema = external_exports.enum(ISSUE_TREE_CONTROL_MODES);
6715
6709
  var issueTreeHoldReleasePolicySchema = external_exports.object({
6716
6710
  strategy: external_exports.enum(ISSUE_TREE_HOLD_RELEASE_POLICY_STRATEGIES).default("manual"),
@@ -6732,10 +6726,7 @@ var releaseIssueTreeHoldSchema = external_exports.object({
6732
6726
  metadata: external_exports.record(external_exports.string(), external_exports.unknown()).optional().nullable()
6733
6727
  }).strict();
6734
6728
 
6735
- // ../paperclip/packages/shared/src/validators/work-product.ts
6736
- function attachmentContentPath(attachmentId) {
6737
- return `/api/attachments/${attachmentId}/content`;
6738
- }
6729
+ // node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/work-product.js
6739
6730
  var issueWorkProductTypeSchema = external_exports.enum([
6740
6731
  "preview_url",
6741
6732
  "runtime_service",
@@ -6762,38 +6753,6 @@ var issueWorkProductReviewStateSchema = external_exports.enum([
6762
6753
  "approved",
6763
6754
  "changes_requested"
6764
6755
  ]);
6765
- var attachmentArtifactWorkProductMetadataSchema = external_exports.object({
6766
- attachmentId: external_exports.string().uuid(),
6767
- contentType: external_exports.string().min(1),
6768
- byteSize: external_exports.number().int().nonnegative(),
6769
- contentPath: external_exports.string().min(1),
6770
- openPath: external_exports.string().min(1),
6771
- downloadPath: external_exports.string().min(1),
6772
- originalFilename: external_exports.string().optional().nullable()
6773
- }).superRefine((value, ctx) => {
6774
- const contentPath = attachmentContentPath(value.attachmentId);
6775
- if (value.contentPath !== contentPath) {
6776
- ctx.addIssue({
6777
- code: external_exports.ZodIssueCode.custom,
6778
- path: ["contentPath"],
6779
- message: "contentPath must point to the same-origin attachment content route"
6780
- });
6781
- }
6782
- if (value.openPath !== contentPath) {
6783
- ctx.addIssue({
6784
- code: external_exports.ZodIssueCode.custom,
6785
- path: ["openPath"],
6786
- message: "openPath must point to the same-origin attachment content route"
6787
- });
6788
- }
6789
- if (value.downloadPath !== `${contentPath}?download=1`) {
6790
- ctx.addIssue({
6791
- code: external_exports.ZodIssueCode.custom,
6792
- path: ["downloadPath"],
6793
- message: "downloadPath must point to the same-origin attachment download route"
6794
- });
6795
- }
6796
- });
6797
6756
  var createIssueWorkProductSchema = external_exports.object({
6798
6757
  projectId: external_exports.string().uuid().optional().nullable(),
6799
6758
  executionWorkspaceId: external_exports.string().uuid().optional().nullable(),
@@ -6813,7 +6772,7 @@ var createIssueWorkProductSchema = external_exports.object({
6813
6772
  });
6814
6773
  var updateIssueWorkProductSchema = createIssueWorkProductSchema.partial();
6815
6774
 
6816
- // ../paperclip/packages/shared/src/validators/goal.ts
6775
+ // node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/goal.js
6817
6776
  var createGoalSchema = external_exports.object({
6818
6777
  title: external_exports.string().min(1),
6819
6778
  description: external_exports.string().optional().nullable(),
@@ -6824,7 +6783,7 @@ var createGoalSchema = external_exports.object({
6824
6783
  });
6825
6784
  var updateGoalSchema = createGoalSchema.partial();
6826
6785
 
6827
- // ../paperclip/packages/shared/src/validators/approval.ts
6786
+ // node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/approval.js
6828
6787
  var createApprovalSchema = external_exports.object({
6829
6788
  type: external_exports.enum(APPROVAL_TYPES),
6830
6789
  requestedByAgentId: external_exports.string().uuid().optional().nullable(),
@@ -6844,7 +6803,7 @@ var addApprovalCommentSchema = external_exports.object({
6844
6803
  body: multilineTextSchema.pipe(external_exports.string().min(1))
6845
6804
  });
6846
6805
 
6847
- // ../paperclip/packages/shared/src/validators/cost.ts
6806
+ // node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/cost.js
6848
6807
  var createCostEventSchema = external_exports.object({
6849
6808
  agentId: external_exports.string().uuid(),
6850
6809
  issueId: external_exports.string().uuid().optional().nullable(),
@@ -6869,7 +6828,7 @@ var updateBudgetSchema = external_exports.object({
6869
6828
  budgetMonthlyCents: external_exports.number().int().nonnegative()
6870
6829
  });
6871
6830
 
6872
- // ../paperclip/packages/shared/src/validators/finance.ts
6831
+ // node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/finance.js
6873
6832
  var createFinanceEventSchema = external_exports.object({
6874
6833
  agentId: external_exports.string().uuid().optional().nullable(),
6875
6834
  issueId: external_exports.string().uuid().optional().nullable(),
@@ -6900,12 +6859,12 @@ var createFinanceEventSchema = external_exports.object({
6900
6859
  currency: value.currency.toUpperCase()
6901
6860
  }));
6902
6861
 
6903
- // ../paperclip/packages/shared/src/validators/asset.ts
6862
+ // node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/asset.js
6904
6863
  var createAssetImageMetadataSchema = external_exports.object({
6905
6864
  namespace: external_exports.string().trim().min(1).max(120).regex(/^[a-zA-Z0-9/_-]+$/).optional()
6906
6865
  });
6907
6866
 
6908
- // ../paperclip/packages/shared/src/validators/access.ts
6867
+ // node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/access.js
6909
6868
  var createCompanyInviteSchema = external_exports.object({
6910
6869
  allowedJoinTypes: external_exports.enum(INVITE_JOIN_TYPES).default("both"),
6911
6870
  humanRole: external_exports.enum(HUMAN_COMPANY_MEMBERSHIP_ROLES).optional().nullable(),
@@ -6954,12 +6913,10 @@ var resolveCliAuthChallengeSchema = external_exports.object({
6954
6913
  token: external_exports.string().min(16).max(256)
6955
6914
  });
6956
6915
  var updateMemberPermissionsSchema = external_exports.object({
6957
- grants: external_exports.array(
6958
- external_exports.object({
6959
- permissionKey: external_exports.enum(PERMISSION_KEYS),
6960
- scope: external_exports.record(external_exports.string(), external_exports.unknown()).optional().nullable()
6961
- })
6962
- )
6916
+ grants: external_exports.array(external_exports.object({
6917
+ permissionKey: external_exports.enum(PERMISSION_KEYS),
6918
+ scope: external_exports.record(external_exports.string(), external_exports.unknown()).optional().nullable()
6919
+ }))
6963
6920
  });
6964
6921
  var editableMembershipStatuses = ["pending", "active", "suspended"];
6965
6922
  var updateCompanyMemberSchema = external_exports.object({
@@ -6997,7 +6954,8 @@ var searchAdminUsersQuerySchema = external_exports.object({
6997
6954
  });
6998
6955
  var profileImageAssetPathPattern = /^\/api\/assets\/[^/?#]+\/content(?:\?[^#]*)?(?:#.*)?$/;
6999
6956
  function isValidProfileImage(value) {
7000
- if (profileImageAssetPathPattern.test(value)) return true;
6957
+ if (profileImageAssetPathPattern.test(value))
6958
+ return true;
7001
6959
  try {
7002
6960
  const url = new URL(value);
7003
6961
  return url.protocol === "https:" || url.protocol === "http:";
@@ -7024,30 +6982,27 @@ var updateCurrentUserProfileSchema = external_exports.object({
7024
6982
  image: external_exports.union([profileImageSchema, external_exports.literal(""), external_exports.null()]).optional().transform((value) => value === "" ? null : value)
7025
6983
  });
7026
6984
 
7027
- // ../paperclip/packages/shared/src/validators/plugin.ts
7028
- var jsonSchemaSchema = external_exports.record(external_exports.string(), external_exports.unknown()).refine(
7029
- (val) => {
7030
- if (Object.keys(val).length === 0) return true;
7031
- return typeof val.type === "string" || val.$ref !== void 0 || val.oneOf !== void 0 || val.anyOf !== void 0 || val.allOf !== void 0;
7032
- },
7033
- { message: "Must be a valid JSON Schema object (requires at least a 'type', '$ref', or composition keyword)" }
7034
- );
6985
+ // node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/validators/plugin.js
6986
+ var jsonSchemaSchema = external_exports.record(external_exports.string(), external_exports.unknown()).refine((val) => {
6987
+ if (Object.keys(val).length === 0)
6988
+ return true;
6989
+ return typeof val.type === "string" || val.$ref !== void 0 || val.oneOf !== void 0 || val.anyOf !== void 0 || val.allOf !== void 0;
6990
+ }, { message: "Must be a valid JSON Schema object (requires at least a 'type', '$ref', or composition keyword)" });
7035
6991
  var CRON_FIELD_PATTERN = /^(\*(?:\/[0-9]+)?|[0-9]+(?:-[0-9]+)?(?:\/[0-9]+)?)(?:,(\*(?:\/[0-9]+)?|[0-9]+(?:-[0-9]+)?(?:\/[0-9]+)?))*$/;
7036
6992
  function isValidCronExpression(expression) {
7037
6993
  const trimmed = expression.trim();
7038
- if (!trimmed) return false;
6994
+ if (!trimmed)
6995
+ return false;
7039
6996
  const fields = trimmed.split(/\s+/);
7040
- if (fields.length !== 5) return false;
6997
+ if (fields.length !== 5)
6998
+ return false;
7041
6999
  return fields.every((f) => CRON_FIELD_PATTERN.test(f));
7042
7000
  }
7043
7001
  var pluginJobDeclarationSchema = external_exports.object({
7044
7002
  jobKey: external_exports.string().min(1),
7045
7003
  displayName: external_exports.string().min(1),
7046
7004
  description: external_exports.string().optional(),
7047
- schedule: external_exports.string().refine(
7048
- (val) => isValidCronExpression(val),
7049
- { message: "schedule must be a valid 5-field cron expression (e.g. '*/15 * * * *')" }
7050
- ).optional()
7005
+ schedule: external_exports.string().refine((val) => isValidCronExpression(val), { message: "schedule must be a valid 5-field cron expression (e.g. '*/15 * * * *')" }).optional()
7051
7006
  });
7052
7007
  var pluginWebhookDeclarationSchema = external_exports.object({
7053
7008
  endpointKey: external_exports.string().min(1),
@@ -7061,10 +7016,7 @@ var pluginToolDeclarationSchema = external_exports.object({
7061
7016
  parametersSchema: jsonSchemaSchema
7062
7017
  });
7063
7018
  var pluginEnvironmentDriverDeclarationSchema = external_exports.object({
7064
- driverKey: external_exports.string().min(1).regex(
7065
- /^[a-z0-9][a-z0-9._-]*$/,
7066
- "Environment driver key must start with a lowercase alphanumeric and contain only lowercase letters, digits, dots, hyphens, or underscores"
7067
- ),
7019
+ driverKey: external_exports.string().min(1).regex(/^[a-z0-9][a-z0-9._-]*$/, "Environment driver key must start with a lowercase alphanumeric and contain only lowercase letters, digits, dots, hyphens, or underscores"),
7068
7020
  kind: external_exports.enum(["environment_driver", "sandbox_provider"]).optional(),
7069
7021
  displayName: external_exports.string().min(1).max(100),
7070
7022
  description: external_exports.string().max(500).optional(),
@@ -7139,10 +7091,7 @@ var pluginManagedRoutineDeclarationSchema = external_exports.object({
7139
7091
  billingCode: external_exports.string().trim().max(200).nullable().optional()
7140
7092
  }).optional()
7141
7093
  });
7142
- var pluginLocalFolderRelativePathSchema = external_exports.string().min(1).max(500).refine(
7143
- (value) => !value.startsWith("/") && !value.includes("..") && !value.includes("\\") && !value.split("/").some((segment) => segment === "" || segment === "."),
7144
- { message: "local folder paths must be relative paths without traversal, empty segments, or backslashes" }
7145
- );
7094
+ var pluginLocalFolderRelativePathSchema = external_exports.string().min(1).max(500).refine((value) => !value.startsWith("/") && !value.includes("..") && !value.includes("\\") && !value.split("/").some((segment) => segment === "" || segment === "."), { message: "local folder paths must be relative paths without traversal, empty segments, or backslashes" });
7146
7095
  var pluginLocalFolderDeclarationSchema = external_exports.object({
7147
7096
  folderKey: external_exports.string().min(1).max(100).regex(/^[a-z0-9][a-z0-9._:-]*$/, {
7148
7097
  message: "folderKey must start with a lowercase alphanumeric and contain only lowercase letters, digits, dots, colons, underscores, or hyphens"
@@ -7154,10 +7103,7 @@ var pluginLocalFolderDeclarationSchema = external_exports.object({
7154
7103
  requiredFiles: external_exports.array(pluginLocalFolderRelativePathSchema).optional()
7155
7104
  });
7156
7105
  var pluginManagedSkillFileDeclarationSchema = external_exports.object({
7157
- path: pluginLocalFolderRelativePathSchema.refine(
7158
- (value) => value.toLowerCase() !== "skill.md",
7159
- { message: "managed skill files cannot replace SKILL.md; use markdown for the main skill file" }
7160
- ),
7106
+ path: pluginLocalFolderRelativePathSchema.refine((value) => value.toLowerCase() !== "skill.md", { message: "managed skill files cannot replace SKILL.md; use markdown for the main skill file" }),
7161
7107
  content: external_exports.string().max(2e5)
7162
7108
  });
7163
7109
  var pluginManagedSkillDeclarationSchema = external_exports.object({
@@ -7374,10 +7320,7 @@ var pluginDatabaseDeclarationSchema = external_exports.object({
7374
7320
  namespaceSlug: external_exports.string().regex(/^[a-z0-9][a-z0-9_]*$/, {
7375
7321
  message: "namespaceSlug must be lowercase letters, digits, or underscores and start with a letter or digit"
7376
7322
  }).max(40).optional(),
7377
- migrationsDir: external_exports.string().min(1).refine(
7378
- (value) => !value.startsWith("/") && !value.includes("..") && !/[\\]/.test(value),
7379
- { message: "migrationsDir must be a relative package path without '..' or backslashes" }
7380
- ),
7323
+ migrationsDir: external_exports.string().min(1).refine((value) => !value.startsWith("/") && !value.includes("..") && !/[\\]/.test(value), { message: "migrationsDir must be a relative package path without '..' or backslashes" }),
7381
7324
  coreReadTables: external_exports.array(external_exports.enum(PLUGIN_DATABASE_CORE_READ_TABLES)).optional()
7382
7325
  });
7383
7326
  var pluginApiRouteDeclarationSchema = external_exports.object({
@@ -7387,10 +7330,7 @@ var pluginApiRouteDeclarationSchema = external_exports.object({
7387
7330
  method: external_exports.enum(PLUGIN_API_ROUTE_METHODS),
7388
7331
  path: external_exports.string().min(1).regex(/^\/[a-zA-Z0-9:_./-]*$/, {
7389
7332
  message: "path must start with / and contain only path-safe literal or :param segments"
7390
- }).refine(
7391
- (value) => !value.includes("..") && !value.includes("//") && value !== "/api" && !value.startsWith("/api/") && value !== "/plugins" && !value.startsWith("/plugins/"),
7392
- { message: "path must stay inside the plugin api namespace" }
7393
- ),
7333
+ }).refine((value) => !value.includes("..") && !value.includes("//") && value !== "/api" && !value.startsWith("/api/") && value !== "/plugins" && !value.startsWith("/plugins/"), { message: "path must stay inside the plugin api namespace" }),
7394
7334
  auth: external_exports.enum(PLUGIN_API_ROUTE_AUTH_MODES),
7395
7335
  capability: external_exports.literal("api.routes.register"),
7396
7336
  checkoutPolicy: external_exports.enum(PLUGIN_API_ROUTE_CHECKOUT_POLICIES).optional(),
@@ -7401,27 +7341,15 @@ var pluginApiRouteDeclarationSchema = external_exports.object({
7401
7341
  ]).optional()
7402
7342
  });
7403
7343
  var pluginManifestV1Schema = external_exports.object({
7404
- id: external_exports.string().min(1).regex(
7405
- /^[a-z0-9][a-z0-9._-]*$/,
7406
- "Plugin id must start with a lowercase alphanumeric and contain only lowercase letters, digits, dots, hyphens, or underscores"
7407
- ),
7344
+ id: external_exports.string().min(1).regex(/^[a-z0-9][a-z0-9._-]*$/, "Plugin id must start with a lowercase alphanumeric and contain only lowercase letters, digits, dots, hyphens, or underscores"),
7408
7345
  apiVersion: external_exports.literal(1),
7409
- version: external_exports.string().min(1).regex(
7410
- /^\d+\.\d+\.\d+(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$/,
7411
- "Version must follow semver (e.g. 1.0.0 or 1.0.0-beta.1)"
7412
- ),
7346
+ version: external_exports.string().min(1).regex(/^\d+\.\d+\.\d+(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$/, "Version must follow semver (e.g. 1.0.0 or 1.0.0-beta.1)"),
7413
7347
  displayName: external_exports.string().min(1).max(100),
7414
7348
  description: external_exports.string().min(1).max(500),
7415
7349
  author: external_exports.string().min(1).max(200),
7416
7350
  categories: external_exports.array(external_exports.enum(PLUGIN_CATEGORIES)).min(1),
7417
- minimumHostVersion: external_exports.string().regex(
7418
- /^\d+\.\d+\.\d+(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$/,
7419
- "minimumHostVersion must follow semver (e.g. 1.0.0)"
7420
- ).optional(),
7421
- minimumPaperclipVersion: external_exports.string().regex(
7422
- /^\d+\.\d+\.\d+(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$/,
7423
- "minimumPaperclipVersion must follow semver (e.g. 1.0.0)"
7424
- ).optional(),
7351
+ minimumHostVersion: external_exports.string().regex(/^\d+\.\d+\.\d+(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$/, "minimumHostVersion must follow semver (e.g. 1.0.0)").optional(),
7352
+ minimumPaperclipVersion: external_exports.string().regex(/^\d+\.\d+\.\d+(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$/, "minimumPaperclipVersion must follow semver (e.g. 1.0.0)").optional(),
7425
7353
  capabilities: external_exports.array(external_exports.enum(PLUGIN_CAPABILITIES)).min(1),
7426
7354
  entrypoints: external_exports.object({
7427
7355
  worker: external_exports.string().min(1),
@@ -7762,7 +7690,7 @@ var listPluginStateSchema = external_exports.object({
7762
7690
  namespace: external_exports.string().min(1).optional()
7763
7691
  });
7764
7692
 
7765
- // ../paperclip/packages/shared/src/api.ts
7693
+ // node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/api.js
7766
7694
  var API_PREFIX = "/api";
7767
7695
  var API = {
7768
7696
  health: `${API_PREFIX}/health`,
@@ -7789,7 +7717,7 @@ var API = {
7789
7717
  admin: `${API_PREFIX}/admin`
7790
7718
  };
7791
7719
 
7792
- // ../paperclip/packages/shared/src/routine-variables.ts
7720
+ // node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/routine-variables.js
7793
7721
  var HUMAN_TIMESTAMP_FORMATTER = new Intl.DateTimeFormat("en-US", {
7794
7722
  year: "numeric",
7795
7723
  month: "long",
@@ -7801,7 +7729,7 @@ var HUMAN_TIMESTAMP_FORMATTER = new Intl.DateTimeFormat("en-US", {
7801
7729
  timeZoneName: "short"
7802
7730
  });
7803
7731
 
7804
- // ../paperclip/packages/shared/src/config-schema.ts
7732
+ // node_modules/.pnpm/@paperclipai+shared@2026.529.0/node_modules/@paperclipai/shared/dist/config-schema.js
7805
7733
  var configMetaSchema = external_exports.object({
7806
7734
  version: external_exports.literal(1),
7807
7735
  updatedAt: external_exports.string(),
@@ -7957,14 +7885,14 @@ var paperclipConfigSchema = external_exports.object({
7957
7885
  }
7958
7886
  });
7959
7887
 
7960
- // node_modules/.pnpm/@paperclipai+plugin-sdk@file+..+paperclip+packages+plugins+sdk_react@19.2.4/node_modules/@paperclipai/plugin-sdk/dist/worker-rpc-host.js
7888
+ // node_modules/.pnpm/@paperclipai+plugin-sdk@2026.529.0_react@19.2.4/node_modules/@paperclipai/plugin-sdk/dist/worker-rpc-host.js
7961
7889
  import fs from "node:fs";
7962
7890
  import { AsyncLocalStorage } from "node:async_hooks";
7963
7891
  import path from "node:path";
7964
7892
  import { createInterface } from "node:readline";
7965
7893
  import { fileURLToPath } from "node:url";
7966
7894
 
7967
- // node_modules/.pnpm/@paperclipai+plugin-sdk@file+..+paperclip+packages+plugins+sdk_react@19.2.4/node_modules/@paperclipai/plugin-sdk/dist/protocol.js
7895
+ // node_modules/.pnpm/@paperclipai+plugin-sdk@2026.529.0_react@19.2.4/node_modules/@paperclipai/plugin-sdk/dist/protocol.js
7968
7896
  var JSONRPC_VERSION = "2.0";
7969
7897
  var JSONRPC_ERROR_CODES = {
7970
7898
  /** Invalid JSON was received by the server. */
@@ -8096,7 +8024,7 @@ var JsonRpcCallError = class extends Error {
8096
8024
  }
8097
8025
  };
8098
8026
 
8099
- // node_modules/.pnpm/@paperclipai+plugin-sdk@file+..+paperclip+packages+plugins+sdk_react@19.2.4/node_modules/@paperclipai/plugin-sdk/dist/worker-rpc-host.js
8027
+ // node_modules/.pnpm/@paperclipai+plugin-sdk@2026.529.0_react@19.2.4/node_modules/@paperclipai/plugin-sdk/dist/worker-rpc-host.js
8100
8028
  var DEFAULT_RPC_TIMEOUT_MS = 3e4;
8101
8029
  function realpathOrResolvedPath(filePath) {
8102
8030
  const resolvedPath = path.resolve(filePath);
@@ -9400,6 +9328,15 @@ function buildCeoAgentRuntimeConfig() {
9400
9328
  }
9401
9329
  };
9402
9330
  }
9331
+ function buildWorkerAgentRuntimeConfig() {
9332
+ return {
9333
+ heartbeat: {
9334
+ enabled: false,
9335
+ intervalSec: DEFAULT_CEO_HEARTBEAT_INTERVAL_SEC,
9336
+ maxConcurrentRuns: DEFAULT_CEO_MAX_CONCURRENT_RUNS
9337
+ }
9338
+ };
9339
+ }
9403
9340
 
9404
9341
  // src/logic/assemble.js
9405
9342
  async function exists(p) {
@@ -9444,6 +9381,11 @@ async function assembleCompany({
9444
9381
  moduleNames,
9445
9382
  extraRoleNames,
9446
9383
  inlineGoals = [],
9384
+ userIssues = [],
9385
+ presetIssues = [],
9386
+ presetRoutines = [],
9387
+ presetLabels = [],
9388
+ enableIsolatedWorktrees = false,
9447
9389
  outputDir,
9448
9390
  templatesDir,
9449
9391
  onProgress = () => {
@@ -9548,9 +9490,20 @@ async function assembleCompany({
9548
9490
  }
9549
9491
  onProgress(`+ agents/${roleName}/ (role)`);
9550
9492
  }
9551
- const initialIssues = [];
9552
- const initialRoutines = [];
9493
+ const initialIssues = Array.isArray(presetIssues) ? presetIssues.map((issue) => ({ ...issue, source: issue.source || "preset" })) : [];
9494
+ const initialRoutines = Array.isArray(presetRoutines) ? presetRoutines.map((routine) => ({ ...routine, source: routine.source || "preset" })) : [];
9495
+ const explicitBootstrapLabels = Array.isArray(presetLabels) ? [...presetLabels] : [];
9553
9496
  const roleAdapterOverrides = /* @__PURE__ */ new Map();
9497
+ const docRoleMap = /* @__PURE__ */ new Map();
9498
+ const addDocRoles = (docName, roles) => {
9499
+ const set = docRoleMap.get(docName) ?? /* @__PURE__ */ new Set();
9500
+ for (const r of roles) set.add(r);
9501
+ docRoleMap.set(docName, set);
9502
+ };
9503
+ const normalizeIssueTitle = (title) => String(title || "").trim().toLowerCase();
9504
+ const seenIssueTitles = new Set(
9505
+ initialIssues.map((issue) => normalizeIssueTitle(issue.title)).filter(Boolean)
9506
+ );
9554
9507
  const resolveAssignee = (assignee, moduleJson) => {
9555
9508
  if (assignee?.startsWith("capability:")) {
9556
9509
  const capName = assignee.slice("capability:".length);
@@ -9561,6 +9514,55 @@ async function assembleCompany({
9561
9514
  }
9562
9515
  return assignee;
9563
9516
  };
9517
+ const resolveReviewGate = (reviewGate) => {
9518
+ if (!reviewGate || typeof reviewGate !== "object") return null;
9519
+ const reviewersRaw = Array.isArray(reviewGate.reviewers) ? reviewGate.reviewers : [];
9520
+ const reviewers = [];
9521
+ const seen = /* @__PURE__ */ new Set();
9522
+ for (const role of reviewersRaw) {
9523
+ if (typeof role !== "string") continue;
9524
+ if (!allRoles.has(role)) continue;
9525
+ if (seen.has(role)) continue;
9526
+ seen.add(role);
9527
+ reviewers.push(role);
9528
+ }
9529
+ const approver = typeof reviewGate.approver === "string" && allRoles.has(reviewGate.approver) ? reviewGate.approver : void 0;
9530
+ if (approver) {
9531
+ const idx = reviewers.indexOf(approver);
9532
+ if (idx !== -1) reviewers.splice(idx, 1);
9533
+ }
9534
+ if (reviewers.length === 0 && !approver) return null;
9535
+ return { reviewers, approver };
9536
+ };
9537
+ const renderReviewGate = (gate) => {
9538
+ const stages = [];
9539
+ for (const role of gate.reviewers) {
9540
+ stages.push(` - stage ${stages.length + 1} (review) \u2192 assign ${JSON.stringify(role)}`);
9541
+ }
9542
+ if (gate.approver) {
9543
+ stages.push(
9544
+ ` - stage ${stages.length + 1} (approval) \u2192 assign ${JSON.stringify(gate.approver)}`
9545
+ );
9546
+ }
9547
+ return `- **executionPolicy** (set when creating this issue; resolve each role to its agentId):
9548
+ ${stages.join("\n")}
9549
+
9550
+ `;
9551
+ };
9552
+ const isFoundationIssue = (issue) => issue?.bootstrapPhase === "foundation" || issue?.phase === "foundation" || issue?.bootstrapOrder === "foundation" || issue?.foundation === true;
9553
+ const resolvedUserIssues = [];
9554
+ for (const issue of Array.isArray(userIssues) ? userIssues : []) {
9555
+ if (!issue || !issue.title) continue;
9556
+ const titleKey = normalizeIssueTitle(issue.title);
9557
+ if (titleKey && seenIssueTitles.has(titleKey)) continue;
9558
+ if (titleKey) seenIssueTitles.add(titleKey);
9559
+ resolvedUserIssues.push({
9560
+ ...issue,
9561
+ assignTo: resolveAssignee(issue.assignTo, null),
9562
+ source: "user"
9563
+ });
9564
+ }
9565
+ initialIssues.unshift(...resolvedUserIssues);
9564
9566
  for (const moduleName of moduleNames) {
9565
9567
  const moduleDir = join(templatesDir, "modules", moduleName);
9566
9568
  if (!await exists(moduleDir)) {
@@ -9575,8 +9577,17 @@ async function assembleCompany({
9575
9577
  continue;
9576
9578
  }
9577
9579
  }
9580
+ if (Array.isArray(moduleJson?.labels)) {
9581
+ explicitBootstrapLabels.push(...moduleJson.labels);
9582
+ }
9578
9583
  const moduleIssues = moduleJson?.issues || moduleJson?.tasks || [];
9579
9584
  for (const issue of moduleIssues) {
9585
+ const titleKey = normalizeIssueTitle(issue.title);
9586
+ if (titleKey && seenIssueTitles.has(titleKey)) {
9587
+ onProgress(`\u25CB issue "${issue.title}" (already provided by preset or earlier module)`);
9588
+ continue;
9589
+ }
9590
+ if (titleKey) seenIssueTitles.add(titleKey);
9580
9591
  initialIssues.push({
9581
9592
  ...issue,
9582
9593
  assignTo: resolveAssignee(issue.assignTo, moduleJson),
@@ -9595,8 +9606,21 @@ async function assembleCompany({
9595
9606
  const docsDir = join(moduleDir, "docs");
9596
9607
  if (await exists(docsDir)) {
9597
9608
  await copyDir(docsDir, join(companyDir, "docs"));
9609
+ const moduleRoles = /* @__PURE__ */ new Set();
9610
+ for (const cap of moduleJson?.capabilities ?? []) {
9611
+ for (const owner of cap.owners ?? []) if (allRoles.has(owner)) moduleRoles.add(owner);
9612
+ }
9613
+ for (const issue of moduleIssues) {
9614
+ if (issue.assignTo && allRoles.has(issue.assignTo)) moduleRoles.add(issue.assignTo);
9615
+ }
9616
+ for (const routine of moduleJson?.routines ?? []) {
9617
+ if (routine.assignTo && allRoles.has(routine.assignTo)) moduleRoles.add(routine.assignTo);
9618
+ }
9619
+ for (const r of moduleJson?.activatesWithRoles ?? []) if (allRoles.has(r)) moduleRoles.add(r);
9620
+ const rolesForDocs = moduleRoles.size > 0 ? moduleRoles : /* @__PURE__ */ new Set(["*"]);
9598
9621
  const docs = await readdir(docsDir);
9599
9622
  for (const doc of docs) {
9623
+ addDocRoles(doc, rolesForDocs);
9600
9624
  onProgress(`+ docs/${doc} (${moduleName})`);
9601
9625
  }
9602
9626
  }
@@ -9711,25 +9735,53 @@ Read and follow: \`$AGENT_HOME/skills/${skillFile}\`
9711
9735
  }
9712
9736
  const finalDocsDir = join(companyDir, "docs");
9713
9737
  if (await exists(finalDocsDir)) {
9714
- const docs = await readdir(finalDocsDir);
9738
+ const docs = (await readdir(finalDocsDir)).sort();
9715
9739
  if (docs.length > 0) {
9716
9740
  const agentsBaseDir = join(companyDir, "agents");
9717
9741
  const agentRoles = await readdir(agentsBaseDir, { withFileTypes: true });
9718
9742
  for (const role of agentRoles) {
9719
9743
  if (!role.isDirectory()) continue;
9720
9744
  const agentsMd = join(agentsBaseDir, role.name, "AGENTS.md");
9721
- if (await exists(agentsMd)) {
9722
- let docRefs = "\n## Shared Documentation\n";
9723
- for (const doc of docs) {
9724
- docRefs += `
9745
+ if (!await exists(agentsMd)) continue;
9746
+ const relevantDocs = docs.filter((doc) => {
9747
+ if (role.name === "ceo") return true;
9748
+ const roles = docRoleMap.get(doc);
9749
+ return !roles || roles.has("*") || roles.has(role.name);
9750
+ });
9751
+ if (relevantDocs.length === 0) continue;
9752
+ let docRefs = "\n## Shared Documentation\n\nReference docs relevant to your role (paths are relative to your workspace home):\n";
9753
+ for (const doc of relevantDocs) {
9754
+ docRefs += `
9725
9755
  Read: \`docs/${doc}\`
9726
9756
  `;
9727
- }
9728
- await appendToFile(agentsMd, docRefs);
9729
9757
  }
9758
+ await appendToFile(agentsMd, docRefs);
9730
9759
  }
9731
9760
  }
9732
9761
  }
9762
+ const agentsBaseDirForSubst = join(companyDir, "agents");
9763
+ if (await exists(agentsBaseDirForSubst)) {
9764
+ const agentRoleDirs = await readdir(agentsBaseDirForSubst, { withFileTypes: true });
9765
+ for (const roleDir of agentRoleDirs) {
9766
+ if (!roleDir.isDirectory()) continue;
9767
+ const absoluteAgentHome = join(agentsBaseDirForSubst, roleDir.name);
9768
+ const subst = async (dir) => {
9769
+ const entries = await readdir(dir, { withFileTypes: true });
9770
+ for (const entry of entries) {
9771
+ const full = join(dir, entry.name);
9772
+ if (entry.isDirectory()) {
9773
+ await subst(full);
9774
+ } else if (entry.name.endsWith(".md")) {
9775
+ const content = await readFile(full, "utf-8");
9776
+ if (content.includes("$AGENT_HOME")) {
9777
+ await writeFile(full, content.split("$AGENT_HOME").join(absoluteAgentHome));
9778
+ }
9779
+ }
9780
+ }
9781
+ };
9782
+ await subst(join(agentsBaseDirForSubst, roleDir.name));
9783
+ }
9784
+ }
9733
9785
  const rolesList = [...allRoles];
9734
9786
  const DEFAULT_BOOTSTRAP_LABELS = [
9735
9787
  { name: "feature", color: "#0075ca", useFor: "New user-facing capability" },
@@ -9824,16 +9876,23 @@ Read: \`docs/${doc}\`
9824
9876
  }
9825
9877
  return "feature";
9826
9878
  };
9827
- const buildBootstrapLabels = (issues) => {
9828
- if (issues.length === 0) return [];
9879
+ const buildBootstrapLabels = (issues, explicitLabels = []) => {
9880
+ if (issues.length === 0 && explicitLabels.length === 0) return [];
9829
9881
  const labelsByName2 = new Map(
9830
9882
  DEFAULT_BOOTSTRAP_LABELS.map((label) => [label.name, { ...label }])
9831
9883
  );
9884
+ for (const label of explicitLabels) {
9885
+ for (const parsedLabel of parseIssueLabels({ labels: [label] })) {
9886
+ labelsByName2.set(parsedLabel.name, parsedLabel);
9887
+ }
9888
+ }
9832
9889
  for (const issue of issues) {
9833
- const explicitLabels = parseIssueLabels(issue);
9834
- if (explicitLabels.length > 0) {
9835
- for (const label of explicitLabels) {
9836
- labelsByName2.set(label.name, label);
9890
+ const explicitLabels2 = parseIssueLabels(issue);
9891
+ if (explicitLabels2.length > 0) {
9892
+ for (const label of explicitLabels2) {
9893
+ if (!labelsByName2.has(label.name)) {
9894
+ labelsByName2.set(label.name, label);
9895
+ }
9837
9896
  }
9838
9897
  continue;
9839
9898
  }
@@ -9848,7 +9907,17 @@ Read: \`docs/${doc}\`
9848
9907
  }
9849
9908
  return [...labelsByName2.values()];
9850
9909
  };
9851
- const bootstrapLabels = buildBootstrapLabels(initialIssues);
9910
+ const orderInitialIssuesForBootstrap = () => {
9911
+ const originalOrder = new Map(initialIssues.map((issue, index) => [issue, index]));
9912
+ const rank = (issue) => {
9913
+ if (isFoundationIssue(issue)) return 0;
9914
+ if (issue?.source === "user") return 1;
9915
+ return 2;
9916
+ };
9917
+ initialIssues.sort((a, b) => rank(a) - rank(b) || originalOrder.get(a) - originalOrder.get(b));
9918
+ };
9919
+ orderInitialIssuesForBootstrap();
9920
+ const bootstrapLabels = buildBootstrapLabels(initialIssues, explicitBootstrapLabels);
9852
9921
  const labelsByName = new Map(bootstrapLabels.map((label) => [label.name, label]));
9853
9922
  const getIssueLabelNames = (issue) => {
9854
9923
  const explicit = parseIssueLabels(issue).map((label) => label.name);
@@ -9860,7 +9929,11 @@ Read: \`docs/${doc}\`
9860
9929
  if (lines.length === 0) return "";
9861
9930
  return lines.map(([k, v]) => `- **${k}**: ${v}`).join("\n") + "\n\n";
9862
9931
  };
9863
- const escapeBody = (text) => text.split("\n").map((l) => l.replace(/^(#+)/, "\\$1")).join("\n");
9932
+ const redactSecrets = (text) => String(text || "").replace(
9933
+ /\b(GH_TOKEN|GITHUB_TOKEN|API_KEY|SECRET|TOKEN|PASSWORD|PASS|PRIVATE_KEY)\s*=\s*[^\s`'"<>]+/gi,
9934
+ "$1=[REDACTED]"
9935
+ ).replace(/\bgh[pousr]_[A-Za-z0-9_]{20,}\b/g, "[REDACTED]").replace(/\b(sk-[A-Za-z0-9_-]{20,}|xox[baprs]-[A-Za-z0-9-]{20,})\b/g, "[REDACTED]");
9936
+ const escapeBody = (text) => redactSecrets(text).split("\n").map((l) => l.replace(/^(#+)/, "\\$1")).join("\n");
9864
9937
  let bootstrap = `# Bootstrap: ${companyName}
9865
9938
 
9866
9939
  `;
@@ -9875,7 +9948,7 @@ Read: \`docs/${doc}\`
9875
9948
  bootstrap += `## Company
9876
9949
 
9877
9950
  `;
9878
- bootstrap += `${companyDescription}
9951
+ bootstrap += `${escapeBody(companyDescription)}
9879
9952
 
9880
9953
  `;
9881
9954
  }
@@ -9899,6 +9972,75 @@ Read: \`docs/${doc}\`
9899
9972
  }
9900
9973
  }
9901
9974
  }
9975
+ const normalizeProjectWorkspace = (proj) => {
9976
+ const explicitWorkspace = proj && typeof proj.workspace === "object" && proj.workspace !== null ? proj.workspace : {};
9977
+ const sourceType = typeof explicitWorkspace.sourceType === "string" && explicitWorkspace.sourceType.trim() ? explicitWorkspace.sourceType.trim() : typeof proj?.workspaceSourceType === "string" && proj.workspaceSourceType.trim() ? proj.workspaceSourceType.trim() : typeof proj?.repoUrl === "string" && proj.repoUrl.trim() ? "git_repo" : "local_path";
9978
+ const localCwd = join(companyDir, "projects", toPascalCase(proj.name));
9979
+ const workspace = {
9980
+ sourceType,
9981
+ ...explicitWorkspace,
9982
+ isPrimary: explicitWorkspace.isPrimary ?? proj?.isPrimary ?? true
9983
+ };
9984
+ if (sourceType === "git_repo") {
9985
+ const repoUrl = explicitWorkspace.repoUrl || proj?.repoUrl;
9986
+ const repoRef = explicitWorkspace.repoRef || proj?.repoRef || proj?.defaultRef;
9987
+ const defaultRef = explicitWorkspace.defaultRef || proj?.defaultRef || repoRef;
9988
+ if (repoUrl) workspace.repoUrl = repoUrl;
9989
+ if (repoRef) workspace.repoRef = repoRef;
9990
+ if (defaultRef) workspace.defaultRef = defaultRef;
9991
+ delete workspace.cwd;
9992
+ } else {
9993
+ if (!workspace.cwd) workspace.cwd = localCwd;
9994
+ const trimmedSetup = typeof workspace.setupCommand === "string" ? workspace.setupCommand.trim() : "";
9995
+ if (!trimmedSetup || trimmedSetup === "git init -b main" || trimmedSetup === "git init") {
9996
+ workspace.setupCommand = "git init -b main && git -c user.email=bootstrap@paperclip.local -c user.name='Paperclip Bootstrap' commit --allow-empty -m 'chore: initialize repository'";
9997
+ }
9998
+ }
9999
+ return workspace;
10000
+ };
10001
+ const renderWorkspaceMetaFields = (workspace) => {
10002
+ const orderedKeys = ["sourceType", "cwd", "repoUrl", "repoRef", "defaultRef", "isPrimary"];
10003
+ const keys = [
10004
+ ...orderedKeys.filter((key) => workspace[key] !== void 0),
10005
+ ...Object.keys(workspace).filter((key) => !orderedKeys.includes(key))
10006
+ ];
10007
+ return keys.map((key) => [`workspace.${key}`, String(workspace[key])]);
10008
+ };
10009
+ const formatWorkspaceObject = (workspace) => {
10010
+ const orderedKeys = ["sourceType", "cwd", "repoUrl", "repoRef", "defaultRef", "isPrimary"];
10011
+ const entries = [
10012
+ ...orderedKeys.filter((key) => workspace[key] !== void 0).map((key) => [key, workspace[key]]),
10013
+ ...Object.entries(workspace).filter(([key]) => !orderedKeys.includes(key))
10014
+ ];
10015
+ const fields = entries.filter(([, value]) => value !== void 0 && value !== null && value !== "").map(([key, value]) => {
10016
+ if (typeof value === "boolean") return `${key}: ${value}`;
10017
+ return `${key}: "${String(value)}"`;
10018
+ });
10019
+ return `{ ${fields.join(", ")} }`;
10020
+ };
10021
+ const isFreshLocalRepo = (workspace) => workspace?.sourceType !== "git_repo";
10022
+ const effectiveExecutionPolicy = (proj, workspace) => {
10023
+ const policy = proj?.executionWorkspacePolicy;
10024
+ if (!policy || typeof policy !== "object") return null;
10025
+ if (policy.defaultMode === "isolated_workspace") {
10026
+ if (!enableIsolatedWorktrees || isFreshLocalRepo(workspace)) return null;
10027
+ }
10028
+ return policy;
10029
+ };
10030
+ const renderExecutionPolicyMetaFields = (proj, workspace) => {
10031
+ const policy = effectiveExecutionPolicy(proj, workspace);
10032
+ if (!policy) return [];
10033
+ const rows = [];
10034
+ if (policy.defaultMode) rows.push(["executionWorkspacePolicy.defaultMode", policy.defaultMode]);
10035
+ const strategy = policy.workspaceStrategy;
10036
+ if (strategy && typeof strategy === "object") {
10037
+ if (strategy.type)
10038
+ rows.push(["executionWorkspacePolicy.workspaceStrategy.type", strategy.type]);
10039
+ if (strategy.baseRef)
10040
+ rows.push(["executionWorkspacePolicy.workspaceStrategy.baseRef", strategy.baseRef]);
10041
+ }
10042
+ return rows;
10043
+ };
9902
10044
  const mainProject = resolvedProjects[0];
9903
10045
  const mainProjectName = mainProject?.name || companyName;
9904
10046
  if (resolvedProjects.length > 0) {
@@ -9906,14 +10048,13 @@ Read: \`docs/${doc}\`
9906
10048
 
9907
10049
  `;
9908
10050
  for (const proj of resolvedProjects) {
9909
- const projCwd = join(companyDir, "projects", toPascalCase(proj.name));
10051
+ const workspace = normalizeProjectWorkspace(proj);
9910
10052
  bootstrap += `### ${proj.name}
9911
10053
 
9912
10054
  `;
9913
10055
  bootstrap += renderMeta([
9914
- ["workspace.sourceType", "local_path"],
9915
- ["workspace.cwd", projCwd],
9916
- ["workspace.isPrimary", "true"],
10056
+ ...renderWorkspaceMetaFields(workspace),
10057
+ ...renderExecutionPolicyMetaFields(proj, workspace),
9917
10058
  [
9918
10059
  "goalIds",
9919
10060
  proj.goals?.length > 0 ? proj.goals.map((g) => `"${g}"`).join(", ") : void 0
@@ -9947,6 +10088,9 @@ Read: \`docs/${doc}\`
9947
10088
  }
9948
10089
  bootstrap += `## Agents
9949
10090
 
10091
+ `;
10092
+ bootstrap += `> **The Company Wizard has already created all agents listed below**, each with its full instructions bundle. Do NOT create new agents. Match them by \`metadata.templateRole\` when assigning issues; only re-create one if it is genuinely missing.
10093
+
9950
10094
  `;
9951
10095
  for (const role of rolesList) {
9952
10096
  const roleMeta = roleMetaByName.get(role) || {};
@@ -9998,6 +10142,8 @@ Read: \`docs/${doc}\`
9998
10142
  const explicitProjectRef = typeof issue.projectIdRef === "string" ? issue.projectIdRef : typeof issue.projectName === "string" ? issue.projectName : typeof issue.project === "string" ? issue.project : void 0;
9999
10143
  const resolvedProjectRef = explicitProjectRef || mainProjectName;
10000
10144
  const issueLabelNames = getIssueLabelNames(issue);
10145
+ const goalRefRaw = issue.goalId || issue.goalIdRef || issue.goal || issue.goalTitle;
10146
+ const goalRef = typeof goalRefRaw === "string" && goalRefRaw.trim().length > 0 ? goalRefRaw.trim() : void 0;
10001
10147
  for (const labelName of issueLabelNames) {
10002
10148
  if (!labelsByName.has(labelName)) {
10003
10149
  labelsByName.set(labelName, {
@@ -10016,8 +10162,13 @@ Read: \`docs/${doc}\`
10016
10162
  ["priority", issue.priority || "medium"],
10017
10163
  ["parentId", parentRef ? `\u2192 "${parentRef}"` : void 0],
10018
10164
  ["projectId", `\u2192 "${resolvedProjectRef}"`],
10165
+ ["goalId", goalRef ? `\u2192 "${goalRef}"` : void 0],
10019
10166
  ["labelIds", `\u2192 [${issueLabelNames.map((name) => `"${name}"`).join(", ")}]`]
10020
10167
  ]);
10168
+ const issueReviewGate = resolveReviewGate(issue.reviewGate);
10169
+ if (issueReviewGate) {
10170
+ bootstrap += renderReviewGate(issueReviewGate);
10171
+ }
10021
10172
  if (issue.description) {
10022
10173
  bootstrap += `${escapeBody(issue.description)}
10023
10174
 
@@ -10036,12 +10187,20 @@ Read: \`docs/${doc}\`
10036
10187
  bootstrap += `- Do not reopen \`done\` parent/subissues without an explicit reason in a comment.
10037
10188
  `;
10038
10189
  bootstrap += `- Do not reuse parent workspaces for subissues unless explicitly requested.
10039
-
10190
+ `;
10191
+ if (moduleNames.includes("pr-review")) {
10192
+ 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 reviewer/approver role to its agentId. Do not create separate child review issues and do not use @-mentions.
10193
+ `;
10194
+ }
10195
+ bootstrap += `
10040
10196
  `;
10041
10197
  }
10042
10198
  if (initialRoutines.length > 0) {
10043
10199
  bootstrap += `## Routines
10044
10200
 
10201
+ `;
10202
+ bootstrap += `> **The Company Wizard has already created the routines listed below** (with board authority, so each could be assigned to its owning agent). Do NOT recreate them. Note: an agent may only create routines assigned to itself, so never try to create another agent's routine.
10203
+
10045
10204
  `;
10046
10205
  for (const routine of initialRoutines) {
10047
10206
  bootstrap += `### ${routine.title}
@@ -10080,23 +10239,25 @@ Read: \`docs/${doc}\`
10080
10239
  `;
10081
10240
  }
10082
10241
  for (const proj of resolvedProjects) {
10083
- const projCwd = join(companyDir, "projects", toPascalCase(proj.name));
10242
+ const workspace = normalizeProjectWorkspace(proj);
10084
10243
  const goalLinks = proj.goals?.length > 0 ? `, goalIds \u2192 [${proj.goals.map((g) => `"${g}"`).join(", ")}]` : "";
10085
- bootstrap += `${stepN++}. **Create project** "${proj.name}" (workspace: { sourceType: "local_path", cwd: \`${projCwd}\`, isPrimary: true }${goalLinks})
10244
+ const activePolicy = effectiveExecutionPolicy(proj, workspace);
10245
+ const policy = activePolicy?.defaultMode ? `, executionWorkspacePolicy.defaultMode: "${activePolicy.defaultMode}"` : "";
10246
+ bootstrap += `${stepN++}. **Create project** "${proj.name}" (workspace: ${formatWorkspaceObject(workspace)}${policy}${goalLinks})
10086
10247
  `;
10087
10248
  }
10088
10249
  if (bootstrapLabels.length > 0) {
10089
10250
  bootstrap += `${stepN++}. **Create labels** \u2014 create each label exactly as listed in the Labels section before creating issues
10090
10251
  `;
10091
10252
  }
10092
- bootstrap += `${stepN++}. **Create agents** \u2014 hire missing agents via governance using the adapter/runtime fields listed above; reuse/update an existing agent with the same metadata.templateRole instead of duplicating it
10253
+ bootstrap += `${stepN++}. **Agents already created** \u2014 the Company Wizard provisioned every agent above with its full instructions bundle. Match them by metadata.templateRole when assigning issues; only hire via governance if one is genuinely missing
10093
10254
  `;
10094
10255
  if (initialIssues.length > 0) {
10095
10256
  bootstrap += `${stepN++}. **Create issues** \u2014 every issue, including subtasks, must carry explicit projectId; subtasks also require parentId
10096
10257
  `;
10097
10258
  }
10098
10259
  if (initialRoutines.length > 0) {
10099
- bootstrap += `${stepN++}. **Create routines** with cron triggers as listed above
10260
+ bootstrap += `${stepN++}. **Routines already created** \u2014 the Company Wizard provisioned the routines above (with their cron triggers) using board authority. Do not recreate them; an agent can only create routines assigned to itself
10100
10261
  `;
10101
10262
  }
10102
10263
  bootstrap += `${stepN}. **Start CEO heartbeat** (one-time initial wakeup)
@@ -10220,6 +10381,12 @@ var PaperclipClient = class {
10220
10381
  return false;
10221
10382
  }
10222
10383
  }
10384
+ /**
10385
+ * Read instance-wide experimental settings (including enableIsolatedWorkspaces).
10386
+ */
10387
+ async getInstanceExperimentalSettings() {
10388
+ return this._fetch("/api/instance/settings/experimental");
10389
+ }
10223
10390
  async createCompany({ name, description }) {
10224
10391
  return this._fetch("/api/companies", {
10225
10392
  method: "POST",
@@ -10406,6 +10573,12 @@ var PaperclipClient = class {
10406
10573
  })
10407
10574
  });
10408
10575
  }
10576
+ async updateIssue(issueId, updates = {}) {
10577
+ return this._fetch(`/api/issues/${issueId}`, {
10578
+ method: "PATCH",
10579
+ body: JSON.stringify(updates || {})
10580
+ });
10581
+ }
10409
10582
  async createRoutine(companyId, {
10410
10583
  title,
10411
10584
  description,
@@ -10504,14 +10677,16 @@ async function loadModules(templatesDir) {
10504
10677
  for (const dir of dirs) {
10505
10678
  if (!dir.isDirectory()) continue;
10506
10679
  const moduleJson = await readJson2(join2(modulesDir, dir.name, "module.meta.json"));
10507
- const readmePath = join2(modulesDir, dir.name, "README.md");
10508
- let description = "";
10509
- if (await exists2(readmePath)) {
10510
- const content = await readFile2(readmePath, "utf-8");
10511
- const descLine = content.split("\n").find((l) => l.length > 0 && !l.startsWith("#"));
10512
- description = descLine?.trim() || "";
10513
- }
10514
- const mod = { name: dir.name, description, ...moduleJson || {} };
10680
+ const mod = { name: dir.name, ...moduleJson || {} };
10681
+ if (!mod.description) {
10682
+ const readmePath = join2(modulesDir, dir.name, "README.md");
10683
+ if (await exists2(readmePath)) {
10684
+ const content = await readFile2(readmePath, "utf-8");
10685
+ const descLine = content.split("\n").find((l) => l.length > 0 && !l.startsWith("#"));
10686
+ mod.description = descLine?.trim() || "";
10687
+ }
10688
+ }
10689
+ if (mod.description === void 0) mod.description = "";
10515
10690
  if (mod.tasks && !mod.issues) {
10516
10691
  mod.issues = mod.tasks;
10517
10692
  delete mod.tasks;
@@ -10586,6 +10761,39 @@ function collectGoals(preset, modules, selectedModules) {
10586
10761
  }
10587
10762
  return goals;
10588
10763
  }
10764
+ function resolveEffectiveModules(preset, modules, selectedModules) {
10765
+ const known = new Set(modules.map((m) => m.name));
10766
+ const requiresByName = new Map(
10767
+ modules.map((m) => [m.name, Array.isArray(m.requires) ? m.requires : []])
10768
+ );
10769
+ const effective = /* @__PURE__ */ new Set();
10770
+ const queue = [];
10771
+ const add = (name) => {
10772
+ if (typeof name !== "string" || !known.has(name) || effective.has(name)) return;
10773
+ effective.add(name);
10774
+ queue.push(name);
10775
+ };
10776
+ for (const moduleName of Array.isArray(preset?.modules) ? preset.modules : []) {
10777
+ add(moduleName);
10778
+ }
10779
+ for (const moduleName of selectedModules ?? []) {
10780
+ add(moduleName);
10781
+ }
10782
+ while (queue.length > 0) {
10783
+ const moduleName = queue.shift();
10784
+ for (const dep of requiresByName.get(moduleName) ?? []) {
10785
+ add(dep);
10786
+ }
10787
+ }
10788
+ return [...effective];
10789
+ }
10790
+ function collectPresetBootstrapData(preset) {
10791
+ return {
10792
+ labels: Array.isArray(preset?.labels) ? preset.labels.map((label) => ({ ...label })) : [],
10793
+ issues: Array.isArray(preset?.issues) ? preset.issues.map((issue) => ({ ...issue })) : [],
10794
+ routines: Array.isArray(preset?.routines) ? preset.routines.map((routine) => ({ ...routine })) : []
10795
+ };
10796
+ }
10589
10797
 
10590
10798
  // src/worker.ts
10591
10799
  var __dirname = path2.dirname(fileURLToPath2(import.meta.url));
@@ -10656,6 +10864,61 @@ async function ensureTemplatesDir(cfg) {
10656
10864
  );
10657
10865
  }
10658
10866
  }
10867
+ function isLikelyAnthropicApiKey(value) {
10868
+ return value.startsWith("sk-ant-");
10869
+ }
10870
+ async function resolveAnthropicApiKey(ctx, configuredValue) {
10871
+ if (typeof configuredValue !== "string") return "";
10872
+ const value = configuredValue.trim();
10873
+ if (!value) return "";
10874
+ if (isLikelyAnthropicApiKey(value)) return value;
10875
+ try {
10876
+ const resolved = await ctx.secrets.resolve(value);
10877
+ return resolved.trim();
10878
+ } catch (err) {
10879
+ const detail = err instanceof Error ? err.message : String(err);
10880
+ throw new Error(
10881
+ `Anthropic API key could not be resolved. Re-save the plugin setting with a valid Anthropic API key (sk-ant-...). ${detail}`
10882
+ );
10883
+ }
10884
+ }
10885
+ async function callAnthropic(apiKey, system, messages) {
10886
+ try {
10887
+ const response = await fetch("https://api.anthropic.com/v1/messages", {
10888
+ method: "POST",
10889
+ headers: {
10890
+ "Content-Type": "application/json",
10891
+ "x-api-key": apiKey,
10892
+ "anthropic-version": "2023-06-01"
10893
+ },
10894
+ body: JSON.stringify({
10895
+ model: "claude-opus-4-8",
10896
+ // High ceiling so the wizard's final config — which reproduces the user's
10897
+ // full spec in the first goal — is never truncated mid-JSON. This is only
10898
+ // an upper bound; generation time tracks the tokens actually produced.
10899
+ max_tokens: 32768,
10900
+ ...system ? { system } : {},
10901
+ messages
10902
+ })
10903
+ });
10904
+ if (!response.ok) {
10905
+ const body = await response.text();
10906
+ return { text: "", error: `Anthropic API error (${response.status}): ${body}` };
10907
+ }
10908
+ const data = await response.json();
10909
+ return { text: data.content?.[0]?.text || "" };
10910
+ } catch (err) {
10911
+ return { text: "", error: err instanceof Error ? err.message : String(err) };
10912
+ }
10913
+ }
10914
+ var aiChatJobs = /* @__PURE__ */ new Map();
10915
+ var AI_CHAT_JOB_TTL_MS = 10 * 60 * 1e3;
10916
+ function sweepAiChatJobs() {
10917
+ const now = Date.now();
10918
+ for (const [id, job] of aiChatJobs) {
10919
+ if (now - job.createdAt > AI_CHAT_JOB_TTL_MS) aiChatJobs.delete(id);
10920
+ }
10921
+ }
10659
10922
  function loadJsonFiles(dir, filename) {
10660
10923
  const items = [];
10661
10924
  const errors = [];
@@ -10701,10 +10964,37 @@ function loadTemplates(templatesDir) {
10701
10964
  loadErrors: [...presetLoad.errors, ...moduleLoad.errors, ...roleLoad.errors]
10702
10965
  };
10703
10966
  }
10967
+ function cfgBool(cfg, key) {
10968
+ const raw = cfg[key];
10969
+ return raw === true || typeof raw === "string" && raw.toLowerCase() === "true";
10970
+ }
10971
+ async function resolveEnableIsolatedWorkspacesFromInstance(cfg, log) {
10972
+ const paperclipUrl = cfg.paperclipUrl || process.env.PAPERCLIP_PUBLIC_URL || "http://localhost:3100";
10973
+ const paperclipEmail = cfg.paperclipEmail || "";
10974
+ const paperclipPassword = cfg.paperclipPassword || "";
10975
+ const instanceClient = new PaperclipClient(paperclipUrl, {
10976
+ email: paperclipEmail,
10977
+ password: paperclipPassword
10978
+ });
10979
+ try {
10980
+ await instanceClient.connect();
10981
+ const experimentalSettings = await instanceClient.getInstanceExperimentalSettings();
10982
+ return experimentalSettings?.enableIsolatedWorkspaces === true;
10983
+ } catch (err) {
10984
+ if (log) {
10985
+ const detail = err instanceof Error ? err.message : String(err);
10986
+ log(`\u26A0 Could not read instance experimental settings: ${detail}. Using fallback false.`);
10987
+ }
10988
+ return false;
10989
+ }
10990
+ }
10704
10991
  function resolveCompaniesDir(cfg) {
10705
10992
  if (cfg.companiesDir) return cfg.companiesDir;
10706
10993
  return path2.join(os.homedir(), ".paperclip", "instances", "default", "companies");
10707
10994
  }
10995
+ function formatRoleName(role) {
10996
+ return role.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
10997
+ }
10708
10998
  function collectInstructionFiles(rootDir) {
10709
10999
  const out = {};
10710
11000
  if (!fs2.existsSync(rootDir)) return out;
@@ -10815,20 +11105,28 @@ var plugin = definePlugin({
10815
11105
  loadModules(templatesDir)
10816
11106
  ]);
10817
11107
  const selectedPreset = presets.find((p) => p.name === params.presetName) || null;
10818
- const goals = collectGoals(
11108
+ const effectiveModules = resolveEffectiveModules(
10819
11109
  selectedPreset,
10820
11110
  allModules,
10821
- new Set(params.selectedModules ?? [])
11111
+ params.selectedModules ?? []
10822
11112
  );
11113
+ const goals = collectGoals(selectedPreset, allModules, new Set(effectiveModules));
11114
+ const presetBootstrapData = collectPresetBootstrapData(selectedPreset);
10823
11115
  const previewGoals = Array.isArray(params.goals) ? params.goals : params.goal ? [params.goal] : [];
10824
11116
  const previewProjects = Array.isArray(params.projects) ? params.projects : [];
11117
+ const previewIssues = Array.isArray(params.issues) ? params.issues : [];
10825
11118
  const result = await assembleCompany({
10826
11119
  companyName,
10827
11120
  userGoals: previewGoals,
10828
11121
  userProjects: previewProjects,
10829
- moduleNames: params.selectedModules ?? [],
11122
+ moduleNames: effectiveModules,
10830
11123
  extraRoleNames: params.selectedRoles ?? [],
10831
11124
  inlineGoals: goals,
11125
+ userIssues: previewIssues,
11126
+ presetIssues: presetBootstrapData.issues,
11127
+ presetRoutines: presetBootstrapData.routines,
11128
+ presetLabels: presetBootstrapData.labels,
11129
+ enableIsolatedWorktrees: await resolveEnableIsolatedWorkspacesFromInstance(cfg),
10832
11130
  outputDir: tmpDir,
10833
11131
  templatesDir
10834
11132
  });
@@ -10863,34 +11161,42 @@ var plugin = definePlugin({
10863
11161
  });
10864
11162
  ctx.actions.register("ai-chat", async (params) => {
10865
11163
  try {
11164
+ if (params.mode === "poll") {
11165
+ const jobId = typeof params.jobId === "string" ? params.jobId : "";
11166
+ const job = jobId ? aiChatJobs.get(jobId) : void 0;
11167
+ if (!job) {
11168
+ return {
11169
+ text: "",
11170
+ status: "error",
11171
+ error: "Unknown or expired generation job. Please retry."
11172
+ };
11173
+ }
11174
+ if (job.status === "pending") return { status: "pending" };
11175
+ aiChatJobs.delete(jobId);
11176
+ if (job.status === "error") return { text: "", status: "error", error: job.error };
11177
+ return { text: job.text, status: "done" };
11178
+ }
10866
11179
  const cfg = await ctx.config.get() ?? {};
10867
- const apiKey = cfg.anthropicApiKey || "";
11180
+ const apiKey = await resolveAnthropicApiKey(ctx, cfg.anthropicApiKey);
10868
11181
  if (!apiKey) {
10869
11182
  return {
10870
11183
  text: "",
10871
11184
  error: "Anthropic API key not configured. Add it in plugin settings (anthropicApiKey)."
10872
11185
  };
10873
11186
  }
10874
- const response = await fetch("https://api.anthropic.com/v1/messages", {
10875
- method: "POST",
10876
- headers: {
10877
- "Content-Type": "application/json",
10878
- "x-api-key": apiKey,
10879
- "anthropic-version": "2023-06-01"
10880
- },
10881
- body: JSON.stringify({
10882
- model: "claude-sonnet-4-20250514",
10883
- max_tokens: 8192,
10884
- ...params.system ? { system: params.system } : {},
10885
- messages: params.messages
10886
- })
10887
- });
10888
- if (!response.ok) {
10889
- const body = await response.text();
10890
- return { text: "", error: `Anthropic API error (${response.status}): ${body}` };
11187
+ if (params.mode === "start") {
11188
+ sweepAiChatJobs();
11189
+ const jobId = `aichat-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
11190
+ aiChatJobs.set(jobId, { status: "pending", createdAt: Date.now() });
11191
+ void callAnthropic(apiKey, params.system, params.messages).then((result) => {
11192
+ aiChatJobs.set(
11193
+ jobId,
11194
+ result.error ? { status: "error", error: result.error, createdAt: Date.now() } : { status: "done", text: result.text, createdAt: Date.now() }
11195
+ );
11196
+ });
11197
+ return { jobId, status: "pending" };
10891
11198
  }
10892
- const data = await response.json();
10893
- return { text: data.content?.[0]?.text || "" };
11199
+ return await callAnthropic(apiKey, params.system, params.messages);
10894
11200
  } catch (err) {
10895
11201
  return { text: "", error: err instanceof Error ? err.message : String(err) };
10896
11202
  }
@@ -10898,7 +11204,8 @@ var plugin = definePlugin({
10898
11204
  ctx.actions.register("check-ai-config", async () => {
10899
11205
  try {
10900
11206
  const cfg = await ctx.config.get() ?? {};
10901
- if (!cfg.anthropicApiKey) {
11207
+ const apiKey = await resolveAnthropicApiKey(ctx, cfg.anthropicApiKey);
11208
+ if (!apiKey) {
10902
11209
  return {
10903
11210
  ok: false,
10904
11211
  error: "Anthropic API key not configured. Add it in plugin settings (anthropicApiKey)."
@@ -10920,8 +11227,11 @@ var plugin = definePlugin({
10920
11227
  const paperclipUrl = cfg.paperclipUrl || process.env.PAPERCLIP_PUBLIC_URL || "http://localhost:3100";
10921
11228
  const paperclipEmail = cfg.paperclipEmail || "";
10922
11229
  const paperclipPassword = cfg.paperclipPassword || "";
10923
- const rawDisableBoardApproval = cfg.disableBoardApprovalOnNewCompanies;
10924
- const disableBoardApprovalOnNewCompanies = rawDisableBoardApproval === true || typeof rawDisableBoardApproval === "string" && rawDisableBoardApproval.toLowerCase() === "true";
11230
+ const disableBoardApprovalOnNewCompanies = cfgBool(
11231
+ cfg,
11232
+ "disableBoardApprovalOnNewCompanies"
11233
+ );
11234
+ const enableIsolatedWorktrees = await resolveEnableIsolatedWorkspacesFromInstance(cfg, log);
10925
11235
  const companyName = typeof params.companyName === "string" ? params.companyName.trim() : "";
10926
11236
  const existingCompanyId = typeof params.existingCompanyId === "string" && params.existingCompanyId.trim() ? params.existingCompanyId.trim() : "";
10927
11237
  if (!companyName) return { error: "companyName is required", logs };
@@ -10935,25 +11245,33 @@ var plugin = definePlugin({
10935
11245
  (Array.isArray(roleTemplates) ? roleTemplates : []).filter((role) => role && typeof role.name === "string").map((role) => [role.name, role])
10936
11246
  );
10937
11247
  const selectedPreset = presets.find((p) => p.name === params.presetName) || null;
10938
- const goals = collectGoals(
11248
+ const effectiveModules = resolveEffectiveModules(
10939
11249
  selectedPreset,
10940
11250
  allModules,
10941
- new Set(params.selectedModules ?? [])
11251
+ params.selectedModules ?? []
10942
11252
  );
11253
+ const goals = collectGoals(selectedPreset, allModules, new Set(effectiveModules));
11254
+ const presetBootstrapData = collectPresetBootstrapData(selectedPreset);
10943
11255
  const outputDir = resolveCompaniesDir(cfg);
10944
11256
  fs2.mkdirSync(outputDir, { recursive: true });
10945
11257
  log("Assembling company workspace...");
10946
11258
  const companyDescription = typeof params.companyDescription === "string" ? params.companyDescription.trim() : "";
10947
11259
  const userGoals = Array.isArray(params.goals) ? params.goals : params.goal ? [params.goal] : [];
10948
11260
  const userProjects = Array.isArray(params.projects) ? params.projects : [];
11261
+ const userIssues = Array.isArray(params.issues) ? params.issues : [];
10949
11262
  const assembleResult = await assembleCompany({
10950
11263
  companyName,
10951
11264
  companyDescription,
10952
11265
  userGoals,
10953
11266
  userProjects,
10954
- moduleNames: params.selectedModules ?? [],
11267
+ moduleNames: effectiveModules,
10955
11268
  extraRoleNames: params.selectedRoles ?? [],
10956
11269
  inlineGoals: goals,
11270
+ userIssues,
11271
+ presetIssues: presetBootstrapData.issues,
11272
+ presetRoutines: presetBootstrapData.routines,
11273
+ presetLabels: presetBootstrapData.labels,
11274
+ enableIsolatedWorktrees,
10957
11275
  outputDir,
10958
11276
  templatesDir,
10959
11277
  onProgress: log
@@ -11018,6 +11336,7 @@ var plugin = definePlugin({
11018
11336
  }
11019
11337
  }
11020
11338
  let ceoAgentId;
11339
+ const teamAgentIds = {};
11021
11340
  let bootstrapIssue;
11022
11341
  try {
11023
11342
  const userCeoAdapter = params.ceoAdapter || {};
@@ -11125,18 +11444,125 @@ var plugin = definePlugin({
11125
11444
  fallbackEntryContent: ceoPromptTemplate,
11126
11445
  log
11127
11446
  });
11447
+ const teamRoles = [...assembleResult.allRoles ?? []].filter(
11448
+ (r) => r && r !== "ceo"
11449
+ );
11450
+ let existingByTemplateRole = /* @__PURE__ */ new Map();
11451
+ if (existingCompanyId && teamRoles.length > 0) {
11452
+ const agents = await client.listAgents(companyId);
11453
+ if (Array.isArray(agents)) {
11454
+ for (const a of agents) {
11455
+ const tr = a?.metadata?.templateRole;
11456
+ if (tr && a?.status !== "terminated" && a?.role !== "ceo") {
11457
+ existingByTemplateRole.set(tr, a);
11458
+ }
11459
+ }
11460
+ }
11461
+ }
11462
+ for (const roleName of teamRoles) {
11463
+ const roleTemplate = roleTemplateByName.get(roleName) || {};
11464
+ const paperclipRole = typeof roleTemplate.paperclipRole === "string" && roleTemplate.paperclipRole.trim() ? roleTemplate.paperclipRole.trim() : "general";
11465
+ const roleTitle = typeof roleTemplate.title === "string" && roleTemplate.title.trim() ? roleTemplate.title.trim() : formatRoleName(roleName);
11466
+ const roleDescription = typeof roleTemplate.description === "string" && roleTemplate.description.trim() ? roleTemplate.description.trim() : void 0;
11467
+ const roleMetadata = {
11468
+ templateRole: roleName,
11469
+ ...roleDescription ? { description: roleDescription } : {}
11470
+ };
11471
+ const roleRuntimeConfig = buildWorkerAgentRuntimeConfig();
11472
+ const roleAdapterConfig = buildCeoAdapterConfig({
11473
+ userCeoAdapter,
11474
+ companyDir,
11475
+ roleAdapterOverrides: assembleResult.roleAdapterOverrides?.get(roleName) ?? {}
11476
+ });
11477
+ const roleInstructionsDir = path2.join(companyDir, "agents", roleName);
11478
+ const roleInstructionFiles = collectInstructionFiles(roleInstructionsDir);
11479
+ const roleInstructionsBundle = Object.keys(roleInstructionFiles).length > 0 ? { entryFile: "AGENTS.md", files: roleInstructionFiles } : void 0;
11480
+ const existingAgent = existingByTemplateRole.get(roleName);
11481
+ if (existingAgent?.id) {
11482
+ try {
11483
+ await client.updateAgent(existingAgent.id, {
11484
+ adapterType,
11485
+ adapterConfig: roleAdapterConfig,
11486
+ runtimeConfig: roleRuntimeConfig,
11487
+ metadata: { ...existingAgent.metadata ?? {}, ...roleMetadata },
11488
+ ...!existingAgent.title && roleTitle ? { title: roleTitle } : {},
11489
+ ...!existingAgent.capabilities && roleDescription ? { capabilities: roleDescription } : {}
11490
+ });
11491
+ log(`\u2713 Reusing ${roleTitle} (${existingAgent.id})`);
11492
+ } catch (err) {
11493
+ log(
11494
+ `\u26A0 Could not update ${roleTitle}: ${err instanceof Error ? err.message : String(err)}`
11495
+ );
11496
+ }
11497
+ teamAgentIds[roleName] = existingAgent.id;
11498
+ continue;
11499
+ }
11500
+ const roleAgent = await client.createAgent(companyId, {
11501
+ name: roleTitle,
11502
+ role: paperclipRole,
11503
+ title: roleTitle,
11504
+ ...roleDescription ? { capabilities: roleDescription } : {},
11505
+ metadata: roleMetadata,
11506
+ reportsTo: ceoAgentId,
11507
+ adapterType,
11508
+ adapterConfig: roleAdapterConfig,
11509
+ instructionsBundle: roleInstructionsBundle,
11510
+ runtimeConfig: roleRuntimeConfig
11511
+ });
11512
+ teamAgentIds[roleName] = roleAgent.id;
11513
+ log(`\u2713 ${roleTitle} created (${roleAgent.id})`);
11514
+ if (roleAgent?._pendingApprovalId) {
11515
+ log(
11516
+ `\u26A0 ${roleTitle} hire pending approval: ${roleAgent._pendingApprovalId}. Approve it in the board.`
11517
+ );
11518
+ if (roleAgent._approvalAutoApproveError) {
11519
+ log(` Auto-approve failed: ${roleAgent._approvalAutoApproveError}`);
11520
+ }
11521
+ }
11522
+ }
11523
+ if (!existingCompanyId) {
11524
+ const routines = Array.isArray(assembleResult.initialRoutines) ? assembleResult.initialRoutines : [];
11525
+ for (const routine of routines) {
11526
+ const title = typeof routine.title === "string" && routine.title.trim() ? routine.title.trim() : typeof routine.name === "string" ? routine.name.trim() : "";
11527
+ if (!title) continue;
11528
+ const role = routine.assignTo;
11529
+ const assigneeAgentId = !role || role === "ceo" ? ceoAgentId : teamAgentIds[role] ?? ceoAgentId;
11530
+ try {
11531
+ const createdRoutine = await client.createRoutine(companyId, {
11532
+ title,
11533
+ description: routine.description,
11534
+ assigneeAgentId,
11535
+ priority: routine.priority || "medium",
11536
+ concurrencyPolicy: routine.concurrencyPolicy || "skip_if_active"
11537
+ });
11538
+ if (routine.schedule && createdRoutine?.id) {
11539
+ await client.createRoutineTrigger(createdRoutine.id, {
11540
+ kind: "schedule",
11541
+ cronExpression: routine.schedule,
11542
+ timezone: "UTC"
11543
+ });
11544
+ }
11545
+ log(
11546
+ `\u2713 Routine "${title}" created${routine.schedule ? ` (${routine.schedule})` : ""}`
11547
+ );
11548
+ } catch (err) {
11549
+ log(
11550
+ `\u26A0 Could not create routine "${title}": ${err instanceof Error ? err.message : String(err)}`
11551
+ );
11552
+ }
11553
+ }
11554
+ }
11128
11555
  const bootstrapDescription = fs2.readFileSync(
11129
11556
  path2.join(companyDir, "BOOTSTRAP.md"),
11130
11557
  "utf-8"
11131
11558
  );
11132
11559
  log("Creating bootstrap task for CEO...");
11133
- const issue = await ctx.issues.create({
11134
- companyId,
11560
+ const issue = await client.createIssue(companyId, {
11135
11561
  title: `Bootstrap ${company.name || companyName}`,
11136
11562
  description: bootstrapDescription,
11137
- assigneeAgentId: ceoAgentId
11563
+ assigneeAgentId: ceoAgentId,
11564
+ status: "todo"
11138
11565
  });
11139
- await ctx.issues.update(issue.id, { status: "todo" }, companyId);
11140
11566
  bootstrapIssue = issue;
11141
11567
  log(`\u2713 Bootstrap task created: ${bootstrapIssue.identifier || bootstrapIssue.id}`);
11142
11568
  } catch (err) {
@@ -11166,7 +11592,7 @@ var plugin = definePlugin({
11166
11592
  companyId,
11167
11593
  issuePrefix: company.issuePrefix,
11168
11594
  paperclipUrl,
11169
- agentIds: { ceo: ceoAgentId },
11595
+ agentIds: { ceo: ceoAgentId, ...teamAgentIds },
11170
11596
  issueIds: [bootstrapIssue.id],
11171
11597
  logs
11172
11598
  };