@wichayutdew/pi-workflows 2.6.0 → 2.7.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/README.md +30 -0
- package/dist/index.js +141 -17
- package/examples/starter-kit/agents/planner.md +4 -0
- package/examples/starter-kit/agents/reviewer.md +4 -0
- package/examples/starter-kit/agents/scout.md +4 -0
- package/examples/starter-kit/agents/worker.md +4 -0
- package/examples/starter-kit/agents/workspace-preparer.md +4 -0
- package/examples/starter-kit/investigate.workflow.yaml +34 -64
- package/examples/starter-kit/jira.workflow.yaml +75 -0
- package/examples/starter-kit/mr-comment.workflow.yaml +48 -115
- package/examples/starter-kit/mr-review.workflow.yaml +36 -93
- package/examples/starter-kit/settings.yaml +2 -1
- package/examples/starter-kit/steps/investigate/investigate.md +18 -55
- package/examples/starter-kit/steps/investigate/retrieve.md +15 -50
- package/examples/starter-kit/steps/investigate/validate.md +10 -36
- package/examples/starter-kit/steps/jira/create.md +25 -0
- package/examples/starter-kit/steps/jira/draft.md +18 -0
- package/examples/starter-kit/steps/jira/plan.md +30 -0
- package/examples/starter-kit/steps/mr-comment/checkout-source.md +7 -60
- package/examples/starter-kit/steps/mr-comment/fetch.md +11 -36
- package/examples/starter-kit/steps/mr-comment/implement.md +10 -34
- package/examples/starter-kit/steps/mr-comment/plan.md +47 -70
- package/examples/starter-kit/steps/mr-comment/publish.md +11 -32
- package/examples/starter-kit/steps/mr-comment/verify.md +8 -42
- package/examples/starter-kit/steps/mr-review/fetch.md +8 -46
- package/examples/starter-kit/steps/mr-review/publish-approved.md +7 -38
- package/examples/starter-kit/steps/mr-review/review-for-approval.md +24 -113
- package/examples/starter-kit/steps/mr-review/verify-published.md +9 -30
- package/examples/starter-kit/steps/shared/prepare-workspace.md +9 -105
- package/examples/starter-kit/steps/shared/publish-remote.md +8 -37
- package/examples/starter-kit/steps/ticket/implement.md +11 -58
- package/examples/starter-kit/steps/ticket/plan.md +49 -171
- package/examples/starter-kit/steps/ticket/verify.md +12 -98
- package/examples/starter-kit/steps/work/implement.md +11 -58
- package/examples/starter-kit/steps/work/plan.md +42 -130
- package/examples/starter-kit/steps/work/verify.md +11 -58
- package/examples/starter-kit/ticket.workflow.yaml +38 -81
- package/examples/starter-kit/work.workflow.yaml +34 -72
- package/package.json +7 -4
- package/schemas/workflow.schema.json +61 -0
- package/scripts/patch-herdr-agent-state.mjs +36 -0
- package/src/config/types.ts +9 -0
- package/src/config/validation/step.ts +117 -0
- package/src/harness/artifact-contract.ts +46 -0
- package/src/harness/gate-submission-action.ts +28 -0
- package/src/harness/status-actions.ts +19 -0
- package/src/herdr-workflow-state.ts +65 -0
package/README.md
CHANGED
|
@@ -36,6 +36,36 @@ dictating your language, framework, or delivery process.
|
|
|
36
36
|
`reviewer`, or `scout`; customize profiles under your user workflow
|
|
37
37
|
directory's `agents/` folder.
|
|
38
38
|
|
|
39
|
+
## Herdr workflow status
|
|
40
|
+
|
|
41
|
+
When Pi runs delegated workflow steps, the parent agent may be idle while child work continues. Pi Workflows includes a Herdr companion extension that reports workflow lifecycle state so the pane remains **working** until the workflow completes, pauses, or is interrupted.
|
|
42
|
+
|
|
43
|
+
The companion is inactive unless Herdr provides `HERDR_ENV=1`, `HERDR_SOCKET_PATH`, and `HERDR_PANE_ID`. It uses Herdr's existing managed Pi reporter, so it does not create a competing pane agent.
|
|
44
|
+
|
|
45
|
+
### Install from npm
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pi install npm:@wichayutdew/pi-workflows
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Start a new Pi session in Herdr, then run a workflow normally. Herdr should show the pane as working while the workflow is active and display the terminal workflow message after completion or interruption.
|
|
52
|
+
|
|
53
|
+
### Reapply after a Herdr update
|
|
54
|
+
|
|
55
|
+
Herdr manages `~/.pi/agent/extensions/herdr-agent-state.ts`; an integration update can replace the workflow lifecycle patch. Locate the installed package with `pi list`, change into that package directory, and run:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npm run patch:herdr
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The script patches the managed integration at its default location. It is idempotent, so it is safe to run after every Herdr update. To patch a non-default integration path, set `HERDR_PI_EXTENSION_PATH` before running the script:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
HERDR_PI_EXTENSION_PATH=/path/to/herdr-agent-state.ts npm run patch:herdr
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Restart Pi or run `/reload` after patching. If Herdr's managed extension changes shape and the script reports an unsupported layout, do not edit it manually; update Pi Workflows or report the integration change.
|
|
68
|
+
|
|
39
69
|
## Explore
|
|
40
70
|
|
|
41
71
|
- [Getting started guide](./GETTING_STARTED.md) — install Pi Workflows and
|
package/dist/index.js
CHANGED
|
@@ -518,6 +518,75 @@ function parseTransitions(value, path, errors) {
|
|
|
518
518
|
}
|
|
519
519
|
return transitions;
|
|
520
520
|
}
|
|
521
|
+
function parseArtifactContract(value, path, errors) {
|
|
522
|
+
if (value === undefined)
|
|
523
|
+
return;
|
|
524
|
+
if (!isJsonObject(value)) {
|
|
525
|
+
errors.push(`${path}: expected an object`);
|
|
526
|
+
return;
|
|
527
|
+
}
|
|
528
|
+
rejectUnknownKeys(value, [
|
|
529
|
+
"maxChars",
|
|
530
|
+
"requiredSubstrings",
|
|
531
|
+
"forbiddenSubstrings",
|
|
532
|
+
"equalOccurrenceGroups",
|
|
533
|
+
"onValidationFailure"
|
|
534
|
+
], path, errors);
|
|
535
|
+
if (value.maxChars === undefined) {
|
|
536
|
+
errors.push(`${path}.maxChars: expected an integer from 1 to 200000`);
|
|
537
|
+
}
|
|
538
|
+
const maxChars = readInteger(value.maxChars, 200000, `${path}.maxChars`, errors, { min: 1, max: 200000 });
|
|
539
|
+
const parseSubstrings = (field) => {
|
|
540
|
+
const values = readStringList(value[field], `${path}.${field}`, errors, /.+/);
|
|
541
|
+
if (values.length > 32) {
|
|
542
|
+
errors.push(`${path}.${field}: at most 32 values are allowed`);
|
|
543
|
+
}
|
|
544
|
+
values.forEach((substring, index) => {
|
|
545
|
+
if (substring.length > 1024) {
|
|
546
|
+
errors.push(`${path}.${field}[${index}]: exceeds 1024 characters`);
|
|
547
|
+
}
|
|
548
|
+
});
|
|
549
|
+
return values;
|
|
550
|
+
};
|
|
551
|
+
const equalOccurrenceGroups = (() => {
|
|
552
|
+
if (value.equalOccurrenceGroups === undefined)
|
|
553
|
+
return [];
|
|
554
|
+
if (!Array.isArray(value.equalOccurrenceGroups)) {
|
|
555
|
+
errors.push(`${path}.equalOccurrenceGroups: expected an array`);
|
|
556
|
+
return [];
|
|
557
|
+
}
|
|
558
|
+
if (value.equalOccurrenceGroups.length > 32) {
|
|
559
|
+
errors.push(`${path}.equalOccurrenceGroups: at most 32 groups are allowed`);
|
|
560
|
+
}
|
|
561
|
+
return value.equalOccurrenceGroups.reduce((groups, group, index) => {
|
|
562
|
+
const groupPath = `${path}.equalOccurrenceGroups[${index}]`;
|
|
563
|
+
const values = readStringList(group, groupPath, errors, /.+/);
|
|
564
|
+
if (values.length < 2) {
|
|
565
|
+
errors.push(`${groupPath}: at least two values are required`);
|
|
566
|
+
}
|
|
567
|
+
if (values.length > 32) {
|
|
568
|
+
errors.push(`${groupPath}: at most 32 values are allowed`);
|
|
569
|
+
}
|
|
570
|
+
values.forEach((substring, valueIndex) => {
|
|
571
|
+
if (substring.length > 1024) {
|
|
572
|
+
errors.push(`${groupPath}[${valueIndex}]: exceeds 1024 characters`);
|
|
573
|
+
}
|
|
574
|
+
});
|
|
575
|
+
return [...groups, values];
|
|
576
|
+
}, []);
|
|
577
|
+
})();
|
|
578
|
+
const onValidationFailure = value.onValidationFailure === undefined ? undefined : readString(value.onValidationFailure, `${path}.onValidationFailure`, errors);
|
|
579
|
+
if (onValidationFailure !== undefined && onValidationFailure !== "retry") {
|
|
580
|
+
errors.push(`${path}.onValidationFailure: expected retry`);
|
|
581
|
+
}
|
|
582
|
+
return {
|
|
583
|
+
maxChars,
|
|
584
|
+
requiredSubstrings: parseSubstrings("requiredSubstrings"),
|
|
585
|
+
forbiddenSubstrings: parseSubstrings("forbiddenSubstrings"),
|
|
586
|
+
equalOccurrenceGroups,
|
|
587
|
+
...onValidationFailure === "retry" ? { onValidationFailure } : {}
|
|
588
|
+
};
|
|
589
|
+
}
|
|
521
590
|
function parseGate(value, path, errors) {
|
|
522
591
|
if (value === undefined)
|
|
523
592
|
return;
|
|
@@ -530,7 +599,8 @@ function parseGate(value, path, errors) {
|
|
|
530
599
|
"submitOutcome",
|
|
531
600
|
"approvedOutcome",
|
|
532
601
|
"rejectedOutcome",
|
|
533
|
-
"timeoutMs"
|
|
602
|
+
"timeoutMs",
|
|
603
|
+
"artifactContract"
|
|
534
604
|
], path, errors);
|
|
535
605
|
const providerValue = value.provider === undefined ? "prompt" : readString(value.provider, `${path}.provider`, errors);
|
|
536
606
|
const provider = providerValue === "prompt" || providerValue === "plannotator" ? providerValue : undefined;
|
|
@@ -540,6 +610,7 @@ function parseGate(value, path, errors) {
|
|
|
540
610
|
const submitOutcome = readString(value.submitOutcome, `${path}.submitOutcome`, errors, { pattern: OUTCOME_PATTERN });
|
|
541
611
|
const approvedOutcome = readString(value.approvedOutcome, `${path}.approvedOutcome`, errors, { pattern: OUTCOME_PATTERN });
|
|
542
612
|
const rejectedOutcome = readString(value.rejectedOutcome, `${path}.rejectedOutcome`, errors, { pattern: OUTCOME_PATTERN });
|
|
613
|
+
const artifactContract = parseArtifactContract(value.artifactContract, `${path}.artifactContract`, errors);
|
|
543
614
|
if (provider === "prompt" && value.timeoutMs !== undefined) {
|
|
544
615
|
errors.push(`${path}.timeoutMs: only valid with provider "plannotator"`);
|
|
545
616
|
}
|
|
@@ -553,12 +624,14 @@ function parseGate(value, path, errors) {
|
|
|
553
624
|
provider,
|
|
554
625
|
submitOutcome,
|
|
555
626
|
approvedOutcome,
|
|
556
|
-
rejectedOutcome
|
|
627
|
+
rejectedOutcome,
|
|
628
|
+
...artifactContract ? { artifactContract } : {}
|
|
557
629
|
} : {
|
|
558
630
|
provider,
|
|
559
631
|
submitOutcome,
|
|
560
632
|
approvedOutcome,
|
|
561
633
|
rejectedOutcome,
|
|
634
|
+
...artifactContract ? { artifactContract } : {},
|
|
562
635
|
timeoutMs: readInteger(value.timeoutMs, 30000, `${path}.timeoutMs`, errors, { min: 1000, max: 30000 })
|
|
563
636
|
};
|
|
564
637
|
}
|
|
@@ -649,6 +722,9 @@ function parseWorkflowStep(value, stepId, path, errors) {
|
|
|
649
722
|
if (Object.hasOwn(transitions, gate.submitOutcome)) {
|
|
650
723
|
errors.push(`${path}.transitions: submitOutcome is handled by the gate and must not be a transition`);
|
|
651
724
|
}
|
|
725
|
+
if (gate.artifactContract?.onValidationFailure === "retry" && !Object.hasOwn(transitions, "retry")) {
|
|
726
|
+
errors.push(`${path}.transitions: artifact-contract retry requires a "retry" transition`);
|
|
727
|
+
}
|
|
652
728
|
}
|
|
653
729
|
if (workspace) {
|
|
654
730
|
workspace.bindOn.forEach((outcome) => {
|
|
@@ -1595,19 +1671,6 @@ function createSubagentDelegationClient(spawnWorker = spawn) {
|
|
|
1595
1671
|
};
|
|
1596
1672
|
}
|
|
1597
1673
|
|
|
1598
|
-
class SubagentDelegationClient {
|
|
1599
|
-
#client = createSubagentDelegationClient();
|
|
1600
|
-
get activeRequestId() {
|
|
1601
|
-
return this.#client.activeRequestId;
|
|
1602
|
-
}
|
|
1603
|
-
delegate(request, options) {
|
|
1604
|
-
return this.#client.delegate(request, options);
|
|
1605
|
-
}
|
|
1606
|
-
cancelActiveAndWait(waitMs) {
|
|
1607
|
-
return this.#client.cancelActiveAndWait(waitMs);
|
|
1608
|
-
}
|
|
1609
|
-
}
|
|
1610
|
-
|
|
1611
1674
|
// src/policy/completion-batch.ts
|
|
1612
1675
|
var isRecord3 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
1613
1676
|
var toolCalls = (message) => {
|
|
@@ -4005,6 +4068,13 @@ function workflowStatusSnapshot() {
|
|
|
4005
4068
|
}
|
|
4006
4069
|
function updateStatus() {
|
|
4007
4070
|
refreshStatusWhileRunning.call(this);
|
|
4071
|
+
const run = this.run;
|
|
4072
|
+
this.pi.events.emit("pi-workflows:state", {
|
|
4073
|
+
state: run?.status === "running" ? "working" : run?.status === "awaiting-gate" || run?.status === "paused" ? "blocked" : run?.status === "completed" ? "completed" : "interrupted",
|
|
4074
|
+
workflowId: run?.workflowId,
|
|
4075
|
+
stepId: run?.currentStepId,
|
|
4076
|
+
message: run?.status === "completed" ? `Workflow "${run.workflowId}" completed` : run?.status === "paused" ? run.pauseReason : undefined
|
|
4077
|
+
});
|
|
4008
4078
|
if (!this.latestContext)
|
|
4009
4079
|
return;
|
|
4010
4080
|
if (this.legacyProgressWidgetContext !== this.latestContext) {
|
|
@@ -6700,6 +6770,44 @@ function createDelegationControlActions() {
|
|
|
6700
6770
|
};
|
|
6701
6771
|
}
|
|
6702
6772
|
|
|
6773
|
+
// src/harness/artifact-contract.ts
|
|
6774
|
+
function countOccurrences(value, substring) {
|
|
6775
|
+
let count = 0;
|
|
6776
|
+
let offset = 0;
|
|
6777
|
+
while (true) {
|
|
6778
|
+
const match = value.indexOf(substring, offset);
|
|
6779
|
+
if (match === -1)
|
|
6780
|
+
return count;
|
|
6781
|
+
count += 1;
|
|
6782
|
+
offset = match + substring.length;
|
|
6783
|
+
}
|
|
6784
|
+
}
|
|
6785
|
+
function validateArtifactContract(artifact, contract) {
|
|
6786
|
+
if (!contract)
|
|
6787
|
+
return;
|
|
6788
|
+
if (artifact.length > contract.maxChars) {
|
|
6789
|
+
return `gate artifact exceeds ${contract.maxChars} characters`;
|
|
6790
|
+
}
|
|
6791
|
+
const required = contract.requiredSubstrings.find((substring) => !artifact.includes(substring));
|
|
6792
|
+
if (required) {
|
|
6793
|
+
return `gate artifact is missing required text: ${JSON.stringify(required)}`;
|
|
6794
|
+
}
|
|
6795
|
+
const forbidden = contract.forbiddenSubstrings.find((substring) => artifact.includes(substring));
|
|
6796
|
+
if (forbidden) {
|
|
6797
|
+
return `gate artifact contains forbidden text: ${JSON.stringify(forbidden)}`;
|
|
6798
|
+
}
|
|
6799
|
+
for (const group of contract.equalOccurrenceGroups) {
|
|
6800
|
+
const counts = group.map((substring) => countOccurrences(artifact, substring));
|
|
6801
|
+
if (counts.some((count) => count === 0)) {
|
|
6802
|
+
return `gate artifact is missing required repeated text: ${JSON.stringify(group)}`;
|
|
6803
|
+
}
|
|
6804
|
+
if (!counts.every((count) => count === counts[0])) {
|
|
6805
|
+
return `gate artifact has unequal repeated text counts: ${JSON.stringify(group)}`;
|
|
6806
|
+
}
|
|
6807
|
+
}
|
|
6808
|
+
return;
|
|
6809
|
+
}
|
|
6810
|
+
|
|
6703
6811
|
// src/harness/gate-submission-action.ts
|
|
6704
6812
|
function isCurrentGateRequest(run, originalRun, requestId) {
|
|
6705
6813
|
return run !== undefined && run.runId === originalRun.runId && run.currentStepId === originalRun.currentStepId && run.pendingGate?.requestId === requestId && run.pendingGate.reviewId === undefined && (run.status === "awaiting-gate" || run.status === "paused");
|
|
@@ -6710,6 +6818,22 @@ async function submitGate(workflow, originalRun, outcome, summary, artifact) {
|
|
|
6710
6818
|
const step = workflow.definition.steps[originalRun.currentStepId];
|
|
6711
6819
|
if (!step?.gate)
|
|
6712
6820
|
throw new Error("Current step has no gate");
|
|
6821
|
+
const contractError = validateArtifactContract(artifact, step.gate.artifactContract);
|
|
6822
|
+
if (contractError) {
|
|
6823
|
+
if (step.gate.artifactContract?.onValidationFailure !== "retry") {
|
|
6824
|
+
throw new Error(contractError);
|
|
6825
|
+
}
|
|
6826
|
+
const retrySummary = `Artifact contract failed: ${contractError}`;
|
|
6827
|
+
this.run = advanceRun(workflow, originalRun, "retry", retrySummary, this.dependencies.now());
|
|
6828
|
+
this.persist();
|
|
6829
|
+
this.updateStatus();
|
|
6830
|
+
this.settleAfterTransition(workflow, {
|
|
6831
|
+
stepId: originalRun.currentStepId,
|
|
6832
|
+
outcome: "retry",
|
|
6833
|
+
summary: retrySummary
|
|
6834
|
+
});
|
|
6835
|
+
return;
|
|
6836
|
+
}
|
|
6713
6837
|
this.run = beginGate(workflow, originalRun, outcome, artifact, requestId, this.dependencies.now(), summary);
|
|
6714
6838
|
this.persist();
|
|
6715
6839
|
this.restoreBaselineTools();
|
|
@@ -7696,6 +7820,6 @@ function createPiWorkflowsExtension(dependencies) {
|
|
|
7696
7820
|
var piWorkflowsExtension = createPiWorkflowsExtension(DEFAULT_DEPENDENCIES4);
|
|
7697
7821
|
var src_default = piWorkflowsExtension;
|
|
7698
7822
|
export {
|
|
7699
|
-
|
|
7700
|
-
|
|
7823
|
+
createPiWorkflowsExtension,
|
|
7824
|
+
src_default as default
|
|
7701
7825
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
version: 1
|
|
2
2
|
id: investigate
|
|
3
3
|
command: investigate
|
|
4
|
-
description: Derive, approve, investigate, and independently validate an evidence-backed finding
|
|
4
|
+
description: 'Derive, approve, investigate, and independently validate an evidence-backed finding. Example: /investigate PROJ-123 Root cause of elevated 500 error rates in checkout service'
|
|
5
5
|
start: retrieve
|
|
6
6
|
maxStepVisits: 12
|
|
7
7
|
summaryMaxChars: 30000
|
|
@@ -12,48 +12,30 @@ steps:
|
|
|
12
12
|
file: steps/investigate/retrieve.md
|
|
13
13
|
agent: scout
|
|
14
14
|
permissions:
|
|
15
|
-
tools: [read, ls, bash]
|
|
16
|
-
mcp:
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
- atlassian/atlassian_getJiraIssueRemoteIssueLinks
|
|
20
|
-
- atlassian/atlassian_searchJiraIssuesUsingJql
|
|
21
|
-
extensions: [pi-web-tools]
|
|
22
|
-
skills: &retrieve-skills [caveman, coding-standards, brainstorming]
|
|
15
|
+
tools: [read, ls, bash, mcp]
|
|
16
|
+
mcp: [atlassian, context7, sourcegraph, glean, grafana]
|
|
17
|
+
extensions: [/]
|
|
18
|
+
skills: [jira-ticket, start-triage, search-code-sourcegraph, caveman]
|
|
23
19
|
bash:
|
|
24
|
-
mode:
|
|
25
|
-
allow: &inspection-bash
|
|
26
|
-
- executable: grep
|
|
27
|
-
- executable: head
|
|
28
|
-
- executable: ls
|
|
29
|
-
- executable: pwd
|
|
30
|
-
- executable: rg
|
|
31
|
-
- executable: stat
|
|
32
|
-
- executable: tail
|
|
33
|
-
- executable: wc
|
|
34
|
-
- executable: git
|
|
35
|
-
argsPrefixes:
|
|
36
|
-
[
|
|
37
|
-
[status],
|
|
38
|
-
[diff],
|
|
39
|
-
[grep],
|
|
40
|
-
[log],
|
|
41
|
-
[ls-files],
|
|
42
|
-
[rev-parse],
|
|
43
|
-
[show],
|
|
44
|
-
[merge-base],
|
|
45
|
-
[rev-list],
|
|
46
|
-
[worktree, list],
|
|
47
|
-
]
|
|
48
|
-
requires:
|
|
49
|
-
tools: [read, ls, bash]
|
|
50
|
-
skills: *retrieve-skills
|
|
20
|
+
mode: unrestricted
|
|
51
21
|
gate:
|
|
52
22
|
provider: plannotator
|
|
53
23
|
submitOutcome: submit
|
|
54
24
|
approvedOutcome: approved
|
|
55
25
|
rejectedOutcome: changes-requested
|
|
56
26
|
timeoutMs: 30000
|
|
27
|
+
artifactContract:
|
|
28
|
+
maxChars: 6000
|
|
29
|
+
requiredSubstrings:
|
|
30
|
+
- '## Brief description'
|
|
31
|
+
- '## Goals'
|
|
32
|
+
- '## Boundaries'
|
|
33
|
+
- '## Evidence & sources'
|
|
34
|
+
- '## Report destination'
|
|
35
|
+
- '## Open evidence gaps'
|
|
36
|
+
forbiddenSubstrings:
|
|
37
|
+
- 'The complete gate artifact is the exact Markdown saved at'
|
|
38
|
+
onValidationFailure: retry
|
|
57
39
|
transitions:
|
|
58
40
|
approved: investigate
|
|
59
41
|
changes-requested: retrieve
|
|
@@ -65,23 +47,20 @@ steps:
|
|
|
65
47
|
file: steps/investigate/investigate.md
|
|
66
48
|
agent: worker
|
|
67
49
|
permissions:
|
|
68
|
-
tools: [read, ls, bash,
|
|
69
|
-
mcp:
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
50
|
+
tools: [read, ls, bash, write, mcp]
|
|
51
|
+
mcp: [atlassian, context7, sourcegraph, glean, grafana, gitlab]
|
|
52
|
+
extensions: [/]
|
|
53
|
+
skills:
|
|
54
|
+
[
|
|
55
|
+
coding-standards,
|
|
56
|
+
systematic-debugging,
|
|
57
|
+
start-triage,
|
|
58
|
+
grafana-logs,
|
|
59
|
+
search-code-sourcegraph,
|
|
60
|
+
caveman,
|
|
61
|
+
]
|
|
80
62
|
bash:
|
|
81
63
|
mode: unrestricted
|
|
82
|
-
requires:
|
|
83
|
-
tools: [read, ls, bash, edit, write]
|
|
84
|
-
skills: *investigation-skills
|
|
85
64
|
transitions:
|
|
86
65
|
ready: validate
|
|
87
66
|
retry: investigate
|
|
@@ -92,21 +71,12 @@ steps:
|
|
|
92
71
|
file: steps/investigate/validate.md
|
|
93
72
|
agent: reviewer
|
|
94
73
|
permissions:
|
|
95
|
-
tools: [read, ls, bash]
|
|
96
|
-
mcp:
|
|
97
|
-
extensions: [
|
|
98
|
-
skills:
|
|
99
|
-
&validation-skills [
|
|
100
|
-
caveman,
|
|
101
|
-
coding-standards,
|
|
102
|
-
systematic-debugging,
|
|
103
|
-
verification-before-completion,
|
|
104
|
-
]
|
|
74
|
+
tools: [read, ls, bash, mcp]
|
|
75
|
+
mcp: [atlassian, sourcegraph, glean, gitlab]
|
|
76
|
+
extensions: [/]
|
|
77
|
+
skills: [verification-before-completion, caveman]
|
|
105
78
|
bash:
|
|
106
79
|
mode: unrestricted
|
|
107
|
-
requires:
|
|
108
|
-
tools: [read, ls, bash]
|
|
109
|
-
skills: *validation-skills
|
|
110
80
|
transitions:
|
|
111
81
|
approved: $done
|
|
112
82
|
gaps: investigate
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
version: 1
|
|
2
|
+
id: jira
|
|
3
|
+
command: jira
|
|
4
|
+
description: 'Draft, approve, and create a Jira Epic with ordered Stories. Example: /jira ACTB Implement multi-region failover for pricing service'
|
|
5
|
+
start: draft
|
|
6
|
+
maxStepVisits: 12
|
|
7
|
+
summaryMaxChars: 30000
|
|
8
|
+
steps:
|
|
9
|
+
draft:
|
|
10
|
+
title: Normalize Epic and Story input
|
|
11
|
+
prompt:
|
|
12
|
+
file: steps/jira/draft.md
|
|
13
|
+
agent: scout
|
|
14
|
+
permissions:
|
|
15
|
+
tools: [read, ls, bash]
|
|
16
|
+
mcp: []
|
|
17
|
+
extensions: [/]
|
|
18
|
+
skills: [jira-ticket, caveman]
|
|
19
|
+
bash:
|
|
20
|
+
mode: unrestricted
|
|
21
|
+
transitions:
|
|
22
|
+
ready: plan
|
|
23
|
+
retry: draft
|
|
24
|
+
blocked: $pause
|
|
25
|
+
plan:
|
|
26
|
+
title: Validate Jira schema and approve Epic and Story plan
|
|
27
|
+
prompt:
|
|
28
|
+
file: steps/jira/plan.md
|
|
29
|
+
agent: planner
|
|
30
|
+
permissions:
|
|
31
|
+
tools: [read, ls, bash, mcp]
|
|
32
|
+
mcp: [atlassian]
|
|
33
|
+
extensions: [/]
|
|
34
|
+
skills: [jira-ticket, caveman]
|
|
35
|
+
bash:
|
|
36
|
+
mode: unrestricted
|
|
37
|
+
gate:
|
|
38
|
+
provider: plannotator
|
|
39
|
+
submitOutcome: submit
|
|
40
|
+
approvedOutcome: approved
|
|
41
|
+
rejectedOutcome: changes-requested
|
|
42
|
+
timeoutMs: 30000
|
|
43
|
+
artifactContract:
|
|
44
|
+
maxChars: 16000
|
|
45
|
+
requiredSubstrings:
|
|
46
|
+
- '# Create Jira Epic and Stories'
|
|
47
|
+
- '## Jira field contract'
|
|
48
|
+
- '## Epic'
|
|
49
|
+
- '## Ordered Stories'
|
|
50
|
+
- '## Creation sequence'
|
|
51
|
+
- '## Safety limits'
|
|
52
|
+
forbiddenSubstrings:
|
|
53
|
+
- 'The complete gate artifact is the exact Markdown saved at'
|
|
54
|
+
onValidationFailure: retry
|
|
55
|
+
transitions:
|
|
56
|
+
approved: create
|
|
57
|
+
changes-requested: plan
|
|
58
|
+
retry: plan
|
|
59
|
+
blocked: $pause
|
|
60
|
+
create:
|
|
61
|
+
title: Create approved Jira Epic and Stories
|
|
62
|
+
prompt:
|
|
63
|
+
file: steps/jira/create.md
|
|
64
|
+
agent: worker
|
|
65
|
+
permissions:
|
|
66
|
+
tools: [read, ls, bash, mcp]
|
|
67
|
+
mcp: [atlassian]
|
|
68
|
+
extensions: [/]
|
|
69
|
+
skills: [jira-ticket, caveman]
|
|
70
|
+
bash:
|
|
71
|
+
mode: unrestricted
|
|
72
|
+
transitions:
|
|
73
|
+
ready: $done
|
|
74
|
+
retry: create
|
|
75
|
+
blocked: $pause
|