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

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 +59 -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 +1151 -559
  7. package/dist/ui/index.js.map +4 -4
  8. package/dist/worker.js +702 -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 +5 -2
  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) {
@@ -9436,6 +9373,17 @@ async function readJson(p) {
9436
9373
  function toPascalCase(name) {
9437
9374
  return name.replace(/[^a-zA-Z0-9\s\-_]/g, "").split(/[\s\-_]+/).filter(Boolean).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join("");
9438
9375
  }
9376
+ function normalizeExecutionBaseRef(ref, fallbackRef) {
9377
+ const candidates = [ref, fallbackRef].filter(
9378
+ (value) => typeof value === "string" && value.trim()
9379
+ );
9380
+ const selected = candidates.length > 0 ? String(candidates[0]).trim() : "";
9381
+ if (!selected) return "origin/main";
9382
+ if (selected.startsWith("origin/") || selected.startsWith("refs/")) {
9383
+ return selected;
9384
+ }
9385
+ return `origin/${selected}`;
9386
+ }
9439
9387
  async function assembleCompany({
9440
9388
  companyName,
9441
9389
  companyDescription = "",
@@ -9444,6 +9392,11 @@ async function assembleCompany({
9444
9392
  moduleNames,
9445
9393
  extraRoleNames,
9446
9394
  inlineGoals = [],
9395
+ userIssues = [],
9396
+ presetIssues = [],
9397
+ presetRoutines = [],
9398
+ presetLabels = [],
9399
+ enableIsolatedWorktrees = false,
9447
9400
  outputDir,
9448
9401
  templatesDir,
9449
9402
  onProgress = () => {
@@ -9548,9 +9501,20 @@ async function assembleCompany({
9548
9501
  }
9549
9502
  onProgress(`+ agents/${roleName}/ (role)`);
9550
9503
  }
9551
- const initialIssues = [];
9552
- const initialRoutines = [];
9504
+ const initialIssues = Array.isArray(presetIssues) ? presetIssues.map((issue) => ({ ...issue, source: issue.source || "preset" })) : [];
9505
+ const initialRoutines = Array.isArray(presetRoutines) ? presetRoutines.map((routine) => ({ ...routine, source: routine.source || "preset" })) : [];
9506
+ const explicitBootstrapLabels = Array.isArray(presetLabels) ? [...presetLabels] : [];
9553
9507
  const roleAdapterOverrides = /* @__PURE__ */ new Map();
9508
+ const docRoleMap = /* @__PURE__ */ new Map();
9509
+ const addDocRoles = (docName, roles) => {
9510
+ const set = docRoleMap.get(docName) ?? /* @__PURE__ */ new Set();
9511
+ for (const r of roles) set.add(r);
9512
+ docRoleMap.set(docName, set);
9513
+ };
9514
+ const normalizeIssueTitle = (title) => String(title || "").trim().toLowerCase();
9515
+ const seenIssueTitles = new Set(
9516
+ initialIssues.map((issue) => normalizeIssueTitle(issue.title)).filter(Boolean)
9517
+ );
9554
9518
  const resolveAssignee = (assignee, moduleJson) => {
9555
9519
  if (assignee?.startsWith("capability:")) {
9556
9520
  const capName = assignee.slice("capability:".length);
@@ -9561,6 +9525,55 @@ async function assembleCompany({
9561
9525
  }
9562
9526
  return assignee;
9563
9527
  };
9528
+ const resolveReviewGate = (reviewGate) => {
9529
+ if (!reviewGate || typeof reviewGate !== "object") return null;
9530
+ const reviewersRaw = Array.isArray(reviewGate.reviewers) ? reviewGate.reviewers : [];
9531
+ const reviewers = [];
9532
+ const seen = /* @__PURE__ */ new Set();
9533
+ for (const role of reviewersRaw) {
9534
+ if (typeof role !== "string") continue;
9535
+ if (!allRoles.has(role)) continue;
9536
+ if (seen.has(role)) continue;
9537
+ seen.add(role);
9538
+ reviewers.push(role);
9539
+ }
9540
+ const approver = typeof reviewGate.approver === "string" && allRoles.has(reviewGate.approver) ? reviewGate.approver : void 0;
9541
+ if (approver) {
9542
+ const idx = reviewers.indexOf(approver);
9543
+ if (idx !== -1) reviewers.splice(idx, 1);
9544
+ }
9545
+ if (reviewers.length === 0 && !approver) return null;
9546
+ return { reviewers, approver };
9547
+ };
9548
+ const renderReviewGate = (gate) => {
9549
+ const stages = [];
9550
+ for (const role of gate.reviewers) {
9551
+ stages.push(` - stage ${stages.length + 1} (review) \u2192 assign ${JSON.stringify(role)}`);
9552
+ }
9553
+ if (gate.approver) {
9554
+ stages.push(
9555
+ ` - stage ${stages.length + 1} (approval) \u2192 assign ${JSON.stringify(gate.approver)}`
9556
+ );
9557
+ }
9558
+ return `- **executionPolicy** (set when creating this issue; resolve each role to its agentId):
9559
+ ${stages.join("\n")}
9560
+
9561
+ `;
9562
+ };
9563
+ const isFoundationIssue = (issue) => issue?.bootstrapPhase === "foundation" || issue?.phase === "foundation" || issue?.bootstrapOrder === "foundation" || issue?.foundation === true;
9564
+ const resolvedUserIssues = [];
9565
+ for (const issue of Array.isArray(userIssues) ? userIssues : []) {
9566
+ if (!issue || !issue.title) continue;
9567
+ const titleKey = normalizeIssueTitle(issue.title);
9568
+ if (titleKey && seenIssueTitles.has(titleKey)) continue;
9569
+ if (titleKey) seenIssueTitles.add(titleKey);
9570
+ resolvedUserIssues.push({
9571
+ ...issue,
9572
+ assignTo: resolveAssignee(issue.assignTo, null),
9573
+ source: "user"
9574
+ });
9575
+ }
9576
+ initialIssues.unshift(...resolvedUserIssues);
9564
9577
  for (const moduleName of moduleNames) {
9565
9578
  const moduleDir = join(templatesDir, "modules", moduleName);
9566
9579
  if (!await exists(moduleDir)) {
@@ -9575,8 +9588,17 @@ async function assembleCompany({
9575
9588
  continue;
9576
9589
  }
9577
9590
  }
9591
+ if (Array.isArray(moduleJson?.labels)) {
9592
+ explicitBootstrapLabels.push(...moduleJson.labels);
9593
+ }
9578
9594
  const moduleIssues = moduleJson?.issues || moduleJson?.tasks || [];
9579
9595
  for (const issue of moduleIssues) {
9596
+ const titleKey = normalizeIssueTitle(issue.title);
9597
+ if (titleKey && seenIssueTitles.has(titleKey)) {
9598
+ onProgress(`\u25CB issue "${issue.title}" (already provided by preset or earlier module)`);
9599
+ continue;
9600
+ }
9601
+ if (titleKey) seenIssueTitles.add(titleKey);
9580
9602
  initialIssues.push({
9581
9603
  ...issue,
9582
9604
  assignTo: resolveAssignee(issue.assignTo, moduleJson),
@@ -9595,8 +9617,21 @@ async function assembleCompany({
9595
9617
  const docsDir = join(moduleDir, "docs");
9596
9618
  if (await exists(docsDir)) {
9597
9619
  await copyDir(docsDir, join(companyDir, "docs"));
9620
+ const moduleRoles = /* @__PURE__ */ new Set();
9621
+ for (const cap of moduleJson?.capabilities ?? []) {
9622
+ for (const owner of cap.owners ?? []) if (allRoles.has(owner)) moduleRoles.add(owner);
9623
+ }
9624
+ for (const issue of moduleIssues) {
9625
+ if (issue.assignTo && allRoles.has(issue.assignTo)) moduleRoles.add(issue.assignTo);
9626
+ }
9627
+ for (const routine of moduleJson?.routines ?? []) {
9628
+ if (routine.assignTo && allRoles.has(routine.assignTo)) moduleRoles.add(routine.assignTo);
9629
+ }
9630
+ for (const r of moduleJson?.activatesWithRoles ?? []) if (allRoles.has(r)) moduleRoles.add(r);
9631
+ const rolesForDocs = moduleRoles.size > 0 ? moduleRoles : /* @__PURE__ */ new Set(["*"]);
9598
9632
  const docs = await readdir(docsDir);
9599
9633
  for (const doc of docs) {
9634
+ addDocRoles(doc, rolesForDocs);
9600
9635
  onProgress(`+ docs/${doc} (${moduleName})`);
9601
9636
  }
9602
9637
  }
@@ -9711,25 +9746,53 @@ Read and follow: \`$AGENT_HOME/skills/${skillFile}\`
9711
9746
  }
9712
9747
  const finalDocsDir = join(companyDir, "docs");
9713
9748
  if (await exists(finalDocsDir)) {
9714
- const docs = await readdir(finalDocsDir);
9749
+ const docs = (await readdir(finalDocsDir)).sort();
9715
9750
  if (docs.length > 0) {
9716
9751
  const agentsBaseDir = join(companyDir, "agents");
9717
9752
  const agentRoles = await readdir(agentsBaseDir, { withFileTypes: true });
9718
9753
  for (const role of agentRoles) {
9719
9754
  if (!role.isDirectory()) continue;
9720
9755
  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 += `
9756
+ if (!await exists(agentsMd)) continue;
9757
+ const relevantDocs = docs.filter((doc) => {
9758
+ if (role.name === "ceo") return true;
9759
+ const roles = docRoleMap.get(doc);
9760
+ return !roles || roles.has("*") || roles.has(role.name);
9761
+ });
9762
+ if (relevantDocs.length === 0) continue;
9763
+ let docRefs = "\n## Shared Documentation\n\nReference docs relevant to your role (paths are relative to your workspace home):\n";
9764
+ for (const doc of relevantDocs) {
9765
+ docRefs += `
9725
9766
  Read: \`docs/${doc}\`
9726
9767
  `;
9727
- }
9728
- await appendToFile(agentsMd, docRefs);
9729
9768
  }
9769
+ await appendToFile(agentsMd, docRefs);
9730
9770
  }
9731
9771
  }
9732
9772
  }
9773
+ const agentsBaseDirForSubst = join(companyDir, "agents");
9774
+ if (await exists(agentsBaseDirForSubst)) {
9775
+ const agentRoleDirs = await readdir(agentsBaseDirForSubst, { withFileTypes: true });
9776
+ for (const roleDir of agentRoleDirs) {
9777
+ if (!roleDir.isDirectory()) continue;
9778
+ const absoluteAgentHome = join(agentsBaseDirForSubst, roleDir.name);
9779
+ const subst = async (dir) => {
9780
+ const entries = await readdir(dir, { withFileTypes: true });
9781
+ for (const entry of entries) {
9782
+ const full = join(dir, entry.name);
9783
+ if (entry.isDirectory()) {
9784
+ await subst(full);
9785
+ } else if (entry.name.endsWith(".md")) {
9786
+ const content = await readFile(full, "utf-8");
9787
+ if (content.includes("$AGENT_HOME")) {
9788
+ await writeFile(full, content.split("$AGENT_HOME").join(absoluteAgentHome));
9789
+ }
9790
+ }
9791
+ }
9792
+ };
9793
+ await subst(join(agentsBaseDirForSubst, roleDir.name));
9794
+ }
9795
+ }
9733
9796
  const rolesList = [...allRoles];
9734
9797
  const DEFAULT_BOOTSTRAP_LABELS = [
9735
9798
  { name: "feature", color: "#0075ca", useFor: "New user-facing capability" },
@@ -9824,16 +9887,23 @@ Read: \`docs/${doc}\`
9824
9887
  }
9825
9888
  return "feature";
9826
9889
  };
9827
- const buildBootstrapLabels = (issues) => {
9828
- if (issues.length === 0) return [];
9890
+ const buildBootstrapLabels = (issues, explicitLabels = []) => {
9891
+ if (issues.length === 0 && explicitLabels.length === 0) return [];
9829
9892
  const labelsByName2 = new Map(
9830
9893
  DEFAULT_BOOTSTRAP_LABELS.map((label) => [label.name, { ...label }])
9831
9894
  );
9895
+ for (const label of explicitLabels) {
9896
+ for (const parsedLabel of parseIssueLabels({ labels: [label] })) {
9897
+ labelsByName2.set(parsedLabel.name, parsedLabel);
9898
+ }
9899
+ }
9832
9900
  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);
9901
+ const explicitLabels2 = parseIssueLabels(issue);
9902
+ if (explicitLabels2.length > 0) {
9903
+ for (const label of explicitLabels2) {
9904
+ if (!labelsByName2.has(label.name)) {
9905
+ labelsByName2.set(label.name, label);
9906
+ }
9837
9907
  }
9838
9908
  continue;
9839
9909
  }
@@ -9848,7 +9918,17 @@ Read: \`docs/${doc}\`
9848
9918
  }
9849
9919
  return [...labelsByName2.values()];
9850
9920
  };
9851
- const bootstrapLabels = buildBootstrapLabels(initialIssues);
9921
+ const orderInitialIssuesForBootstrap = () => {
9922
+ const originalOrder = new Map(initialIssues.map((issue, index) => [issue, index]));
9923
+ const rank = (issue) => {
9924
+ if (isFoundationIssue(issue)) return 0;
9925
+ if (issue?.source === "user") return 1;
9926
+ return 2;
9927
+ };
9928
+ initialIssues.sort((a, b) => rank(a) - rank(b) || originalOrder.get(a) - originalOrder.get(b));
9929
+ };
9930
+ orderInitialIssuesForBootstrap();
9931
+ const bootstrapLabels = buildBootstrapLabels(initialIssues, explicitBootstrapLabels);
9852
9932
  const labelsByName = new Map(bootstrapLabels.map((label) => [label.name, label]));
9853
9933
  const getIssueLabelNames = (issue) => {
9854
9934
  const explicit = parseIssueLabels(issue).map((label) => label.name);
@@ -9860,7 +9940,11 @@ Read: \`docs/${doc}\`
9860
9940
  if (lines.length === 0) return "";
9861
9941
  return lines.map(([k, v]) => `- **${k}**: ${v}`).join("\n") + "\n\n";
9862
9942
  };
9863
- const escapeBody = (text) => text.split("\n").map((l) => l.replace(/^(#+)/, "\\$1")).join("\n");
9943
+ const redactSecrets = (text) => String(text || "").replace(
9944
+ /\b(GH_TOKEN|GITHUB_TOKEN|API_KEY|SECRET|TOKEN|PASSWORD|PASS|PRIVATE_KEY)\s*=\s*[^\s`'"<>]+/gi,
9945
+ "$1=[REDACTED]"
9946
+ ).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]");
9947
+ const escapeBody = (text) => redactSecrets(text).split("\n").map((l) => l.replace(/^(#+)/, "\\$1")).join("\n");
9864
9948
  let bootstrap = `# Bootstrap: ${companyName}
9865
9949
 
9866
9950
  `;
@@ -9875,7 +9959,7 @@ Read: \`docs/${doc}\`
9875
9959
  bootstrap += `## Company
9876
9960
 
9877
9961
  `;
9878
- bootstrap += `${companyDescription}
9962
+ bootstrap += `${escapeBody(companyDescription)}
9879
9963
 
9880
9964
  `;
9881
9965
  }
@@ -9899,6 +9983,87 @@ Read: \`docs/${doc}\`
9899
9983
  }
9900
9984
  }
9901
9985
  }
9986
+ const normalizeProjectWorkspace = (proj) => {
9987
+ const explicitWorkspace = proj && typeof proj.workspace === "object" && proj.workspace !== null ? proj.workspace : {};
9988
+ 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";
9989
+ const localCwd = join(companyDir, "projects", toPascalCase(proj.name));
9990
+ const workspace = {
9991
+ sourceType,
9992
+ ...explicitWorkspace,
9993
+ isPrimary: explicitWorkspace.isPrimary ?? proj?.isPrimary ?? true
9994
+ };
9995
+ if (sourceType === "git_repo") {
9996
+ const repoUrl = explicitWorkspace.repoUrl || proj?.repoUrl;
9997
+ const repoRef = explicitWorkspace.repoRef || proj?.repoRef || proj?.defaultRef;
9998
+ const defaultRef = explicitWorkspace.defaultRef || proj?.defaultRef || repoRef;
9999
+ if (repoUrl) workspace.repoUrl = repoUrl;
10000
+ if (repoRef) workspace.repoRef = repoRef;
10001
+ if (defaultRef) workspace.defaultRef = defaultRef;
10002
+ delete workspace.cwd;
10003
+ } else {
10004
+ if (!workspace.cwd) workspace.cwd = localCwd;
10005
+ const trimmedSetup = typeof workspace.setupCommand === "string" ? workspace.setupCommand.trim() : "";
10006
+ if (!trimmedSetup || trimmedSetup === "git init -b main" || trimmedSetup === "git init") {
10007
+ 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'";
10008
+ }
10009
+ }
10010
+ return workspace;
10011
+ };
10012
+ const renderWorkspaceMetaFields = (workspace) => {
10013
+ const orderedKeys = ["sourceType", "cwd", "repoUrl", "repoRef", "defaultRef", "isPrimary"];
10014
+ const keys = [
10015
+ ...orderedKeys.filter((key) => workspace[key] !== void 0),
10016
+ ...Object.keys(workspace).filter((key) => !orderedKeys.includes(key))
10017
+ ];
10018
+ return keys.map((key) => [`workspace.${key}`, String(workspace[key])]);
10019
+ };
10020
+ const formatWorkspaceObject = (workspace) => {
10021
+ const orderedKeys = ["sourceType", "cwd", "repoUrl", "repoRef", "defaultRef", "isPrimary"];
10022
+ const entries = [
10023
+ ...orderedKeys.filter((key) => workspace[key] !== void 0).map((key) => [key, workspace[key]]),
10024
+ ...Object.entries(workspace).filter(([key]) => !orderedKeys.includes(key))
10025
+ ];
10026
+ const fields = entries.filter(([, value]) => value !== void 0 && value !== null && value !== "").map(([key, value]) => {
10027
+ if (typeof value === "boolean") return `${key}: ${value}`;
10028
+ return `${key}: "${String(value)}"`;
10029
+ });
10030
+ return `{ ${fields.join(", ")} }`;
10031
+ };
10032
+ const isFreshLocalRepo = (workspace) => workspace?.sourceType !== "git_repo";
10033
+ const effectiveExecutionPolicy = (proj, workspace) => {
10034
+ const policy = proj?.executionWorkspacePolicy;
10035
+ if (!policy || typeof policy !== "object") return null;
10036
+ if (policy.defaultMode === "isolated_workspace") {
10037
+ if (!enableIsolatedWorktrees || isFreshLocalRepo(workspace)) return null;
10038
+ const strategy = policy.workspaceStrategy;
10039
+ if (!strategy || typeof strategy !== "object") return policy;
10040
+ if (strategy.type !== "git_worktree") return policy;
10041
+ const workspaceStrategy = { ...strategy };
10042
+ const normalizedBaseRef = normalizeExecutionBaseRef(
10043
+ workspaceStrategy.baseRef,
10044
+ workspace?.repoRef || workspace?.defaultRef
10045
+ );
10046
+ if (normalizedBaseRef) {
10047
+ workspaceStrategy.baseRef = normalizedBaseRef;
10048
+ }
10049
+ return { ...policy, workspaceStrategy };
10050
+ }
10051
+ return policy;
10052
+ };
10053
+ const renderExecutionPolicyMetaFields = (proj, workspace) => {
10054
+ const policy = effectiveExecutionPolicy(proj, workspace);
10055
+ if (!policy) return [];
10056
+ const rows = [];
10057
+ if (policy.defaultMode) rows.push(["executionWorkspacePolicy.defaultMode", policy.defaultMode]);
10058
+ const strategy = policy.workspaceStrategy;
10059
+ if (strategy && typeof strategy === "object") {
10060
+ if (strategy.type)
10061
+ rows.push(["executionWorkspacePolicy.workspaceStrategy.type", strategy.type]);
10062
+ if (strategy.baseRef)
10063
+ rows.push(["executionWorkspacePolicy.workspaceStrategy.baseRef", strategy.baseRef]);
10064
+ }
10065
+ return rows;
10066
+ };
9902
10067
  const mainProject = resolvedProjects[0];
9903
10068
  const mainProjectName = mainProject?.name || companyName;
9904
10069
  if (resolvedProjects.length > 0) {
@@ -9906,14 +10071,13 @@ Read: \`docs/${doc}\`
9906
10071
 
9907
10072
  `;
9908
10073
  for (const proj of resolvedProjects) {
9909
- const projCwd = join(companyDir, "projects", toPascalCase(proj.name));
10074
+ const workspace = normalizeProjectWorkspace(proj);
9910
10075
  bootstrap += `### ${proj.name}
9911
10076
 
9912
10077
  `;
9913
10078
  bootstrap += renderMeta([
9914
- ["workspace.sourceType", "local_path"],
9915
- ["workspace.cwd", projCwd],
9916
- ["workspace.isPrimary", "true"],
10079
+ ...renderWorkspaceMetaFields(workspace),
10080
+ ...renderExecutionPolicyMetaFields(proj, workspace),
9917
10081
  [
9918
10082
  "goalIds",
9919
10083
  proj.goals?.length > 0 ? proj.goals.map((g) => `"${g}"`).join(", ") : void 0
@@ -9947,6 +10111,9 @@ Read: \`docs/${doc}\`
9947
10111
  }
9948
10112
  bootstrap += `## Agents
9949
10113
 
10114
+ `;
10115
+ 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.
10116
+
9950
10117
  `;
9951
10118
  for (const role of rolesList) {
9952
10119
  const roleMeta = roleMetaByName.get(role) || {};
@@ -9998,6 +10165,8 @@ Read: \`docs/${doc}\`
9998
10165
  const explicitProjectRef = typeof issue.projectIdRef === "string" ? issue.projectIdRef : typeof issue.projectName === "string" ? issue.projectName : typeof issue.project === "string" ? issue.project : void 0;
9999
10166
  const resolvedProjectRef = explicitProjectRef || mainProjectName;
10000
10167
  const issueLabelNames = getIssueLabelNames(issue);
10168
+ const goalRefRaw = issue.goalId || issue.goalIdRef || issue.goal || issue.goalTitle;
10169
+ const goalRef = typeof goalRefRaw === "string" && goalRefRaw.trim().length > 0 ? goalRefRaw.trim() : void 0;
10001
10170
  for (const labelName of issueLabelNames) {
10002
10171
  if (!labelsByName.has(labelName)) {
10003
10172
  labelsByName.set(labelName, {
@@ -10016,8 +10185,13 @@ Read: \`docs/${doc}\`
10016
10185
  ["priority", issue.priority || "medium"],
10017
10186
  ["parentId", parentRef ? `\u2192 "${parentRef}"` : void 0],
10018
10187
  ["projectId", `\u2192 "${resolvedProjectRef}"`],
10188
+ ["goalId", goalRef ? `\u2192 "${goalRef}"` : void 0],
10019
10189
  ["labelIds", `\u2192 [${issueLabelNames.map((name) => `"${name}"`).join(", ")}]`]
10020
10190
  ]);
10191
+ const issueReviewGate = resolveReviewGate(issue.reviewGate);
10192
+ if (issueReviewGate) {
10193
+ bootstrap += renderReviewGate(issueReviewGate);
10194
+ }
10021
10195
  if (issue.description) {
10022
10196
  bootstrap += `${escapeBody(issue.description)}
10023
10197
 
@@ -10036,12 +10210,20 @@ Read: \`docs/${doc}\`
10036
10210
  bootstrap += `- Do not reopen \`done\` parent/subissues without an explicit reason in a comment.
10037
10211
  `;
10038
10212
  bootstrap += `- Do not reuse parent workspaces for subissues unless explicitly requested.
10039
-
10213
+ `;
10214
+ if (moduleNames.includes("pr-review")) {
10215
+ bootstrap += `- Required PR reviews use the issue's \`executionPolicy\`: a \`review\` stage for the Code Reviewer (plus any relevant domain reviewer \u2014 QA/UI/UX/DevOps), then a final \`approval\` stage for the Product Owner. Resolve each reviewer/approver role to its agentId. Do not create separate child review issues and do not use @-mentions.
10216
+ `;
10217
+ }
10218
+ bootstrap += `
10040
10219
  `;
10041
10220
  }
10042
10221
  if (initialRoutines.length > 0) {
10043
10222
  bootstrap += `## Routines
10044
10223
 
10224
+ `;
10225
+ 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.
10226
+
10045
10227
  `;
10046
10228
  for (const routine of initialRoutines) {
10047
10229
  bootstrap += `### ${routine.title}
@@ -10080,23 +10262,25 @@ Read: \`docs/${doc}\`
10080
10262
  `;
10081
10263
  }
10082
10264
  for (const proj of resolvedProjects) {
10083
- const projCwd = join(companyDir, "projects", toPascalCase(proj.name));
10265
+ const workspace = normalizeProjectWorkspace(proj);
10084
10266
  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})
10267
+ const activePolicy = effectiveExecutionPolicy(proj, workspace);
10268
+ const policy = activePolicy?.defaultMode ? `, executionWorkspacePolicy.defaultMode: "${activePolicy.defaultMode}"` : "";
10269
+ bootstrap += `${stepN++}. **Create project** "${proj.name}" (workspace: ${formatWorkspaceObject(workspace)}${policy}${goalLinks})
10086
10270
  `;
10087
10271
  }
10088
10272
  if (bootstrapLabels.length > 0) {
10089
10273
  bootstrap += `${stepN++}. **Create labels** \u2014 create each label exactly as listed in the Labels section before creating issues
10090
10274
  `;
10091
10275
  }
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
10276
+ 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
10277
  `;
10094
10278
  if (initialIssues.length > 0) {
10095
10279
  bootstrap += `${stepN++}. **Create issues** \u2014 every issue, including subtasks, must carry explicit projectId; subtasks also require parentId
10096
10280
  `;
10097
10281
  }
10098
10282
  if (initialRoutines.length > 0) {
10099
- bootstrap += `${stepN++}. **Create routines** with cron triggers as listed above
10283
+ 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
10284
  `;
10101
10285
  }
10102
10286
  bootstrap += `${stepN}. **Start CEO heartbeat** (one-time initial wakeup)
@@ -10220,6 +10404,12 @@ var PaperclipClient = class {
10220
10404
  return false;
10221
10405
  }
10222
10406
  }
10407
+ /**
10408
+ * Read instance-wide experimental settings (including enableIsolatedWorkspaces).
10409
+ */
10410
+ async getInstanceExperimentalSettings() {
10411
+ return this._fetch("/api/instance/settings/experimental");
10412
+ }
10223
10413
  async createCompany({ name, description }) {
10224
10414
  return this._fetch("/api/companies", {
10225
10415
  method: "POST",
@@ -10406,6 +10596,12 @@ var PaperclipClient = class {
10406
10596
  })
10407
10597
  });
10408
10598
  }
10599
+ async updateIssue(issueId, updates = {}) {
10600
+ return this._fetch(`/api/issues/${issueId}`, {
10601
+ method: "PATCH",
10602
+ body: JSON.stringify(updates || {})
10603
+ });
10604
+ }
10409
10605
  async createRoutine(companyId, {
10410
10606
  title,
10411
10607
  description,
@@ -10504,14 +10700,16 @@ async function loadModules(templatesDir) {
10504
10700
  for (const dir of dirs) {
10505
10701
  if (!dir.isDirectory()) continue;
10506
10702
  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 || {} };
10703
+ const mod = { name: dir.name, ...moduleJson || {} };
10704
+ if (!mod.description) {
10705
+ const readmePath = join2(modulesDir, dir.name, "README.md");
10706
+ if (await exists2(readmePath)) {
10707
+ const content = await readFile2(readmePath, "utf-8");
10708
+ const descLine = content.split("\n").find((l) => l.length > 0 && !l.startsWith("#"));
10709
+ mod.description = descLine?.trim() || "";
10710
+ }
10711
+ }
10712
+ if (mod.description === void 0) mod.description = "";
10515
10713
  if (mod.tasks && !mod.issues) {
10516
10714
  mod.issues = mod.tasks;
10517
10715
  delete mod.tasks;
@@ -10586,6 +10784,39 @@ function collectGoals(preset, modules, selectedModules) {
10586
10784
  }
10587
10785
  return goals;
10588
10786
  }
10787
+ function resolveEffectiveModules(preset, modules, selectedModules) {
10788
+ const known = new Set(modules.map((m) => m.name));
10789
+ const requiresByName = new Map(
10790
+ modules.map((m) => [m.name, Array.isArray(m.requires) ? m.requires : []])
10791
+ );
10792
+ const effective = /* @__PURE__ */ new Set();
10793
+ const queue = [];
10794
+ const add = (name) => {
10795
+ if (typeof name !== "string" || !known.has(name) || effective.has(name)) return;
10796
+ effective.add(name);
10797
+ queue.push(name);
10798
+ };
10799
+ for (const moduleName of Array.isArray(preset?.modules) ? preset.modules : []) {
10800
+ add(moduleName);
10801
+ }
10802
+ for (const moduleName of selectedModules ?? []) {
10803
+ add(moduleName);
10804
+ }
10805
+ while (queue.length > 0) {
10806
+ const moduleName = queue.shift();
10807
+ for (const dep of requiresByName.get(moduleName) ?? []) {
10808
+ add(dep);
10809
+ }
10810
+ }
10811
+ return [...effective];
10812
+ }
10813
+ function collectPresetBootstrapData(preset) {
10814
+ return {
10815
+ labels: Array.isArray(preset?.labels) ? preset.labels.map((label) => ({ ...label })) : [],
10816
+ issues: Array.isArray(preset?.issues) ? preset.issues.map((issue) => ({ ...issue })) : [],
10817
+ routines: Array.isArray(preset?.routines) ? preset.routines.map((routine) => ({ ...routine })) : []
10818
+ };
10819
+ }
10589
10820
 
10590
10821
  // src/worker.ts
10591
10822
  var __dirname = path2.dirname(fileURLToPath2(import.meta.url));
@@ -10656,6 +10887,61 @@ async function ensureTemplatesDir(cfg) {
10656
10887
  );
10657
10888
  }
10658
10889
  }
10890
+ function isLikelyAnthropicApiKey(value) {
10891
+ return value.startsWith("sk-ant-");
10892
+ }
10893
+ async function resolveAnthropicApiKey(ctx, configuredValue) {
10894
+ if (typeof configuredValue !== "string") return "";
10895
+ const value = configuredValue.trim();
10896
+ if (!value) return "";
10897
+ if (isLikelyAnthropicApiKey(value)) return value;
10898
+ try {
10899
+ const resolved = await ctx.secrets.resolve(value);
10900
+ return resolved.trim();
10901
+ } catch (err) {
10902
+ const detail = err instanceof Error ? err.message : String(err);
10903
+ throw new Error(
10904
+ `Anthropic API key could not be resolved. Re-save the plugin setting with a valid Anthropic API key (sk-ant-...). ${detail}`
10905
+ );
10906
+ }
10907
+ }
10908
+ async function callAnthropic(apiKey, system, messages) {
10909
+ try {
10910
+ const response = await fetch("https://api.anthropic.com/v1/messages", {
10911
+ method: "POST",
10912
+ headers: {
10913
+ "Content-Type": "application/json",
10914
+ "x-api-key": apiKey,
10915
+ "anthropic-version": "2023-06-01"
10916
+ },
10917
+ body: JSON.stringify({
10918
+ model: "claude-opus-4-8",
10919
+ // High ceiling so the wizard's final config — which reproduces the user's
10920
+ // full spec in the first goal — is never truncated mid-JSON. This is only
10921
+ // an upper bound; generation time tracks the tokens actually produced.
10922
+ max_tokens: 32768,
10923
+ ...system ? { system } : {},
10924
+ messages
10925
+ })
10926
+ });
10927
+ if (!response.ok) {
10928
+ const body = await response.text();
10929
+ return { text: "", error: `Anthropic API error (${response.status}): ${body}` };
10930
+ }
10931
+ const data = await response.json();
10932
+ return { text: data.content?.[0]?.text || "" };
10933
+ } catch (err) {
10934
+ return { text: "", error: err instanceof Error ? err.message : String(err) };
10935
+ }
10936
+ }
10937
+ var aiChatJobs = /* @__PURE__ */ new Map();
10938
+ var AI_CHAT_JOB_TTL_MS = 10 * 60 * 1e3;
10939
+ function sweepAiChatJobs() {
10940
+ const now = Date.now();
10941
+ for (const [id, job] of aiChatJobs) {
10942
+ if (now - job.createdAt > AI_CHAT_JOB_TTL_MS) aiChatJobs.delete(id);
10943
+ }
10944
+ }
10659
10945
  function loadJsonFiles(dir, filename) {
10660
10946
  const items = [];
10661
10947
  const errors = [];
@@ -10701,10 +10987,37 @@ function loadTemplates(templatesDir) {
10701
10987
  loadErrors: [...presetLoad.errors, ...moduleLoad.errors, ...roleLoad.errors]
10702
10988
  };
10703
10989
  }
10990
+ function cfgBool(cfg, key) {
10991
+ const raw = cfg[key];
10992
+ return raw === true || typeof raw === "string" && raw.toLowerCase() === "true";
10993
+ }
10994
+ async function resolveEnableIsolatedWorkspacesFromInstance(cfg, log) {
10995
+ const paperclipUrl = cfg.paperclipUrl || process.env.PAPERCLIP_PUBLIC_URL || "http://localhost:3100";
10996
+ const paperclipEmail = cfg.paperclipEmail || "";
10997
+ const paperclipPassword = cfg.paperclipPassword || "";
10998
+ const instanceClient = new PaperclipClient(paperclipUrl, {
10999
+ email: paperclipEmail,
11000
+ password: paperclipPassword
11001
+ });
11002
+ try {
11003
+ await instanceClient.connect();
11004
+ const experimentalSettings = await instanceClient.getInstanceExperimentalSettings();
11005
+ return experimentalSettings?.enableIsolatedWorkspaces === true;
11006
+ } catch (err) {
11007
+ if (log) {
11008
+ const detail = err instanceof Error ? err.message : String(err);
11009
+ log(`\u26A0 Could not read instance experimental settings: ${detail}. Using fallback false.`);
11010
+ }
11011
+ return false;
11012
+ }
11013
+ }
10704
11014
  function resolveCompaniesDir(cfg) {
10705
11015
  if (cfg.companiesDir) return cfg.companiesDir;
10706
11016
  return path2.join(os.homedir(), ".paperclip", "instances", "default", "companies");
10707
11017
  }
11018
+ function formatRoleName(role) {
11019
+ return role.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
11020
+ }
10708
11021
  function collectInstructionFiles(rootDir) {
10709
11022
  const out = {};
10710
11023
  if (!fs2.existsSync(rootDir)) return out;
@@ -10815,20 +11128,28 @@ var plugin = definePlugin({
10815
11128
  loadModules(templatesDir)
10816
11129
  ]);
10817
11130
  const selectedPreset = presets.find((p) => p.name === params.presetName) || null;
10818
- const goals = collectGoals(
11131
+ const effectiveModules = resolveEffectiveModules(
10819
11132
  selectedPreset,
10820
11133
  allModules,
10821
- new Set(params.selectedModules ?? [])
11134
+ params.selectedModules ?? []
10822
11135
  );
11136
+ const goals = collectGoals(selectedPreset, allModules, new Set(effectiveModules));
11137
+ const presetBootstrapData = collectPresetBootstrapData(selectedPreset);
10823
11138
  const previewGoals = Array.isArray(params.goals) ? params.goals : params.goal ? [params.goal] : [];
10824
11139
  const previewProjects = Array.isArray(params.projects) ? params.projects : [];
11140
+ const previewIssues = Array.isArray(params.issues) ? params.issues : [];
10825
11141
  const result = await assembleCompany({
10826
11142
  companyName,
10827
11143
  userGoals: previewGoals,
10828
11144
  userProjects: previewProjects,
10829
- moduleNames: params.selectedModules ?? [],
11145
+ moduleNames: effectiveModules,
10830
11146
  extraRoleNames: params.selectedRoles ?? [],
10831
11147
  inlineGoals: goals,
11148
+ userIssues: previewIssues,
11149
+ presetIssues: presetBootstrapData.issues,
11150
+ presetRoutines: presetBootstrapData.routines,
11151
+ presetLabels: presetBootstrapData.labels,
11152
+ enableIsolatedWorktrees: await resolveEnableIsolatedWorkspacesFromInstance(cfg),
10832
11153
  outputDir: tmpDir,
10833
11154
  templatesDir
10834
11155
  });
@@ -10863,34 +11184,42 @@ var plugin = definePlugin({
10863
11184
  });
10864
11185
  ctx.actions.register("ai-chat", async (params) => {
10865
11186
  try {
11187
+ if (params.mode === "poll") {
11188
+ const jobId = typeof params.jobId === "string" ? params.jobId : "";
11189
+ const job = jobId ? aiChatJobs.get(jobId) : void 0;
11190
+ if (!job) {
11191
+ return {
11192
+ text: "",
11193
+ status: "error",
11194
+ error: "Unknown or expired generation job. Please retry."
11195
+ };
11196
+ }
11197
+ if (job.status === "pending") return { status: "pending" };
11198
+ aiChatJobs.delete(jobId);
11199
+ if (job.status === "error") return { text: "", status: "error", error: job.error };
11200
+ return { text: job.text, status: "done" };
11201
+ }
10866
11202
  const cfg = await ctx.config.get() ?? {};
10867
- const apiKey = cfg.anthropicApiKey || "";
11203
+ const apiKey = await resolveAnthropicApiKey(ctx, cfg.anthropicApiKey);
10868
11204
  if (!apiKey) {
10869
11205
  return {
10870
11206
  text: "",
10871
11207
  error: "Anthropic API key not configured. Add it in plugin settings (anthropicApiKey)."
10872
11208
  };
10873
11209
  }
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}` };
11210
+ if (params.mode === "start") {
11211
+ sweepAiChatJobs();
11212
+ const jobId = `aichat-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
11213
+ aiChatJobs.set(jobId, { status: "pending", createdAt: Date.now() });
11214
+ void callAnthropic(apiKey, params.system, params.messages).then((result) => {
11215
+ aiChatJobs.set(
11216
+ jobId,
11217
+ result.error ? { status: "error", error: result.error, createdAt: Date.now() } : { status: "done", text: result.text, createdAt: Date.now() }
11218
+ );
11219
+ });
11220
+ return { jobId, status: "pending" };
10891
11221
  }
10892
- const data = await response.json();
10893
- return { text: data.content?.[0]?.text || "" };
11222
+ return await callAnthropic(apiKey, params.system, params.messages);
10894
11223
  } catch (err) {
10895
11224
  return { text: "", error: err instanceof Error ? err.message : String(err) };
10896
11225
  }
@@ -10898,7 +11227,8 @@ var plugin = definePlugin({
10898
11227
  ctx.actions.register("check-ai-config", async () => {
10899
11228
  try {
10900
11229
  const cfg = await ctx.config.get() ?? {};
10901
- if (!cfg.anthropicApiKey) {
11230
+ const apiKey = await resolveAnthropicApiKey(ctx, cfg.anthropicApiKey);
11231
+ if (!apiKey) {
10902
11232
  return {
10903
11233
  ok: false,
10904
11234
  error: "Anthropic API key not configured. Add it in plugin settings (anthropicApiKey)."
@@ -10920,8 +11250,11 @@ var plugin = definePlugin({
10920
11250
  const paperclipUrl = cfg.paperclipUrl || process.env.PAPERCLIP_PUBLIC_URL || "http://localhost:3100";
10921
11251
  const paperclipEmail = cfg.paperclipEmail || "";
10922
11252
  const paperclipPassword = cfg.paperclipPassword || "";
10923
- const rawDisableBoardApproval = cfg.disableBoardApprovalOnNewCompanies;
10924
- const disableBoardApprovalOnNewCompanies = rawDisableBoardApproval === true || typeof rawDisableBoardApproval === "string" && rawDisableBoardApproval.toLowerCase() === "true";
11253
+ const disableBoardApprovalOnNewCompanies = cfgBool(
11254
+ cfg,
11255
+ "disableBoardApprovalOnNewCompanies"
11256
+ );
11257
+ const enableIsolatedWorktrees = await resolveEnableIsolatedWorkspacesFromInstance(cfg, log);
10925
11258
  const companyName = typeof params.companyName === "string" ? params.companyName.trim() : "";
10926
11259
  const existingCompanyId = typeof params.existingCompanyId === "string" && params.existingCompanyId.trim() ? params.existingCompanyId.trim() : "";
10927
11260
  if (!companyName) return { error: "companyName is required", logs };
@@ -10935,25 +11268,33 @@ var plugin = definePlugin({
10935
11268
  (Array.isArray(roleTemplates) ? roleTemplates : []).filter((role) => role && typeof role.name === "string").map((role) => [role.name, role])
10936
11269
  );
10937
11270
  const selectedPreset = presets.find((p) => p.name === params.presetName) || null;
10938
- const goals = collectGoals(
11271
+ const effectiveModules = resolveEffectiveModules(
10939
11272
  selectedPreset,
10940
11273
  allModules,
10941
- new Set(params.selectedModules ?? [])
11274
+ params.selectedModules ?? []
10942
11275
  );
11276
+ const goals = collectGoals(selectedPreset, allModules, new Set(effectiveModules));
11277
+ const presetBootstrapData = collectPresetBootstrapData(selectedPreset);
10943
11278
  const outputDir = resolveCompaniesDir(cfg);
10944
11279
  fs2.mkdirSync(outputDir, { recursive: true });
10945
11280
  log("Assembling company workspace...");
10946
11281
  const companyDescription = typeof params.companyDescription === "string" ? params.companyDescription.trim() : "";
10947
11282
  const userGoals = Array.isArray(params.goals) ? params.goals : params.goal ? [params.goal] : [];
10948
11283
  const userProjects = Array.isArray(params.projects) ? params.projects : [];
11284
+ const userIssues = Array.isArray(params.issues) ? params.issues : [];
10949
11285
  const assembleResult = await assembleCompany({
10950
11286
  companyName,
10951
11287
  companyDescription,
10952
11288
  userGoals,
10953
11289
  userProjects,
10954
- moduleNames: params.selectedModules ?? [],
11290
+ moduleNames: effectiveModules,
10955
11291
  extraRoleNames: params.selectedRoles ?? [],
10956
11292
  inlineGoals: goals,
11293
+ userIssues,
11294
+ presetIssues: presetBootstrapData.issues,
11295
+ presetRoutines: presetBootstrapData.routines,
11296
+ presetLabels: presetBootstrapData.labels,
11297
+ enableIsolatedWorktrees,
10957
11298
  outputDir,
10958
11299
  templatesDir,
10959
11300
  onProgress: log
@@ -11018,6 +11359,7 @@ var plugin = definePlugin({
11018
11359
  }
11019
11360
  }
11020
11361
  let ceoAgentId;
11362
+ const teamAgentIds = {};
11021
11363
  let bootstrapIssue;
11022
11364
  try {
11023
11365
  const userCeoAdapter = params.ceoAdapter || {};
@@ -11125,18 +11467,125 @@ var plugin = definePlugin({
11125
11467
  fallbackEntryContent: ceoPromptTemplate,
11126
11468
  log
11127
11469
  });
11470
+ const teamRoles = [...assembleResult.allRoles ?? []].filter(
11471
+ (r) => r && r !== "ceo"
11472
+ );
11473
+ let existingByTemplateRole = /* @__PURE__ */ new Map();
11474
+ if (existingCompanyId && teamRoles.length > 0) {
11475
+ const agents = await client.listAgents(companyId);
11476
+ if (Array.isArray(agents)) {
11477
+ for (const a of agents) {
11478
+ const tr = a?.metadata?.templateRole;
11479
+ if (tr && a?.status !== "terminated" && a?.role !== "ceo") {
11480
+ existingByTemplateRole.set(tr, a);
11481
+ }
11482
+ }
11483
+ }
11484
+ }
11485
+ for (const roleName of teamRoles) {
11486
+ const roleTemplate = roleTemplateByName.get(roleName) || {};
11487
+ const paperclipRole = typeof roleTemplate.paperclipRole === "string" && roleTemplate.paperclipRole.trim() ? roleTemplate.paperclipRole.trim() : "general";
11488
+ const roleTitle = typeof roleTemplate.title === "string" && roleTemplate.title.trim() ? roleTemplate.title.trim() : formatRoleName(roleName);
11489
+ const roleDescription = typeof roleTemplate.description === "string" && roleTemplate.description.trim() ? roleTemplate.description.trim() : void 0;
11490
+ const roleMetadata = {
11491
+ templateRole: roleName,
11492
+ ...roleDescription ? { description: roleDescription } : {}
11493
+ };
11494
+ const roleRuntimeConfig = buildWorkerAgentRuntimeConfig();
11495
+ const roleAdapterConfig = buildCeoAdapterConfig({
11496
+ userCeoAdapter,
11497
+ companyDir,
11498
+ roleAdapterOverrides: assembleResult.roleAdapterOverrides?.get(roleName) ?? {}
11499
+ });
11500
+ const roleInstructionsDir = path2.join(companyDir, "agents", roleName);
11501
+ const roleInstructionFiles = collectInstructionFiles(roleInstructionsDir);
11502
+ const roleInstructionsBundle = Object.keys(roleInstructionFiles).length > 0 ? { entryFile: "AGENTS.md", files: roleInstructionFiles } : void 0;
11503
+ const existingAgent = existingByTemplateRole.get(roleName);
11504
+ if (existingAgent?.id) {
11505
+ try {
11506
+ await client.updateAgent(existingAgent.id, {
11507
+ adapterType,
11508
+ adapterConfig: roleAdapterConfig,
11509
+ runtimeConfig: roleRuntimeConfig,
11510
+ metadata: { ...existingAgent.metadata ?? {}, ...roleMetadata },
11511
+ ...!existingAgent.title && roleTitle ? { title: roleTitle } : {},
11512
+ ...!existingAgent.capabilities && roleDescription ? { capabilities: roleDescription } : {}
11513
+ });
11514
+ log(`\u2713 Reusing ${roleTitle} (${existingAgent.id})`);
11515
+ } catch (err) {
11516
+ log(
11517
+ `\u26A0 Could not update ${roleTitle}: ${err instanceof Error ? err.message : String(err)}`
11518
+ );
11519
+ }
11520
+ teamAgentIds[roleName] = existingAgent.id;
11521
+ continue;
11522
+ }
11523
+ const roleAgent = await client.createAgent(companyId, {
11524
+ name: roleTitle,
11525
+ role: paperclipRole,
11526
+ title: roleTitle,
11527
+ ...roleDescription ? { capabilities: roleDescription } : {},
11528
+ metadata: roleMetadata,
11529
+ reportsTo: ceoAgentId,
11530
+ adapterType,
11531
+ adapterConfig: roleAdapterConfig,
11532
+ instructionsBundle: roleInstructionsBundle,
11533
+ runtimeConfig: roleRuntimeConfig
11534
+ });
11535
+ teamAgentIds[roleName] = roleAgent.id;
11536
+ log(`\u2713 ${roleTitle} created (${roleAgent.id})`);
11537
+ if (roleAgent?._pendingApprovalId) {
11538
+ log(
11539
+ `\u26A0 ${roleTitle} hire pending approval: ${roleAgent._pendingApprovalId}. Approve it in the board.`
11540
+ );
11541
+ if (roleAgent._approvalAutoApproveError) {
11542
+ log(` Auto-approve failed: ${roleAgent._approvalAutoApproveError}`);
11543
+ }
11544
+ }
11545
+ }
11546
+ if (!existingCompanyId) {
11547
+ const routines = Array.isArray(assembleResult.initialRoutines) ? assembleResult.initialRoutines : [];
11548
+ for (const routine of routines) {
11549
+ const title = typeof routine.title === "string" && routine.title.trim() ? routine.title.trim() : typeof routine.name === "string" ? routine.name.trim() : "";
11550
+ if (!title) continue;
11551
+ const role = routine.assignTo;
11552
+ const assigneeAgentId = !role || role === "ceo" ? ceoAgentId : teamAgentIds[role] ?? ceoAgentId;
11553
+ try {
11554
+ const createdRoutine = await client.createRoutine(companyId, {
11555
+ title,
11556
+ description: routine.description,
11557
+ assigneeAgentId,
11558
+ priority: routine.priority || "medium",
11559
+ concurrencyPolicy: routine.concurrencyPolicy || "skip_if_active"
11560
+ });
11561
+ if (routine.schedule && createdRoutine?.id) {
11562
+ await client.createRoutineTrigger(createdRoutine.id, {
11563
+ kind: "schedule",
11564
+ cronExpression: routine.schedule,
11565
+ timezone: "UTC"
11566
+ });
11567
+ }
11568
+ log(
11569
+ `\u2713 Routine "${title}" created${routine.schedule ? ` (${routine.schedule})` : ""}`
11570
+ );
11571
+ } catch (err) {
11572
+ log(
11573
+ `\u26A0 Could not create routine "${title}": ${err instanceof Error ? err.message : String(err)}`
11574
+ );
11575
+ }
11576
+ }
11577
+ }
11128
11578
  const bootstrapDescription = fs2.readFileSync(
11129
11579
  path2.join(companyDir, "BOOTSTRAP.md"),
11130
11580
  "utf-8"
11131
11581
  );
11132
11582
  log("Creating bootstrap task for CEO...");
11133
- const issue = await ctx.issues.create({
11134
- companyId,
11583
+ const issue = await client.createIssue(companyId, {
11135
11584
  title: `Bootstrap ${company.name || companyName}`,
11136
11585
  description: bootstrapDescription,
11137
- assigneeAgentId: ceoAgentId
11586
+ assigneeAgentId: ceoAgentId,
11587
+ status: "todo"
11138
11588
  });
11139
- await ctx.issues.update(issue.id, { status: "todo" }, companyId);
11140
11589
  bootstrapIssue = issue;
11141
11590
  log(`\u2713 Bootstrap task created: ${bootstrapIssue.identifier || bootstrapIssue.id}`);
11142
11591
  } catch (err) {
@@ -11166,7 +11615,7 @@ var plugin = definePlugin({
11166
11615
  companyId,
11167
11616
  issuePrefix: company.issuePrefix,
11168
11617
  paperclipUrl,
11169
- agentIds: { ceo: ceoAgentId },
11618
+ agentIds: { ceo: ceoAgentId, ...teamAgentIds },
11170
11619
  issueIds: [bootstrapIssue.id],
11171
11620
  logs
11172
11621
  };