@umudik/task-bridge 0.0.1
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/LICENSE +21 -0
- package/README.md +75 -0
- package/apps/backend/dist/config.js +26 -0
- package/apps/backend/dist/db/epic-workflow-db.js +125 -0
- package/apps/backend/dist/db/library-db.js +123 -0
- package/apps/backend/dist/db/projects-db.js +110 -0
- package/apps/backend/dist/db/tasks-db.js +282 -0
- package/apps/backend/dist/db/users-db.js +117 -0
- package/apps/backend/dist/db/workflow-db.js +186 -0
- package/apps/backend/dist/db/workflow-template-db.js +715 -0
- package/apps/backend/dist/domain/project-member.js +15 -0
- package/apps/backend/dist/domain/task-template-graph.js +63 -0
- package/apps/backend/dist/domain/task.js +93 -0
- package/apps/backend/dist/domain/work-status.js +30 -0
- package/apps/backend/dist/domain/workflow-stage.js +186 -0
- package/apps/backend/dist/domain/workflow-state.js +73 -0
- package/apps/backend/dist/domain/workflow-template-id.js +6 -0
- package/apps/backend/dist/errors/app-error.js +24 -0
- package/apps/backend/dist/index.js +67 -0
- package/apps/backend/dist/lib/bridge-project.js +24 -0
- package/apps/backend/dist/lib/inbox-cursor.js +34 -0
- package/apps/backend/dist/lib/strings.js +15 -0
- package/apps/backend/dist/logger.js +29 -0
- package/apps/backend/dist/mappers/task-response.js +261 -0
- package/apps/backend/dist/middleware/auth.js +29 -0
- package/apps/backend/dist/openapi.js +716 -0
- package/apps/backend/dist/routes/admin-users.js +79 -0
- package/apps/backend/dist/routes/auth.js +81 -0
- package/apps/backend/dist/routes/connect.js +1 -0
- package/apps/backend/dist/routes/docs.js +13 -0
- package/apps/backend/dist/routes/health.js +6 -0
- package/apps/backend/dist/routes/library.js +139 -0
- package/apps/backend/dist/routes/projects.js +95 -0
- package/apps/backend/dist/routes/tasks.js +522 -0
- package/apps/backend/dist/routes/web.js +79 -0
- package/apps/backend/dist/routes/workflow-templates.js +152 -0
- package/apps/backend/dist/routes/workflow.js +165 -0
- package/apps/backend/dist/services/connect-target.js +4 -0
- package/apps/backend/dist/services/epic-service.js +269 -0
- package/apps/backend/dist/services/library-service.js +222 -0
- package/apps/backend/dist/services/project-registry.js +122 -0
- package/apps/backend/dist/services/task-assignee-service.js +42 -0
- package/apps/backend/dist/services/task-claim-policy.js +310 -0
- package/apps/backend/dist/services/task-queue.js +105 -0
- package/apps/backend/dist/services/task-service.js +198 -0
- package/apps/backend/dist/services/workflow-rules.js +18 -0
- package/apps/backend/dist/services/workflow-service.js +418 -0
- package/apps/backend/dist/services/workflow-spawn-service.js +179 -0
- package/apps/backend/dist/services/workflow-state-service.js +157 -0
- package/apps/backend/dist/services/workflow-template-service.js +204 -0
- package/apps/backend/public/assets/index-Bl1ciVpY.js +409 -0
- package/apps/backend/public/assets/index-ByKECv-I.css +1 -0
- package/apps/backend/public/index.html +13 -0
- package/bin/task-bridge.mjs +86 -0
- package/package.json +41 -0
|
@@ -0,0 +1,715 @@
|
|
|
1
|
+
import { countSpawnableTemplates } from "../domain/task-template-graph.js";
|
|
2
|
+
import { DEFAULT_WORKFLOW_TEMPLATE_ID } from "../domain/workflow-template-id.js";
|
|
3
|
+
import { serializeTaskTemplates } from "../domain/workflow-stage.js";
|
|
4
|
+
import { getProjectsDb } from "./projects-db.js";
|
|
5
|
+
const DEPRECATED_TEMPLATE_IDS = [
|
|
6
|
+
"go",
|
|
7
|
+
"nodejs",
|
|
8
|
+
"sdlc-classic",
|
|
9
|
+
"scrum-sprint",
|
|
10
|
+
"devops-cicd",
|
|
11
|
+
"agentic-engineering",
|
|
12
|
+
"senior-team",
|
|
13
|
+
"software-team",
|
|
14
|
+
"spec-review-gate",
|
|
15
|
+
"plan-decompose",
|
|
16
|
+
"ready-for-pr",
|
|
17
|
+
"review-security",
|
|
18
|
+
];
|
|
19
|
+
function task(id, title, description = "", assigneeRole = "", children = [], dependsOn = []) {
|
|
20
|
+
return {
|
|
21
|
+
id,
|
|
22
|
+
title,
|
|
23
|
+
description,
|
|
24
|
+
assigneeRole: assigneeRole || null,
|
|
25
|
+
dependsOn,
|
|
26
|
+
children,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function chain(id, title, description, assigneeRole, steps) {
|
|
30
|
+
let previousId = null;
|
|
31
|
+
const children = steps.map((step) => {
|
|
32
|
+
let dependsOn;
|
|
33
|
+
if (previousId !== null) {
|
|
34
|
+
dependsOn = [previousId];
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
dependsOn = [];
|
|
38
|
+
}
|
|
39
|
+
const node = Object.assign({}, step, { dependsOn });
|
|
40
|
+
previousId = step.id;
|
|
41
|
+
return node;
|
|
42
|
+
});
|
|
43
|
+
return task(id, title, description, assigneeRole, children);
|
|
44
|
+
}
|
|
45
|
+
const DEFAULT_TEMPLATE_SEEDS = [
|
|
46
|
+
{
|
|
47
|
+
id: DEFAULT_WORKFLOW_TEMPLATE_ID,
|
|
48
|
+
title: "Empty workflow",
|
|
49
|
+
description: "Minimal pipeline with one step. Customize stages on the Pipeline tab.",
|
|
50
|
+
stages: [
|
|
51
|
+
{
|
|
52
|
+
id: "backlog",
|
|
53
|
+
title: "Backlog",
|
|
54
|
+
description: "",
|
|
55
|
+
purpose: "",
|
|
56
|
+
rules: [],
|
|
57
|
+
position: 0,
|
|
58
|
+
autoAssign: false,
|
|
59
|
+
taskTemplates: [],
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
id: "ai-sdlc",
|
|
65
|
+
title: "AI Spec-Driven SDLC",
|
|
66
|
+
description: `Single canonical pipeline for AI-assisted delivery.
|
|
67
|
+
|
|
68
|
+
**Sources:** GitHub Spec Kit, Thoughtworks SDD, Specorator, GSI-Protocol, pangon/ai-sdlc-scaffold.
|
|
69
|
+
|
|
70
|
+
**Golden rule:** Never skip human gates. Never open a public PR before **Human Pre-PR Approval**. Draft branch work is fine during implementation; gh pr ready only after human sign-off.`,
|
|
71
|
+
stages: [
|
|
72
|
+
{
|
|
73
|
+
id: "constitution",
|
|
74
|
+
title: "Constitution",
|
|
75
|
+
description: `## Objective
|
|
76
|
+
Codify non-negotiable project rules agents must always obey (Spec Kit /speckit.constitution, Specorator memory/constitution.md).
|
|
77
|
+
|
|
78
|
+
## Entry
|
|
79
|
+
New epic or greenfield feature.
|
|
80
|
+
|
|
81
|
+
## Exit
|
|
82
|
+
AGENTS.md / CLAUDE.md committed with language, frameworks, testing, security, and dependency policies.
|
|
83
|
+
|
|
84
|
+
## Gate
|
|
85
|
+
Tech lead confirms constitution is enforceable — not aspirational markdown.`,
|
|
86
|
+
purpose: "Project governance",
|
|
87
|
+
rules: ["AGENTS.md exists", "Testing policy defined", "Security baseline stated"],
|
|
88
|
+
position: 0,
|
|
89
|
+
autoAssign: false,
|
|
90
|
+
taskTemplates: [
|
|
91
|
+
task("cn-agents-md", "Write AGENTS.md / CLAUDE.md", "**Output:** root agent instructions.\n\n- Language & framework versions\n- Test commands that must exit 0\n- Lint/typecheck commands\n- Branch naming & commit style\n- Files agents must never edit\n- Human gate policy: no PR without approval", "tech-lead", [
|
|
92
|
+
task("cn-testing", "Define testing constitution", "**Output:** testing section in constitution.\n\n- Unit vs integration boundaries\n- TDD expectation\n- Coverage expectations for new logic\n- Flaky test policy (fix, don't skip)", "qa"),
|
|
93
|
+
task("cn-security", "Define security baseline", "**Output:** security rules in constitution.\n\n- No secrets in repo\n- Auth patterns to follow\n- Dependency update policy\n- Input validation expectations", "architect"),
|
|
94
|
+
task("cn-deps", "Dependency & tooling rules", "**Output:** allowed deps, package manager, CI commands.\n\n- Prefer stdlib before new packages\n- Pin versions policy\n- How to run build locally", "architect"),
|
|
95
|
+
]),
|
|
96
|
+
],
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
id: "discovery",
|
|
100
|
+
title: "Discovery",
|
|
101
|
+
description: `## Objective
|
|
102
|
+
Validate the problem before writing specs (Specorator Stage 1–2: Idea + Research).
|
|
103
|
+
|
|
104
|
+
## Entry
|
|
105
|
+
Constitution in place.
|
|
106
|
+
|
|
107
|
+
## Exit
|
|
108
|
+
Problem statement, stakeholders, GOAL-* artifacts, explicit out-of-scope.
|
|
109
|
+
|
|
110
|
+
## Gate
|
|
111
|
+
Evidence that building this is worth the engineering cost.`,
|
|
112
|
+
purpose: "Problem-solution fit",
|
|
113
|
+
rules: ["Problem statement written", "Stakeholders listed", "Out of scope explicit"],
|
|
114
|
+
position: 1,
|
|
115
|
+
autoAssign: false,
|
|
116
|
+
taskTemplates: [
|
|
117
|
+
task("dc-stakeholders", "Identify stakeholders", "**Output:** stakeholders.md\n\n- Decision makers (who approves gates)\n- End users\n- Maintainers / on-call\n- Security or compliance reviewers if applicable", "product"),
|
|
118
|
+
task("dc-problem", "Write problem statement", "**Output:** problem statement in idea.md\n\n- Current pain (quantify if possible)\n- Desired outcome\n- Why now\n- What happens if we don't build this"),
|
|
119
|
+
task("dc-goals", "Define goals", "**Output:** GOAL-* files\n\nMeasurable outcomes, not feature lists. Each goal links to a business or user outcome.", "product"),
|
|
120
|
+
task("dc-constraints", "List constraints", "**Output:** CON-* files\n\nBudget, timeline, compliance, tech stack limits, team capacity.", "product"),
|
|
121
|
+
task("dc-assumptions", "Capture assumptions", "**Output:** ASM-* files\n\nBeliefs not yet validated. Flag highest-risk assumptions for research.", "product"),
|
|
122
|
+
task("dc-research", "Research alternatives", "**Output:** research.md (Specorator Stage 2)\n\n- ≥2 alternatives explored\n- Build vs buy vs integrate\n- Risks named with severity", "architect"),
|
|
123
|
+
task("dc-scope-out", "Define out of scope", "**Output:** explicit non-goals in idea.md\n\nPrevents agent scope creep during implementation.", "product"),
|
|
124
|
+
],
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
id: "specification",
|
|
128
|
+
title: "Specification",
|
|
129
|
+
description: `## Objective
|
|
130
|
+
Write the authoritative spec — code is derived from this, not from chat context (Thoughtworks SDD, Jama spec-anchored).
|
|
131
|
+
|
|
132
|
+
## Entry
|
|
133
|
+
Discovery complete.
|
|
134
|
+
|
|
135
|
+
## Exit
|
|
136
|
+
User stories, REQ-* in EARS notation, acceptance criteria, BDD scenarios, traceability matrix.
|
|
137
|
+
|
|
138
|
+
## Gate
|
|
139
|
+
Every requirement is testable; no vague "should work well" language.`,
|
|
140
|
+
purpose: "Intent capture",
|
|
141
|
+
rules: ["EARS or Given/When/Then AC", "REQ IDs stable", "Traceability GOAL→US→REQ"],
|
|
142
|
+
position: 2,
|
|
143
|
+
autoAssign: true,
|
|
144
|
+
taskTemplates: [
|
|
145
|
+
task("sp-stories", "Write user stories", "**Output:** US-* files\n\nFormat: As a [role], I want [action], so that [benefit]. Each story links to a GOAL-*.", "product"),
|
|
146
|
+
task("sp-functional", "Functional requirements (EARS)", "**Output:** REQ-F-* files\n\nUse EARS patterns: Ubiquitous, Event-driven, State-driven, Unwanted behaviour. Stable IDs for traceability.", "product"),
|
|
147
|
+
task("sp-nonfunctional", "Non-functional requirements", "**Output:** REQ-NF-* files\n\nPerformance, availability, security, observability, accessibility targets with measurable thresholds.", "architect"),
|
|
148
|
+
task("sp-acceptance", "Acceptance criteria", "**Output:** AC per user story\n\nGiven/When/Then or checklist items a QA can execute without guessing.", "product"),
|
|
149
|
+
task("sp-bdd", "BDD / Gherkin scenarios", "**Output:** .feature files or equivalent\n\nHappy path + error paths. Backend: API contract scenarios. Frontend: user-visible behaviour.", "qa"),
|
|
150
|
+
task("sp-traceability", "Traceability matrix", "**Output:** RTM draft linking GOAL → US → REQ → future tests\n\nRequired for regulated or audit-sensitive work.", "product"),
|
|
151
|
+
task("sp-edge-cases", "Edge cases & error catalogue", "**Output:** enumerated edge cases\n\nEmpty states, timeouts, permissions denied, rate limits, partial failures.", "qa"),
|
|
152
|
+
task("sp-review-checklist", "Spec review checklist", "**Output:** completed Spec Kit Review & Acceptance Checklist\n\nMark pass/fail per item before human gate.", "tech-lead"),
|
|
153
|
+
],
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
id: "clarify",
|
|
157
|
+
title: "Clarify",
|
|
158
|
+
description: `## Objective
|
|
159
|
+
Surface ambiguities before design — mandatory Spec Kit step before planning (/speckit.clarify).
|
|
160
|
+
|
|
161
|
+
## Entry
|
|
162
|
+
Draft specification exists.
|
|
163
|
+
|
|
164
|
+
## Exit
|
|
165
|
+
Clarifications section added; open questions resolved or explicitly deferred with owner.
|
|
166
|
+
|
|
167
|
+
## Gate
|
|
168
|
+
No TBD items blocking design. Agent cannot proceed with guessed requirements.`,
|
|
169
|
+
purpose: "Ambiguity removal",
|
|
170
|
+
rules: ["Clarifications documented", "No blocking TBDs", "Deferred items have owner"],
|
|
171
|
+
position: 3,
|
|
172
|
+
autoAssign: true,
|
|
173
|
+
taskTemplates: [
|
|
174
|
+
task("cl-scan", "Scan spec for ambiguity", "**Action:** structured pass over all spec artifacts.\n\nFlag vague adjectives, missing error behaviour, undefined actors, implicit dependencies.", "agent"),
|
|
175
|
+
task("cl-questions", "Generate clarification questions", "**Output:** numbered questions for human\n\nPrioritize by risk: security > data > UX > nice-to-have.", "agent"),
|
|
176
|
+
task("cl-answers", "Record human answers", "**Output:** Clarifications section in spec\n\nEach Q→A dated and attributed. Update affected REQ-* IDs.", "product"),
|
|
177
|
+
task("cl-consistency", "Consistency pass", "**Action:** ensure clarifications don't contradict GOAL-* or CON-* constraints.", "tech-lead"),
|
|
178
|
+
],
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
id: "spec-approval",
|
|
182
|
+
title: "Spec Approval",
|
|
183
|
+
description: `## Objective
|
|
184
|
+
**Human gate 1** — formal approval before any architecture or code (SDDD mandatory validation checkpoint).
|
|
185
|
+
|
|
186
|
+
## Entry
|
|
187
|
+
Specification + Clarify complete.
|
|
188
|
+
|
|
189
|
+
## Exit
|
|
190
|
+
Spec status: Draft → **Approved**. Baseline tagged or versioned.
|
|
191
|
+
|
|
192
|
+
## Gate
|
|
193
|
+
Product + tech lead sign-off. **No design work until this gate passes.**`,
|
|
194
|
+
purpose: "Human gate — spec",
|
|
195
|
+
rules: ["Human sign-off recorded", "Spec frozen", "No code before approval"],
|
|
196
|
+
position: 4,
|
|
197
|
+
autoAssign: true,
|
|
198
|
+
taskTemplates: [
|
|
199
|
+
chain("sa-product-review", "Product review", "**Action:** product owner reads all US-* and REQ-* artifacts.\n\nConfirm spec matches original intent. Reject if scope drift detected.", "product", [
|
|
200
|
+
task("sa-tech-review", "Technical feasibility review", "**Action:** tech lead confirms spec is implementable within constraints.\n\nFlag impossible NFRs or missing infra dependencies.", "tech-lead"),
|
|
201
|
+
task("sa-ambiguity-final", "Final ambiguity sweep", "**Action:** remove remaining vague language agents could misinterpret.\n\nReplace 'fast', 'secure', 'user-friendly' with measurable criteria.", "tech-lead"),
|
|
202
|
+
task("sa-approve", "Approve specification", "**Output:** Approved status on all spec artifacts + approval record (date, approver).\n\nThis unlocks Design stage.", "tech-lead"),
|
|
203
|
+
task("sa-freeze", "Freeze spec baseline", "**Output:** git tag or spec version number\n\nImplementation must trace to this baseline. Changes require spec amendment + re-approval.", "tech-lead"),
|
|
204
|
+
]),
|
|
205
|
+
],
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
id: "design",
|
|
209
|
+
title: "Design",
|
|
210
|
+
description: `## Objective
|
|
211
|
+
Technical blueprint from approved spec (Spec Kit /speckit.plan, GSI Architecture phase).
|
|
212
|
+
|
|
213
|
+
## Entry
|
|
214
|
+
Spec Approval gate passed.
|
|
215
|
+
|
|
216
|
+
## Exit
|
|
217
|
+
architecture.md, data-model.md, api-design.md, ADRs for irreversible decisions.
|
|
218
|
+
|
|
219
|
+
## Gate
|
|
220
|
+
Architect + tech lead review. Constitution compliance verified.`,
|
|
221
|
+
purpose: "Technical blueprint",
|
|
222
|
+
rules: ["Architecture doc complete", "ADRs for key decisions", "Constitution compliant"],
|
|
223
|
+
position: 5,
|
|
224
|
+
autoAssign: true,
|
|
225
|
+
taskTemplates: [
|
|
226
|
+
task("ds-architecture", "System architecture", "**Output:** architecture.md\n\nComponents, boundaries, data flow, sync/async patterns, failure modes.", "architect"),
|
|
227
|
+
task("ds-data-model", "Data model", "**Output:** data-model.md\n\nEntities, schemas, migrations, indexes, retention, PII handling.", "architect"),
|
|
228
|
+
task("ds-api", "API design", "**Output:** api-design.md or OpenAPI draft\n\nEndpoints, auth, errors, idempotency, versioning.", "architect"),
|
|
229
|
+
task("ds-security", "Security & threat model", "**Output:** security section or threat-model.md\n\nSTRIDE-lite: spoofing, tampering, elevation, data exposure.", "architect"),
|
|
230
|
+
task("ds-adr", "Write ADRs", "**Output:** DEC-* files\n\nContext, options, decision, consequences. Required for irreversible choices.", "architect"),
|
|
231
|
+
task("ds-components", "Component boundaries", "**Output:** component list for agent decomposition\n\nEach component: inputs, outputs, owner, test boundary.", "architect"),
|
|
232
|
+
task("ds-nfr-map", "Map NFRs to design", "**Output:** table linking REQ-NF-* to architecture elements\n\nProves non-functionals are designed, not hoped for.", "architect"),
|
|
233
|
+
],
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
id: "plan-approval",
|
|
237
|
+
title: "Plan Approval",
|
|
238
|
+
description: `## Objective
|
|
239
|
+
**Human gate 2** — architects approve technical plan before task breakdown (Spec Kit: validate plan before tasks).
|
|
240
|
+
|
|
241
|
+
## Entry
|
|
242
|
+
Design artifacts complete.
|
|
243
|
+
|
|
244
|
+
## Exit
|
|
245
|
+
Plan status: Approved. Constitution + spec alignment confirmed.
|
|
246
|
+
|
|
247
|
+
## Gate
|
|
248
|
+
**Never jump spec → code.** Plan must be reviewed before decomposition.`,
|
|
249
|
+
purpose: "Human gate — plan",
|
|
250
|
+
rules: ["Architect sign-off", "Plan matches spec", "No tasks before approval"],
|
|
251
|
+
position: 6,
|
|
252
|
+
autoAssign: true,
|
|
253
|
+
taskTemplates: [
|
|
254
|
+
chain("pa-architect-review", "Architect review", "**Action:** review architecture.md against approved REQ-* set.\n\nVerify no spec requirements are orphaned.", "architect", [
|
|
255
|
+
task("pa-constitution-check", "Constitution compliance", "**Action:** verify plan obeys AGENTS.md rules.\n\nFramework choices, testing approach, security patterns.", "tech-lead"),
|
|
256
|
+
task("pa-risk-review", "Risk & trade-off review", "**Action:** review ADRs and flagged risks.\n\nAccept or mitigate before tasks are written.", "tech-lead"),
|
|
257
|
+
task("pa-approve", "Approve technical plan", "**Output:** Approved status on design artifacts.\n\nUnlocks Tasks stage.", "tech-lead"),
|
|
258
|
+
]),
|
|
259
|
+
],
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
id: "tasks",
|
|
263
|
+
title: "Tasks",
|
|
264
|
+
description: `## Objective
|
|
265
|
+
Decompose plan into atomic agent-executable packets (Spec Kit /speckit.tasks, Specorator Stage 6).
|
|
266
|
+
|
|
267
|
+
## Entry
|
|
268
|
+
Plan Approval gate passed.
|
|
269
|
+
|
|
270
|
+
## Exit
|
|
271
|
+
tasks.md with bounded packets, dependencies, acceptance criteria per task, test plan.
|
|
272
|
+
|
|
273
|
+
## Gate
|
|
274
|
+
Each task fits one agent context window; every task links to REQ-* IDs.`,
|
|
275
|
+
purpose: "Work breakdown",
|
|
276
|
+
rules: ["Tasks atomic", "Dependencies mapped", "Each task has AC"],
|
|
277
|
+
position: 7,
|
|
278
|
+
autoAssign: true,
|
|
279
|
+
taskTemplates: [
|
|
280
|
+
task("tk-phases", "Define implementation phases", "**Output:** phased plan in tasks.md\n\nEach phase ends with something deployable/testable locally — not a monolith at the end.", "architect"),
|
|
281
|
+
task("tk-backlog", "Generate task backlog", "**Output:** tasks.md with stable task IDs\n\nExample: 'Create POST /users validating email format (REQ-F-012)' not 'build auth'.", "architect"),
|
|
282
|
+
task("tk-boundaries", "Bound task packets", "**Action:** split until each task is completable in one agent session.\n\nInclude file list hint per task where possible.", "architect"),
|
|
283
|
+
task("tk-deps", "Map dependencies", "**Output:** dependsOn graph\n\nMark [P] parallel-safe vs sequential. Critical path identified.", "architect"),
|
|
284
|
+
task("tk-ac", "Acceptance criteria per task", "**Output:** testable AC under each task\n\nAgent marks done only when AC objectively met.", "qa"),
|
|
285
|
+
task("tk-test-plan", "Test plan per task", "**Output:** test-plan.md entries\n\nUnit, integration, contract tests expected per task.", "qa"),
|
|
286
|
+
task("tk-order", "Prioritize execution order", "**Output:** ordered task list\n\nRisk spikes and foundation tasks first.", "tech-lead"),
|
|
287
|
+
],
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
id: "tasks-approval",
|
|
291
|
+
title: "Tasks Approval",
|
|
292
|
+
description: `## Objective
|
|
293
|
+
**Human gate 3** — approve task breakdown before any agent writes code (SDDD task validation checkpoint).
|
|
294
|
+
|
|
295
|
+
## Entry
|
|
296
|
+
tasks.md complete.
|
|
297
|
+
|
|
298
|
+
## Exit
|
|
299
|
+
Tasks approved. Implementation may begin.
|
|
300
|
+
|
|
301
|
+
## Gate
|
|
302
|
+
Human confirms scope per task is logical, complete, and not oversized.`,
|
|
303
|
+
purpose: "Human gate — tasks",
|
|
304
|
+
rules: ["Task breakdown approved", "No implementation before approval"],
|
|
305
|
+
position: 8,
|
|
306
|
+
autoAssign: true,
|
|
307
|
+
taskTemplates: [
|
|
308
|
+
chain("ta-scope-review", "Scope review", "**Action:** human reads tasks.md end-to-end.\n\nEach task independently reviewable in a future PR diff.", "tech-lead", [
|
|
309
|
+
task("ta-coverage", "Requirement coverage check", "**Action:** every approved REQ-* maps to ≥1 task.\n\nNo orphan requirements.", "qa"),
|
|
310
|
+
task("ta-sizing", "Task sizing check", "**Action:** reject tasks that are epics in disguise.\n\nSplit anything estimated >1 agent session.", "tech-lead"),
|
|
311
|
+
task("ta-approve", "Approve task breakdown", "**Output:** Approved status on tasks.md.\n\nUnlocks Agent Context + Implementation.", "tech-lead"),
|
|
312
|
+
]),
|
|
313
|
+
],
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
id: "agent-context",
|
|
317
|
+
title: "Agent Context",
|
|
318
|
+
description: `## Objective
|
|
319
|
+
Prepare repo knowledge layer so agents don't hallucinate structure (pangon ai-sdlc-scaffold, context-window efficiency).
|
|
320
|
+
|
|
321
|
+
## Entry
|
|
322
|
+
Tasks Approval gate passed.
|
|
323
|
+
|
|
324
|
+
## Exit
|
|
325
|
+
Indexes, status.md, spec/design indexes, .env.example updated.
|
|
326
|
+
|
|
327
|
+
## Gate
|
|
328
|
+
Agent can find GOAL/US/REQ/DEC/tasks without loading entire repo.`,
|
|
329
|
+
purpose: "Context engineering",
|
|
330
|
+
rules: ["Status doc current", "Indexes updated", ".env.example current"],
|
|
331
|
+
position: 9,
|
|
332
|
+
autoAssign: true,
|
|
333
|
+
taskTemplates: [
|
|
334
|
+
task("cx-status", "Create or update status.md", "**Output:** status.md\n\nCurrent phase, active task, blockers, last handoff, next agent action.", "agent"),
|
|
335
|
+
task("cx-spec-index", "Spec artifact index", "**Output:** phase index linking GOAL/US/REQ paths\n\nMinimize tokens per agent invocation.", "agent"),
|
|
336
|
+
task("cx-decisions-index", "Decisions index", "**Output:** DEC-* index by component and phase.", "agent"),
|
|
337
|
+
task("cx-repo-map", "Repo map", "**Output:** entry points, module boundaries, test locations.", "agent"),
|
|
338
|
+
task("cx-branch", "Create feature branch", "**Output:** feature branch from dev/main\n\nWork stays local. **Do not open PR yet** — draft branch only.", "engineer"),
|
|
339
|
+
task("cx-env-example", "Update .env.example", "**Output:** documented placeholders for any new config\n\nNever commit real secrets.", "engineer"),
|
|
340
|
+
],
|
|
341
|
+
},
|
|
342
|
+
{
|
|
343
|
+
id: "implementation",
|
|
344
|
+
title: "Implementation",
|
|
345
|
+
description: `## Objective
|
|
346
|
+
Execute approved tasks one at a time with TDD + logging (Spec Kit /speckit.implement, Specorator Stage 7).
|
|
347
|
+
|
|
348
|
+
## Entry
|
|
349
|
+
Agent context ready; feature branch exists.
|
|
350
|
+
|
|
351
|
+
## Exit
|
|
352
|
+
All tasks done; implementation-log.md entries; code + tests committed to branch.
|
|
353
|
+
|
|
354
|
+
## Gate
|
|
355
|
+
One task at a time. Design gaps stop work — update spec/ADR, don't guess.
|
|
356
|
+
|
|
357
|
+
**Note:** Draft PR optional during this stage; must stay draft until Human Pre-PR Approval.`,
|
|
358
|
+
purpose: "Build",
|
|
359
|
+
rules: ["One task at a time", "TDD", "Log each task", "No public PR yet"],
|
|
360
|
+
position: 10,
|
|
361
|
+
autoAssign: true,
|
|
362
|
+
taskTemplates: [
|
|
363
|
+
chain("im-loop", "Task execution loop", "Repeat for each approved task until tasks.md is complete.", "", [
|
|
364
|
+
task("im-pick", "Pick next pending task", "**Action:** select next task from tasks.md by priority.\n\nRead linked REQ-* and design sections before any edit.", "agent"),
|
|
365
|
+
task("im-context", "Load minimal context", "**Action:** open only files listed in task packet + constitution.\n\nDo not load entire repo into context.", "agent"),
|
|
366
|
+
task("im-tdd", "Implement with TDD", "**Action:** write failing test → implement → refactor.\n\nMinimal diff; match existing conventions.", "agent"),
|
|
367
|
+
task("im-gap", "Handle design gaps", "**Action:** if spec/design insufficient → STOP.\n\nUpdate spec or ADR; get human re-approval if scope changes.", "agent"),
|
|
368
|
+
task("im-log", "Write implementation log", "**Output:** implementation-log/TASK-*.md\n\nFiles changed, decisions, debt, verification commands run.", "agent"),
|
|
369
|
+
task("im-commit", "Commit task increment", "**Action:** atomic commit per task with task ID in message.\n\nPush to feature branch (still no public PR).", "agent"),
|
|
370
|
+
]),
|
|
371
|
+
task("im-docs", "Update documentation", "**Output:** README, API docs, inline docs where behaviour is non-obvious.", "engineer"),
|
|
372
|
+
],
|
|
373
|
+
},
|
|
374
|
+
{
|
|
375
|
+
id: "verification",
|
|
376
|
+
title: "Verification",
|
|
377
|
+
description: `## Objective
|
|
378
|
+
Programmatic quality gates — subprocess exit codes, not agent self-report (GSD-2 / Spec Loop Engine pattern).
|
|
379
|
+
|
|
380
|
+
## Entry
|
|
381
|
+
Implementation complete on feature branch.
|
|
382
|
+
|
|
383
|
+
## Exit
|
|
384
|
+
Lint, typecheck, unit, integration, contract tests all exit 0.
|
|
385
|
+
|
|
386
|
+
## Gate
|
|
387
|
+
Retry loop until green. Agent cannot claim success without command output.`,
|
|
388
|
+
purpose: "Automated QA",
|
|
389
|
+
rules: ["Lint exit 0", "Typecheck exit 0", "All tests exit 0"],
|
|
390
|
+
position: 11,
|
|
391
|
+
autoAssign: true,
|
|
392
|
+
taskTemplates: [
|
|
393
|
+
task("vf-lint", "Run linter", "**Command:** project lint (eslint, detekt, etc.)\n\nFix all errors; warnings per team policy.", "qa"),
|
|
394
|
+
task("vf-types", "Run type checker", "**Command:** tsc / mypy / kotlin compile\n\nZero type errors on changed modules.", "qa"),
|
|
395
|
+
task("vf-unit", "Run unit tests", "**Command:** unit test suite\n\nNo skipped tests on critical paths without documented reason.", "qa"),
|
|
396
|
+
task("vf-integration", "Run integration tests", "**Command:** integration suite\n\nDB, API, service boundaries exercised.", "qa"),
|
|
397
|
+
task("vf-contract", "Contract / BDD verify", "**Command:** Gherkin runner or SpecBridge\n\nBehaviour matches approved scenarios.", "qa"),
|
|
398
|
+
task("vf-retry", "Fix until green", "**Action:** on failure → fix → re-run.\n\nNo proceeding while red. Max retries logged in status.md.", "engineer"),
|
|
399
|
+
task("vf-test-report", "Write test report", "**Output:** test-report.md (Specorator Stage 8)\n\nSuites run, pass/fail counts, known gaps.", "qa"),
|
|
400
|
+
],
|
|
401
|
+
},
|
|
402
|
+
{
|
|
403
|
+
id: "review-security",
|
|
404
|
+
title: "Review & Security",
|
|
405
|
+
description: `## Objective
|
|
406
|
+
Security audit + human review of agent output before pre-PR approval (Specorator QA track, agentic security review).
|
|
407
|
+
|
|
408
|
+
## Entry
|
|
409
|
+
Verification green.
|
|
410
|
+
|
|
411
|
+
## Exit
|
|
412
|
+
Security checklist complete; peer review notes; no secrets in diff; debt logged.
|
|
413
|
+
|
|
414
|
+
## Gate
|
|
415
|
+
This is review of **local branch work** — still no public PR.`,
|
|
416
|
+
purpose: "Security & peer review",
|
|
417
|
+
rules: ["Secrets scan clean", "Peer review done", "Debt logged"],
|
|
418
|
+
position: 12,
|
|
419
|
+
autoAssign: true,
|
|
420
|
+
taskTemplates: [
|
|
421
|
+
task("rs-secrets", "Secrets scan", "**Action:** scan diff for keys, tokens, credentials, .env leaks.\n\nUse gitleaks or equivalent.", "qa"),
|
|
422
|
+
task("rs-auth", "Auth & injection review", "**Action:** review authz, session handling, SQL/command injection, XSS surfaces.", "architect"),
|
|
423
|
+
task("rs-deps", "Dependency audit", "**Action:** SCA scan; CVEs fixed, accepted with ADR, or mitigated.", "engineer"),
|
|
424
|
+
task("rs-diff-review", "Human diff review", "**Action:** human reads full branch diff — not rubber-stamp.\n\nFocus on agent-generated code quality.", "tech-lead"),
|
|
425
|
+
task("rs-anti-skip", "Anti-rationalization pass", "**Action:** reject excuses: 'tests flaky', 'types later', 'works on my machine'.\n\nAll gates must genuinely pass.", "tech-lead"),
|
|
426
|
+
task("rs-debt", "Log technical debt", "**Output:** technical-debt.md entries\n\nShortcuts explicit with owner and follow-up task.", "engineer"),
|
|
427
|
+
],
|
|
428
|
+
},
|
|
429
|
+
{
|
|
430
|
+
id: "analyze",
|
|
431
|
+
title: "Analyze",
|
|
432
|
+
description: `## Objective
|
|
433
|
+
Cross-artifact consistency check (Spec Kit /speckit.analyze, Specorator /spec:analyze).
|
|
434
|
+
|
|
435
|
+
## Entry
|
|
436
|
+
Review & Security complete.
|
|
437
|
+
|
|
438
|
+
## Exit
|
|
439
|
+
traceability.md updated; spec ↔ plan ↔ tasks ↔ code alignment verified.
|
|
440
|
+
|
|
441
|
+
## Gate
|
|
442
|
+
No drift between approved spec and implementation. Gaps documented with resolution plan.`,
|
|
443
|
+
purpose: "Consistency analysis",
|
|
444
|
+
rules: ["RTM complete", "No spec drift", "Gaps documented"],
|
|
445
|
+
position: 13,
|
|
446
|
+
autoAssign: true,
|
|
447
|
+
taskTemplates: [
|
|
448
|
+
task("an-spec-plan", "Spec ↔ plan alignment", "**Action:** verify design covers all approved REQ-*.\n\nFlag orphan requirements or orphan design elements.", "qa"),
|
|
449
|
+
task("an-plan-code", "Plan ↔ code alignment", "**Action:** verify each task's AC is met in code.\n\nWalk tasks.md checklist item by item.", "qa"),
|
|
450
|
+
task("an-rtm", "Update traceability matrix", "**Output:** traceability.md (Specorator Stage 9)\n\nGOAL → US → REQ → task → test → file mapping.", "qa"),
|
|
451
|
+
task("an-drift", "Spec drift report", "**Output:** list any code behaviour not in spec.\n\nEither update spec (with re-approval) or revert code.", "tech-lead"),
|
|
452
|
+
],
|
|
453
|
+
},
|
|
454
|
+
{
|
|
455
|
+
id: "human-pre-pr-approval",
|
|
456
|
+
title: "Human Pre-PR Approval",
|
|
457
|
+
description: `## Objective
|
|
458
|
+
**Human gate 4 — mandatory before any PR is opened or marked ready.**
|
|
459
|
+
|
|
460
|
+
This is the fix for PR hierarchy: humans approve that branch work is complete and safe to **expose** as a pull request.
|
|
461
|
+
|
|
462
|
+
## Entry
|
|
463
|
+
Analyze stage complete; all automated gates green.
|
|
464
|
+
|
|
465
|
+
## Exit
|
|
466
|
+
Written approval record: "authorized to open PR".
|
|
467
|
+
|
|
468
|
+
## Gate
|
|
469
|
+
**No gh pr create, no gh pr ready, no public PR until this gate passes.** Agents must not self-open PRs.`,
|
|
470
|
+
purpose: "Human gate — pre-PR",
|
|
471
|
+
rules: ["Human written approval", "No PR before this gate", "All upstream gates passed"],
|
|
472
|
+
position: 14,
|
|
473
|
+
autoAssign: true,
|
|
474
|
+
taskTemplates: [
|
|
475
|
+
chain("hp-demo", "Demo or walkthrough", "**Action:** author demos feature to approver (live or recording).\n\nApprover understands what will appear in the PR.", "engineer", [
|
|
476
|
+
task("hp-checklist", "Pre-PR checklist", "**Action:** confirm constitution, spec, plan, tasks, tests, security, analyze all passed.\n\nChecklist signed by approver.", "tech-lead"),
|
|
477
|
+
task("hp-traceability", "Traceability sign-off", "**Action:** approver confirms RTM is accurate.\n\nRequired for audit-sensitive work.", "qa"),
|
|
478
|
+
task("hp-approve", "Authorize PR creation", "**Output:** approval record in status.md or issue comment.\n\nExplicit: 'Approved to open PR to [target branch]'. **This unlocks Open PR stage.**", "tech-lead"),
|
|
479
|
+
]),
|
|
480
|
+
],
|
|
481
|
+
},
|
|
482
|
+
{
|
|
483
|
+
id: "open-pr",
|
|
484
|
+
title: "Open PR",
|
|
485
|
+
description: `## Objective
|
|
486
|
+
Create and publish the pull request — **only after Human Pre-PR Approval** (Specorator: mark ready after testing + human review, not before).
|
|
487
|
+
|
|
488
|
+
## Entry
|
|
489
|
+
Human Pre-PR Approval gate passed with written authorization.
|
|
490
|
+
|
|
491
|
+
## Exit
|
|
492
|
+
PR opened (or draft → ready), description complete, CI triggered.
|
|
493
|
+
|
|
494
|
+
## Gate
|
|
495
|
+
PR description links spec, tasks, test plan, and REQ-* IDs.`,
|
|
496
|
+
purpose: "Publish PR",
|
|
497
|
+
rules: ["Pre-PR approval on record", "PR description complete", "CI triggered"],
|
|
498
|
+
position: 15,
|
|
499
|
+
autoAssign: true,
|
|
500
|
+
taskTemplates: [
|
|
501
|
+
task("pr-desc", "Write PR description", "**Output:** PR body with:\n\n- Summary & motivation\n- Links to GOAL/US/REQ IDs\n- Test plan (commands + manual steps)\n- Screenshots if UI\n- Known limitations / debt", "engineer"),
|
|
502
|
+
task("pr-create", "Open pull request", "**Action:** gh pr create to dev/main (or team target).\n\nOnly execute after hp-approve task is done.", "engineer"),
|
|
503
|
+
task("pr-ready", "Mark PR ready for review", "**Action:** gh pr ready if was draft.\n\nMoves from WIP to reviewable state for team.", "engineer"),
|
|
504
|
+
task("pr-ci", "CI pipeline green", "**Action:** wait for CI; fix failures on branch.\n\nRe-push until all checks pass.", "engineer"),
|
|
505
|
+
],
|
|
506
|
+
},
|
|
507
|
+
{
|
|
508
|
+
id: "pr-review",
|
|
509
|
+
title: "PR Review",
|
|
510
|
+
description: `## Objective
|
|
511
|
+
Team review cycle on the open PR — address feedback until merge-ready (Specorator Stage 9 Review).
|
|
512
|
+
|
|
513
|
+
## Entry
|
|
514
|
+
PR open and CI green.
|
|
515
|
+
|
|
516
|
+
## Exit
|
|
517
|
+
All review threads resolved; merge approval from required reviewers.
|
|
518
|
+
|
|
519
|
+
## Gate
|
|
520
|
+
Human merge approval. Agent does not self-merge.`,
|
|
521
|
+
purpose: "PR review cycle",
|
|
522
|
+
rules: ["Review threads resolved", "CI green", "Merge approval recorded"],
|
|
523
|
+
position: 16,
|
|
524
|
+
autoAssign: true,
|
|
525
|
+
taskTemplates: [
|
|
526
|
+
task("rv-respond", "Address review comments", "**Action:** respond to each thread; push fixes or explain deferrals with linked debt item.", "engineer"),
|
|
527
|
+
task("rv-rereview", "Request re-review", "**Action:** re-request reviewers after substantive changes.", "engineer"),
|
|
528
|
+
task("rv-ci-recheck", "Re-run CI after changes", "**Action:** confirm CI green after each review fix round.", "engineer"),
|
|
529
|
+
task("rv-merge-approve", "Merge approval", "**Output:** required approvers sign off.\n\nRecord in PR before merge.", "tech-lead"),
|
|
530
|
+
task("rv-merge", "Merge to target branch", "**Action:** merge PR to dev/main per team convention.\n\nDelete feature branch if policy requires.", "engineer"),
|
|
531
|
+
],
|
|
532
|
+
},
|
|
533
|
+
{
|
|
534
|
+
id: "done",
|
|
535
|
+
title: "Done",
|
|
536
|
+
description: `## Objective
|
|
537
|
+
Epic closed after merge to dev. Production deployment is a separate release track.
|
|
538
|
+
|
|
539
|
+
## Entry
|
|
540
|
+
PR merged.
|
|
541
|
+
|
|
542
|
+
## Exit
|
|
543
|
+
Epic marked done; optional retrospective scheduled.
|
|
544
|
+
|
|
545
|
+
## Note
|
|
546
|
+
Deploy to staging/production is **not** part of this template — use your release pipeline separately.`,
|
|
547
|
+
purpose: "Closed",
|
|
548
|
+
rules: [],
|
|
549
|
+
position: 17,
|
|
550
|
+
autoAssign: false,
|
|
551
|
+
taskTemplates: null,
|
|
552
|
+
},
|
|
553
|
+
],
|
|
554
|
+
},
|
|
555
|
+
];
|
|
556
|
+
function removeDeprecatedTemplates() {
|
|
557
|
+
migrateWorkflowTemplateTables();
|
|
558
|
+
const db = getProjectsDb();
|
|
559
|
+
for (const id of DEPRECATED_TEMPLATE_IDS) {
|
|
560
|
+
deleteWorkflowTemplateStages(id);
|
|
561
|
+
db.prepare("DELETE FROM workflow_templates WHERE id = ?").run(id);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
function insertTemplateStages(template) {
|
|
565
|
+
for (const stage of template.stages) {
|
|
566
|
+
let taskTemplates = [];
|
|
567
|
+
if (stage.taskTemplates !== null) {
|
|
568
|
+
taskTemplates = stage.taskTemplates;
|
|
569
|
+
}
|
|
570
|
+
insertWorkflowTemplateStageRow({
|
|
571
|
+
templateId: template.id,
|
|
572
|
+
id: stage.id,
|
|
573
|
+
title: stage.title,
|
|
574
|
+
description: stage.description,
|
|
575
|
+
purpose: stage.purpose,
|
|
576
|
+
rulesJson: JSON.stringify(stage.rules),
|
|
577
|
+
position: stage.position,
|
|
578
|
+
autoAssign: stage.autoAssign,
|
|
579
|
+
spawnTaskCount: countSpawnableTemplates(taskTemplates),
|
|
580
|
+
taskTemplatesJson: serializeTaskTemplates(taskTemplates),
|
|
581
|
+
layoutX: null,
|
|
582
|
+
layoutY: null,
|
|
583
|
+
});
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
function upsertBuiltinTemplate(template) {
|
|
587
|
+
if (template.id === "ai-sdlc") {
|
|
588
|
+
const existing = listWorkflowTemplateRows({ id: template.id });
|
|
589
|
+
if (existing.length > 0) {
|
|
590
|
+
deleteWorkflowTemplateStages(template.id);
|
|
591
|
+
getProjectsDb()
|
|
592
|
+
.prepare("UPDATE workflow_templates SET title = ?, description = ?, updated_at = datetime('now') WHERE id = ?")
|
|
593
|
+
.run(template.title, template.description, template.id);
|
|
594
|
+
}
|
|
595
|
+
else {
|
|
596
|
+
insertWorkflowTemplateRow({
|
|
597
|
+
id: template.id,
|
|
598
|
+
title: template.title,
|
|
599
|
+
description: template.description,
|
|
600
|
+
});
|
|
601
|
+
}
|
|
602
|
+
insertTemplateStages(template);
|
|
603
|
+
return;
|
|
604
|
+
}
|
|
605
|
+
const existing = listWorkflowTemplateRows({ id: template.id });
|
|
606
|
+
if (existing.length > 0)
|
|
607
|
+
return;
|
|
608
|
+
insertWorkflowTemplateRow({
|
|
609
|
+
id: template.id,
|
|
610
|
+
title: template.title,
|
|
611
|
+
description: template.description,
|
|
612
|
+
});
|
|
613
|
+
insertTemplateStages(template);
|
|
614
|
+
}
|
|
615
|
+
export function migrateWorkflowTemplateTables() {
|
|
616
|
+
const db = getProjectsDb();
|
|
617
|
+
db.exec(`
|
|
618
|
+
CREATE TABLE IF NOT EXISTS workflow_templates (
|
|
619
|
+
id TEXT PRIMARY KEY,
|
|
620
|
+
title TEXT NOT NULL,
|
|
621
|
+
description TEXT NOT NULL DEFAULT '',
|
|
622
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
623
|
+
);
|
|
624
|
+
|
|
625
|
+
CREATE TABLE IF NOT EXISTS workflow_template_stages (
|
|
626
|
+
template_id TEXT NOT NULL,
|
|
627
|
+
id TEXT NOT NULL,
|
|
628
|
+
title TEXT NOT NULL,
|
|
629
|
+
description TEXT NOT NULL DEFAULT '',
|
|
630
|
+
purpose TEXT NOT NULL DEFAULT '',
|
|
631
|
+
rules_json TEXT NOT NULL DEFAULT '[]',
|
|
632
|
+
position INTEGER NOT NULL DEFAULT 0,
|
|
633
|
+
auto_assign INTEGER NOT NULL DEFAULT 0,
|
|
634
|
+
layout_x REAL,
|
|
635
|
+
layout_y REAL,
|
|
636
|
+
spawn_task_count INTEGER NOT NULL DEFAULT 0,
|
|
637
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
638
|
+
PRIMARY KEY (template_id, id)
|
|
639
|
+
);
|
|
640
|
+
|
|
641
|
+
CREATE INDEX IF NOT EXISTS idx_workflow_template_stages_template
|
|
642
|
+
ON workflow_template_stages(template_id);
|
|
643
|
+
`);
|
|
644
|
+
const columns = db.prepare("PRAGMA table_info(workflow_template_stages)").all();
|
|
645
|
+
const names = new Set(columns.map((column) => column.name));
|
|
646
|
+
if (!names.has("task_templates_json")) {
|
|
647
|
+
db.exec("ALTER TABLE workflow_template_stages ADD COLUMN task_templates_json TEXT NOT NULL DEFAULT '[]'");
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
export function countWorkflowTemplates() {
|
|
651
|
+
migrateWorkflowTemplateTables();
|
|
652
|
+
const row = getProjectsDb()
|
|
653
|
+
.prepare("SELECT COUNT(*) AS count FROM workflow_templates")
|
|
654
|
+
.get();
|
|
655
|
+
return row.count;
|
|
656
|
+
}
|
|
657
|
+
export function listWorkflowTemplateRows(filter) {
|
|
658
|
+
migrateWorkflowTemplateTables();
|
|
659
|
+
const id = filter.id;
|
|
660
|
+
if (id !== "") {
|
|
661
|
+
return getProjectsDb()
|
|
662
|
+
.prepare("SELECT id, title, description, updated_at FROM workflow_templates WHERE id = ?")
|
|
663
|
+
.all(id);
|
|
664
|
+
}
|
|
665
|
+
return getProjectsDb()
|
|
666
|
+
.prepare("SELECT id, title, description, updated_at FROM workflow_templates ORDER BY title COLLATE NOCASE ASC")
|
|
667
|
+
.all();
|
|
668
|
+
}
|
|
669
|
+
export function listWorkflowTemplateStageRows(templateId) {
|
|
670
|
+
migrateWorkflowTemplateTables();
|
|
671
|
+
return getProjectsDb()
|
|
672
|
+
.prepare(`SELECT template_id, id, title, description, purpose, rules_json, position, auto_assign, layout_x, layout_y, spawn_task_count, task_templates_json
|
|
673
|
+
FROM workflow_template_stages WHERE template_id = ? ORDER BY position ASC, title COLLATE NOCASE ASC`)
|
|
674
|
+
.all(templateId);
|
|
675
|
+
}
|
|
676
|
+
export function deleteWorkflowTemplateStages(templateId) {
|
|
677
|
+
migrateWorkflowTemplateTables();
|
|
678
|
+
getProjectsDb()
|
|
679
|
+
.prepare("DELETE FROM workflow_template_stages WHERE template_id = ?")
|
|
680
|
+
.run(templateId);
|
|
681
|
+
}
|
|
682
|
+
export function deleteWorkflowTemplateRow(templateId) {
|
|
683
|
+
migrateWorkflowTemplateTables();
|
|
684
|
+
const id = templateId;
|
|
685
|
+
deleteWorkflowTemplateStages(id);
|
|
686
|
+
const result = getProjectsDb().prepare("DELETE FROM workflow_templates WHERE id = ?").run(id);
|
|
687
|
+
return result.changes > 0;
|
|
688
|
+
}
|
|
689
|
+
export function insertWorkflowTemplateRow(row) {
|
|
690
|
+
migrateWorkflowTemplateTables();
|
|
691
|
+
getProjectsDb()
|
|
692
|
+
.prepare(`INSERT INTO workflow_templates (id, title, description, updated_at)
|
|
693
|
+
VALUES (?, ?, ?, datetime('now'))`)
|
|
694
|
+
.run(row.id, row.title, row.description);
|
|
695
|
+
}
|
|
696
|
+
export function insertWorkflowTemplateStageRow(row) {
|
|
697
|
+
migrateWorkflowTemplateTables();
|
|
698
|
+
let autoAssignFlag = 0;
|
|
699
|
+
if (row.autoAssign) {
|
|
700
|
+
autoAssignFlag = 1;
|
|
701
|
+
}
|
|
702
|
+
getProjectsDb()
|
|
703
|
+
.prepare(`INSERT INTO workflow_template_stages
|
|
704
|
+
(template_id, id, title, description, purpose, rules_json, position, auto_assign, layout_x, layout_y, spawn_task_count, task_templates_json, updated_at)
|
|
705
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, datetime('now'))`)
|
|
706
|
+
.run(row.templateId, row.id, row.title, row.description, row.purpose, row.rulesJson, row.position, autoAssignFlag, row.layoutX, row.layoutY, row.spawnTaskCount, row.taskTemplatesJson);
|
|
707
|
+
}
|
|
708
|
+
export { DEFAULT_WORKFLOW_TEMPLATE_ID } from "../domain/workflow-template-id.js";
|
|
709
|
+
export function seedDefaultWorkflowTemplates() {
|
|
710
|
+
migrateWorkflowTemplateTables();
|
|
711
|
+
removeDeprecatedTemplates();
|
|
712
|
+
for (const template of DEFAULT_TEMPLATE_SEEDS) {
|
|
713
|
+
upsertBuiltinTemplate(template);
|
|
714
|
+
}
|
|
715
|
+
}
|