@penclipai/server 2026.704.0 → 2026.714.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/index.d.ts +1 -1
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/process/execute.d.ts.map +1 -1
- package/dist/adapters/process/execute.js +1 -0
- package/dist/adapters/process/execute.js.map +1 -1
- package/dist/adapters/registry.d.ts.map +1 -1
- package/dist/adapters/registry.js +79 -51
- package/dist/adapters/registry.js.map +1 -1
- package/dist/adapters/utils.d.ts +5 -0
- package/dist/adapters/utils.d.ts.map +1 -1
- package/dist/adapters/utils.js.map +1 -1
- package/dist/agent-auth-jwt.d.ts +5 -1
- package/dist/agent-auth-jwt.d.ts.map +1 -1
- package/dist/agent-auth-jwt.js +72 -20
- package/dist/agent-auth-jwt.js.map +1 -1
- package/dist/app.d.ts +2 -0
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +10 -0
- package/dist/app.js.map +1 -1
- package/dist/built-ins/agents/reflection-coach/AGENTS.md +47 -0
- package/dist/built-ins/agents/reflection-coach/routines/recent-agent-reflection.md +77 -0
- package/dist/errors.d.ts +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +2 -2
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +208 -116
- package/dist/index.js.map +1 -1
- package/dist/middleware/api-compression.d.ts +8 -0
- package/dist/middleware/api-compression.d.ts.map +1 -0
- package/dist/middleware/api-compression.js +207 -0
- package/dist/middleware/api-compression.js.map +1 -0
- package/dist/middleware/auth.d.ts.map +1 -1
- package/dist/middleware/auth.js +130 -3
- package/dist/middleware/auth.js.map +1 -1
- package/dist/middleware/error-handler.d.ts.map +1 -1
- package/dist/middleware/error-handler.js +27 -0
- package/dist/middleware/error-handler.js.map +1 -1
- package/dist/onboarding-assets/default/AGENTS.md +1 -0
- package/dist/redaction.d.ts.map +1 -1
- package/dist/redaction.js +11 -0
- package/dist/redaction.js.map +1 -1
- package/dist/routes/access.d.ts.map +1 -1
- package/dist/routes/access.js +4 -3
- package/dist/routes/access.js.map +1 -1
- package/dist/routes/adapters.d.ts.map +1 -1
- package/dist/routes/adapters.js +2 -0
- package/dist/routes/adapters.js.map +1 -1
- package/dist/routes/agents.d.ts.map +1 -1
- package/dist/routes/agents.js +222 -87
- package/dist/routes/agents.js.map +1 -1
- package/dist/routes/attention.d.ts +3 -0
- package/dist/routes/attention.d.ts.map +1 -0
- package/dist/routes/attention.js +24 -0
- package/dist/routes/attention.js.map +1 -0
- package/dist/routes/authz.d.ts.map +1 -1
- package/dist/routes/authz.js +29 -1
- package/dist/routes/authz.js.map +1 -1
- package/dist/routes/board-chat.d.ts.map +1 -1
- package/dist/routes/board-chat.js +4 -1
- package/dist/routes/board-chat.js.map +1 -1
- package/dist/routes/built-in-agents.d.ts +3 -0
- package/dist/routes/built-in-agents.d.ts.map +1 -0
- package/dist/routes/built-in-agents.js +267 -0
- package/dist/routes/built-in-agents.js.map +1 -0
- package/dist/routes/cases.d.ts +46 -0
- package/dist/routes/cases.d.ts.map +1 -0
- package/dist/routes/cases.js +1395 -0
- package/dist/routes/cases.js.map +1 -0
- package/dist/routes/companies.d.ts.map +1 -1
- package/dist/routes/companies.js +4 -1
- package/dist/routes/companies.js.map +1 -1
- package/dist/routes/company-skills.d.ts.map +1 -1
- package/dist/routes/company-skills.js +453 -33
- package/dist/routes/company-skills.js.map +1 -1
- package/dist/routes/environments.d.ts.map +1 -1
- package/dist/routes/environments.js +71 -8
- package/dist/routes/environments.js.map +1 -1
- package/dist/routes/execution-workspaces.d.ts.map +1 -1
- package/dist/routes/execution-workspaces.js +89 -3
- package/dist/routes/execution-workspaces.js.map +1 -1
- package/dist/routes/health.d.ts +2 -0
- package/dist/routes/health.d.ts.map +1 -1
- package/dist/routes/health.js +30 -0
- package/dist/routes/health.js.map +1 -1
- package/dist/routes/inbox-dismissals.d.ts.map +1 -1
- package/dist/routes/inbox-dismissals.js +80 -19
- package/dist/routes/inbox-dismissals.js.map +1 -1
- package/dist/routes/index.d.ts +2 -0
- package/dist/routes/index.d.ts.map +1 -1
- package/dist/routes/index.js +2 -0
- package/dist/routes/index.js.map +1 -1
- package/dist/routes/issues.d.ts +25 -0
- package/dist/routes/issues.d.ts.map +1 -1
- package/dist/routes/issues.js +1455 -46
- package/dist/routes/issues.js.map +1 -1
- package/dist/routes/openapi.d.ts.map +1 -1
- package/dist/routes/openapi.js +448 -11
- package/dist/routes/openapi.js.map +1 -1
- package/dist/routes/pipelines.js +2 -2
- package/dist/routes/pipelines.js.map +1 -1
- package/dist/routes/resource-memberships.d.ts.map +1 -1
- package/dist/routes/resource-memberships.js +13 -5
- package/dist/routes/resource-memberships.js.map +1 -1
- package/dist/routes/secrets.d.ts.map +1 -1
- package/dist/routes/secrets.js +261 -1
- package/dist/routes/secrets.js.map +1 -1
- package/dist/routes/sidebar-badges.d.ts.map +1 -1
- package/dist/routes/sidebar-badges.js +18 -2
- package/dist/routes/sidebar-badges.js.map +1 -1
- package/dist/routes/user-profiles.d.ts.map +1 -1
- package/dist/routes/user-profiles.js +5 -4
- package/dist/routes/user-profiles.js.map +1 -1
- package/dist/server-info.d.ts +2 -0
- package/dist/server-info.d.ts.map +1 -1
- package/dist/server-info.js +20 -5
- package/dist/server-info.js.map +1 -1
- package/dist/services/access.d.ts +4 -4
- package/dist/services/access.d.ts.map +1 -1
- package/dist/services/activity.d.ts +3 -3
- package/dist/services/activity.d.ts.map +1 -1
- package/dist/services/activity.js +5 -4
- package/dist/services/activity.js.map +1 -1
- package/dist/services/adapter-registry-bootstrap.reconcile.test.js +1 -0
- package/dist/services/adapter-registry-bootstrap.reconcile.test.js.map +1 -1
- package/dist/services/agent-secret-bindings.d.ts +15 -0
- package/dist/services/agent-secret-bindings.d.ts.map +1 -1
- package/dist/services/agent-secret-bindings.js +43 -0
- package/dist/services/agent-secret-bindings.js.map +1 -1
- package/dist/services/agents.d.ts +194 -133
- package/dist/services/agents.d.ts.map +1 -1
- package/dist/services/agents.js +107 -4
- package/dist/services/agents.js.map +1 -1
- package/dist/services/approvals.d.ts +10 -10
- package/dist/services/approvals.d.ts.map +1 -1
- package/dist/services/approvals.js +9 -1
- package/dist/services/approvals.js.map +1 -1
- package/dist/services/assets.d.ts +5 -5
- package/dist/services/attention.d.ts +11 -0
- package/dist/services/attention.d.ts.map +1 -0
- package/dist/services/attention.js +1024 -0
- package/dist/services/attention.js.map +1 -0
- package/dist/services/authorization.d.ts +15 -2
- package/dist/services/authorization.d.ts.map +1 -1
- package/dist/services/authorization.js +324 -8
- package/dist/services/authorization.js.map +1 -1
- package/dist/services/board-auth.d.ts +2 -2
- package/dist/services/budgets.d.ts.map +1 -1
- package/dist/services/budgets.js +8 -7
- package/dist/services/budgets.js.map +1 -1
- package/dist/services/built-in-agent-metadata.d.ts +9 -0
- package/dist/services/built-in-agent-metadata.d.ts.map +1 -0
- package/dist/services/built-in-agent-metadata.js +39 -0
- package/dist/services/built-in-agent-metadata.js.map +1 -0
- package/dist/services/built-in-agents.d.ts +394 -0
- package/dist/services/built-in-agents.d.ts.map +1 -0
- package/dist/services/built-in-agents.js +1426 -0
- package/dist/services/built-in-agents.js.map +1 -0
- package/dist/services/change-consent-gate.d.ts +18 -0
- package/dist/services/change-consent-gate.d.ts.map +1 -0
- package/dist/services/change-consent-gate.js +170 -0
- package/dist/services/change-consent-gate.js.map +1 -0
- package/dist/services/companies.d.ts +14 -8
- package/dist/services/companies.d.ts.map +1 -1
- package/dist/services/companies.js +6 -1
- package/dist/services/companies.js.map +1 -1
- package/dist/services/company-artifacts.d.ts +4 -1
- package/dist/services/company-artifacts.d.ts.map +1 -1
- package/dist/services/company-artifacts.js +9 -1
- package/dist/services/company-artifacts.js.map +1 -1
- package/dist/services/company-member-roles.d.ts.map +1 -1
- package/dist/services/company-member-roles.js +2 -0
- package/dist/services/company-member-roles.js.map +1 -1
- package/dist/services/company-portability.d.ts +1 -1
- package/dist/services/company-portability.d.ts.map +1 -1
- package/dist/services/company-portability.js +113 -8
- package/dist/services/company-portability.js.map +1 -1
- package/dist/services/company-search.d.ts.map +1 -1
- package/dist/services/company-search.js +843 -294
- package/dist/services/company-search.js.map +1 -1
- package/dist/services/company-skills.d.ts +64 -3
- package/dist/services/company-skills.d.ts.map +1 -1
- package/dist/services/company-skills.js +1205 -20
- package/dist/services/company-skills.js.map +1 -1
- package/dist/services/costs.d.ts +9 -8
- package/dist/services/costs.d.ts.map +1 -1
- package/dist/services/costs.js +9 -2
- package/dist/services/costs.js.map +1 -1
- package/dist/services/dashboard.d.ts +2 -0
- package/dist/services/dashboard.d.ts.map +1 -1
- package/dist/services/dashboard.js +60 -17
- package/dist/services/dashboard.js.map +1 -1
- package/dist/services/database-backup-health.d.ts +34 -0
- package/dist/services/database-backup-health.d.ts.map +1 -0
- package/dist/services/database-backup-health.js +104 -0
- package/dist/services/database-backup-health.js.map +1 -0
- package/dist/services/document-annotations.d.ts +169 -1
- package/dist/services/document-annotations.d.ts.map +1 -1
- package/dist/services/document-annotations.js +272 -1
- package/dist/services/document-annotations.js.map +1 -1
- package/dist/services/documents.d.ts +368 -0
- package/dist/services/documents.d.ts.map +1 -1
- package/dist/services/documents.js +2 -2
- package/dist/services/documents.js.map +1 -1
- package/dist/services/environment-config.d.ts.map +1 -1
- package/dist/services/environment-config.js +6 -0
- package/dist/services/environment-config.js.map +1 -1
- package/dist/services/environment-custom-image-runtime.d.ts +28 -0
- package/dist/services/environment-custom-image-runtime.d.ts.map +1 -1
- package/dist/services/environment-custom-image-runtime.js +106 -7
- package/dist/services/environment-custom-image-runtime.js.map +1 -1
- package/dist/services/environment-custom-images.d.ts +31 -1
- package/dist/services/environment-custom-images.d.ts.map +1 -1
- package/dist/services/environment-custom-images.js +110 -4
- package/dist/services/environment-custom-images.js.map +1 -1
- package/dist/services/environment-execution-target.d.ts.map +1 -1
- package/dist/services/environment-execution-target.js +1 -3
- package/dist/services/environment-execution-target.js.map +1 -1
- package/dist/services/environment-probe.d.ts +1 -0
- package/dist/services/environment-probe.d.ts.map +1 -1
- package/dist/services/environment-probe.js +99 -5
- package/dist/services/environment-probe.js.map +1 -1
- package/dist/services/environments.d.ts +3 -1
- package/dist/services/environments.d.ts.map +1 -1
- package/dist/services/environments.js +98 -3
- package/dist/services/environments.js.map +1 -1
- package/dist/services/execution-workspace-policy.d.ts +29 -3
- package/dist/services/execution-workspace-policy.d.ts.map +1 -1
- package/dist/services/execution-workspace-policy.js +44 -1
- package/dist/services/execution-workspace-policy.js.map +1 -1
- package/dist/services/execution-workspaces.d.ts +64 -1
- package/dist/services/execution-workspaces.d.ts.map +1 -1
- package/dist/services/execution-workspaces.js +634 -3
- package/dist/services/execution-workspaces.js.map +1 -1
- package/dist/services/external-objects.d.ts +26 -26
- package/dist/services/feedback.d.ts +2 -2
- package/dist/services/finance.d.ts +5 -5
- package/dist/services/goals.d.ts +8 -8
- package/dist/services/heartbeat-stop-metadata.d.ts +2 -2
- package/dist/services/heartbeat-stop-metadata.d.ts.map +1 -1
- package/dist/services/heartbeat-stop-metadata.js +4 -0
- package/dist/services/heartbeat-stop-metadata.js.map +1 -1
- package/dist/services/heartbeat-stop-metadata.test.js +9 -0
- package/dist/services/heartbeat-stop-metadata.test.js.map +1 -1
- package/dist/services/heartbeat.d.ts +133 -28
- package/dist/services/heartbeat.d.ts.map +1 -1
- package/dist/services/heartbeat.js +1963 -239
- package/dist/services/heartbeat.js.map +1 -1
- package/dist/services/inbox-dismissals.d.ts +26 -0
- package/dist/services/inbox-dismissals.d.ts.map +1 -1
- package/dist/services/inbox-dismissals.js +33 -18
- package/dist/services/inbox-dismissals.js.map +1 -1
- package/dist/services/index.d.ts +3 -1
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +3 -1
- package/dist/services/index.js.map +1 -1
- package/dist/services/instance-settings.d.ts +25 -1
- package/dist/services/instance-settings.d.ts.map +1 -1
- package/dist/services/instance-settings.js +103 -5
- package/dist/services/instance-settings.js.map +1 -1
- package/dist/services/issue-continuation-summary.js +1 -1
- package/dist/services/issue-continuation-summary.js.map +1 -1
- package/dist/services/issue-recovery-actions.d.ts +3 -0
- package/dist/services/issue-recovery-actions.d.ts.map +1 -1
- package/dist/services/issue-recovery-actions.js +9 -0
- package/dist/services/issue-recovery-actions.js.map +1 -1
- package/dist/services/issue-rewake-throttle.d.ts +92 -0
- package/dist/services/issue-rewake-throttle.d.ts.map +1 -0
- package/dist/services/issue-rewake-throttle.js +139 -0
- package/dist/services/issue-rewake-throttle.js.map +1 -0
- package/dist/services/issue-thread-interactions.d.ts +8 -1
- package/dist/services/issue-thread-interactions.d.ts.map +1 -1
- package/dist/services/issue-thread-interactions.js +231 -16
- package/dist/services/issue-thread-interactions.js.map +1 -1
- package/dist/services/issue-visibility.d.ts +4 -0
- package/dist/services/issue-visibility.d.ts.map +1 -0
- package/dist/services/issue-visibility.js +9 -0
- package/dist/services/issue-visibility.js.map +1 -0
- package/dist/services/issues.d.ts +225 -105
- package/dist/services/issues.d.ts.map +1 -1
- package/dist/services/issues.js +540 -18
- package/dist/services/issues.js.map +1 -1
- package/dist/services/local-service-supervisor.d.ts +3 -0
- package/dist/services/local-service-supervisor.d.ts.map +1 -1
- package/dist/services/local-service-supervisor.js +51 -0
- package/dist/services/local-service-supervisor.js.map +1 -1
- package/dist/services/pipeline-case-outputs.d.ts.map +1 -1
- package/dist/services/pipeline-case-outputs.js +2 -1
- package/dist/services/pipeline-case-outputs.js.map +1 -1
- package/dist/services/pipelines-aggregation.d.ts.map +1 -1
- package/dist/services/pipelines-aggregation.js +3 -2
- package/dist/services/pipelines-aggregation.js.map +1 -1
- package/dist/services/pipelines.d.ts +165 -165
- package/dist/services/pipelines.d.ts.map +1 -1
- package/dist/services/pipelines.js +6 -4
- package/dist/services/pipelines.js.map +1 -1
- package/dist/services/plugin-database.d.ts +2 -2
- package/dist/services/plugin-environment-driver.d.ts +1 -1
- package/dist/services/plugin-host-services.d.ts.map +1 -1
- package/dist/services/plugin-host-services.js +3 -1
- package/dist/services/plugin-host-services.js.map +1 -1
- package/dist/services/plugin-managed-routines.d.ts +1 -0
- package/dist/services/plugin-managed-routines.d.ts.map +1 -1
- package/dist/services/plugin-registry.d.ts +21 -21
- package/dist/services/productivity-review.d.ts +1 -0
- package/dist/services/productivity-review.d.ts.map +1 -1
- package/dist/services/productivity-review.js +6 -5
- package/dist/services/productivity-review.js.map +1 -1
- package/dist/services/projects.d.ts +9 -9
- package/dist/services/recovery/service.d.ts +82 -54
- package/dist/services/recovery/service.d.ts.map +1 -1
- package/dist/services/recovery/service.js +200 -35
- package/dist/services/recovery/service.js.map +1 -1
- package/dist/services/recovery/successful-run-handoff.d.ts +1 -0
- package/dist/services/recovery/successful-run-handoff.d.ts.map +1 -1
- package/dist/services/recovery/successful-run-handoff.js +2 -0
- package/dist/services/recovery/successful-run-handoff.js.map +1 -1
- package/dist/services/recovery/successful-run-handoff.test.js +20 -0
- package/dist/services/recovery/successful-run-handoff.test.js.map +1 -1
- package/dist/services/resource-memberships.d.ts +13 -10
- package/dist/services/resource-memberships.d.ts.map +1 -1
- package/dist/services/resource-memberships.js +89 -20
- package/dist/services/resource-memberships.js.map +1 -1
- package/dist/services/responsible-user-denial-run-outcomes.d.ts +60 -0
- package/dist/services/responsible-user-denial-run-outcomes.d.ts.map +1 -0
- package/dist/services/responsible-user-denial-run-outcomes.js +56 -0
- package/dist/services/responsible-user-denial-run-outcomes.js.map +1 -0
- package/dist/services/responsible-user-denial-run-outcomes.test.d.ts +2 -0
- package/dist/services/responsible-user-denial-run-outcomes.test.d.ts.map +1 -0
- package/dist/services/responsible-user-denial-run-outcomes.test.js +75 -0
- package/dist/services/responsible-user-denial-run-outcomes.test.js.map +1 -0
- package/dist/services/routines.d.ts +30 -8
- package/dist/services/routines.d.ts.map +1 -1
- package/dist/services/routines.js +241 -18
- package/dist/services/routines.js.map +1 -1
- package/dist/services/run-liveness.d.ts.map +1 -1
- package/dist/services/run-liveness.js +21 -0
- package/dist/services/run-liveness.js.map +1 -1
- package/dist/services/run-log-store.d.ts +1 -0
- package/dist/services/run-log-store.d.ts.map +1 -1
- package/dist/services/run-log-store.js +4 -0
- package/dist/services/run-log-store.js.map +1 -1
- package/dist/services/run-scratch.d.ts +42 -0
- package/dist/services/run-scratch.d.ts.map +1 -0
- package/dist/services/run-scratch.js +111 -0
- package/dist/services/run-scratch.js.map +1 -0
- package/dist/services/run-scratch.test.d.ts +2 -0
- package/dist/services/run-scratch.test.d.ts.map +1 -0
- package/dist/services/run-scratch.test.js +98 -0
- package/dist/services/run-scratch.test.js.map +1 -0
- package/dist/services/secrets.d.ts +1261 -64
- package/dist/services/secrets.d.ts.map +1 -1
- package/dist/services/secrets.js +1089 -96
- package/dist/services/secrets.js.map +1 -1
- package/dist/services/task-watchdogs.d.ts +1 -0
- package/dist/services/task-watchdogs.d.ts.map +1 -1
- package/dist/services/task-watchdogs.js +78 -9
- package/dist/services/task-watchdogs.js.map +1 -1
- package/dist/services/work-timeline.d.ts.map +1 -1
- package/dist/services/work-timeline.js +34 -2
- package/dist/services/work-timeline.js.map +1 -1
- package/dist/services/workspace-runtime-read-model.d.ts +30 -29
- package/dist/services/workspace-runtime-read-model.d.ts.map +1 -1
- package/dist/services/workspace-runtime-read-model.js.map +1 -1
- package/dist/services/workspace-runtime.d.ts +59 -13
- package/dist/services/workspace-runtime.d.ts.map +1 -1
- package/dist/services/workspace-runtime.js +1121 -102
- package/dist/services/workspace-runtime.js.map +1 -1
- package/dist/skills-catalog/catalog/bundled/paperclip-operations/reflection-coach/SKILL.md +202 -0
- package/dist/skills-catalog/catalog/bundled/product/paperclip-capsules/SKILL.md +1 -1
- package/dist/skills-catalog/catalog/bundled/product/wireframe/SKILL.md +1 -1
- package/dist/skills-catalog/catalog/optional/content/release-announcement/SKILL.md +90 -0
- package/dist/skills-catalog/catalog/optional/finance/ramp/SKILL.md +98 -0
- package/dist/skills-catalog/generated/catalog.json +84 -12
- package/dist/ui-branding.d.ts +7 -0
- package/dist/ui-branding.d.ts.map +1 -1
- package/dist/ui-branding.js +8 -2
- package/dist/ui-branding.js.map +1 -1
- package/dist/version.d.ts +14 -0
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +114 -3
- package/dist/version.js.map +1 -1
- package/package.json +19 -20
- package/skills/paperclip/SKILL.md +45 -10
- package/skills/paperclip/references/api-reference.md +246 -1
- package/skills/paperclip/references/cases.md +295 -0
- package/skills/paperclip/references/company-skills.md +1 -1
- package/skills/paperclip-board/SKILL.md +3 -4
- package/skills/paperclip-converting-plans-to-tasks/SKILL.md +3 -7
- package/skills/para-memory-files/SKILL.md +3 -7
- package/ui-dist/assets/{abnfDiagram-VRR7QNED-BsFz2IiG.js → abnfDiagram-VRR7QNED-Dtgfy1PK.js} +1 -1
- package/ui-dist/assets/{arc-HZhAwbOs.js → arc-BGdvNvs8.js} +1 -1
- package/ui-dist/assets/{architectureDiagram-ZJ3FMSHR-BteMjuOn.js → architectureDiagram-ZJ3FMSHR-CK19SQDx.js} +1 -1
- package/ui-dist/assets/{blockDiagram-677ZJIJ3-Iq66uZjf.js → blockDiagram-677ZJIJ3-Kh4N3XG4.js} +1 -1
- package/ui-dist/assets/{browser-ponyfill-BBsuyZJt.js → browser-ponyfill-B3hXtEFW.js} +1 -1
- package/ui-dist/assets/{c4Diagram-LMCZKHZV-_nlglj7I.js → c4Diagram-LMCZKHZV-CBHpGrgU.js} +1 -1
- package/ui-dist/assets/channel-4fjB8e8N.js +1 -0
- package/ui-dist/assets/{chunk-2Q5K7J3B-Cvz7WwSQ.js → chunk-2Q5K7J3B-BdHbqi7k.js} +1 -1
- package/ui-dist/assets/{chunk-32BRIVSS-LLubniCS.js → chunk-32BRIVSS-DxtzZzpt.js} +1 -1
- package/ui-dist/assets/{chunk-5VM5RSS4-BOst5hcr.js → chunk-5VM5RSS4-DMKxBbgu.js} +1 -1
- package/ui-dist/assets/{chunk-EX3LRPZG-D5WNShVm.js → chunk-EX3LRPZG-BaIOPi4v.js} +1 -1
- package/ui-dist/assets/{chunk-JWPE2WC7-CA07x4av.js → chunk-JWPE2WC7-DGo3MPmr.js} +1 -1
- package/ui-dist/assets/{chunk-MOJQB5TN-Clfi83rK.js → chunk-MOJQB5TN-BEhQg0uD.js} +1 -1
- package/ui-dist/assets/{chunk-RYQCIY6F-BhZ6p7YJ.js → chunk-RYQCIY6F-HPJ6zRpJ.js} +1 -1
- package/ui-dist/assets/{chunk-V7JOEXUC-CdexJGoV.js → chunk-V7JOEXUC-Bl_6cAJD.js} +1 -1
- package/ui-dist/assets/{chunk-VR4S4FIN-8vjmBhr1.js → chunk-VR4S4FIN-KMjgGCsw.js} +1 -1
- package/ui-dist/assets/{chunk-XXDRQBXY-CqmCaplj.js → chunk-XXDRQBXY-oWGAIKjr.js} +1 -1
- package/ui-dist/assets/classDiagram-OUVF2IWQ-CTXxO5l9.js +1 -0
- package/ui-dist/assets/classDiagram-v2-EOCWNBFH-CTXxO5l9.js +1 -0
- package/ui-dist/assets/{cose-bilkent-JH36ORCC-CY-zAygY.js → cose-bilkent-JH36ORCC-Ckqse1pH.js} +1 -1
- package/ui-dist/assets/{cynefin-VYW2F7L2-BQSQ1HKr.js → cynefin-VYW2F7L2-DfZ8Hzqi.js} +1 -1
- package/ui-dist/assets/{cynefinDiagram-TSTJHNR4-NJCuFrZL.js → cynefinDiagram-TSTJHNR4-BkDQo9oi.js} +1 -1
- package/ui-dist/assets/{dagre-VKFMJZFB-DAUPIc8g.js → dagre-VKFMJZFB-ClghXQ6E.js} +1 -1
- package/ui-dist/assets/{diagram-FQU43EPY-DvMwJlCi.js → diagram-FQU43EPY-D5a0CwpV.js} +1 -1
- package/ui-dist/assets/{diagram-G47NLZAW-DPY0Jz_y.js → diagram-G47NLZAW-hVjYR_xl.js} +1 -1
- package/ui-dist/assets/{diagram-NH7WQ7WH-BpopeEhp.js → diagram-NH7WQ7WH-BlDPgD5Z.js} +1 -1
- package/ui-dist/assets/{diagram-OA4YK3LP-Qpu05z9X.js → diagram-OA4YK3LP-D0iZKIS3.js} +1 -1
- package/ui-dist/assets/{diagram-WEI45ONY-DHnvw9XU.js → diagram-WEI45ONY-m6hrfD0J.js} +1 -1
- package/ui-dist/assets/{ebnfDiagram-CCIWWBDH-D61S54_7.js → ebnfDiagram-CCIWWBDH-D4SQYLod.js} +1 -1
- package/ui-dist/assets/{erDiagram-Q63AITRT-pplAN_x2.js → erDiagram-Q63AITRT-Byzb6-I5.js} +1 -1
- package/ui-dist/assets/{flowDiagram-23GEKE2U-BaBcbyDq.js → flowDiagram-23GEKE2U-CaTUkFO6.js} +1 -1
- package/ui-dist/assets/{ganttDiagram-NO4QXBWP-BOJSII2b.js → ganttDiagram-NO4QXBWP-DmdMQ3ES.js} +1 -1
- package/ui-dist/assets/{gitGraphDiagram-IHSO6WYX-aYAaO4a2.js → gitGraphDiagram-IHSO6WYX-Bt-1g2CS.js} +1 -1
- package/ui-dist/assets/{index-CZxYajxF.js → index-2Dk9yO0W.js} +1 -1
- package/ui-dist/assets/{index-B8H0SHw1.js → index-8jLpgFNU.js} +1 -1
- package/ui-dist/assets/{index-3EKATXgc.js → index-AP_iimxs.js} +1 -1
- package/ui-dist/assets/{index-C2JgdjPa.js → index-BNJasQY9.js} +1 -1
- package/ui-dist/assets/{index-BaiskB3o.js → index-BO-aNmyX.js} +1 -1
- package/ui-dist/assets/{index-B5YenxAQ.js → index-BPCzCn1Y.js} +1 -1
- package/ui-dist/assets/{index-Da2kqT1M.js → index-BSLnLTb2.js} +1 -1
- package/ui-dist/assets/{index-By0oeEvz.js → index-CCZ2qgHN.js} +1 -1
- package/ui-dist/assets/{index-bUFCSEgv.js → index-CLZXR1k9.js} +1 -1
- package/ui-dist/assets/{index-CJlw4l9L.js → index-CTNfrE1s.js} +1 -1
- package/ui-dist/assets/{index-TmpY6Xh_.js → index-ChNd25s7.js} +1 -1
- package/ui-dist/assets/{index-BRgdHUNR.js → index-CjHiMOEO.js} +1 -1
- package/ui-dist/assets/{index-DrL6pHSJ.js → index-CmeJQpXZ.js} +1 -1
- package/ui-dist/assets/index-CyuYtn7U.css +1 -0
- package/ui-dist/assets/{index-CKKytnOd.js → index-CzZjM8eh.js} +1 -1
- package/ui-dist/assets/{index-Dceamza_.js → index-D-6T0Aft.js} +1 -1
- package/ui-dist/assets/{index-CjDqB1SX.js → index-DG_7V1pG.js} +1 -1
- package/ui-dist/assets/index-DIKcgxCt.js +676 -0
- package/ui-dist/assets/{index-BKVeJ3Jh.js → index-DiUerHmi.js} +1 -1
- package/ui-dist/assets/{index-C-nKjFZh.js → index-NZ7v5Fc2.js} +1 -1
- package/ui-dist/assets/{index-CvPPuNs1.js → index-Py70EvBg.js} +1 -1
- package/ui-dist/assets/{index-LHkZdu0h.js → index-R3aYn0qM.js} +1 -1
- package/ui-dist/assets/{index-BT8b79Bd.js → index-YXpm7gW-.js} +1 -1
- package/ui-dist/assets/{index-CemenVOf.js → index-n4q3gzki.js} +1 -1
- package/ui-dist/assets/{index-D3ODiUup.js → index-vlZ3GoYY.js} +1 -1
- package/ui-dist/assets/{infoDiagram-FWYZ7A6U-C7_90qGq.js → infoDiagram-FWYZ7A6U-jdi5ciVg.js} +1 -1
- package/ui-dist/assets/{ishikawaDiagram-FXEZZL3T-T-nPPdTt.js → ishikawaDiagram-FXEZZL3T-CMz5VvYp.js} +1 -1
- package/ui-dist/assets/{journeyDiagram-5HDEW3XC-C3hqQN0R.js → journeyDiagram-5HDEW3XC-DK6dk2R-.js} +1 -1
- package/ui-dist/assets/{kanban-definition-HUTT4EX6-CPoD9DUm.js → kanban-definition-HUTT4EX6-DX5cZL-D.js} +1 -1
- package/ui-dist/assets/{linear-D-S8yr3Z.js → linear-CI96ABKp.js} +1 -1
- package/ui-dist/assets/{mermaid.core-DhvH8shK.js → mermaid.core-DnsEVfbd.js} +4 -4
- package/ui-dist/assets/{mindmap-definition-LN4V7U3C-CxCIKrKo.js → mindmap-definition-LN4V7U3C-BdDCY7hf.js} +1 -1
- package/ui-dist/assets/{pegDiagram-2B236MQR-D4G-PC6N.js → pegDiagram-2B236MQR-DuY4TF-f.js} +1 -1
- package/ui-dist/assets/{pieDiagram-ENE6RG2P-N4X8UvqY.js → pieDiagram-ENE6RG2P-bgFw7dm3.js} +1 -1
- package/ui-dist/assets/{quadrantDiagram-ABIIQ3AL-CZohoDln.js → quadrantDiagram-ABIIQ3AL-BCZVWyWS.js} +1 -1
- package/ui-dist/assets/{railroadDiagram-RFXS5EU6-fMGQVhwF.js → railroadDiagram-RFXS5EU6-D9V5_Cgc.js} +1 -1
- package/ui-dist/assets/{requirementDiagram-TGXJPOKE-CK0IuUmk.js → requirementDiagram-TGXJPOKE-CItsya2r.js} +1 -1
- package/ui-dist/assets/{sankeyDiagram-HTMAVEWB-pSfb3CqG.js → sankeyDiagram-HTMAVEWB-Cz9IHsZO.js} +1 -1
- package/ui-dist/assets/{sequenceDiagram-DBY2YBRQ-CbhkqIeq.js → sequenceDiagram-DBY2YBRQ-hMSqTiwK.js} +1 -1
- package/ui-dist/assets/{sizeCapture-X5ZJPWSS-B6vqqPx-.js → sizeCapture-X5ZJPWSS-0g9M5wMf.js} +1 -1
- package/ui-dist/assets/{stateDiagram-2N3HPSRC-DIJf9h5C.js → stateDiagram-2N3HPSRC-F8_YhgWl.js} +1 -1
- package/ui-dist/assets/stateDiagram-v2-6OUMAXLB-fZImUBtq.js +1 -0
- package/ui-dist/assets/{swimlanes-5IMT3BWC-DIX_LV8O.js → swimlanes-5IMT3BWC-CCZqPbpE.js} +2 -2
- package/ui-dist/assets/swimlanesDiagram-G3AALYLV-9C1UT51R.js +8 -0
- package/ui-dist/assets/{timeline-definition-FHXFAJF6-CD-Pxb_g.js → timeline-definition-FHXFAJF6-BeUIr18x.js} +1 -1
- package/ui-dist/assets/{vennDiagram-L72KCM5P-BAZsWL0R.js → vennDiagram-L72KCM5P-D3d5h_G4.js} +1 -1
- package/ui-dist/assets/{wardleyDiagram-EHGQE667-CnNyfwX5.js → wardleyDiagram-EHGQE667-Bzt-As9A.js} +1 -1
- package/ui-dist/assets/{xychartDiagram-FW5EYKEG-j9YgsD3Y.js → xychartDiagram-FW5EYKEG-C2mly0xf.js} +1 -1
- package/ui-dist/fonts/InterVariable-Italic.woff2 +0 -0
- package/ui-dist/fonts/InterVariable.woff2 +0 -0
- package/ui-dist/fonts/NOTICE.md +17 -0
- package/ui-dist/index.html +2 -2
- package/ui-dist/locales/en/common.json +1142 -5
- package/ui-dist/locales/zh-CN/common.json +1140 -3
- package/ui-dist/assets/channel-CsiI2LYw.js +0 -1
- package/ui-dist/assets/classDiagram-OUVF2IWQ-CBn1Jqo8.js +0 -1
- package/ui-dist/assets/classDiagram-v2-EOCWNBFH-CBn1Jqo8.js +0 -1
- package/ui-dist/assets/index-BsL8K1vL.css +0 -1
- package/ui-dist/assets/index-D__fTsb2.js +0 -643
- package/ui-dist/assets/stateDiagram-v2-6OUMAXLB-DpwLD7YL.js +0 -1
- package/ui-dist/assets/swimlanesDiagram-G3AALYLV-Cklauutg.js +0 -8
package/dist/services/issues.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { Buffer } from "node:buffer";
|
|
2
2
|
import { createHash } from "node:crypto";
|
|
3
|
-
import { and, asc, desc, eq, gt, inArray, isNull, like, lt, ne, notInArray, or, sql } from "drizzle-orm";
|
|
4
|
-
import { activityLog, agentWakeupRequests, agents, authUsers, approvals, assets, companies, companyMemberships, documentRevisions, documents, goals, heartbeatRuns, executionWorkspaces, issueApprovals, issueAttachments, issueInboxArchives, issueLabels, issueWatchdogs, issuePlanDecompositions, issueRecoveryActions, issueRelations, issueComments, issueDocuments, issueReadStates, issueThreadInteractions, issues, labels, projectWorkspaces, projects, workspaceOperations, } from "@penclipai/db";
|
|
3
|
+
import { and, asc, desc, eq, gt, gte, inArray, isNull, like, lt, ne, notInArray, or, sql } from "drizzle-orm";
|
|
4
|
+
import { activityLog, agentWakeupRequests, agents, authUsers, approvals, assets, companies, companyMemberships, documentRevisions, documents, goals, heartbeatRuns, routineRuns, executionWorkspaces, issueApprovals, issueAttachments, issueInboxArchives, issueLabels, issueWatchdogs, issuePlanDecompositions, issueRecoveryActions, issueRelations, issueComments, issueDocuments, issueReadStates, issueThreadInteractions, issues, labels, projectWorkspaces, projects, workspaceOperations, } from "@penclipai/db";
|
|
5
5
|
import { clampIssueRequestDepth, extractAgentMentionIds, extractProjectMentionIds, issueCommentAuthorTypeSchema, issueCommentMetadataSchema, issueCommentPresentationSchema, isUuidLike, normalizeIssueIdentifier as normalizeIssueReferenceIdentifier, } from "@penclipai/shared";
|
|
6
6
|
import { conflict, HttpError, notFound, unprocessable } from "../errors.js";
|
|
7
7
|
import { logger } from "../middleware/logger.js";
|
|
8
|
-
import { defaultIssueExecutionWorkspaceSettingsForProject, gateProjectExecutionWorkspacePolicy, issueExecutionWorkspaceModeForPersistedWorkspace, parseIssueExecutionWorkspaceSettings, parseProjectExecutionWorkspacePolicy, } from "./execution-workspace-policy.js";
|
|
8
|
+
import { defaultIssueExecutionWorkspaceSettingsForProject, gateProjectExecutionWorkspacePolicy, issueExecutionWorkspaceModeForPersistedWorkspace, isUnrunnableWorktreeCombo, parseIssueExecutionWorkspaceSettings, parseProjectExecutionWorkspacePolicy, resolvePinnedIssueWorkspaceStrategyType, WORKSPACE_WORKTREE_REQUIRES_PROJECT_CODE, WORKSPACE_WORKTREE_REQUIRES_PROJECT_MESSAGE, WORKSPACE_WORKTREE_REQUIRES_PROJECT_REMEDIATION, } from "./execution-workspace-policy.js";
|
|
9
9
|
import { mergeExecutionWorkspaceConfig } from "./execution-workspaces.js";
|
|
10
10
|
import { buildInitialIssueMonitorFields, normalizeIssueExecutionPolicy } from "./issue-execution-policy.js";
|
|
11
11
|
import { instanceSettingsService } from "./instance-settings.js";
|
|
@@ -19,10 +19,20 @@ import { summarizeIssueWatchdog, upsertIssueWatchdogForIssue, } from "./task-wat
|
|
|
19
19
|
import { isVerifiedIssueTreeControlInteractionWake, issueTreeControlService, } from "./issue-tree-control.js";
|
|
20
20
|
import { parseIssueGraphLivenessIncidentKey, RECOVERY_ORIGIN_KINDS, } from "./recovery/origins.js";
|
|
21
21
|
import { classifyIssueGraphLiveness } from "./recovery/issue-graph-liveness.js";
|
|
22
|
+
import { visibleIssueCondition } from "./issue-visibility.js";
|
|
22
23
|
const ALL_ISSUE_STATUSES = ["backlog", "todo", "in_progress", "in_review", "blocked", "done", "cancelled"];
|
|
23
24
|
const MAX_ISSUE_COMMENT_PAGE_LIMIT = 500;
|
|
24
25
|
export const ISSUE_LIST_DEFAULT_LIMIT = 500;
|
|
25
26
|
export const ISSUE_LIST_MAX_LIMIT = 1000;
|
|
27
|
+
export const ISSUE_BLOCKER_DIAGNOSTICS_MAX_BLOCKERS = 100;
|
|
28
|
+
export const ISSUE_WAKE_DIAGNOSTICS_MAX_WAKE_REQUESTS = 50;
|
|
29
|
+
export const ISSUE_WAKE_DIAGNOSTICS_MAX_ACTIVITY_RECORDS = 50;
|
|
30
|
+
export const ISSUE_WAKE_DIAGNOSTICS_LOOKBACK_DAYS = 14;
|
|
31
|
+
export const ISSUE_SUBTREE_DIAGNOSTICS_MAX_DEPTH = 8;
|
|
32
|
+
export const ISSUE_SUBTREE_DIAGNOSTICS_MAX_NODES = 100;
|
|
33
|
+
export const ISSUE_SUBTREE_DIAGNOSTICS_MAX_BLOCKERS_PER_NODE = 20;
|
|
34
|
+
export const ISSUE_SUBTREE_DIAGNOSTICS_MAX_WAKE_REQUESTS_PER_NODE = 5;
|
|
35
|
+
export const ISSUE_SUBTREE_DIAGNOSTICS_MAX_ACTIVITY_RECORDS_PER_NODE = 5;
|
|
26
36
|
const ISSUE_LIST_RELATED_QUERY_CHUNK_SIZE = 500;
|
|
27
37
|
export const MAX_CHILD_ISSUES_CREATED_BY_HELPER = 25;
|
|
28
38
|
const MAX_CHILD_COMPLETION_SUMMARIES = 20;
|
|
@@ -37,6 +47,22 @@ const ISSUE_COMMENT_RUN_LOG_DERIVATION_CHUNK_BYTES = 256_000;
|
|
|
37
47
|
const ISSUE_COMMENT_RUN_LOG_DERIVATION_END_SLACK_MS = 60_000;
|
|
38
48
|
const ISSUE_COMMENT_RUN_LOG_DERIVATION_MAX_PARALLEL_READS = 8;
|
|
39
49
|
const DELETED_ISSUE_COMMENT_BODY = "";
|
|
50
|
+
const ISSUE_WAKE_DIAGNOSTICS_ACTIVITY_ACTIONS = ["issue.tree_hold_wakeup_deferred"];
|
|
51
|
+
function wakeRequestTargetsIssue(issueId) {
|
|
52
|
+
return sql `(
|
|
53
|
+
${agentWakeupRequests.payload} ->> 'issueId' = ${issueId}
|
|
54
|
+
or ${agentWakeupRequests.payload} ->> 'taskId' = ${issueId}
|
|
55
|
+
or ${agentWakeupRequests.payload} -> '_paperclipWakeContext' ->> 'issueId' = ${issueId}
|
|
56
|
+
or ${agentWakeupRequests.payload} -> '_paperclipWakeContext' ->> 'taskId' = ${issueId}
|
|
57
|
+
)`;
|
|
58
|
+
}
|
|
59
|
+
function wakeDiagnosticActivityTargetsIssue(issueId) {
|
|
60
|
+
return sql `(
|
|
61
|
+
(${activityLog.entityType} = 'issue' and ${activityLog.entityId} = ${issueId})
|
|
62
|
+
or ${activityLog.details} ->> 'issueId' = ${issueId}
|
|
63
|
+
or ${activityLog.details} ->> 'rootIssueId' = ${issueId}
|
|
64
|
+
)`;
|
|
65
|
+
}
|
|
40
66
|
function assertTransition(from, to) {
|
|
41
67
|
if (from === to)
|
|
42
68
|
return;
|
|
@@ -58,12 +84,82 @@ function applyStatusSideEffects(status, patch) {
|
|
|
58
84
|
}
|
|
59
85
|
return patch;
|
|
60
86
|
}
|
|
87
|
+
function workspaceWorktreeRequiresProjectDetails() {
|
|
88
|
+
return {
|
|
89
|
+
code: WORKSPACE_WORKTREE_REQUIRES_PROJECT_CODE,
|
|
90
|
+
remediation: WORKSPACE_WORKTREE_REQUIRES_PROJECT_REMEDIATION,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function assertExplicitPinnedWorktreeIssueRunnable(input) {
|
|
94
|
+
const settings = parseIssueExecutionWorkspaceSettings(input.executionWorkspaceSettings);
|
|
95
|
+
const mode = settings?.mode;
|
|
96
|
+
if (mode !== "isolated_workspace" && mode !== "operator_branch")
|
|
97
|
+
return;
|
|
98
|
+
const resolvedMode = mode;
|
|
99
|
+
if (isUnrunnableWorktreeCombo({
|
|
100
|
+
issue: {
|
|
101
|
+
projectId: input.projectId ?? null,
|
|
102
|
+
projectWorkspaceId: input.projectWorkspaceId ?? null,
|
|
103
|
+
executionWorkspaceId: input.executionWorkspaceId ?? null,
|
|
104
|
+
executionWorkspacePreference: input.executionWorkspacePreference ?? null,
|
|
105
|
+
},
|
|
106
|
+
resolvedMode,
|
|
107
|
+
resolvedStrategy: resolvePinnedIssueWorkspaceStrategyType({
|
|
108
|
+
mode: resolvedMode,
|
|
109
|
+
issueSettings: settings,
|
|
110
|
+
}),
|
|
111
|
+
hasResolvablePriorSessionWorkspace: false,
|
|
112
|
+
})) {
|
|
113
|
+
throw unprocessable(WORKSPACE_WORKTREE_REQUIRES_PROJECT_MESSAGE, workspaceWorktreeRequiresProjectDetails());
|
|
114
|
+
}
|
|
115
|
+
}
|
|
61
116
|
function readStringFromRecord(record, key) {
|
|
62
117
|
if (!record || typeof record !== "object")
|
|
63
118
|
return null;
|
|
64
119
|
const value = record[key];
|
|
65
120
|
return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
|
|
66
121
|
}
|
|
122
|
+
async function resolveResponsibleUserIdForIssueCreate(reader, companyId, input) {
|
|
123
|
+
const explicitResponsibleUserId = readStringFromRecord(input, "explicitResponsibleUserId");
|
|
124
|
+
if (explicitResponsibleUserId && input.trustExplicitResponsibleUserId === true)
|
|
125
|
+
return explicitResponsibleUserId;
|
|
126
|
+
if (input.originKind === "routine_execution" && input.originRunId) {
|
|
127
|
+
const routineRun = await reader
|
|
128
|
+
.select({ responsibleUserId: routineRuns.responsibleUserId })
|
|
129
|
+
.from(routineRuns)
|
|
130
|
+
.where(and(eq(routineRuns.companyId, companyId), eq(routineRuns.id, input.originRunId)))
|
|
131
|
+
.then((rows) => rows[0] ?? null);
|
|
132
|
+
if (routineRun?.responsibleUserId)
|
|
133
|
+
return routineRun.responsibleUserId;
|
|
134
|
+
}
|
|
135
|
+
const actorResponsibleUserId = readStringFromRecord(input, "actorResponsibleUserId");
|
|
136
|
+
if (actorResponsibleUserId)
|
|
137
|
+
return actorResponsibleUserId;
|
|
138
|
+
if (input.actorRunId) {
|
|
139
|
+
const actorRun = await reader
|
|
140
|
+
.select({ responsibleUserId: heartbeatRuns.responsibleUserId })
|
|
141
|
+
.from(heartbeatRuns)
|
|
142
|
+
.where(and(eq(heartbeatRuns.companyId, companyId), eq(heartbeatRuns.id, input.actorRunId)))
|
|
143
|
+
.then((rows) => rows[0] ?? null);
|
|
144
|
+
if (actorRun?.responsibleUserId)
|
|
145
|
+
return actorRun.responsibleUserId;
|
|
146
|
+
}
|
|
147
|
+
if (input.parentId) {
|
|
148
|
+
const parent = await reader
|
|
149
|
+
.select({
|
|
150
|
+
responsibleUserId: issues.responsibleUserId,
|
|
151
|
+
createdByUserId: issues.createdByUserId,
|
|
152
|
+
})
|
|
153
|
+
.from(issues)
|
|
154
|
+
.where(and(eq(issues.companyId, companyId), eq(issues.id, input.parentId)))
|
|
155
|
+
.then((rows) => rows[0] ?? null);
|
|
156
|
+
if (parent?.responsibleUserId)
|
|
157
|
+
return parent.responsibleUserId;
|
|
158
|
+
if (parent?.createdByUserId)
|
|
159
|
+
return parent.createdByUserId;
|
|
160
|
+
}
|
|
161
|
+
return input.createdByUserId ?? null;
|
|
162
|
+
}
|
|
67
163
|
function buildReusedExecutionWorkspaceConfigPatchFromIssueSettings(settings) {
|
|
68
164
|
return {
|
|
69
165
|
environmentId: settings?.environmentId ?? null,
|
|
@@ -72,6 +168,34 @@ function buildReusedExecutionWorkspaceConfigPatchFromIssueSettings(settings) {
|
|
|
72
168
|
workspaceRuntime: settings?.workspaceRuntime ?? null,
|
|
73
169
|
};
|
|
74
170
|
}
|
|
171
|
+
// Accepted-plan children are not realized yet, so carry only unresolved
|
|
172
|
+
// workspace intent and let the first child run render/persist its own branch.
|
|
173
|
+
function buildPreRealizationExecutionWorkspaceSettings(raw) {
|
|
174
|
+
const settings = parseIssueExecutionWorkspaceSettings(raw, { includeEnvironmentId: true });
|
|
175
|
+
if (!settings)
|
|
176
|
+
return null;
|
|
177
|
+
const mode = settings.mode && settings.mode !== "inherit" && settings.mode !== "reuse_existing"
|
|
178
|
+
? settings.mode
|
|
179
|
+
: null;
|
|
180
|
+
const next = {};
|
|
181
|
+
if (mode)
|
|
182
|
+
next.mode = mode;
|
|
183
|
+
if (settings.environmentId !== undefined)
|
|
184
|
+
next.environmentId = settings.environmentId;
|
|
185
|
+
if (settings.workspaceRuntime)
|
|
186
|
+
next.workspaceRuntime = settings.workspaceRuntime;
|
|
187
|
+
if (settings.workspaceStrategy) {
|
|
188
|
+
next.workspaceStrategy = {
|
|
189
|
+
type: settings.workspaceStrategy.type,
|
|
190
|
+
...(settings.workspaceStrategy.baseRef ? { baseRef: settings.workspaceStrategy.baseRef } : {}),
|
|
191
|
+
...(settings.workspaceStrategy.branchTemplate ? { branchTemplate: settings.workspaceStrategy.branchTemplate } : {}),
|
|
192
|
+
...(settings.workspaceStrategy.worktreeParentDir ? { worktreeParentDir: settings.workspaceStrategy.worktreeParentDir } : {}),
|
|
193
|
+
...(settings.workspaceStrategy.provisionCommand ? { provisionCommand: settings.workspaceStrategy.provisionCommand } : {}),
|
|
194
|
+
...(settings.workspaceStrategy.teardownCommand ? { teardownCommand: settings.workspaceStrategy.teardownCommand } : {}),
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
return Object.keys(next).length > 0 ? next : null;
|
|
198
|
+
}
|
|
75
199
|
function toTimestampMs(value) {
|
|
76
200
|
if (!value)
|
|
77
201
|
return null;
|
|
@@ -195,7 +319,7 @@ function sameRunLock(checkoutRunId, actorRunId) {
|
|
|
195
319
|
return checkoutRunId === actorRunId;
|
|
196
320
|
return checkoutRunId == null;
|
|
197
321
|
}
|
|
198
|
-
export const TERMINAL_HEARTBEAT_RUN_STATUSES = new Set(["succeeded", "failed", "cancelled", "timed_out"]);
|
|
322
|
+
export const TERMINAL_HEARTBEAT_RUN_STATUSES = new Set(["succeeded", "interrupted", "failed", "cancelled", "timed_out"]);
|
|
199
323
|
const ISSUE_LIST_DESCRIPTION_MAX_CHARS = 1200;
|
|
200
324
|
const ISSUE_LIST_DESCRIPTION_MAX_BYTES = ISSUE_LIST_DESCRIPTION_MAX_CHARS * 4;
|
|
201
325
|
function escapeLikePattern(value) {
|
|
@@ -277,6 +401,8 @@ const ACCEPTED_PLAN_DECOMPOSITION_FINGERPRINT_CHILD_METADATA_KEYS = new Set([
|
|
|
277
401
|
"updatedByUserId",
|
|
278
402
|
"actorAgentId",
|
|
279
403
|
"actorUserId",
|
|
404
|
+
"executionWorkspaceInheritanceMode",
|
|
405
|
+
"skipExecutionWorkspaceInheritance",
|
|
280
406
|
]);
|
|
281
407
|
function normalizeAcceptedPlanDecompositionFingerprintChild(child) {
|
|
282
408
|
return Object.fromEntries(Object.entries(child).filter(([key]) => !ACCEPTED_PLAN_DECOMPOSITION_FINGERPRINT_CHILD_METADATA_KEYS.has(key)));
|
|
@@ -1017,6 +1143,7 @@ async function liveDescendantCountMapForIssues(dbOrTx, companyId, issueIds) {
|
|
|
1017
1143
|
JOIN heartbeat_runs live_run ON live_run.id = live_issue.execution_run_id
|
|
1018
1144
|
WHERE live_issue.company_id = ${companyId}
|
|
1019
1145
|
AND live_issue.hidden_at IS NULL
|
|
1146
|
+
AND live_issue.harness_kind IS NULL
|
|
1020
1147
|
AND live_run.company_id = ${companyId}
|
|
1021
1148
|
AND live_run.status IN ('queued', 'running')
|
|
1022
1149
|
UNION
|
|
@@ -1025,6 +1152,7 @@ async function liveDescendantCountMapForIssues(dbOrTx, companyId, issueIds) {
|
|
|
1025
1152
|
JOIN issues live_issue ON live_issue.id::text = (live_run.context_snapshot ->> 'issueId')
|
|
1026
1153
|
WHERE live_issue.company_id = ${companyId}
|
|
1027
1154
|
AND live_issue.hidden_at IS NULL
|
|
1155
|
+
AND live_issue.harness_kind IS NULL
|
|
1028
1156
|
AND live_run.company_id = ${companyId}
|
|
1029
1157
|
AND live_run.status IN ('queued', 'running')
|
|
1030
1158
|
),
|
|
@@ -1034,6 +1162,7 @@ async function liveDescendantCountMapForIssues(dbOrTx, companyId, issueIds) {
|
|
|
1034
1162
|
JOIN issues parent ON parent.id = live_issues.parent_id
|
|
1035
1163
|
WHERE parent.company_id = ${companyId}
|
|
1036
1164
|
AND parent.hidden_at IS NULL
|
|
1165
|
+
AND parent.harness_kind IS NULL
|
|
1037
1166
|
UNION ALL
|
|
1038
1167
|
SELECT
|
|
1039
1168
|
live_ancestors.live_issue_id,
|
|
@@ -1044,6 +1173,7 @@ async function liveDescendantCountMapForIssues(dbOrTx, companyId, issueIds) {
|
|
|
1044
1173
|
JOIN issues parent ON parent.id = live_ancestors.next_parent_id
|
|
1045
1174
|
WHERE parent.company_id = ${companyId}
|
|
1046
1175
|
AND parent.hidden_at IS NULL
|
|
1176
|
+
AND parent.harness_kind IS NULL
|
|
1047
1177
|
AND NOT parent.id = ANY(live_ancestors.visited_issue_ids)
|
|
1048
1178
|
)
|
|
1049
1179
|
SELECT
|
|
@@ -1203,7 +1333,7 @@ async function listIssueProductivityReviewMap(dbOrTx, companyId, sourceIssueIds)
|
|
|
1203
1333
|
updatedAt: issues.updatedAt,
|
|
1204
1334
|
})
|
|
1205
1335
|
.from(issues)
|
|
1206
|
-
.where(and(eq(issues.companyId, companyId), eq(issues.originKind, PRODUCTIVITY_REVIEW_ORIGIN_KIND), inArray(issues.originId, chunk),
|
|
1336
|
+
.where(and(eq(issues.companyId, companyId), eq(issues.originKind, PRODUCTIVITY_REVIEW_ORIGIN_KIND), inArray(issues.originId, chunk), visibleIssueCondition(), notInArray(issues.status, PRODUCTIVITY_REVIEW_TERMINAL_STATUSES)))
|
|
1207
1337
|
.orderBy(desc(issues.createdAt), desc(issues.id));
|
|
1208
1338
|
reviewRows.push(...rows);
|
|
1209
1339
|
}
|
|
@@ -1400,7 +1530,7 @@ async function listIssueBlockerAttentionMap(dbOrTx, companyId, issueRows) {
|
|
|
1400
1530
|
const recoveryRows = await dbOrTx
|
|
1401
1531
|
.select({ id: issues.id, originId: issues.originId })
|
|
1402
1532
|
.from(issues)
|
|
1403
|
-
.where(and(eq(issues.companyId, companyId), eq(issues.originKind, BLOCKER_ATTENTION_OPEN_RECOVERY_ORIGIN_KIND),
|
|
1533
|
+
.where(and(eq(issues.companyId, companyId), eq(issues.originKind, BLOCKER_ATTENTION_OPEN_RECOVERY_ORIGIN_KIND), visibleIssueCondition(), notInArray(issues.status, BLOCKER_ATTENTION_OPEN_RECOVERY_TERMINAL_STATUSES)));
|
|
1404
1534
|
for (const row of recoveryRows) {
|
|
1405
1535
|
const parsed = parseIssueGraphLivenessIncidentKey(row.originId);
|
|
1406
1536
|
if (!parsed || parsed.companyId !== companyId)
|
|
@@ -1576,6 +1706,7 @@ const issueListSelect = {
|
|
|
1576
1706
|
`,
|
|
1577
1707
|
status: issues.status,
|
|
1578
1708
|
workMode: issues.workMode,
|
|
1709
|
+
harnessKind: issues.harnessKind,
|
|
1579
1710
|
priority: issues.priority,
|
|
1580
1711
|
assigneeAgentId: issues.assigneeAgentId,
|
|
1581
1712
|
assigneeUserId: issues.assigneeUserId,
|
|
@@ -1585,6 +1716,7 @@ const issueListSelect = {
|
|
|
1585
1716
|
executionLockedAt: issues.executionLockedAt,
|
|
1586
1717
|
createdByAgentId: issues.createdByAgentId,
|
|
1587
1718
|
createdByUserId: issues.createdByUserId,
|
|
1719
|
+
responsibleUserId: issues.responsibleUserId,
|
|
1588
1720
|
issueNumber: issues.issueNumber,
|
|
1589
1721
|
identifier: issues.identifier,
|
|
1590
1722
|
originKind: issues.originKind,
|
|
@@ -1984,7 +2116,7 @@ async function listIssueBlockedInboxAttentionMap(dbOrTx, companyId, issueRows) {
|
|
|
1984
2116
|
dbOrTx
|
|
1985
2117
|
.select()
|
|
1986
2118
|
.from(issues)
|
|
1987
|
-
.where(and(eq(issues.companyId, companyId),
|
|
2119
|
+
.where(and(eq(issues.companyId, companyId), visibleIssueCondition(), notInArray(issues.status, [...BLOCKED_INBOX_TERMINAL_STATUSES]))),
|
|
1988
2120
|
dbOrTx
|
|
1989
2121
|
.select({
|
|
1990
2122
|
companyId: issueRelations.companyId,
|
|
@@ -2345,7 +2477,7 @@ function assertValidAssigneeAgentFilter(assigneeAgentFilter) {
|
|
|
2345
2477
|
async function blockedInboxIssueConditions(dbOrTx, companyId, filters) {
|
|
2346
2478
|
const conditions = [
|
|
2347
2479
|
eq(issues.companyId, companyId),
|
|
2348
|
-
|
|
2480
|
+
visibleIssueCondition(),
|
|
2349
2481
|
notInArray(issues.status, [...BLOCKED_INBOX_TERMINAL_STATUSES]),
|
|
2350
2482
|
];
|
|
2351
2483
|
const touchedByUserId = filters?.touchedByUserId?.trim() || undefined;
|
|
@@ -3268,7 +3400,7 @@ export function issueService(db) {
|
|
|
3268
3400
|
includeBlockedInboxAttention: true,
|
|
3269
3401
|
});
|
|
3270
3402
|
}
|
|
3271
|
-
const conditions = [eq(issues.companyId, companyId)];
|
|
3403
|
+
const conditions = [eq(issues.companyId, companyId), visibleIssueCondition()];
|
|
3272
3404
|
const assigneeAgentFilter = parseIssueAssigneeAgentFilter(filters?.assigneeAgentId);
|
|
3273
3405
|
assertValidAssigneeAgentFilter(assigneeAgentFilter);
|
|
3274
3406
|
const limit = typeof filters?.limit === "number" && Number.isFinite(filters.limit)
|
|
@@ -3390,7 +3522,6 @@ export function issueService(db) {
|
|
|
3390
3522
|
if (filters?.excludeRoutineExecutions && !filters?.originKind && !filters?.originId) {
|
|
3391
3523
|
conditions.push(ne(issues.originKind, "routine_execution"));
|
|
3392
3524
|
}
|
|
3393
|
-
conditions.push(isNull(issues.hiddenAt));
|
|
3394
3525
|
const priorityOrder = sql `CASE ${issues.priority} WHEN 'critical' THEN 0 WHEN 'high' THEN 1 WHEN 'medium' THEN 2 WHEN 'low' THEN 3 ELSE 4 END`;
|
|
3395
3526
|
const searchOrder = sql `
|
|
3396
3527
|
CASE
|
|
@@ -3495,7 +3626,7 @@ export function issueService(db) {
|
|
|
3495
3626
|
if (filters?.attention === "blocked") {
|
|
3496
3627
|
return countBlockedInboxIssues(db, companyId, filters);
|
|
3497
3628
|
}
|
|
3498
|
-
const conditions = [eq(issues.companyId, companyId),
|
|
3629
|
+
const conditions = [eq(issues.companyId, companyId), visibleIssueCondition()];
|
|
3499
3630
|
const statuses = parseStatusFilter(filters?.status);
|
|
3500
3631
|
if (statuses.length === 1)
|
|
3501
3632
|
conditions.push(eq(issues.status, statuses[0]));
|
|
@@ -3540,7 +3671,7 @@ export function issueService(db) {
|
|
|
3540
3671
|
countUnreadTouchedByUser: async (companyId, userId, status) => {
|
|
3541
3672
|
const conditions = [
|
|
3542
3673
|
eq(issues.companyId, companyId),
|
|
3543
|
-
|
|
3674
|
+
visibleIssueCondition(),
|
|
3544
3675
|
nonPluginOperationIssueCondition(),
|
|
3545
3676
|
unreadForUserCondition(companyId, userId),
|
|
3546
3677
|
];
|
|
@@ -3648,6 +3779,348 @@ export function issueService(db) {
|
|
|
3648
3779
|
const relations = await getIssueRelationSummaryMap(issue.companyId, [issueId], db);
|
|
3649
3780
|
return relations.get(issueId) ?? { blockedBy: [], blocks: [] };
|
|
3650
3781
|
},
|
|
3782
|
+
getBlockerDiagnostics: async (issueId, maxBlockers = ISSUE_BLOCKER_DIAGNOSTICS_MAX_BLOCKERS) => {
|
|
3783
|
+
const issue = await db
|
|
3784
|
+
.select({ id: issues.id, companyId: issues.companyId })
|
|
3785
|
+
.from(issues)
|
|
3786
|
+
.where(eq(issues.id, issueId))
|
|
3787
|
+
.then((rows) => rows[0] ?? null);
|
|
3788
|
+
if (!issue)
|
|
3789
|
+
throw notFound("Issue not found");
|
|
3790
|
+
const cappedMax = Math.max(0, Math.min(maxBlockers, ISSUE_BLOCKER_DIAGNOSTICS_MAX_BLOCKERS));
|
|
3791
|
+
const blockerRows = await db
|
|
3792
|
+
.select({
|
|
3793
|
+
id: issues.id,
|
|
3794
|
+
companyId: issues.companyId,
|
|
3795
|
+
projectId: issues.projectId,
|
|
3796
|
+
parentId: issues.parentId,
|
|
3797
|
+
identifier: issues.identifier,
|
|
3798
|
+
title: issues.title,
|
|
3799
|
+
status: issues.status,
|
|
3800
|
+
priority: issues.priority,
|
|
3801
|
+
assigneeAgentId: issues.assigneeAgentId,
|
|
3802
|
+
assigneeUserId: issues.assigneeUserId,
|
|
3803
|
+
})
|
|
3804
|
+
.from(issueRelations)
|
|
3805
|
+
.innerJoin(issues, eq(issueRelations.issueId, issues.id))
|
|
3806
|
+
.where(and(eq(issueRelations.companyId, issue.companyId), eq(issueRelations.type, "blocks"), eq(issueRelations.relatedIssueId, issue.id), eq(issues.companyId, issue.companyId)))
|
|
3807
|
+
.orderBy(asc(issues.title), asc(issues.id))
|
|
3808
|
+
.limit(cappedMax + 1);
|
|
3809
|
+
const readiness = await listIssueDependencyReadinessMap(db, issue.companyId, [issue.id]);
|
|
3810
|
+
return {
|
|
3811
|
+
blockers: blockerRows.slice(0, cappedMax),
|
|
3812
|
+
readiness: readiness.get(issue.id) ?? createIssueDependencyReadiness(issue.id),
|
|
3813
|
+
truncated: blockerRows.length > cappedMax,
|
|
3814
|
+
};
|
|
3815
|
+
},
|
|
3816
|
+
getWakeDiagnostics: async (issueId, opts) => {
|
|
3817
|
+
const issue = await db
|
|
3818
|
+
.select({ id: issues.id, companyId: issues.companyId })
|
|
3819
|
+
.from(issues)
|
|
3820
|
+
.where(eq(issues.id, issueId))
|
|
3821
|
+
.then((rows) => rows[0] ?? null);
|
|
3822
|
+
if (!issue)
|
|
3823
|
+
throw notFound("Issue not found");
|
|
3824
|
+
const maxWakeRequests = Math.max(0, Math.min(opts?.maxWakeRequests ?? ISSUE_WAKE_DIAGNOSTICS_MAX_WAKE_REQUESTS, ISSUE_WAKE_DIAGNOSTICS_MAX_WAKE_REQUESTS));
|
|
3825
|
+
const maxActivityRecords = Math.max(0, Math.min(opts?.maxActivityRecords ?? ISSUE_WAKE_DIAGNOSTICS_MAX_ACTIVITY_RECORDS, ISSUE_WAKE_DIAGNOSTICS_MAX_ACTIVITY_RECORDS));
|
|
3826
|
+
const lookbackDays = Math.max(1, Math.min(opts?.lookbackDays ?? ISSUE_WAKE_DIAGNOSTICS_LOOKBACK_DAYS, ISSUE_WAKE_DIAGNOSTICS_LOOKBACK_DAYS));
|
|
3827
|
+
const since = new Date(Date.now() - lookbackDays * 24 * 60 * 60 * 1000);
|
|
3828
|
+
const wakeRows = await db
|
|
3829
|
+
.select({
|
|
3830
|
+
agentId: agentWakeupRequests.agentId,
|
|
3831
|
+
source: agentWakeupRequests.source,
|
|
3832
|
+
reason: agentWakeupRequests.reason,
|
|
3833
|
+
status: agentWakeupRequests.status,
|
|
3834
|
+
coalescedCount: agentWakeupRequests.coalescedCount,
|
|
3835
|
+
runId: agentWakeupRequests.runId,
|
|
3836
|
+
requestedAt: agentWakeupRequests.requestedAt,
|
|
3837
|
+
claimedAt: agentWakeupRequests.claimedAt,
|
|
3838
|
+
finishedAt: agentWakeupRequests.finishedAt,
|
|
3839
|
+
error: agentWakeupRequests.error,
|
|
3840
|
+
})
|
|
3841
|
+
.from(agentWakeupRequests)
|
|
3842
|
+
.where(and(eq(agentWakeupRequests.companyId, issue.companyId), gte(agentWakeupRequests.requestedAt, since), wakeRequestTargetsIssue(issue.id)))
|
|
3843
|
+
.orderBy(desc(agentWakeupRequests.requestedAt), desc(agentWakeupRequests.createdAt))
|
|
3844
|
+
.limit(maxWakeRequests + 1);
|
|
3845
|
+
const activityRows = await db
|
|
3846
|
+
.select({
|
|
3847
|
+
action: activityLog.action,
|
|
3848
|
+
entityType: activityLog.entityType,
|
|
3849
|
+
entityId: activityLog.entityId,
|
|
3850
|
+
agentId: activityLog.agentId,
|
|
3851
|
+
runId: activityLog.runId,
|
|
3852
|
+
details: activityLog.details,
|
|
3853
|
+
createdAt: activityLog.createdAt,
|
|
3854
|
+
})
|
|
3855
|
+
.from(activityLog)
|
|
3856
|
+
.where(and(eq(activityLog.companyId, issue.companyId), gte(activityLog.createdAt, since), inArray(activityLog.action, [...ISSUE_WAKE_DIAGNOSTICS_ACTIVITY_ACTIONS]), wakeDiagnosticActivityTargetsIssue(issue.id)))
|
|
3857
|
+
.orderBy(desc(activityLog.createdAt))
|
|
3858
|
+
.limit(maxActivityRecords + 1);
|
|
3859
|
+
return {
|
|
3860
|
+
wakeRequests: wakeRows.slice(0, maxWakeRequests),
|
|
3861
|
+
activityRecords: activityRows.slice(0, maxActivityRecords),
|
|
3862
|
+
truncatedWakeRequests: wakeRows.length > maxWakeRequests,
|
|
3863
|
+
truncatedActivityRecords: activityRows.length > maxActivityRecords,
|
|
3864
|
+
caps: {
|
|
3865
|
+
maxWakeRequests: ISSUE_WAKE_DIAGNOSTICS_MAX_WAKE_REQUESTS,
|
|
3866
|
+
maxActivityRecords: ISSUE_WAKE_DIAGNOSTICS_MAX_ACTIVITY_RECORDS,
|
|
3867
|
+
lookbackDays: ISSUE_WAKE_DIAGNOSTICS_LOOKBACK_DAYS,
|
|
3868
|
+
},
|
|
3869
|
+
};
|
|
3870
|
+
},
|
|
3871
|
+
getSubtreeDiagnostics: async (issueId, opts) => {
|
|
3872
|
+
const issue = await db
|
|
3873
|
+
.select({ id: issues.id, companyId: issues.companyId })
|
|
3874
|
+
.from(issues)
|
|
3875
|
+
.where(eq(issues.id, issueId))
|
|
3876
|
+
.then((rows) => rows[0] ?? null);
|
|
3877
|
+
if (!issue)
|
|
3878
|
+
throw notFound("Issue not found");
|
|
3879
|
+
const maxDepth = Math.max(0, Math.min(opts?.maxDepth ?? ISSUE_SUBTREE_DIAGNOSTICS_MAX_DEPTH, ISSUE_SUBTREE_DIAGNOSTICS_MAX_DEPTH));
|
|
3880
|
+
const maxNodes = Math.max(1, Math.min(opts?.maxNodes ?? ISSUE_SUBTREE_DIAGNOSTICS_MAX_NODES, ISSUE_SUBTREE_DIAGNOSTICS_MAX_NODES));
|
|
3881
|
+
const maxBlockersPerNode = Math.max(0, Math.min(opts?.maxBlockersPerNode ?? ISSUE_SUBTREE_DIAGNOSTICS_MAX_BLOCKERS_PER_NODE, ISSUE_SUBTREE_DIAGNOSTICS_MAX_BLOCKERS_PER_NODE));
|
|
3882
|
+
const maxWakeRequestsPerNode = Math.max(0, Math.min(opts?.maxWakeRequestsPerNode ?? ISSUE_SUBTREE_DIAGNOSTICS_MAX_WAKE_REQUESTS_PER_NODE, ISSUE_SUBTREE_DIAGNOSTICS_MAX_WAKE_REQUESTS_PER_NODE));
|
|
3883
|
+
const maxActivityRecordsPerNode = Math.max(0, Math.min(opts?.maxActivityRecordsPerNode ?? ISSUE_SUBTREE_DIAGNOSTICS_MAX_ACTIVITY_RECORDS_PER_NODE, ISSUE_SUBTREE_DIAGNOSTICS_MAX_ACTIVITY_RECORDS_PER_NODE));
|
|
3884
|
+
const lookbackDays = Math.max(1, Math.min(opts?.lookbackDays ?? ISSUE_WAKE_DIAGNOSTICS_LOOKBACK_DAYS, ISSUE_WAKE_DIAGNOSTICS_LOOKBACK_DAYS));
|
|
3885
|
+
const since = new Date(Date.now() - lookbackDays * 24 * 60 * 60 * 1000);
|
|
3886
|
+
const sinceIso = since.toISOString();
|
|
3887
|
+
const rawSubtreeRows = await db.execute(sql `
|
|
3888
|
+
WITH RECURSIVE issue_tree AS (
|
|
3889
|
+
SELECT
|
|
3890
|
+
id,
|
|
3891
|
+
company_id,
|
|
3892
|
+
project_id,
|
|
3893
|
+
parent_id,
|
|
3894
|
+
identifier,
|
|
3895
|
+
title,
|
|
3896
|
+
status,
|
|
3897
|
+
priority,
|
|
3898
|
+
assignee_agent_id,
|
|
3899
|
+
assignee_user_id,
|
|
3900
|
+
created_at,
|
|
3901
|
+
updated_at,
|
|
3902
|
+
0 AS depth,
|
|
3903
|
+
ARRAY[id] AS path
|
|
3904
|
+
FROM issues
|
|
3905
|
+
WHERE company_id = ${issue.companyId}
|
|
3906
|
+
AND id = ${issue.id}
|
|
3907
|
+
AND hidden_at IS NULL
|
|
3908
|
+
AND harness_kind IS NULL
|
|
3909
|
+
UNION ALL
|
|
3910
|
+
SELECT
|
|
3911
|
+
child.id,
|
|
3912
|
+
child.company_id,
|
|
3913
|
+
child.project_id,
|
|
3914
|
+
child.parent_id,
|
|
3915
|
+
child.identifier,
|
|
3916
|
+
child.title,
|
|
3917
|
+
child.status,
|
|
3918
|
+
child.priority,
|
|
3919
|
+
child.assignee_agent_id,
|
|
3920
|
+
child.assignee_user_id,
|
|
3921
|
+
child.created_at,
|
|
3922
|
+
child.updated_at,
|
|
3923
|
+
issue_tree.depth + 1,
|
|
3924
|
+
issue_tree.path || child.id
|
|
3925
|
+
FROM issues child
|
|
3926
|
+
JOIN issue_tree ON child.parent_id = issue_tree.id
|
|
3927
|
+
WHERE child.company_id = ${issue.companyId}
|
|
3928
|
+
AND child.hidden_at IS NULL
|
|
3929
|
+
AND child.harness_kind IS NULL
|
|
3930
|
+
AND issue_tree.depth < ${maxDepth + 1}
|
|
3931
|
+
AND NOT child.id = ANY(issue_tree.path)
|
|
3932
|
+
)
|
|
3933
|
+
SELECT
|
|
3934
|
+
id,
|
|
3935
|
+
company_id AS "companyId",
|
|
3936
|
+
project_id AS "projectId",
|
|
3937
|
+
parent_id AS "parentId",
|
|
3938
|
+
identifier,
|
|
3939
|
+
title,
|
|
3940
|
+
status,
|
|
3941
|
+
priority,
|
|
3942
|
+
assignee_agent_id AS "assigneeAgentId",
|
|
3943
|
+
assignee_user_id AS "assigneeUserId",
|
|
3944
|
+
created_at AS "createdAt",
|
|
3945
|
+
updated_at AS "updatedAt",
|
|
3946
|
+
depth::int AS depth
|
|
3947
|
+
FROM issue_tree
|
|
3948
|
+
ORDER BY depth ASC, created_at ASC, id ASC
|
|
3949
|
+
LIMIT ${maxNodes + 1}
|
|
3950
|
+
`);
|
|
3951
|
+
const subtreeRows = Array.from(rawSubtreeRows)
|
|
3952
|
+
.map((row) => ({ ...row, depth: Number(row.depth) }));
|
|
3953
|
+
const rowsWithinDepth = subtreeRows.filter((row) => row.depth <= maxDepth);
|
|
3954
|
+
const nodes = rowsWithinDepth.slice(0, maxNodes);
|
|
3955
|
+
const truncatedNodes = rowsWithinDepth.length > maxNodes;
|
|
3956
|
+
const truncatedDepth = truncatedNodes || subtreeRows.some((row) => row.depth > maxDepth);
|
|
3957
|
+
const nodeIds = nodes.map((node) => node.id);
|
|
3958
|
+
const readiness = nodeIds.length > 0
|
|
3959
|
+
? await listIssueDependencyReadinessMap(db, issue.companyId, nodeIds)
|
|
3960
|
+
: new Map();
|
|
3961
|
+
const blockersByIssueId = new Map();
|
|
3962
|
+
const wakeRequestsByIssueId = new Map();
|
|
3963
|
+
const activityRecordsByIssueId = new Map();
|
|
3964
|
+
const truncatedBlockerIssueIds = new Set();
|
|
3965
|
+
const truncatedWakeIssueIds = new Set();
|
|
3966
|
+
const truncatedActivityIssueIds = new Set();
|
|
3967
|
+
if (nodeIds.length > 0) {
|
|
3968
|
+
const nodeIdValues = sql.join(nodeIds.map((id) => sql `${id}`), sql `, `);
|
|
3969
|
+
const rawBlockerRows = Array.from(await db.execute(sql `
|
|
3970
|
+
WITH blocker_rows AS (
|
|
3971
|
+
SELECT
|
|
3972
|
+
blocker.id,
|
|
3973
|
+
blocker.company_id AS "companyId",
|
|
3974
|
+
blocker.project_id AS "projectId",
|
|
3975
|
+
blocker.parent_id AS "parentId",
|
|
3976
|
+
blocker.identifier,
|
|
3977
|
+
blocker.title,
|
|
3978
|
+
blocker.status,
|
|
3979
|
+
blocker.priority,
|
|
3980
|
+
blocker.assignee_agent_id AS "assigneeAgentId",
|
|
3981
|
+
blocker.assignee_user_id AS "assigneeUserId",
|
|
3982
|
+
relation.related_issue_id AS "blockedIssueId",
|
|
3983
|
+
relation.created_at AS "relationCreatedAt",
|
|
3984
|
+
row_number() OVER (
|
|
3985
|
+
PARTITION BY relation.related_issue_id
|
|
3986
|
+
ORDER BY blocker.title ASC, blocker.id ASC
|
|
3987
|
+
)::int AS "rowNumber"
|
|
3988
|
+
FROM issue_relations relation
|
|
3989
|
+
INNER JOIN issues blocker ON blocker.id = relation.issue_id
|
|
3990
|
+
WHERE relation.company_id = ${issue.companyId}
|
|
3991
|
+
AND relation.type = 'blocks'
|
|
3992
|
+
AND blocker.company_id = ${issue.companyId}
|
|
3993
|
+
AND blocker.hidden_at IS NULL
|
|
3994
|
+
AND blocker.harness_kind IS NULL
|
|
3995
|
+
AND relation.related_issue_id::text IN (${nodeIdValues})
|
|
3996
|
+
)
|
|
3997
|
+
SELECT *
|
|
3998
|
+
FROM blocker_rows
|
|
3999
|
+
WHERE "rowNumber" <= ${maxBlockersPerNode + 1}
|
|
4000
|
+
ORDER BY "blockedIssueId" ASC, "rowNumber" ASC
|
|
4001
|
+
`));
|
|
4002
|
+
for (const row of rawBlockerRows) {
|
|
4003
|
+
const normalized = { ...row, rowNumber: Number(row.rowNumber) };
|
|
4004
|
+
if (normalized.rowNumber > maxBlockersPerNode) {
|
|
4005
|
+
truncatedBlockerIssueIds.add(normalized.blockedIssueId);
|
|
4006
|
+
continue;
|
|
4007
|
+
}
|
|
4008
|
+
const rows = blockersByIssueId.get(normalized.blockedIssueId) ?? [];
|
|
4009
|
+
rows.push(normalized);
|
|
4010
|
+
blockersByIssueId.set(normalized.blockedIssueId, rows);
|
|
4011
|
+
}
|
|
4012
|
+
const wakeTargetIssueIdSql = sql `
|
|
4013
|
+
coalesce(
|
|
4014
|
+
wake.payload ->> 'issueId',
|
|
4015
|
+
wake.payload ->> 'taskId',
|
|
4016
|
+
wake.payload -> '_paperclipWakeContext' ->> 'issueId',
|
|
4017
|
+
wake.payload -> '_paperclipWakeContext' ->> 'taskId'
|
|
4018
|
+
)
|
|
4019
|
+
`;
|
|
4020
|
+
const rawWakeRows = Array.from(await db.execute(sql `
|
|
4021
|
+
WITH wake_rows AS (
|
|
4022
|
+
SELECT
|
|
4023
|
+
${wakeTargetIssueIdSql} AS "issueId",
|
|
4024
|
+
wake.agent_id AS "agentId",
|
|
4025
|
+
wake.source,
|
|
4026
|
+
wake.reason,
|
|
4027
|
+
wake.status,
|
|
4028
|
+
wake.coalesced_count AS "coalescedCount",
|
|
4029
|
+
wake.run_id AS "runId",
|
|
4030
|
+
wake.requested_at AS "requestedAt",
|
|
4031
|
+
wake.claimed_at AS "claimedAt",
|
|
4032
|
+
wake.finished_at AS "finishedAt",
|
|
4033
|
+
wake.error,
|
|
4034
|
+
row_number() OVER (
|
|
4035
|
+
PARTITION BY ${wakeTargetIssueIdSql}
|
|
4036
|
+
ORDER BY wake.requested_at DESC, wake.created_at DESC
|
|
4037
|
+
)::int AS "rowNumber"
|
|
4038
|
+
FROM agent_wakeup_requests wake
|
|
4039
|
+
WHERE wake.company_id = ${issue.companyId}
|
|
4040
|
+
AND wake.requested_at >= ${sinceIso}::timestamptz
|
|
4041
|
+
AND ${wakeTargetIssueIdSql} IN (${nodeIdValues})
|
|
4042
|
+
)
|
|
4043
|
+
SELECT *
|
|
4044
|
+
FROM wake_rows
|
|
4045
|
+
WHERE "rowNumber" <= ${maxWakeRequestsPerNode + 1}
|
|
4046
|
+
ORDER BY "issueId" ASC, "requestedAt" DESC
|
|
4047
|
+
`));
|
|
4048
|
+
for (const row of rawWakeRows) {
|
|
4049
|
+
const normalized = { ...row, rowNumber: Number(row.rowNumber) };
|
|
4050
|
+
if (normalized.rowNumber > maxWakeRequestsPerNode) {
|
|
4051
|
+
truncatedWakeIssueIds.add(normalized.issueId);
|
|
4052
|
+
continue;
|
|
4053
|
+
}
|
|
4054
|
+
const rows = wakeRequestsByIssueId.get(normalized.issueId) ?? [];
|
|
4055
|
+
rows.push(normalized);
|
|
4056
|
+
wakeRequestsByIssueId.set(normalized.issueId, rows);
|
|
4057
|
+
}
|
|
4058
|
+
const activityTargetIssueIdSql = sql `
|
|
4059
|
+
coalesce(
|
|
4060
|
+
CASE WHEN activity.entity_type = 'issue' THEN activity.entity_id ELSE NULL END,
|
|
4061
|
+
activity.details ->> 'issueId',
|
|
4062
|
+
activity.details ->> 'rootIssueId'
|
|
4063
|
+
)
|
|
4064
|
+
`;
|
|
4065
|
+
const activityActionValues = sql.join(ISSUE_WAKE_DIAGNOSTICS_ACTIVITY_ACTIONS.map((action) => sql `${action}`), sql `, `);
|
|
4066
|
+
const rawActivityRows = Array.from(await db.execute(sql `
|
|
4067
|
+
WITH activity_rows AS (
|
|
4068
|
+
SELECT
|
|
4069
|
+
${activityTargetIssueIdSql} AS "issueId",
|
|
4070
|
+
activity.action,
|
|
4071
|
+
activity.entity_type AS "entityType",
|
|
4072
|
+
activity.entity_id AS "entityId",
|
|
4073
|
+
activity.agent_id AS "agentId",
|
|
4074
|
+
activity.run_id AS "runId",
|
|
4075
|
+
activity.details,
|
|
4076
|
+
activity.created_at AS "createdAt",
|
|
4077
|
+
row_number() OVER (
|
|
4078
|
+
PARTITION BY ${activityTargetIssueIdSql}
|
|
4079
|
+
ORDER BY activity.created_at DESC, activity.id DESC
|
|
4080
|
+
)::int AS "rowNumber"
|
|
4081
|
+
FROM activity_log activity
|
|
4082
|
+
WHERE activity.company_id = ${issue.companyId}
|
|
4083
|
+
AND activity.created_at >= ${sinceIso}::timestamptz
|
|
4084
|
+
AND activity.action IN (${activityActionValues})
|
|
4085
|
+
AND ${activityTargetIssueIdSql} IN (${nodeIdValues})
|
|
4086
|
+
)
|
|
4087
|
+
SELECT *
|
|
4088
|
+
FROM activity_rows
|
|
4089
|
+
WHERE "rowNumber" <= ${maxActivityRecordsPerNode + 1}
|
|
4090
|
+
ORDER BY "issueId" ASC, "createdAt" DESC
|
|
4091
|
+
`));
|
|
4092
|
+
for (const row of rawActivityRows) {
|
|
4093
|
+
const normalized = { ...row, rowNumber: Number(row.rowNumber) };
|
|
4094
|
+
if (normalized.rowNumber > maxActivityRecordsPerNode) {
|
|
4095
|
+
truncatedActivityIssueIds.add(normalized.issueId);
|
|
4096
|
+
continue;
|
|
4097
|
+
}
|
|
4098
|
+
const rows = activityRecordsByIssueId.get(normalized.issueId) ?? [];
|
|
4099
|
+
rows.push(normalized);
|
|
4100
|
+
activityRecordsByIssueId.set(normalized.issueId, rows);
|
|
4101
|
+
}
|
|
4102
|
+
}
|
|
4103
|
+
return {
|
|
4104
|
+
nodes,
|
|
4105
|
+
blockersByIssueId,
|
|
4106
|
+
readinessByIssueId: readiness,
|
|
4107
|
+
wakeRequestsByIssueId,
|
|
4108
|
+
activityRecordsByIssueId,
|
|
4109
|
+
truncatedNodes,
|
|
4110
|
+
truncatedDepth,
|
|
4111
|
+
truncatedBlockerIssueIds,
|
|
4112
|
+
truncatedWakeIssueIds,
|
|
4113
|
+
truncatedActivityIssueIds,
|
|
4114
|
+
caps: {
|
|
4115
|
+
maxDepth,
|
|
4116
|
+
maxNodes,
|
|
4117
|
+
maxBlockersPerNode,
|
|
4118
|
+
maxWakeRequestsPerNode,
|
|
4119
|
+
maxActivityRecordsPerNode,
|
|
4120
|
+
lookbackDays,
|
|
4121
|
+
},
|
|
4122
|
+
};
|
|
4123
|
+
},
|
|
3651
4124
|
getDependencyReadiness: async (issueId, dbOrTx = db) => {
|
|
3652
4125
|
const issue = await dbOrTx
|
|
3653
4126
|
.select({ id: issues.id, companyId: issues.companyId })
|
|
@@ -3788,15 +4261,30 @@ export function issueService(db) {
|
|
|
3788
4261
|
if (childCount >= MAX_CHILD_ISSUES_CREATED_BY_HELPER) {
|
|
3789
4262
|
throw unprocessable(`Parent issue already has the maximum ${MAX_CHILD_ISSUES_CREATED_BY_HELPER} child issues for this helper`);
|
|
3790
4263
|
}
|
|
3791
|
-
const { acceptanceCriteria, blockParentUntilDone, actorAgentId, actorUserId, ...issueData } = data;
|
|
4264
|
+
const { acceptanceCriteria, blockParentUntilDone, executionWorkspaceInheritanceMode = "linkage", actorAgentId, actorUserId, ...issueData } = data;
|
|
4265
|
+
const inheritStrategyOnly = executionWorkspaceInheritanceMode === "strategy_only";
|
|
4266
|
+
const hasExplicitExecutionWorkspaceOverride = issueData.executionWorkspaceId !== undefined ||
|
|
4267
|
+
issueData.executionWorkspacePreference !== undefined ||
|
|
4268
|
+
issueData.executionWorkspaceSettings !== undefined;
|
|
4269
|
+
const inheritedPreRealizationWorkspaceSettings = inheritStrategyOnly && !hasExplicitExecutionWorkspaceOverride
|
|
4270
|
+
? buildPreRealizationExecutionWorkspaceSettings(parent.executionWorkspaceSettings)
|
|
4271
|
+
: null;
|
|
3792
4272
|
let child = await issueService(db).create(parent.companyId, {
|
|
3793
4273
|
...issueData,
|
|
3794
4274
|
parentId: parent.id,
|
|
3795
4275
|
projectId: issueData.projectId ?? parent.projectId,
|
|
4276
|
+
projectWorkspaceId: issueData.projectWorkspaceId ?? (inheritStrategyOnly ? parent.projectWorkspaceId : undefined),
|
|
3796
4277
|
goalId: issueData.goalId ?? parent.goalId,
|
|
4278
|
+
actorResponsibleUserId: issueData.actorResponsibleUserId ?? null,
|
|
4279
|
+
trustExplicitResponsibleUserId: issueData.trustExplicitResponsibleUserId === true,
|
|
3797
4280
|
requestDepth: clampIssueRequestDepth(Math.max(clampIssueRequestDepth(parent.requestDepth) + 1, issueData.requestDepth ?? 0)),
|
|
3798
4281
|
description: appendAcceptanceCriteriaToDescription(issueData.description, acceptanceCriteria),
|
|
3799
|
-
|
|
4282
|
+
...(inheritedPreRealizationWorkspaceSettings
|
|
4283
|
+
? { executionWorkspaceSettings: inheritedPreRealizationWorkspaceSettings }
|
|
4284
|
+
: {}),
|
|
4285
|
+
...(inheritStrategyOnly
|
|
4286
|
+
? { skipExecutionWorkspaceInheritance: true }
|
|
4287
|
+
: { inheritExecutionWorkspaceFromIssueId: parent.id }),
|
|
3800
4288
|
});
|
|
3801
4289
|
if (blockParentUntilDone) {
|
|
3802
4290
|
const existingBlockers = await db
|
|
@@ -3938,7 +4426,10 @@ export function issueService(db) {
|
|
|
3938
4426
|
if (!nextChildInput) {
|
|
3939
4427
|
throw new Error("Accepted-plan decomposition child cursor moved past the requested children");
|
|
3940
4428
|
}
|
|
3941
|
-
const createdChild = await issueService(tx).createChild(sourceIssue.id,
|
|
4429
|
+
const createdChild = await issueService(tx).createChild(sourceIssue.id, {
|
|
4430
|
+
...nextChildInput,
|
|
4431
|
+
executionWorkspaceInheritanceMode: "strategy_only",
|
|
4432
|
+
});
|
|
3942
4433
|
const nextIds = [...existingChildIssueIds, createdChild.issue.id];
|
|
3943
4434
|
const now = new Date();
|
|
3944
4435
|
const nextStatus = nextIds.length === data.children.length ? "completed" : "in_flight";
|
|
@@ -4046,7 +4537,7 @@ export function issueService(db) {
|
|
|
4046
4537
|
});
|
|
4047
4538
|
},
|
|
4048
4539
|
create: async (companyId, data) => {
|
|
4049
|
-
const { labelIds: inputLabelIds, blockedByIssueIds, inheritExecutionWorkspaceFromIssueId, watchdog, watchdogActorRunId, ...issueData } = data;
|
|
4540
|
+
const { labelIds: inputLabelIds, blockedByIssueIds, inheritExecutionWorkspaceFromIssueId, skipExecutionWorkspaceInheritance, watchdog, watchdogActorRunId, actorRunId, actorResponsibleUserId, trustExplicitResponsibleUserId, ...issueData } = data;
|
|
4050
4541
|
const isolatedWorkspacesEnabled = (await instanceSettings.getExperimental()).enableIsolatedWorkspaces;
|
|
4051
4542
|
if (!isolatedWorkspacesEnabled) {
|
|
4052
4543
|
delete issueData.executionWorkspaceId;
|
|
@@ -4071,7 +4562,9 @@ export function issueService(db) {
|
|
|
4071
4562
|
let executionWorkspaceId = issueData.executionWorkspaceId ?? null;
|
|
4072
4563
|
let executionWorkspacePreference = issueData.executionWorkspacePreference ?? null;
|
|
4073
4564
|
let executionWorkspaceSettings = issueData.executionWorkspaceSettings ?? null;
|
|
4074
|
-
const workspaceInheritanceIssueId =
|
|
4565
|
+
const workspaceInheritanceIssueId = skipExecutionWorkspaceInheritance
|
|
4566
|
+
? null
|
|
4567
|
+
: inheritExecutionWorkspaceFromIssueId ?? issueData.parentId ?? null;
|
|
4075
4568
|
const hasExplicitExecutionWorkspaceOverride = issueData.executionWorkspaceId !== undefined ||
|
|
4076
4569
|
issueData.executionWorkspacePreference !== undefined ||
|
|
4077
4570
|
issueData.executionWorkspaceSettings !== undefined;
|
|
@@ -4162,6 +4655,15 @@ export function issueService(db) {
|
|
|
4162
4655
|
if (executionWorkspaceId) {
|
|
4163
4656
|
await assertValidExecutionWorkspace(companyId, issueData.projectId, executionWorkspaceId, tx);
|
|
4164
4657
|
}
|
|
4658
|
+
if (isolatedWorkspacesEnabled && issueData.executionWorkspaceSettings !== undefined) {
|
|
4659
|
+
assertExplicitPinnedWorktreeIssueRunnable({
|
|
4660
|
+
projectId: issueData.projectId ?? null,
|
|
4661
|
+
projectWorkspaceId,
|
|
4662
|
+
executionWorkspaceId,
|
|
4663
|
+
executionWorkspacePreference,
|
|
4664
|
+
executionWorkspaceSettings: issueData.executionWorkspaceSettings,
|
|
4665
|
+
});
|
|
4666
|
+
}
|
|
4165
4667
|
// Self-correcting counter: use MAX(issue_number) + 1 if the counter
|
|
4166
4668
|
// has drifted below the actual max, preventing identifier collisions.
|
|
4167
4669
|
const [maxRow] = await tx
|
|
@@ -4178,8 +4680,19 @@ export function issueService(db) {
|
|
|
4178
4680
|
.returning({ issueCounter: companies.issueCounter, issuePrefix: companies.issuePrefix });
|
|
4179
4681
|
const issueNumber = company.issueCounter;
|
|
4180
4682
|
const identifier = `${company.issuePrefix}-${issueNumber}`;
|
|
4683
|
+
const responsibleUserId = await resolveResponsibleUserIdForIssueCreate(tx, companyId, {
|
|
4684
|
+
explicitResponsibleUserId: issueData.responsibleUserId ?? null,
|
|
4685
|
+
createdByUserId: issueData.createdByUserId ?? null,
|
|
4686
|
+
parentId: issueData.parentId ?? null,
|
|
4687
|
+
originKind: issueData.originKind ?? "manual",
|
|
4688
|
+
originRunId: issueData.originRunId ?? null,
|
|
4689
|
+
actorRunId: actorRunId ?? null,
|
|
4690
|
+
actorResponsibleUserId: actorResponsibleUserId ?? null,
|
|
4691
|
+
trustExplicitResponsibleUserId: trustExplicitResponsibleUserId === true,
|
|
4692
|
+
});
|
|
4181
4693
|
const values = {
|
|
4182
4694
|
...issueData,
|
|
4695
|
+
responsibleUserId,
|
|
4183
4696
|
requestDepth: clampIssueRequestDepth(issueData.requestDepth),
|
|
4184
4697
|
originKind: issueData.originKind ?? "manual",
|
|
4185
4698
|
goalId: resolveIssueGoalId({
|
|
@@ -4324,6 +4837,15 @@ export function issueService(db) {
|
|
|
4324
4837
|
await assertValidExecutionWorkspace(existing.companyId, nextProjectId, nextExecutionWorkspaceId);
|
|
4325
4838
|
}
|
|
4326
4839
|
}
|
|
4840
|
+
if (isolatedWorkspacesEnabled && issueData.executionWorkspaceSettings !== undefined) {
|
|
4841
|
+
assertExplicitPinnedWorktreeIssueRunnable({
|
|
4842
|
+
projectId: nextProjectId ?? null,
|
|
4843
|
+
projectWorkspaceId: nextProjectWorkspaceId ?? null,
|
|
4844
|
+
executionWorkspaceId: nextExecutionWorkspaceId ?? null,
|
|
4845
|
+
executionWorkspacePreference: nextExecutionWorkspacePreference ?? null,
|
|
4846
|
+
executionWorkspaceSettings: issueData.executionWorkspaceSettings,
|
|
4847
|
+
});
|
|
4848
|
+
}
|
|
4327
4849
|
applyStatusSideEffects(issueData.status, patch);
|
|
4328
4850
|
if (issueData.status && issueData.status !== "done") {
|
|
4329
4851
|
patch.completedAt = null;
|
|
@@ -4422,7 +4944,7 @@ export function issueService(db) {
|
|
|
4422
4944
|
.where(eq(issues.companyId, companyId));
|
|
4423
4945
|
let cleared = 0;
|
|
4424
4946
|
for (const row of rows) {
|
|
4425
|
-
const settings = parseIssueExecutionWorkspaceSettings(row.executionWorkspaceSettings);
|
|
4947
|
+
const settings = parseIssueExecutionWorkspaceSettings(row.executionWorkspaceSettings, { includeEnvironmentId: true });
|
|
4426
4948
|
if (settings?.environmentId !== environmentId)
|
|
4427
4949
|
continue;
|
|
4428
4950
|
await db
|