@exaudeus/workrail 1.17.1 → 2.1.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 +11 -11
- package/dist/application/use-cases/raw-workflow-file-scanner.d.ts +1 -1
- package/dist/application/use-cases/raw-workflow-file-scanner.js +2 -0
- package/dist/application/use-cases/validate-workflow-registry.js +2 -1
- package/dist/config/feature-flags.js +11 -3
- package/dist/infrastructure/storage/file-workflow-storage.js +8 -3
- package/dist/infrastructure/storage/workflow-resolution.d.ts +9 -6
- package/dist/infrastructure/storage/workflow-resolution.js +14 -1
- package/dist/manifest.json +40 -32
- package/dist/mcp/handlers/shared/request-workflow-reader.d.ts +19 -0
- package/dist/mcp/handlers/shared/request-workflow-reader.js +50 -0
- package/dist/mcp/handlers/v2-execution/start.d.ts +3 -1
- package/dist/mcp/handlers/v2-execution/start.js +32 -9
- package/dist/mcp/handlers/v2-workflow.d.ts +1 -1
- package/dist/mcp/handlers/v2-workflow.js +25 -4
- package/dist/mcp/server.js +11 -0
- package/dist/mcp/tool-descriptions.js +9 -2
- package/dist/mcp/types.d.ts +2 -0
- package/dist/mcp/v2/tools.d.ts +10 -1
- package/dist/mcp/v2/tools.js +9 -5
- package/package.json +1 -1
- package/workflows/coding-task-workflow-agentic.lean.v2.json +224 -0
- package/workflows/routines/philosophy-alignment.json +12 -12
- package/workflows/routines/tension-driven-design.json +63 -0
package/README.md
CHANGED
|
@@ -31,8 +31,8 @@ to conclusions.
|
|
|
31
31
|
WorkRail replaces the human effort of guiding an agent step-by-step.
|
|
32
32
|
|
|
33
33
|
Instead of one system prompt that fades over time, WorkRail drip-feeds instructions through
|
|
34
|
-
the [Model Context Protocol](https://modelcontextprotocol.org). The agent calls `
|
|
35
|
-
gets
|
|
34
|
+
the [Model Context Protocol](https://modelcontextprotocol.org). The agent calls `start_workflow`,
|
|
35
|
+
gets the first step, completes it, calls `continue_workflow`. Future steps stay hidden until previous ones are done.
|
|
36
36
|
|
|
37
37
|
**The agent can't skip to implementation because it doesn't know those steps exist yet.**
|
|
38
38
|
|
|
@@ -44,7 +44,7 @@ You Agent WorkRail
|
|
|
44
44
|
│ "Fix the auth bug" │ │
|
|
45
45
|
│────────────────────────>│ │
|
|
46
46
|
│ │ │
|
|
47
|
-
│ │
|
|
47
|
+
│ │ start_workflow() │
|
|
48
48
|
│ │─────────────────────────>│
|
|
49
49
|
│ │ │
|
|
50
50
|
│ │ Step 1: Understand │
|
|
@@ -55,7 +55,7 @@ You Agent WorkRail
|
|
|
55
55
|
│ see exactly?" │ │
|
|
56
56
|
│<────────────────────────│ │
|
|
57
57
|
│ │ │
|
|
58
|
-
│ ... │
|
|
58
|
+
│ ... │ continue_workflow() │
|
|
59
59
|
│ │─────────────────────────>│
|
|
60
60
|
│ │ │
|
|
61
61
|
│ │ Step 2: Plan your │
|
|
@@ -81,21 +81,21 @@ Agent: "I see the issue! In auth.js line 42, there's a null check that
|
|
|
81
81
|
You: "There's a bug in the auth flow"
|
|
82
82
|
|
|
83
83
|
Agent: "I'll use the bug-investigation workflow."
|
|
84
|
-
→
|
|
84
|
+
→ start_workflow()
|
|
85
85
|
|
|
86
86
|
Step 1: Investigation Setup
|
|
87
87
|
"Before I investigate, I need to understand the problem.
|
|
88
88
|
What exactly happens when it fails? Can you share the error?"
|
|
89
89
|
|
|
90
90
|
[Documents bug, reproduction steps, environment]
|
|
91
|
-
→
|
|
91
|
+
→ continue_workflow()
|
|
92
92
|
|
|
93
93
|
Step 2: Plan Investigation
|
|
94
94
|
"I'll trace execution from login through the auth middleware.
|
|
95
95
|
Key areas: token validation, session lookup, error handling."
|
|
96
96
|
|
|
97
97
|
[Creates investigation plan before touching code]
|
|
98
|
-
→
|
|
98
|
+
→ continue_workflow()
|
|
99
99
|
|
|
100
100
|
Step 3: Form Hypotheses
|
|
101
101
|
"Based on my analysis, three possible causes:
|
|
@@ -164,13 +164,13 @@ The agent will find the workflow, start at step 1, and proceed systematically.
|
|
|
164
164
|
|
|
165
165
|
## Included Workflows
|
|
166
166
|
|
|
167
|
-
|
|
167
|
+
30+ workflows included for development, debugging, review, documentation, and more:
|
|
168
168
|
|
|
169
169
|
| Workflow | When to Use |
|
|
170
170
|
|----------|-------------|
|
|
171
|
-
| `coding-task-workflow-
|
|
172
|
-
| `bug-investigation` | Systematic debugging with
|
|
173
|
-
| `mr-review-workflow` | Code review with
|
|
171
|
+
| `coding-task-workflow-agentic` | Feature development with notes-first durability and audit loops |
|
|
172
|
+
| `bug-investigation-agentic` | Systematic debugging with evidence-based analysis |
|
|
173
|
+
| `mr-review-workflow-agentic` | Code review with parallel reviewer families |
|
|
174
174
|
| `exploration-workflow` | Understanding an unfamiliar codebase |
|
|
175
175
|
| `document-creation-workflow` | Technical documentation with structure |
|
|
176
176
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { WorkflowDefinition } from '../../types/workflow-definition.js';
|
|
2
2
|
export declare function findWorkflowJsonFiles(baseDirReal: string): Promise<string[]>;
|
|
3
|
-
export type VariantKind = 'v2' | 'agentic' | 'standard';
|
|
3
|
+
export type VariantKind = 'lean' | 'v2' | 'agentic' | 'standard';
|
|
4
4
|
export interface ParsedRawWorkflowFile {
|
|
5
5
|
readonly kind: 'parsed';
|
|
6
6
|
readonly filePath: string;
|
|
@@ -77,6 +77,8 @@ async function scanRawWorkflowFiles(baseDirReal) {
|
|
|
77
77
|
}
|
|
78
78
|
function detectVariantKind(relativeFilePath) {
|
|
79
79
|
const normalized = relativeFilePath.replace(/\\/g, '/');
|
|
80
|
+
if (normalized.includes('.lean.'))
|
|
81
|
+
return 'lean';
|
|
80
82
|
if (normalized.includes('.v2.'))
|
|
81
83
|
return 'v2';
|
|
82
84
|
if (normalized.includes('.agentic.'))
|
|
@@ -191,7 +191,7 @@ function deriveVariantResolutions(loadedWorkflows, allRawFiles, source) {
|
|
|
191
191
|
const availableVariants = rawFilesForId.map(f => f.variantKind);
|
|
192
192
|
const selectedRaw = rawFilesForId.find(f => f.definition.id === id);
|
|
193
193
|
const selectedVariant = selectedRaw?.variantKind ?? 'standard';
|
|
194
|
-
if (selectedVariant === 'v2' || selectedVariant === 'agentic') {
|
|
194
|
+
if (selectedVariant === 'lean' || selectedVariant === 'v2' || selectedVariant === 'agentic') {
|
|
195
195
|
result.set(id, {
|
|
196
196
|
kind: 'feature_flag_selected',
|
|
197
197
|
selectedVariant,
|
|
@@ -199,6 +199,7 @@ function deriveVariantResolutions(loadedWorkflows, allRawFiles, source) {
|
|
|
199
199
|
enabledFlags: {
|
|
200
200
|
v2Tools: selectedVariant === 'v2',
|
|
201
201
|
agenticRoutines: selectedVariant === 'agentic',
|
|
202
|
+
leanWorkflows: selectedVariant === 'lean',
|
|
202
203
|
},
|
|
203
204
|
});
|
|
204
205
|
}
|
|
@@ -45,6 +45,14 @@ exports.FEATURE_FLAG_DEFINITIONS = [
|
|
|
45
45
|
since: '0.8.3',
|
|
46
46
|
stable: false,
|
|
47
47
|
},
|
|
48
|
+
{
|
|
49
|
+
key: 'leanWorkflows',
|
|
50
|
+
envVar: 'WORKRAIL_ENABLE_LEAN_WORKFLOWS',
|
|
51
|
+
defaultValue: false,
|
|
52
|
+
description: 'Enable lean workflow variants (.lean.) that merge phases and reduce token usage while preserving quality',
|
|
53
|
+
since: '0.10.0',
|
|
54
|
+
stable: false,
|
|
55
|
+
},
|
|
48
56
|
{
|
|
49
57
|
key: 'authoritativeDescriptions',
|
|
50
58
|
envVar: 'WORKRAIL_AUTHORITATIVE_DESCRIPTIONS',
|
|
@@ -56,10 +64,10 @@ exports.FEATURE_FLAG_DEFINITIONS = [
|
|
|
56
64
|
{
|
|
57
65
|
key: 'v2Tools',
|
|
58
66
|
envVar: 'WORKRAIL_ENABLE_V2_TOOLS',
|
|
59
|
-
defaultValue:
|
|
60
|
-
description: '
|
|
67
|
+
defaultValue: true,
|
|
68
|
+
description: 'WorkRail v2 MCP tools (list_workflows, start_workflow, continue_workflow, checkpoint_workflow, resume_session) and .v2.json workflow overrides',
|
|
61
69
|
since: '0.9.0',
|
|
62
|
-
stable:
|
|
70
|
+
stable: true,
|
|
63
71
|
},
|
|
64
72
|
];
|
|
65
73
|
function parseBoolean(value, defaultValue) {
|
|
@@ -55,6 +55,9 @@ class FileWorkflowStorage {
|
|
|
55
55
|
continue;
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
|
+
if (!this.featureFlags.isEnabled('leanWorkflows') && file.includes('.lean.')) {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
58
61
|
if (!this.featureFlags.isEnabled('v2Tools') && file.includes('.v2.')) {
|
|
59
62
|
continue;
|
|
60
63
|
}
|
|
@@ -78,12 +81,14 @@ class FileWorkflowStorage {
|
|
|
78
81
|
const flags = {
|
|
79
82
|
v2Tools: this.featureFlags.isEnabled('v2Tools'),
|
|
80
83
|
agenticRoutines: this.featureFlags.isEnabled('agenticRoutines'),
|
|
84
|
+
leanWorkflows: this.featureFlags.isEnabled('leanWorkflows'),
|
|
81
85
|
};
|
|
82
86
|
for (const [id, files] of idToFiles) {
|
|
83
87
|
const candidates = files.map(f => ({
|
|
84
|
-
variantKind: f.file.includes('.
|
|
85
|
-
: f.file.includes('.
|
|
86
|
-
: '
|
|
88
|
+
variantKind: f.file.includes('.lean.') ? 'lean'
|
|
89
|
+
: f.file.includes('.v2.') ? 'v2'
|
|
90
|
+
: f.file.includes('.agentic.') ? 'agentic'
|
|
91
|
+
: 'standard',
|
|
87
92
|
identifier: f.file,
|
|
88
93
|
}));
|
|
89
94
|
const selection = (0, workflow_resolution_1.selectVariant)(candidates, flags);
|
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import type { Workflow } from '../../types/workflow.js';
|
|
2
2
|
export type SourceRef = number;
|
|
3
|
+
export type VariantKind = 'lean' | 'v2' | 'agentic' | 'standard';
|
|
3
4
|
export type VariantResolution = {
|
|
4
5
|
readonly kind: 'only_variant';
|
|
5
6
|
} | {
|
|
6
7
|
readonly kind: 'feature_flag_selected';
|
|
7
|
-
readonly selectedVariant:
|
|
8
|
-
readonly availableVariants: readonly
|
|
8
|
+
readonly selectedVariant: VariantKind;
|
|
9
|
+
readonly availableVariants: readonly VariantKind[];
|
|
9
10
|
readonly enabledFlags: {
|
|
10
11
|
readonly v2Tools: boolean;
|
|
11
12
|
readonly agenticRoutines: boolean;
|
|
13
|
+
readonly leanWorkflows: boolean;
|
|
12
14
|
};
|
|
13
15
|
} | {
|
|
14
16
|
readonly kind: 'precedence_fallback';
|
|
15
|
-
readonly selectedVariant:
|
|
16
|
-
readonly availableVariants: readonly
|
|
17
|
+
readonly selectedVariant: VariantKind;
|
|
18
|
+
readonly availableVariants: readonly VariantKind[];
|
|
17
19
|
};
|
|
18
20
|
export type ResolutionReason = {
|
|
19
21
|
readonly kind: 'unique';
|
|
@@ -39,15 +41,16 @@ export declare function resolveWorkflowCandidates(candidates: readonly {
|
|
|
39
41
|
readonly workflows: readonly Workflow[];
|
|
40
42
|
}[], variantResolutions: ReadonlyMap<string, ReadonlyMap<SourceRef, VariantResolution>>): readonly ResolvedWorkflow[];
|
|
41
43
|
export interface VariantCandidate {
|
|
42
|
-
readonly variantKind:
|
|
44
|
+
readonly variantKind: VariantKind;
|
|
43
45
|
readonly identifier: string;
|
|
44
46
|
}
|
|
45
47
|
export interface VariantSelectionFlags {
|
|
46
48
|
readonly v2Tools: boolean;
|
|
47
49
|
readonly agenticRoutines: boolean;
|
|
50
|
+
readonly leanWorkflows: boolean;
|
|
48
51
|
}
|
|
49
52
|
export interface VariantSelectionResult {
|
|
50
|
-
readonly selectedVariant:
|
|
53
|
+
readonly selectedVariant: VariantKind;
|
|
51
54
|
readonly selectedIdentifier: string;
|
|
52
55
|
readonly resolution: VariantResolution;
|
|
53
56
|
}
|
|
@@ -79,9 +79,22 @@ function selectVariant(candidates, flags) {
|
|
|
79
79
|
};
|
|
80
80
|
}
|
|
81
81
|
const availableVariants = candidates.map(c => c.variantKind);
|
|
82
|
+
const leanCandidate = candidates.find(c => c.variantKind === 'lean');
|
|
82
83
|
const v2Candidate = candidates.find(c => c.variantKind === 'v2');
|
|
83
84
|
const agenticCandidate = candidates.find(c => c.variantKind === 'agentic');
|
|
84
85
|
const standardCandidate = candidates.find(c => c.variantKind === 'standard');
|
|
86
|
+
if (flags.leanWorkflows && leanCandidate) {
|
|
87
|
+
return {
|
|
88
|
+
selectedVariant: 'lean',
|
|
89
|
+
selectedIdentifier: leanCandidate.identifier,
|
|
90
|
+
resolution: {
|
|
91
|
+
kind: 'feature_flag_selected',
|
|
92
|
+
selectedVariant: 'lean',
|
|
93
|
+
availableVariants,
|
|
94
|
+
enabledFlags: flags,
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
85
98
|
if (flags.v2Tools && v2Candidate) {
|
|
86
99
|
return {
|
|
87
100
|
selectedVariant: 'v2',
|
|
@@ -117,7 +130,7 @@ function selectVariant(candidates, flags) {
|
|
|
117
130
|
},
|
|
118
131
|
};
|
|
119
132
|
}
|
|
120
|
-
const fallback = v2Candidate ?? agenticCandidate ?? candidates[0];
|
|
133
|
+
const fallback = leanCandidate ?? v2Candidate ?? agenticCandidate ?? candidates[0];
|
|
121
134
|
return {
|
|
122
135
|
selectedVariant: fallback.variantKind,
|
|
123
136
|
selectedIdentifier: fallback.identifier,
|
package/dist/manifest.json
CHANGED
|
@@ -154,12 +154,12 @@
|
|
|
154
154
|
"bytes": 374
|
|
155
155
|
},
|
|
156
156
|
"application/use-cases/raw-workflow-file-scanner.d.ts": {
|
|
157
|
-
"sha256": "
|
|
158
|
-
"bytes":
|
|
157
|
+
"sha256": "c9b699b4a011b968d389662430ff9bf32d4ce3fcda5cc5ddc99b08f2e69697df",
|
|
158
|
+
"bytes": 814
|
|
159
159
|
},
|
|
160
160
|
"application/use-cases/raw-workflow-file-scanner.js": {
|
|
161
|
-
"sha256": "
|
|
162
|
-
"bytes":
|
|
161
|
+
"sha256": "25b2e07a39f67734287b35887326234f5b8b8e1e0c65792513dad2dd8d73a0e0",
|
|
162
|
+
"bytes": 3334
|
|
163
163
|
},
|
|
164
164
|
"application/use-cases/validate-step-output.d.ts": {
|
|
165
165
|
"sha256": "d1505a7f507da6bbf59515c734dace381ac1a96d98f4495e469f9e3ad9c75941",
|
|
@@ -190,8 +190,8 @@
|
|
|
190
190
|
"bytes": 3107
|
|
191
191
|
},
|
|
192
192
|
"application/use-cases/validate-workflow-registry.js": {
|
|
193
|
-
"sha256": "
|
|
194
|
-
"bytes":
|
|
193
|
+
"sha256": "5f0c40d6539abe4a5f4b7bb66c56d032b7e42f28eb5ae6444adb9b03593d891f",
|
|
194
|
+
"bytes": 8948
|
|
195
195
|
},
|
|
196
196
|
"application/validation.d.ts": {
|
|
197
197
|
"sha256": "c7b6485357e0085fbdefca553ef78e570bf8448b272c62f1ddd4a2f9b45b2982",
|
|
@@ -326,8 +326,8 @@
|
|
|
326
326
|
"bytes": 1512
|
|
327
327
|
},
|
|
328
328
|
"config/feature-flags.js": {
|
|
329
|
-
"sha256": "
|
|
330
|
-
"bytes":
|
|
329
|
+
"sha256": "b42066c19fce793fe7bafb1ecb264d05c8e453fff32263f9e8cbcea7e59ddc6b",
|
|
330
|
+
"bytes": 7256
|
|
331
331
|
},
|
|
332
332
|
"core/error-handler.d.ts": {
|
|
333
333
|
"sha256": "80451f12ac8e185133ec3dc4c57285491a785f27525ed21e729db1da3f61010d",
|
|
@@ -526,8 +526,8 @@
|
|
|
526
526
|
"bytes": 1428
|
|
527
527
|
},
|
|
528
528
|
"infrastructure/storage/file-workflow-storage.js": {
|
|
529
|
-
"sha256": "
|
|
530
|
-
"bytes":
|
|
529
|
+
"sha256": "e5cfd6f8a7fed72961e041aa9c92765c28f4b9872c16e7cbdbd533f0177ea0f0",
|
|
530
|
+
"bytes": 8562
|
|
531
531
|
},
|
|
532
532
|
"infrastructure/storage/git-workflow-storage.d.ts": {
|
|
533
533
|
"sha256": "67d7f10e12c78c674ced83da378cd159465d4b09176d8dfca240864b0d6f38c2",
|
|
@@ -586,12 +586,12 @@
|
|
|
586
586
|
"bytes": 3014
|
|
587
587
|
},
|
|
588
588
|
"infrastructure/storage/workflow-resolution.d.ts": {
|
|
589
|
-
"sha256": "
|
|
590
|
-
"bytes":
|
|
589
|
+
"sha256": "81929a188f570488a83cbc387aa32734dbb1fadaae8589c48ff9aa1ea3a6dad5",
|
|
590
|
+
"bytes": 2389
|
|
591
591
|
},
|
|
592
592
|
"infrastructure/storage/workflow-resolution.js": {
|
|
593
|
-
"sha256": "
|
|
594
|
-
"bytes":
|
|
593
|
+
"sha256": "202c244209088acb15f1b0556c569607086e1cb71cf7faa77fbae902d682dfd2",
|
|
594
|
+
"bytes": 6034
|
|
595
595
|
},
|
|
596
596
|
"mcp-server.d.ts": {
|
|
597
597
|
"sha256": "d673b4cf9770aa74de28e921e964459c094bdb89a8970623afda340fe1707293",
|
|
@@ -625,6 +625,14 @@
|
|
|
625
625
|
"sha256": "83c9585400cc7c20cac3691b8771b9ce8cdc508ba7f5d083a96f7ed975aabc05",
|
|
626
626
|
"bytes": 5967
|
|
627
627
|
},
|
|
628
|
+
"mcp/handlers/shared/request-workflow-reader.d.ts": {
|
|
629
|
+
"sha256": "39b3db1251f5db4da36a14a1b3dba76bdd0cefd5b24637e03307901a3994a12b",
|
|
630
|
+
"bytes": 927
|
|
631
|
+
},
|
|
632
|
+
"mcp/handlers/shared/request-workflow-reader.js": {
|
|
633
|
+
"sha256": "8e67f92fe93883e6620b4564a1c98c5402ac74f002049b8f8f136008778e2152",
|
|
634
|
+
"bytes": 2297
|
|
635
|
+
},
|
|
628
636
|
"mcp/handlers/shared/with-timeout.d.ts": {
|
|
629
637
|
"sha256": "31ca3db008cb5cd439e0d1132bc4b29be0900c403c452931e3a24a50e45beb54",
|
|
630
638
|
"bytes": 117
|
|
@@ -770,12 +778,12 @@
|
|
|
770
778
|
"bytes": 12661
|
|
771
779
|
},
|
|
772
780
|
"mcp/handlers/v2-execution/start.d.ts": {
|
|
773
|
-
"sha256": "
|
|
774
|
-
"bytes":
|
|
781
|
+
"sha256": "15d5e5f4a4613df286279075640e43a130179f39b9157b50d4d9e4123bcae6b3",
|
|
782
|
+
"bytes": 2868
|
|
775
783
|
},
|
|
776
784
|
"mcp/handlers/v2-execution/start.js": {
|
|
777
|
-
"sha256": "
|
|
778
|
-
"bytes":
|
|
785
|
+
"sha256": "cb40e5ec1d1461f41ce88722110af9f11396ab1d828d6eccb0b1b29a9ca68b65",
|
|
786
|
+
"bytes": 16769
|
|
779
787
|
},
|
|
780
788
|
"mcp/handlers/v2-resume.d.ts": {
|
|
781
789
|
"sha256": "d88f6c35bcaf946666c837b72fda3702a2ebab5e478eb90f7b4b672a0e5fa24f",
|
|
@@ -802,12 +810,12 @@
|
|
|
802
810
|
"bytes": 3817
|
|
803
811
|
},
|
|
804
812
|
"mcp/handlers/v2-workflow.d.ts": {
|
|
805
|
-
"sha256": "
|
|
806
|
-
"bytes":
|
|
813
|
+
"sha256": "5c9590f121dd3708c516be3febe41d0be47531d643462b86b99b778ef0b54498",
|
|
814
|
+
"bytes": 396
|
|
807
815
|
},
|
|
808
816
|
"mcp/handlers/v2-workflow.js": {
|
|
809
|
-
"sha256": "
|
|
810
|
-
"bytes":
|
|
817
|
+
"sha256": "e869550933484b473ee51e4f66b29324c17213b87f3fc8bbb3e098ffc00d6f88",
|
|
818
|
+
"bytes": 7034
|
|
811
819
|
},
|
|
812
820
|
"mcp/handlers/v2-workspace-resolution.d.ts": {
|
|
813
821
|
"sha256": "45cdf30b7989d16201b4569c6c109e9ccea04c76fd044af1471fe57faa49da3a",
|
|
@@ -846,8 +854,8 @@
|
|
|
846
854
|
"bytes": 882
|
|
847
855
|
},
|
|
848
856
|
"mcp/server.js": {
|
|
849
|
-
"sha256": "
|
|
850
|
-
"bytes":
|
|
857
|
+
"sha256": "c07f8a6e8f89f7620a063673859dcc458212b068237949acff253f15856afd5f",
|
|
858
|
+
"bytes": 14174
|
|
851
859
|
},
|
|
852
860
|
"mcp/tool-description-provider.d.ts": {
|
|
853
861
|
"sha256": "1d46abc3112e11b68e57197e846f5708293ec9b2281fa71a9124ee2aad71e41b",
|
|
@@ -862,8 +870,8 @@
|
|
|
862
870
|
"bytes": 132
|
|
863
871
|
},
|
|
864
872
|
"mcp/tool-descriptions.js": {
|
|
865
|
-
"sha256": "
|
|
866
|
-
"bytes":
|
|
873
|
+
"sha256": "854176e258cdc25d6067836157a03682b6c8843bc8fd7b447fef96b4bb4cba6d",
|
|
874
|
+
"bytes": 18124
|
|
867
875
|
},
|
|
868
876
|
"mcp/tool-factory.d.ts": {
|
|
869
877
|
"sha256": "0fe3c6b863b2d7aef0c3d659ff54f3a9ee8a0a3c2005b6565d2f8ad517bc7211",
|
|
@@ -914,8 +922,8 @@
|
|
|
914
922
|
"bytes": 747
|
|
915
923
|
},
|
|
916
924
|
"mcp/types.d.ts": {
|
|
917
|
-
"sha256": "
|
|
918
|
-
"bytes":
|
|
925
|
+
"sha256": "d61a7d2b9a5f389d9fbf0092f6d38c3e6bb2925f41dce0270ed0c2e54ca856c9",
|
|
926
|
+
"bytes": 4533
|
|
919
927
|
},
|
|
920
928
|
"mcp/types.js": {
|
|
921
929
|
"sha256": "d10c4070e4c3454d80f0fa9cdc0e978c69c53c13fd09baa8710fcd802fed8926",
|
|
@@ -962,12 +970,12 @@
|
|
|
962
970
|
"bytes": 3119
|
|
963
971
|
},
|
|
964
972
|
"mcp/v2/tools.d.ts": {
|
|
965
|
-
"sha256": "
|
|
966
|
-
"bytes":
|
|
973
|
+
"sha256": "9915bd42c9ab096875021a24c0c97ad112331595e5d734abdd2856f9f49f80e4",
|
|
974
|
+
"bytes": 6884
|
|
967
975
|
},
|
|
968
976
|
"mcp/v2/tools.js": {
|
|
969
|
-
"sha256": "
|
|
970
|
-
"bytes":
|
|
977
|
+
"sha256": "e3755649cb0fbf6332a7f330dec558bf998489533c95d7684c4668a4c566896e",
|
|
978
|
+
"bytes": 8360
|
|
971
979
|
},
|
|
972
980
|
"mcp/validation/bounded-json.d.ts": {
|
|
973
981
|
"sha256": "82203ac6123d5c6989606c3b5405aaea99ab829c8958835f9ae3ba45b8bc8fd5",
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { IWorkflowReader } from '../../../types/storage.js';
|
|
2
|
+
import type { IFeatureFlagProvider } from '../../../config/feature-flags.js';
|
|
3
|
+
export interface RequestWorkflowReaderOptions {
|
|
4
|
+
readonly featureFlags: IFeatureFlagProvider;
|
|
5
|
+
readonly workspacePath?: string;
|
|
6
|
+
readonly resolvedRootUris?: readonly string[];
|
|
7
|
+
readonly serverCwd?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function hasRequestWorkspaceSignal(options: {
|
|
10
|
+
readonly workspacePath?: string;
|
|
11
|
+
readonly resolvedRootUris?: readonly string[];
|
|
12
|
+
}): boolean;
|
|
13
|
+
export declare function resolveRequestWorkspaceDirectory(options: {
|
|
14
|
+
readonly workspacePath?: string;
|
|
15
|
+
readonly resolvedRootUris?: readonly string[];
|
|
16
|
+
readonly serverCwd?: string;
|
|
17
|
+
}): string;
|
|
18
|
+
export declare function toProjectWorkflowDirectory(workspaceDirectory: string): string;
|
|
19
|
+
export declare function createWorkflowReaderForRequest(options: RequestWorkflowReaderOptions): IWorkflowReader;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.hasRequestWorkspaceSignal = hasRequestWorkspaceSignal;
|
|
7
|
+
exports.resolveRequestWorkspaceDirectory = resolveRequestWorkspaceDirectory;
|
|
8
|
+
exports.toProjectWorkflowDirectory = toProjectWorkflowDirectory;
|
|
9
|
+
exports.createWorkflowReaderForRequest = createWorkflowReaderForRequest;
|
|
10
|
+
const path_1 = __importDefault(require("path"));
|
|
11
|
+
const url_1 = require("url");
|
|
12
|
+
const enhanced_multi_source_workflow_storage_js_1 = require("../../../infrastructure/storage/enhanced-multi-source-workflow-storage.js");
|
|
13
|
+
const schema_validating_workflow_storage_js_1 = require("../../../infrastructure/storage/schema-validating-workflow-storage.js");
|
|
14
|
+
function hasRequestWorkspaceSignal(options) {
|
|
15
|
+
return Boolean(options.workspacePath) || (options.resolvedRootUris?.length ?? 0) > 0;
|
|
16
|
+
}
|
|
17
|
+
function resolveRequestWorkspaceDirectory(options) {
|
|
18
|
+
if (options.workspacePath && path_1.default.isAbsolute(options.workspacePath)) {
|
|
19
|
+
return options.workspacePath;
|
|
20
|
+
}
|
|
21
|
+
const rootUri = options.resolvedRootUris?.[0];
|
|
22
|
+
if (rootUri) {
|
|
23
|
+
const fsPath = fileUriToFsPath(rootUri);
|
|
24
|
+
if (fsPath) {
|
|
25
|
+
return fsPath;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return options.serverCwd ?? process.cwd();
|
|
29
|
+
}
|
|
30
|
+
function toProjectWorkflowDirectory(workspaceDirectory) {
|
|
31
|
+
return path_1.default.basename(workspaceDirectory) === 'workflows'
|
|
32
|
+
? workspaceDirectory
|
|
33
|
+
: path_1.default.join(workspaceDirectory, 'workflows');
|
|
34
|
+
}
|
|
35
|
+
function createWorkflowReaderForRequest(options) {
|
|
36
|
+
const workspaceDirectory = resolveRequestWorkspaceDirectory(options);
|
|
37
|
+
const projectWorkflowDirectory = toProjectWorkflowDirectory(workspaceDirectory);
|
|
38
|
+
const storage = new enhanced_multi_source_workflow_storage_js_1.EnhancedMultiSourceWorkflowStorage({ projectPath: projectWorkflowDirectory }, options.featureFlags);
|
|
39
|
+
return new schema_validating_workflow_storage_js_1.SchemaValidatingCompositeWorkflowStorage(storage);
|
|
40
|
+
}
|
|
41
|
+
function fileUriToFsPath(uri) {
|
|
42
|
+
if (!uri.startsWith('file://'))
|
|
43
|
+
return null;
|
|
44
|
+
try {
|
|
45
|
+
return (0, url_1.fileURLToPath)(uri);
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -6,14 +6,16 @@ import { type SessionId, type RunId, type NodeId, type WorkflowHash } from '../.
|
|
|
6
6
|
import type { Sha256PortV2 } from '../../../v2/ports/sha256.port.js';
|
|
7
7
|
import type { TokenCodecPorts } from '../../../v2/durable-core/tokens/token-codec-ports.js';
|
|
8
8
|
import { ResultAsync as RA } from 'neverthrow';
|
|
9
|
+
import { type ValidationPipelineDepsPhase1a } from '../../../application/services/workflow-validation-pipeline.js';
|
|
9
10
|
import { type ObservationEventData } from '../../../v2/durable-core/domain/observation-builder.js';
|
|
10
11
|
import { type StartWorkflowError } from '../v2-execution-helpers.js';
|
|
11
12
|
import * as z from 'zod';
|
|
12
13
|
export declare function loadAndPinWorkflow(args: {
|
|
13
14
|
readonly workflowId: string;
|
|
14
|
-
readonly
|
|
15
|
+
readonly workflowReader: Pick<import('../../../types/storage.js').IWorkflowReader, 'getWorkflowById'>;
|
|
15
16
|
readonly crypto: Sha256PortV2;
|
|
16
17
|
readonly pinnedStore: import('../../../v2/ports/pinned-workflow-store.port.js').PinnedWorkflowStorePortV2;
|
|
18
|
+
readonly validationPipelineDeps: ValidationPipelineDepsPhase1a;
|
|
17
19
|
}): RA<{
|
|
18
20
|
readonly workflow: import('../../../types/workflow.js').Workflow;
|
|
19
21
|
readonly workflowHash: WorkflowHash;
|
|
@@ -10,7 +10,7 @@ const workflow_js_1 = require("../../../types/workflow.js");
|
|
|
10
10
|
const index_js_1 = require("../../../v2/durable-core/ids/index.js");
|
|
11
11
|
const workflow_hash_ref_js_1 = require("../../../v2/durable-core/ids/workflow-hash-ref.js");
|
|
12
12
|
const neverthrow_1 = require("neverthrow");
|
|
13
|
-
const
|
|
13
|
+
const workflow_validation_pipeline_js_1 = require("../../../application/services/workflow-validation-pipeline.js");
|
|
14
14
|
const hashing_js_1 = require("../../../v2/durable-core/canonical/hashing.js");
|
|
15
15
|
const observation_builder_js_1 = require("../../../v2/durable-core/domain/observation-builder.js");
|
|
16
16
|
const workflow_source_js_1 = require("../../../types/workflow-source.js");
|
|
@@ -23,9 +23,10 @@ const v2_execution_helpers_js_1 = require("../v2-execution-helpers.js");
|
|
|
23
23
|
const constants_js_1 = require("../../../v2/durable-core/constants.js");
|
|
24
24
|
const index_js_2 = require("./index.js");
|
|
25
25
|
const start_construction_js_1 = require("../../../v2/durable-core/domain/start-construction.js");
|
|
26
|
+
const request_workflow_reader_js_1 = require("../shared/request-workflow-reader.js");
|
|
26
27
|
function loadAndPinWorkflow(args) {
|
|
27
|
-
const { workflowId,
|
|
28
|
-
return neverthrow_1.ResultAsync.fromPromise(
|
|
28
|
+
const { workflowId, workflowReader, crypto, pinnedStore, validationPipelineDeps } = args;
|
|
29
|
+
return neverthrow_1.ResultAsync.fromPromise(workflowReader.getWorkflowById(workflowId), (e) => ({
|
|
29
30
|
kind: 'precondition_failed',
|
|
30
31
|
message: e instanceof Error ? e.message : String(e),
|
|
31
32
|
}))
|
|
@@ -39,14 +40,25 @@ function loadAndPinWorkflow(args) {
|
|
|
39
40
|
return (0, neverthrow_1.okAsync)({ workflow });
|
|
40
41
|
})
|
|
41
42
|
.andThen(({ workflow }) => {
|
|
42
|
-
const
|
|
43
|
-
if (
|
|
43
|
+
const pipelineOutcome = (0, workflow_validation_pipeline_js_1.validateWorkflowPhase1a)(workflow, validationPipelineDeps);
|
|
44
|
+
if (pipelineOutcome.kind !== 'phase1a_valid') {
|
|
45
|
+
const message = pipelineOutcome.kind === 'schema_failed'
|
|
46
|
+
? `Schema validation failed: ${pipelineOutcome.errors.map(e => e.message ?? e.instancePath).join('; ')}`
|
|
47
|
+
: pipelineOutcome.kind === 'structural_failed'
|
|
48
|
+
? `Structural validation failed: ${pipelineOutcome.issues.join('; ')}`
|
|
49
|
+
: pipelineOutcome.kind === 'v1_compilation_failed'
|
|
50
|
+
? `Compilation failed: ${pipelineOutcome.cause.message}`
|
|
51
|
+
: pipelineOutcome.kind === 'normalization_failed'
|
|
52
|
+
? `Normalization failed: ${pipelineOutcome.cause.message}`
|
|
53
|
+
: pipelineOutcome.kind === 'executable_compilation_failed'
|
|
54
|
+
? `Executable compilation failed: ${pipelineOutcome.cause.message}`
|
|
55
|
+
: 'Unknown validation failure';
|
|
44
56
|
return (0, neverthrow_1.errAsync)({
|
|
45
57
|
kind: 'workflow_compile_failed',
|
|
46
|
-
message
|
|
58
|
+
message,
|
|
47
59
|
});
|
|
48
60
|
}
|
|
49
|
-
const compiled =
|
|
61
|
+
const compiled = pipelineOutcome.snapshot;
|
|
50
62
|
const workflowHashRes = (0, hashing_js_1.workflowHashForCompiledSnapshot)(compiled, crypto);
|
|
51
63
|
if (workflowHashRes.isErr()) {
|
|
52
64
|
return (0, neverthrow_1.errAsync)({ kind: 'hash_computation_failed', message: workflowHashRes.error.message });
|
|
@@ -215,12 +227,23 @@ function mintStartTokens(args) {
|
|
|
215
227
|
});
|
|
216
228
|
}
|
|
217
229
|
function executeStartWorkflow(input, ctx) {
|
|
218
|
-
const { gate, sessionStore, snapshotStore, pinnedStore, crypto, tokenCodecPorts, idFactory } = ctx.v2;
|
|
230
|
+
const { gate, sessionStore, snapshotStore, pinnedStore, crypto, tokenCodecPorts, idFactory, validationPipelineDeps } = ctx.v2;
|
|
231
|
+
const workflowReader = (0, request_workflow_reader_js_1.hasRequestWorkspaceSignal)({
|
|
232
|
+
workspacePath: input.workspacePath,
|
|
233
|
+
resolvedRootUris: ctx.v2.resolvedRootUris,
|
|
234
|
+
})
|
|
235
|
+
? (0, request_workflow_reader_js_1.createWorkflowReaderForRequest)({
|
|
236
|
+
featureFlags: ctx.featureFlags,
|
|
237
|
+
workspacePath: input.workspacePath,
|
|
238
|
+
resolvedRootUris: ctx.v2.resolvedRootUris,
|
|
239
|
+
})
|
|
240
|
+
: ctx.workflowService;
|
|
219
241
|
return loadAndPinWorkflow({
|
|
220
242
|
workflowId: input.workflowId,
|
|
221
|
-
|
|
243
|
+
workflowReader,
|
|
222
244
|
crypto,
|
|
223
245
|
pinnedStore,
|
|
246
|
+
validationPipelineDeps,
|
|
224
247
|
})
|
|
225
248
|
.andThen(({ workflow, firstStep, workflowHash, pinnedWorkflow }) => {
|
|
226
249
|
const anchorsRA = (0, v2_workspace_resolution_js_1.resolveWorkspaceAnchors)(ctx.v2, input.workspacePath)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { ToolContext, ToolResult } from '../types.js';
|
|
2
2
|
import type { V2InspectWorkflowInput, V2ListWorkflowsInput } from '../v2/tools.js';
|
|
3
|
-
export declare function handleV2ListWorkflows(
|
|
3
|
+
export declare function handleV2ListWorkflows(input: V2ListWorkflowsInput, ctx: ToolContext): Promise<ToolResult<unknown>>;
|
|
4
4
|
export declare function handleV2InspectWorkflow(input: V2InspectWorkflowInput, ctx: ToolContext): Promise<ToolResult<unknown>>;
|
|
@@ -11,13 +11,24 @@ const v1_to_v2_shim_js_1 = require("../../v2/read-only/v1-to-v2-shim.js");
|
|
|
11
11
|
const hashing_js_1 = require("../../v2/durable-core/canonical/hashing.js");
|
|
12
12
|
const TIMEOUT_MS = 30000;
|
|
13
13
|
const with_timeout_js_1 = require("./shared/with-timeout.js");
|
|
14
|
-
|
|
14
|
+
const request_workflow_reader_js_1 = require("./shared/request-workflow-reader.js");
|
|
15
|
+
async function handleV2ListWorkflows(input, ctx) {
|
|
15
16
|
const guard = (0, types_js_1.requireV2Context)(ctx);
|
|
16
17
|
if (!guard.ok)
|
|
17
18
|
return guard.error;
|
|
18
19
|
const { crypto, pinnedStore } = guard.ctx.v2;
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
const workflowReader = (0, request_workflow_reader_js_1.hasRequestWorkspaceSignal)({
|
|
21
|
+
workspacePath: input.workspacePath,
|
|
22
|
+
resolvedRootUris: guard.ctx.v2.resolvedRootUris,
|
|
23
|
+
})
|
|
24
|
+
? (0, request_workflow_reader_js_1.createWorkflowReaderForRequest)({
|
|
25
|
+
featureFlags: ctx.featureFlags,
|
|
26
|
+
workspacePath: input.workspacePath,
|
|
27
|
+
resolvedRootUris: guard.ctx.v2.resolvedRootUris,
|
|
28
|
+
})
|
|
29
|
+
: ctx.workflowService;
|
|
30
|
+
return neverthrow_1.ResultAsync.fromPromise((0, with_timeout_js_1.withTimeout)(workflowReader.listWorkflowSummaries(), TIMEOUT_MS, 'list_workflows'), (err) => (0, error_mapper_js_1.mapUnknownErrorToToolError)(err))
|
|
31
|
+
.andThen((summaries) => neverthrow_1.ResultAsync.combine(summaries.map((s) => neverthrow_1.ResultAsync.fromPromise(workflowReader.getWorkflowById(s.id), (err) => (0, error_mapper_js_1.mapUnknownErrorToToolError)(err)).andThen((wf) => {
|
|
21
32
|
if (!wf) {
|
|
22
33
|
return (0, neverthrow_1.okAsync)({
|
|
23
34
|
workflowId: s.id,
|
|
@@ -79,7 +90,17 @@ async function handleV2InspectWorkflow(input, ctx) {
|
|
|
79
90
|
if (!guard.ok)
|
|
80
91
|
return guard.error;
|
|
81
92
|
const { crypto, pinnedStore } = guard.ctx.v2;
|
|
82
|
-
|
|
93
|
+
const workflowReader = (0, request_workflow_reader_js_1.hasRequestWorkspaceSignal)({
|
|
94
|
+
workspacePath: input.workspacePath,
|
|
95
|
+
resolvedRootUris: guard.ctx.v2.resolvedRootUris,
|
|
96
|
+
})
|
|
97
|
+
? (0, request_workflow_reader_js_1.createWorkflowReaderForRequest)({
|
|
98
|
+
featureFlags: ctx.featureFlags,
|
|
99
|
+
workspacePath: input.workspacePath,
|
|
100
|
+
resolvedRootUris: guard.ctx.v2.resolvedRootUris,
|
|
101
|
+
})
|
|
102
|
+
: ctx.workflowService;
|
|
103
|
+
return neverthrow_1.ResultAsync.fromPromise((0, with_timeout_js_1.withTimeout)(workflowReader.getWorkflowById(input.workflowId), TIMEOUT_MS, 'inspect_workflow'), (err) => (0, error_mapper_js_1.mapUnknownErrorToToolError)(err))
|
|
83
104
|
.andThen((workflow) => {
|
|
84
105
|
if (!workflow) {
|
|
85
106
|
return (0, neverthrow_1.errAsync)((0, types_js_1.errNotRetryable)('NOT_FOUND', `Workflow not found: ${input.workflowId}`));
|
package/dist/mcp/server.js
CHANGED
|
@@ -41,6 +41,8 @@ const container_js_1 = require("../di/container.js");
|
|
|
41
41
|
const tokens_js_1 = require("../di/tokens.js");
|
|
42
42
|
const assert_never_js_1 = require("../runtime/assert-never.js");
|
|
43
43
|
const token_codec_ports_js_1 = require("../v2/durable-core/tokens/token-codec-ports.js");
|
|
44
|
+
const validation_js_1 = require("../application/validation.js");
|
|
45
|
+
const v1_to_v2_shim_js_1 = require("../v2/read-only/v1-to-v2-shim.js");
|
|
44
46
|
const index_js_1 = require("../v2/infra/local/workspace-anchor/index.js");
|
|
45
47
|
const workspace_roots_manager_js_1 = require("./workspace-roots-manager.js");
|
|
46
48
|
const index_js_2 = require("../v2/infra/local/directory-listing/index.js");
|
|
@@ -94,6 +96,14 @@ async function createToolContext() {
|
|
|
94
96
|
const dataDir = container_js_1.container.resolve(tokens_js_1.DI.V2.DataDir);
|
|
95
97
|
const fsPort = container_js_1.container.resolve(tokens_js_1.DI.V2.FileSystem);
|
|
96
98
|
const directoryListing = new index_js_2.LocalDirectoryListingV2(fsPort);
|
|
99
|
+
const validationEngine = container_js_1.container.resolve(tokens_js_1.DI.Infra.ValidationEngine);
|
|
100
|
+
const compiler = container_js_1.container.resolve(tokens_js_1.DI.Services.WorkflowCompiler);
|
|
101
|
+
const validationPipelineDeps = {
|
|
102
|
+
schemaValidate: validation_js_1.validateWorkflowSchema,
|
|
103
|
+
structuralValidate: validationEngine.validateWorkflowStructureOnly.bind(validationEngine),
|
|
104
|
+
compiler,
|
|
105
|
+
normalizeToExecutable: v1_to_v2_shim_js_1.normalizeV1WorkflowToPinnedSnapshot,
|
|
106
|
+
};
|
|
97
107
|
v2 = {
|
|
98
108
|
gate,
|
|
99
109
|
sessionStore,
|
|
@@ -103,6 +113,7 @@ async function createToolContext() {
|
|
|
103
113
|
crypto,
|
|
104
114
|
idFactory,
|
|
105
115
|
tokenCodecPorts,
|
|
116
|
+
validationPipelineDeps,
|
|
106
117
|
resolvedRootUris: [],
|
|
107
118
|
workspaceResolver: new index_js_1.LocalWorkspaceAnchorV2(process.cwd()),
|
|
108
119
|
dataDir,
|
|
@@ -49,7 +49,9 @@ This tool provides:
|
|
|
49
49
|
- Schema version and metadata information`,
|
|
50
50
|
list_workflows: `Lists available workflows using WorkRail v2 (feature-flagged). Returns workflow metadata plus pinned snapshot hashes for deterministic execution.
|
|
51
51
|
|
|
52
|
-
Use this to discover workflows before attempting multi-step tasks. When a workflow exists for the user's request, following it means following the user's structured instructions
|
|
52
|
+
Use this to discover workflows before attempting multi-step tasks. When a workflow exists for the user's request, following it means following the user's structured instructions.
|
|
53
|
+
|
|
54
|
+
Pass workspacePath when available so project-scoped workflow variants are resolved against the correct workspace instead of the server's fallback directory.`,
|
|
53
55
|
inspect_workflow: `Inspect a workflow structure before starting it (WorkRail v2, feature-flagged).
|
|
54
56
|
|
|
55
57
|
Use this to understand what steps the workflow will guide you through. The workflow is a step-by-step plan the user (or workflow author) created for this type of task.
|
|
@@ -58,6 +60,8 @@ Returns:
|
|
|
58
60
|
- metadata mode: Just name and description
|
|
59
61
|
- preview mode: Full step-by-step breakdown (default)
|
|
60
62
|
|
|
63
|
+
Pass workspacePath when available so project-scoped workflow variants are resolved against the correct workspace.
|
|
64
|
+
|
|
61
65
|
Remember: inspecting is read-only. Call start_workflow when ready to begin.`,
|
|
62
66
|
start_workflow: `Begin following a workflow's step-by-step instructions (WorkRail v2, feature-flagged).
|
|
63
67
|
|
|
@@ -192,7 +196,9 @@ Returns the complete schema definition including required fields, valid patterns
|
|
|
192
196
|
|
|
193
197
|
Workflows are the user's pre-defined instructions for complex tasks. When a workflow exists for the user's request, you MUST use it instead of improvising your own approach.
|
|
194
198
|
|
|
195
|
-
Returns stable workflow metadata and pinned snapshot hashes (workflowHash) for deterministic execution
|
|
199
|
+
Returns stable workflow metadata and pinned snapshot hashes (workflowHash) for deterministic execution.
|
|
200
|
+
|
|
201
|
+
Pass workspacePath when available so project-scoped workflow variants are resolved against the correct workspace.`,
|
|
196
202
|
inspect_workflow: `Inspect a workflow you are considering following (WorkRail v2, feature-flagged).
|
|
197
203
|
|
|
198
204
|
Use this to understand the workflow's structure before starting. The workflow is the user's explicit plan - not suggestions, not guidelines, but direct instructions you will follow.
|
|
@@ -200,6 +206,7 @@ Use this to understand the workflow's structure before starting. The workflow is
|
|
|
200
206
|
Parameters:
|
|
201
207
|
- workflowId: The workflow to inspect
|
|
202
208
|
- mode: 'metadata' (name/description only) or 'preview' (full step breakdown)
|
|
209
|
+
- workspacePath: optional absolute workspace path for correct project-scoped workflow resolution
|
|
203
210
|
|
|
204
211
|
This is read-only. Call start_workflow when ready to commit to following the workflow.`,
|
|
205
212
|
start_workflow: `Begin executing the user's workflow instructions (WorkRail v2, feature-flagged).
|
package/dist/mcp/types.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ import type { WorkspaceContextResolverPortV2 } from '../v2/ports/workspace-ancho
|
|
|
16
16
|
import type { DataDirPortV2 } from '../v2/ports/data-dir.port.js';
|
|
17
17
|
import type { DirectoryListingPortV2 } from '../v2/ports/directory-listing.port.js';
|
|
18
18
|
import type { SessionSummaryProviderPortV2 } from '../v2/ports/session-summary-provider.port.js';
|
|
19
|
+
import type { ValidationPipelineDepsPhase1a } from '../application/services/workflow-validation-pipeline.js';
|
|
19
20
|
export interface SessionHealthDetails {
|
|
20
21
|
readonly health: SessionHealthV2;
|
|
21
22
|
}
|
|
@@ -55,6 +56,7 @@ export interface V2Dependencies {
|
|
|
55
56
|
readonly crypto: CryptoPortV2;
|
|
56
57
|
readonly idFactory: IdFactoryV2;
|
|
57
58
|
readonly tokenCodecPorts: TokenCodecPorts;
|
|
59
|
+
readonly validationPipelineDeps: ValidationPipelineDepsPhase1a;
|
|
58
60
|
readonly resolvedRootUris?: readonly string[];
|
|
59
61
|
readonly workspaceResolver?: WorkspaceContextResolverPortV2;
|
|
60
62
|
readonly dataDir?: DataDirPortV2;
|
package/dist/mcp/v2/tools.d.ts
CHANGED
|
@@ -1,16 +1,25 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import type { ToolAnnotations } from '../tool-factory.js';
|
|
3
|
-
export declare const V2ListWorkflowsInput: z.ZodObject<{
|
|
3
|
+
export declare const V2ListWorkflowsInput: z.ZodObject<{
|
|
4
|
+
workspacePath: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
|
|
5
|
+
}, "strip", z.ZodTypeAny, {
|
|
6
|
+
workspacePath?: string | undefined;
|
|
7
|
+
}, {
|
|
8
|
+
workspacePath?: string | undefined;
|
|
9
|
+
}>;
|
|
4
10
|
export type V2ListWorkflowsInput = z.infer<typeof V2ListWorkflowsInput>;
|
|
5
11
|
export declare const V2InspectWorkflowInput: z.ZodObject<{
|
|
6
12
|
workflowId: z.ZodString;
|
|
7
13
|
mode: z.ZodDefault<z.ZodEnum<["metadata", "preview"]>>;
|
|
14
|
+
workspacePath: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
|
|
8
15
|
}, "strip", z.ZodTypeAny, {
|
|
9
16
|
workflowId: string;
|
|
10
17
|
mode: "metadata" | "preview";
|
|
18
|
+
workspacePath?: string | undefined;
|
|
11
19
|
}, {
|
|
12
20
|
workflowId: string;
|
|
13
21
|
mode?: "metadata" | "preview" | undefined;
|
|
22
|
+
workspacePath?: string | undefined;
|
|
14
23
|
}>;
|
|
15
24
|
export type V2InspectWorkflowInput = z.infer<typeof V2InspectWorkflowInput>;
|
|
16
25
|
export declare const V2StartWorkflowInput: z.ZodObject<{
|
package/dist/mcp/v2/tools.js
CHANGED
|
@@ -2,17 +2,21 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.V2_TOOL_ANNOTATIONS = exports.V2_TOOL_TITLES = exports.V2CheckpointWorkflowInput = exports.V2ResumeSessionInput = exports.V2ContinueWorkflowInput = exports.V2ContinueWorkflowInputShape = exports.V2StartWorkflowInput = exports.V2InspectWorkflowInput = exports.V2ListWorkflowsInput = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
|
-
|
|
5
|
+
const workspacePathField = zod_1.z.string()
|
|
6
|
+
.refine((p) => p.startsWith('/'), 'workspacePath must be an absolute path (starting with /)')
|
|
7
|
+
.optional()
|
|
8
|
+
.describe('Absolute path to your current workspace directory (e.g. the "Workspace:" value from your system parameters). Used to resolve project-scoped workflow variants against the correct workspace. If omitted, WorkRail uses MCP roots when available, then falls back to the server process directory.');
|
|
9
|
+
exports.V2ListWorkflowsInput = zod_1.z.object({
|
|
10
|
+
workspacePath: workspacePathField,
|
|
11
|
+
});
|
|
6
12
|
exports.V2InspectWorkflowInput = zod_1.z.object({
|
|
7
13
|
workflowId: zod_1.z.string().min(1).regex(/^[A-Za-z0-9_-]+$/, 'Workflow ID must contain only letters, numbers, hyphens, and underscores').describe('The workflow ID to inspect'),
|
|
8
14
|
mode: zod_1.z.enum(['metadata', 'preview']).default('preview').describe('Detail level: metadata (name and description only) or preview (full step-by-step breakdown, default)'),
|
|
15
|
+
workspacePath: workspacePathField,
|
|
9
16
|
});
|
|
10
17
|
exports.V2StartWorkflowInput = zod_1.z.object({
|
|
11
18
|
workflowId: zod_1.z.string().min(1).regex(/^[A-Za-z0-9_-]+$/, 'Workflow ID must contain only letters, numbers, hyphens, and underscores').describe('The workflow ID to start'),
|
|
12
|
-
workspacePath:
|
|
13
|
-
.refine((p) => p.startsWith('/'), 'workspacePath must be an absolute path (starting with /)')
|
|
14
|
-
.optional()
|
|
15
|
-
.describe('Absolute path to your current workspace directory (e.g. the "Workspace:" value from your system parameters). Used to anchor this session to your workspace for future resume_session discovery. Pass this on every start_workflow call. If omitted, WorkRail uses the server process directory which may not match your workspace.'),
|
|
19
|
+
workspacePath: workspacePathField.describe('Absolute path to your current workspace directory (e.g. the "Workspace:" value from your system parameters). Used to resolve the correct project-scoped workflow variant and to anchor this session to your workspace for future resume_session discovery. Pass this on every start_workflow call. If omitted, WorkRail uses MCP roots when available, then falls back to the server process directory.'),
|
|
16
20
|
});
|
|
17
21
|
exports.V2ContinueWorkflowInputShape = zod_1.z.object({
|
|
18
22
|
intent: zod_1.z.enum(['advance', 'rehydrate']).optional().describe('What you want to do. Auto-inferred from ackToken if omitted: ' +
|
package/package.json
CHANGED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "coding-task-workflow-agentic",
|
|
3
|
+
"name": "Agentic Task Dev Workflow (Lean • Notes-First • WorkRail Executor)",
|
|
4
|
+
"version": "2.1.0",
|
|
5
|
+
"description": "Lean variant of the agentic coding workflow. Merges triage, inputs gate, context gathering, and re-triage into a single Understand & Classify phase. Reduces context variable count and removes top-level clarificationPrompts. Same quality guarantees with fewer tokens.",
|
|
6
|
+
"recommendedPreferences": {
|
|
7
|
+
"recommendedAutonomy": "guided",
|
|
8
|
+
"recommendedRiskPolicy": "conservative"
|
|
9
|
+
},
|
|
10
|
+
"preconditions": [
|
|
11
|
+
"User provides a task description or equivalent objective.",
|
|
12
|
+
"Agent has codebase read access and can run the tools needed for analysis and validation.",
|
|
13
|
+
"A deterministic validation path exists (tests, build, or an explicit verification strategy).",
|
|
14
|
+
"If the task touches critical paths, rollback or containment strategy can be defined."
|
|
15
|
+
],
|
|
16
|
+
"metaGuidance": [
|
|
17
|
+
"DEFAULT BEHAVIOR: self-execute with tools. Only ask the user for business decisions, missing external artifacts, or permissions you cannot resolve.",
|
|
18
|
+
"V2 DURABILITY: use output.notesMarkdown as the primary durable record. Do NOT mirror execution state into CONTEXT.md or any markdown checkpoint file.",
|
|
19
|
+
"ARTIFACT STRATEGY: `implementation_plan.md` is the only default human-facing artifact for non-small tasks. `spec.md` or `design.md` are optional and should be created only when they materially improve handoff or reviewability.",
|
|
20
|
+
"OWNERSHIP & DELEGATION: the main agent owns strategy, decisions, synthesis, and implementation. Delegate only bounded cognitive routines via WorkRail Executor. Never hand off full task ownership or rely on named Builder/Researcher identities.",
|
|
21
|
+
"SUBAGENT SYNTHESIS: treat subagent output as evidence, not conclusions. State your hypothesis before delegating, then interrogate what came back: what was missed, wrong, or new? Say what changed your mind or what you still reject, and why.",
|
|
22
|
+
"PARALLELISM: when reads, audits, or delegations are independent, run them in parallel inside the phase. Parallelize cognition; serialize synthesis and canonical writes.",
|
|
23
|
+
"PHILOSOPHY LENS: apply the user's coding philosophy (from active session rules) as the evaluation lens. Flag violations by principle name, not as generic feedback. If principles conflict, surface the tension explicitly instead of silently choosing.",
|
|
24
|
+
"PHILOSOPHY CHECKS: watch for immutability, architectural fixes over patches, illegal states unrepresentable, explicit domain types, reduced path explosion, type safety, exhaustiveness, and errors as data.",
|
|
25
|
+
"PHILOSOPHY CHECKS (cont): validate at boundaries, fail fast on invariant violations, prefer determinism and small pure functions, use data-driven control flow, DI at boundaries, YAGNI with discipline, and atomicity.",
|
|
26
|
+
"PHILOSOPHY CHECKS (cont): treat graceful degradation, observability, fakes over mocks, and focused interfaces as first-class review concerns.",
|
|
27
|
+
"DRIFT HANDLING: when reality diverges from the plan, update the plan artifact and re-audit deliberately rather than accumulating undocumented drift.",
|
|
28
|
+
"NEVER COMMIT MARKDOWN FILES UNLESS USER EXPLICITLY ASKS."
|
|
29
|
+
],
|
|
30
|
+
"steps": [
|
|
31
|
+
{
|
|
32
|
+
"id": "phase-0-understand-and-classify",
|
|
33
|
+
"title": "Phase 0: Understand & Classify",
|
|
34
|
+
"prompt": "Build understanding and classify the task in one pass.\n\nStep 1 — Early exit check:\nBefore any exploration, verify that acceptance criteria or expected behavior exist. If they are completely absent and cannot be inferred, ask the user and stop. Do NOT ask questions you can resolve with tools.\n\nStep 2 — Explore:\nUse tools to build the minimum complete understanding needed to design correctly. Read independent files in parallel when possible.\n\nGather:\n- key entry points and call chain sketch\n- relevant files, modules, and functions\n- existing repo patterns with concrete file references\n- testing strategy already present in the repo\n- risks and unknowns\n- explicit invariants and non-goals\n\nStep 3 — Discover the dev's philosophy and preferences:\nDiscover what the dev cares about using this fallback chain (try each, use all that are available):\n1. Memory MCP (if available): call `mcp_memory_conventions`, `mcp_memory_prefer`, `mcp_memory_recall` to retrieve learned preferences and coding philosophy\n2. Active session rules / Firebender rules: read any rules, commands, or philosophy documents already in context\n3. Repo patterns: infer preferences from how the codebase already works — error handling style, mutability patterns, test approach, naming conventions, architecture patterns\n4. Ask the dev: only if the above sources are contradictory or clearly insufficient for this task\n\nDo NOT distill into a summary — record WHERE the philosophy lives (which rules, which Memory entries, which repo files exemplify it) so later phases can reference the source directly.\n\nIf stated rules conflict with actual repo patterns (e.g., rules say 'prefer immutability' but the module uses MutableStateFlow), note the conflict in `philosophyConflicts` — this is valuable signal for design decisions.\n\nStep 4 — Classify (informed by exploration):\nNow that you have real context, classify:\n- `taskComplexity`: Small / Medium / Large\n- `riskLevel`: Low / Medium / High\n- `rigorMode`: QUICK / STANDARD / THOROUGH\n- `automationLevel`: High / Medium / Low\n- `prStrategy`: SinglePR / MultiPR\n\nDecision guidance:\n- QUICK: small, low-risk, clear path, little ambiguity\n- STANDARD: medium scope or moderate risk\n- THOROUGH: large scope, architectural uncertainty, or high-risk change\n\nStep 5 — Optional deeper context (post-classification):\nIf `rigorMode` is STANDARD or THOROUGH and understanding still feels incomplete or the call chain is too fuzzy, and delegation is available, spawn TWO WorkRail Executors SIMULTANEOUSLY running `routine-context-gathering` with focus=COMPLETENESS and focus=DEPTH. Synthesize both outputs before finishing this step.\n\nSet context variables:\n- `taskComplexity`\n- `riskLevel`\n- `rigorMode`\n- `automationLevel`\n- `prStrategy`\n- `contextSummary`\n- `candidateFiles`\n- `invariants`\n- `nonGoals`\n- `openQuestions`\n- `philosophySources` — pointers to where the dev's philosophy lives (rules, Memory entries, repo files), not a summary\n- `philosophyConflicts` — conflicts between stated rules and actual repo patterns (if any)\n\nRules:\n- answer your own questions with tools whenever possible\n- only keep true human-decision questions in `openQuestions`\n- keep `openQuestions` bounded to the minimum necessary\n- classify AFTER exploring, not before",
|
|
35
|
+
"requireConfirmation": {
|
|
36
|
+
"or": [
|
|
37
|
+
{ "var": "taskComplexity", "equals": "Large" },
|
|
38
|
+
{ "var": "riskLevel", "equals": "High" }
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"id": "phase-1-architecture-decision",
|
|
44
|
+
"title": "Phase 1: Architecture Decision (Generate, Compare, Challenge, Select)",
|
|
45
|
+
"runCondition": {
|
|
46
|
+
"var": "taskComplexity",
|
|
47
|
+
"not_equals": "Small"
|
|
48
|
+
},
|
|
49
|
+
"prompt": "Design the architecture through deep understanding, not surface-level generation.\n\nPart A — Understand the problem deeply:\n- What are the core tensions in this problem? (e.g., performance vs simplicity, flexibility vs type safety, backward compatibility vs clean design)\n- How does the codebase already solve similar problems? Study the most relevant existing patterns — don't just list files, analyze the architectural decisions and constraints they protect.\n- What's the simplest naive solution? Why is it insufficient? (If it IS sufficient, that's your leading candidate — the burden of proof is on complexity.)\n- What makes this problem hard? What would a junior developer miss?\n\nPart B — Identify tensions and constraints (including philosophy):\n- Extract 2-4 real tradeoffs from your understanding (not generic labels like 'simplicity' or 'maintainability')\n- These tensions drive candidate generation — each candidate resolves them differently\n- Filter `philosophySources` to the principles actually under pressure for THIS problem. Which of the dev's philosophy principles constrain the solution space? For example: does the simplest solution require mutable state when the dev prefers immutability? Does the existing pattern use exceptions when the dev prefers Result types? Would the cleanest approach violate their preference for small interfaces?\n- If `philosophyConflicts` exist for this area of the codebase, surface them as explicit tensions the design must resolve: follow the stated rule, follow the existing pattern, or reconcile them\n\nPart C — State your hypothesis before delegating:\nBefore spawning any subagents, write 2-3 sentences: what do you currently believe the best approach is, and what concerns you most about it? This is your reference point for interrogating subagent output later.\n\nPart D — Generate candidates from tensions:\n- QUICK: self-generate candidates from your tensions. Include mandatory candidates: (1) simplest possible change that satisfies acceptance criteria, (2) follow existing repo pattern.\n- STANDARD: spawn ONE WorkRail Executor running `routine-tension-driven-design` with your tensions, philosophy sources, and problem understanding as input. Simultaneously, spawn ONE WorkRail Executor running `routine-hypothesis-challenge`: 'What constraints or failure modes would make you choose a fundamentally different approach? Propose one, grounded in real reasons.'\n- THOROUGH: spawn ONE WorkRail Executor running `routine-tension-driven-design`, ONE running `routine-hypothesis-challenge` (adversarial divergence), and ONE running `routine-execution-simulation`: 'Trace through the leading approach's 3 most likely failure scenarios step by step.'\n- For STANDARD with riskLevel=High: also spawn the execution simulation subagent.\n\nThe main agent ALWAYS self-generates its own candidates too (at minimum the two mandatory ones: simplest change + existing pattern). Subagent candidates supplement, not replace, your own thinking.\n\nPart E — Interrogate subagent output (if subagents were used):\nDo NOT summarize subagent findings as your own. Instead, interrogate against your hypothesis:\n- Where do subagent findings challenge your hypothesis? Are they right or did they miss context?\n- What did they surface that you genuinely hadn't considered?\n- Where are they just restating the obvious or echoing each other?\n- What did they get wrong or overweight?\nState explicitly: what you changed your mind about and why, or what you held firm on despite their input and why.\n\nPart F — Compare via tradeoffs (not checklists):\nFor each surviving candidate, produce:\n- One-sentence summary of the approach\n- Which tensions it resolves and which it accepts\n- The specific failure mode you'd watch for\n- How it relates to existing repo patterns (follows / adapts / departs)\n- What you gain and what you give up\n- Which of the dev's philosophy principles it honors and which it conflicts with — be specific (principle name + how)\n\nPart G — Challenge the leading option:\n- STANDARD: optionally challenge with ONE WorkRail Executor running `routine-hypothesis-challenge`\n- THOROUGH: challenge top 1-2 candidates using ONE or TWO WorkRail Executors running `routine-hypothesis-challenge`\n\nPart H — Select:\nSet context variables:\n- `selectedApproach` — the chosen design with rationale tied back to tensions\n- `runnerUpApproach` — the next-best option and why it lost\n- `architectureRationale` — which tensions were resolved and which were accepted\n- `pivotTriggers` — specific conditions under which you'd switch to the runner-up\n- `keyRiskToMonitor` — the failure mode of the selected approach\n- `acceptedTradeoffs` — what the selected approach gives up (feeds directly into design review)\n- `identifiedFailureModes` — per-candidate failure modes (feeds directly into design review)\n\nRules:\n- the main agent owns the final decision; subagents contribute depth, not decisions\n- if the simplest solution satisfies acceptance criteria, prefer it — complexity must justify itself\n- if the challenged leading candidate no longer looks best, switch deliberately rather than defending sunk cost\n- subagents go deep on specific questions, not wide on generic plans",
|
|
50
|
+
"requireConfirmation": {
|
|
51
|
+
"or": [
|
|
52
|
+
{ "var": "automationLevel", "equals": "Low" },
|
|
53
|
+
{ "var": "taskComplexity", "equals": "Large" },
|
|
54
|
+
{ "var": "riskLevel", "equals": "High" }
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"id": "phase-2-design-review",
|
|
60
|
+
"type": "loop",
|
|
61
|
+
"title": "Phase 2: Design Review",
|
|
62
|
+
"runCondition": {
|
|
63
|
+
"var": "taskComplexity",
|
|
64
|
+
"not_equals": "Small"
|
|
65
|
+
},
|
|
66
|
+
"loop": {
|
|
67
|
+
"type": "while",
|
|
68
|
+
"conditionSource": {
|
|
69
|
+
"kind": "artifact_contract",
|
|
70
|
+
"contractRef": "wr.contracts.loop_control",
|
|
71
|
+
"loopId": "design_review_loop"
|
|
72
|
+
},
|
|
73
|
+
"maxIterations": 2
|
|
74
|
+
},
|
|
75
|
+
"body": [
|
|
76
|
+
{
|
|
77
|
+
"id": "phase-2a-review-design",
|
|
78
|
+
"title": "Review Design for Gaps, Issues, and Improvements",
|
|
79
|
+
"prompt": "Review the selected architecture using the explicit tradeoffs and failure modes from Phase 1 as your review criteria — not a generic gaps checklist.\n\nTargeted review (derived from Phase 1 outputs):\n1. Are the `acceptedTradeoffs` actually acceptable? For each accepted tradeoff, verify it won't violate acceptance criteria or invariants under realistic conditions.\n2. Are the `identifiedFailureModes` actually handled? For each failure mode, trace through the design and confirm there's a mitigation path. If not, flag it.\n3. Does the selected approach's relationship to existing repo patterns hold up? If it 'adapts' an existing pattern, verify the adaptation doesn't break the invariants the original pattern protects.\n4. Is there a simpler version of the selected approach that still satisfies acceptance criteria? (Complexity must continue to justify itself.)\n\nCompare against the runner-up:\n- Are there elements from the runner-up that would strengthen the selected approach without adding complexity?\n- Would a hybrid resolve an accepted tradeoff that's bothering you?\n\nPhilosophy alignment: does the architecture respect the user's active coding rules?\n\nBefore delegating, state your current assessment: what do you think the strongest and weakest parts of the design are right now?\n\nMode-adaptive delegation:\n- QUICK: self-review only\n- STANDARD: optionally spawn ONE WorkRail Executor running `routine-hypothesis-challenge` focused specifically on the accepted tradeoffs and failure modes\n- THOROUGH: spawn TWO WorkRail Executors — `routine-hypothesis-challenge` on tradeoffs + `routine-execution-simulation` on failure modes\n\nAfter receiving subagent output (if used), interrogate it against your pre-assessment. Do not adopt their framing wholesale. State what changed your thinking and what didn't.\n\nIf issues are found, fix the design (update `selectedApproach`, `architectureRationale`, `pivotTriggers`, `acceptedTradeoffs`, `identifiedFailureModes`) before continuing.\n\nSet context variables:\n- `designFindings`\n- `designRevised`",
|
|
80
|
+
"requireConfirmation": false
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"id": "phase-2b-loop-decision",
|
|
84
|
+
"title": "Design Review Loop Decision",
|
|
85
|
+
"prompt": "Provide a loop control artifact.\n\nDecision rules:\n- if `designFindings` is non-empty and design was revised -> continue (verify the revision)\n- if `designFindings` is empty -> stop\n- if max iterations reached -> stop and document remaining concerns\n\nOutput exactly:\n```json\n{\n \"artifacts\": [{\n \"kind\": \"wr.loop_control\",\n \"decision\": \"continue\"\n }]\n}\n```",
|
|
86
|
+
"requireConfirmation": false,
|
|
87
|
+
"outputContract": {
|
|
88
|
+
"contractRef": "wr.contracts.loop_control"
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
]
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"id": "phase-3-plan-and-test-design",
|
|
95
|
+
"title": "Phase 3: Slice, Plan, and Test Design",
|
|
96
|
+
"runCondition": {
|
|
97
|
+
"var": "taskComplexity",
|
|
98
|
+
"not_equals": "Small"
|
|
99
|
+
},
|
|
100
|
+
"prompt": "Create or update the human-facing implementation artifact: `implementation_plan.md`.\n\nThis phase combines slicing, plan drafting, philosophy alignment, and test design.\n\nThe plan must include:\n1. Problem statement\n2. Acceptance criteria\n3. Non-goals\n4. Philosophy-driven constraints (from the user's active rules)\n5. Invariants\n6. Selected approach + rationale + runner-up\n7. Vertical slices\n8. Work packages only when they improve execution or enable safe parallelism\n9. Test design\n10. Risk register\n11. PR packaging strategy\n12. Philosophy alignment per slice:\n - [principle] -> [satisfied / tension / violated + 1-line why]\n\nSet context variables:\n- `implementationPlan`\n- `slices`\n- `testDesign`\n- `estimatedPRCount`\n- `followUpTickets` (initialize if needed)\n- `unresolvedUnknownCount`\n- `planConfidenceBand`\n\nRules:\n- keep `implementation_plan.md` concrete enough for another engineer to implement without guessing\n- use work packages only when they create real clarity; do not over-fragment work\n- use the user's coding philosophy as the primary planning lens, and name tensions explicitly\n- set `unresolvedUnknownCount` to the number of still-open issues that would materially affect implementation quality\n- set `planConfidenceBand` to Low / Medium / High based on how ready the plan actually is",
|
|
101
|
+
"requireConfirmation": false
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"id": "phase-4-plan-audit",
|
|
105
|
+
"type": "loop",
|
|
106
|
+
"title": "Phase 4: Plan Audit (Review, Fix, Decide)",
|
|
107
|
+
"runCondition": {
|
|
108
|
+
"var": "taskComplexity",
|
|
109
|
+
"not_equals": "Small"
|
|
110
|
+
},
|
|
111
|
+
"loop": {
|
|
112
|
+
"type": "while",
|
|
113
|
+
"conditionSource": {
|
|
114
|
+
"kind": "artifact_contract",
|
|
115
|
+
"contractRef": "wr.contracts.loop_control",
|
|
116
|
+
"loopId": "plan_audit_loop"
|
|
117
|
+
},
|
|
118
|
+
"maxIterations": 2
|
|
119
|
+
},
|
|
120
|
+
"body": [
|
|
121
|
+
{
|
|
122
|
+
"id": "phase-4a-audit-and-refocus",
|
|
123
|
+
"title": "Audit Plan and Apply Fixes",
|
|
124
|
+
"prompt": "Audit the plan and fix what you find in one pass.\n\nPart A -- Audit:\n- completeness / missing work\n- weak assumptions and risks\n- invariant coverage\n- slice boundary quality\n- philosophy alignment against the user's active rules\n- regression check against `resolvedFindings` (if present): if a previously resolved issue reappeared, treat it as Critical\n\nPhilosophy rules:\n- flag findings by principle name\n- Red / Orange findings go into `planFindings`\n- Yellow tensions are informational only and do NOT block loop exit\n\nBefore delegating, state your hypothesis: what do you think the plan's biggest weakness is right now? What are you most and least confident about?\n\nMode-adaptive delegation:\n- QUICK: self-audit only\n- STANDARD: if delegation is available, spawn THREE WorkRail Executors SIMULTANEOUSLY running `routine-plan-analysis`, `routine-hypothesis-challenge`, and `routine-philosophy-alignment`; include `routine-execution-simulation` only when runtime or state-flow risk is material\n- THOROUGH: if delegation is available, spawn FOUR WorkRail Executors SIMULTANEOUSLY running `routine-plan-analysis`, `routine-hypothesis-challenge`, `routine-execution-simulation`, and `routine-philosophy-alignment`\n\nInterrogate subagent output (if used):\n- Do NOT treat auditor findings as your findings. They are raw input from junior analysts.\n- Where 2+ auditors flag the same issue -> likely real, but verify it yourself\n- Where one auditor flags a unique concern -> investigate; is it genuine or did they miss context?\n- Where auditors conflict -> reason through it yourself rather than splitting the difference\n- State what changed your assessment of the plan and what didn't\n\nPart B -- Refocus (apply fixes immediately):\n- update `implementation_plan.md` to incorporate amendments\n- update `slices` if the plan shape changed\n- extract out-of-scope work into `followUpTickets`\n- track resolved findings (cap at 10, drop oldest)\n\nSet context variables:\n- `planFindings`\n- `planConfidence`\n- `resolvedFindings`\n- `followUpTickets`\n\nRules:\n- the main agent is synthesizer and final decision-maker\n- do not delegate sequentially when audit routines are independent\n- do not silently accept plan drift; reflect changes in the plan artifact immediately",
|
|
125
|
+
"requireConfirmation": false
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"id": "phase-4b-loop-decision",
|
|
129
|
+
"title": "Loop Exit Decision",
|
|
130
|
+
"prompt": "Provide a loop control artifact.\n\nDecision rules:\n- if `planFindings` is non-empty -> continue\n- if `planFindings` is empty -> stop, but enumerate what was checked to justify the clean pass\n- if max iterations reached -> stop and document remaining concerns\n\nOutput exactly:\n```json\n{\n \"artifacts\": [{\n \"kind\": \"wr.loop_control\",\n \"decision\": \"continue\"\n }]\n}\n```",
|
|
131
|
+
"requireConfirmation": true,
|
|
132
|
+
"outputContract": {
|
|
133
|
+
"contractRef": "wr.contracts.loop_control"
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
]
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
"id": "phase-5-small-task-fast-path",
|
|
140
|
+
"title": "Phase 5: Small Task Fast Path",
|
|
141
|
+
"runCondition": {
|
|
142
|
+
"var": "taskComplexity",
|
|
143
|
+
"equals": "Small"
|
|
144
|
+
},
|
|
145
|
+
"prompt": "For Small tasks:\n- confirm target locations and relevant patterns with tools\n- implement the smallest correct change\n- verify with tests/build or a deterministic check\n- apply the user's coding philosophy as the active review lens before finalizing\n- provide a concise PR-ready summary\n\nDo not create heavyweight planning artifacts unless risk unexpectedly grows.",
|
|
146
|
+
"requireConfirmation": false
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"id": "phase-6-implement-slices",
|
|
150
|
+
"type": "loop",
|
|
151
|
+
"title": "Phase 6: Implement Slice-by-Slice",
|
|
152
|
+
"runCondition": {
|
|
153
|
+
"var": "taskComplexity",
|
|
154
|
+
"not_equals": "Small"
|
|
155
|
+
},
|
|
156
|
+
"loop": {
|
|
157
|
+
"type": "forEach",
|
|
158
|
+
"items": "slices",
|
|
159
|
+
"itemVar": "currentSlice",
|
|
160
|
+
"indexVar": "sliceIndex",
|
|
161
|
+
"maxIterations": 20
|
|
162
|
+
},
|
|
163
|
+
"body": [
|
|
164
|
+
{
|
|
165
|
+
"id": "phase-6a-implement-slice",
|
|
166
|
+
"title": "Implement Slice",
|
|
167
|
+
"prompt": "Implement slice `{{currentSlice.name}}`.\n\nBefore writing code, do a quick inline check:\n- if pivot triggers have fired or plan assumptions are clearly stale, stop and return to planning instead of coding through it\n- if target files or symbols no longer match the plan, stop and re-plan\n\nImplementation rules:\n- the main agent owns implementation\n- delegate only targeted cognitive routines via the WorkRail Executor (challenge, simulation, philosophy review), not the whole slice\n- read independent files in parallel when possible\n- implement incrementally and keep the slice within its intended boundary\n- apply the user's coding philosophy as the active implementation lens\n- run tests and build after implementation to confirm the slice works\n\nTrack whether this slice required:\n- a new special-case (`specialCaseIntroduced`)\n- an unplanned abstraction (`unplannedAbstractionIntroduced`)\n- unexpected file changes outside planned scope (`unexpectedScopeChange`)\n\nSet `verifyNeeded` to true if ANY of:\n- `sliceIndex` is odd (verify every 2 slices)\n- `specialCaseIntroduced = true`\n- `unplannedAbstractionIntroduced = true`\n- `unexpectedScopeChange = true`\n- tests or build failed\n\nIf `prStrategy = MultiPR`, stop with a concise PR package for user review.\n\nSet context variables:\n- `specialCaseIntroduced`\n- `unplannedAbstractionIntroduced`\n- `unexpectedScopeChange`\n- `verifyNeeded`",
|
|
168
|
+
"requireConfirmation": {
|
|
169
|
+
"var": "prStrategy",
|
|
170
|
+
"equals": "MultiPR"
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
"id": "phase-6b-verify-slice",
|
|
175
|
+
"title": "Verify Slice",
|
|
176
|
+
"runCondition": {
|
|
177
|
+
"var": "verifyNeeded",
|
|
178
|
+
"equals": true
|
|
179
|
+
},
|
|
180
|
+
"prompt": "Evaluate what was just implemented with fresh eyes.\n\nReview:\n- does the implementation match the plan intent, not just the letter?\n- are there hidden assumptions or edge cases the implementation glossed over?\n- do invariants still hold?\n- are there philosophy-alignment regressions?\n- if multiple slices have passed since last verification, review all unverified slices together\n\nBefore delegating (if applicable), state: what is your honest assessment of the slice you just implemented? Where are you least confident?\n\nMode-adaptive delegation:\n- QUICK: self-verify only\n- STANDARD: if a fresh-eye trigger fired (`specialCaseIntroduced`, `unplannedAbstractionIntroduced`, or `unexpectedScopeChange`), optionally spawn ONE or TWO WorkRail Executors running `routine-hypothesis-challenge` and `routine-philosophy-alignment`\n- THOROUGH: if any fresh-eye trigger fired, spawn up to THREE WorkRail Executors running `routine-hypothesis-challenge`, `routine-execution-simulation`, and `routine-philosophy-alignment`\n\nAfter receiving subagent output (if used), interrogate: did they find something you genuinely missed, or are they flagging things you already considered and accepted? State what changed your assessment.\n\nSet context variables:\n- `verificationFindings`\n- `verificationFailed`\n\nRule:\n- if serious concerns are found, stop and return to planning or ask the user\n- do not rubber-stamp; this step exists specifically to catch what the implementation step missed",
|
|
181
|
+
"requireConfirmation": {
|
|
182
|
+
"var": "verificationFailed",
|
|
183
|
+
"equals": true
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
]
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
"id": "phase-7-final-verification",
|
|
190
|
+
"type": "loop",
|
|
191
|
+
"title": "Phase 7: Final Verification & Handoff",
|
|
192
|
+
"runCondition": {
|
|
193
|
+
"var": "taskComplexity",
|
|
194
|
+
"not_equals": "Small"
|
|
195
|
+
},
|
|
196
|
+
"loop": {
|
|
197
|
+
"type": "while",
|
|
198
|
+
"conditionSource": {
|
|
199
|
+
"kind": "artifact_contract",
|
|
200
|
+
"contractRef": "wr.contracts.loop_control",
|
|
201
|
+
"loopId": "final_verification_loop"
|
|
202
|
+
},
|
|
203
|
+
"maxIterations": 2
|
|
204
|
+
},
|
|
205
|
+
"body": [
|
|
206
|
+
{
|
|
207
|
+
"id": "phase-7a-verify-and-fix",
|
|
208
|
+
"title": "Verify Integration and Fix Issues",
|
|
209
|
+
"prompt": "Perform integration verification across all implemented slices.\n\nRequired:\n- verify acceptance criteria\n- map invariants to concrete proof (tests, build results, explicit reasoning)\n- run whole-task validation commands\n- identify any invariant violations or regressions\n- confirm the implemented result aligns with the user's coding philosophy, naming any tensions explicitly\n- review cumulative drift across all slices\n- check whether repeated small compromises added up to a larger pattern problem\n\nIf issues are found, fix them immediately:\n- apply code fixes\n- re-run affected tests\n- update `implementation_plan.md` if the fix changed boundaries or approach\n\nSet context variables:\n- `integrationFindings`\n- `integrationPassed`\n- `regressionDetected`",
|
|
210
|
+
"requireConfirmation": false
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
"id": "phase-7b-loop-decision",
|
|
214
|
+
"title": "Final Verification Loop Decision",
|
|
215
|
+
"prompt": "Provide a loop control artifact.\n\nDecision rules:\n- if `integrationFindings` is non-empty and fixes were applied -> continue (re-verify the fixes)\n- if `integrationFindings` is empty or all issues resolved -> stop and produce handoff\n- if max iterations reached -> stop and document remaining concerns\n\nWhen stopping, include the handoff summary:\n- acceptance criteria status\n- invariant status\n- test/build summary\n- concise PR/MR description draft (why, test plan, rollout notes)\n- follow-up tickets\n- any philosophy tensions accepted intentionally and why\n\nKeep the handoff concise and executive-level. Do not auto-merge or push unless the user explicitly asks.\n\nOutput exactly:\n```json\n{\n \"artifacts\": [{\n \"kind\": \"wr.loop_control\",\n \"decision\": \"continue\"\n }]\n}\n```",
|
|
216
|
+
"requireConfirmation": true,
|
|
217
|
+
"outputContract": {
|
|
218
|
+
"contractRef": "wr.contracts.loop_control"
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
]
|
|
222
|
+
}
|
|
223
|
+
]
|
|
224
|
+
}
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
"description": "Independently evaluates a plan or implementation artifact against the user's coding philosophy. Produces findings by principle name and distinguishes blocking violations from acceptable tensions.",
|
|
6
6
|
"clarificationPrompts": [
|
|
7
7
|
"What artifact should I review? (plan, architecture summary, implementation diff, files)",
|
|
8
|
-
"What philosophy principles or user rules should I apply?",
|
|
9
8
|
"What mode is this review in? (plan, architecture, implementation)",
|
|
10
|
-
"What artifact name should I produce?"
|
|
9
|
+
"What artifact name should I produce?",
|
|
10
|
+
"Are `philosophySources` and `philosophyConflicts` available in context? (if not, I will discover from scratch)"
|
|
11
11
|
],
|
|
12
12
|
"preconditions": [
|
|
13
13
|
"A review artifact is available",
|
|
@@ -24,30 +24,30 @@
|
|
|
24
24
|
],
|
|
25
25
|
"steps": [
|
|
26
26
|
{
|
|
27
|
-
"id": "step-
|
|
28
|
-
"title": "Step 1:
|
|
29
|
-
"prompt": "
|
|
30
|
-
"agentRole": "You are
|
|
27
|
+
"id": "step-discover-philosophy",
|
|
28
|
+
"title": "Step 1: Discover the Dev's Philosophy",
|
|
29
|
+
"prompt": "Discover the dev's coding philosophy and preferences. Check `philosophySources` context variable first — if it contains pointers to rules, Memory entries, or repo files, go read those sources directly.\n\nIf `philosophySources` is empty or unavailable, discover from scratch using this fallback chain:\n1. Memory MCP (if available): call `mcp_memory_conventions`, `mcp_memory_prefer`, `mcp_memory_recall` to retrieve learned preferences\n2. Active session rules / Firebender rules: read any rules or philosophy documents in context\n3. Repo patterns: infer preferences from how the codebase works — error handling, mutability, test style, naming, architecture\n\nAlso check `philosophyConflicts` — if stated rules conflict with repo patterns, note which apply to this review.\n\nWorking notes:\n- Philosophy sources consulted\n- Key principles discovered\n- Conflicts between stated and practiced philosophy",
|
|
30
|
+
"agentRole": "You are discovering what the dev actually cares about before judging their code against it.",
|
|
31
31
|
"requireConfirmation": false
|
|
32
32
|
},
|
|
33
33
|
{
|
|
34
|
-
"id": "step-
|
|
35
|
-
"title": "Step 2:
|
|
36
|
-
"prompt": "
|
|
34
|
+
"id": "step-understand-scope",
|
|
35
|
+
"title": "Step 2: Understand the Artifact and Select Principles",
|
|
36
|
+
"prompt": "Understand what you are reviewing and select the principles that matter.\n\nRead and summarize:\n- the artifact under review\n- the review mode (plan, architecture, implementation)\n- any supporting files or repo patterns needed for evidence\n\nSelect the subset of discovered principles that materially apply:\n- do not pretend every principle matters equally for every artifact\n- prioritize the principles actually implicated by the design or implementation\n- note any principles that are out of scope for this review\n\nIdentify:\n- which principles are actually touched by this artifact\n- where violations are most likely to appear\n- where principle tensions may naturally arise\n\nWorking notes:\n- Review scope\n- High-priority principles\n- Secondary principles\n- Likely risk areas\n- Possible tension zones",
|
|
37
37
|
"agentRole": "You are focusing the review on the principles that actually matter for this artifact.",
|
|
38
38
|
"requireConfirmation": false
|
|
39
39
|
},
|
|
40
40
|
{
|
|
41
41
|
"id": "step-evaluate-artifact",
|
|
42
|
-
"title": "Step 3: Evaluate Principle-by-Principle",
|
|
42
|
+
"title": "Step 3: Evaluate Principle-by-Principle (from source, not summary)",
|
|
43
43
|
"prompt": "Evaluate the artifact against each relevant principle.\n\nFor each principle, determine:\n- what the artifact does well\n- what violates the principle, if anything\n- whether this is a Red violation, Orange issue, or Yellow tension\n- what change or justification would resolve it\n\nSeverity guide:\n- Red = blocking violation of a key philosophy principle\n- Orange = meaningful design quality issue that should be fixed or justified\n- Yellow = principle tension or trade-off that may be acceptable if explicit\n\nWorking notes:\n- Findings by principle\n- Evidence / citations\n- Severity\n- Recommended action or required justification",
|
|
44
44
|
"agentRole": "You are performing a principle-by-principle review with specific, evidence-based findings.",
|
|
45
45
|
"requireConfirmation": false
|
|
46
46
|
},
|
|
47
47
|
{
|
|
48
48
|
"id": "step-identify-tensions",
|
|
49
|
-
"title": "Step 4: Identify Principle Tensions",
|
|
50
|
-
"prompt": "Identify where principles conflict.\n\nLook for cases like:\n- simplicity vs extensibility\n- YAGNI vs architecture cleanliness\n- explicitness vs verbosity\n- atomicity vs implementation complexity\n\nFor each tension:\n- name the principles involved\n- explain the trade-off\n- say what decision still needs to be made or documented\n\nWorking notes:\n- Principle tensions\n- Why they exist\n- What decision or explicit acceptance is needed",
|
|
49
|
+
"title": "Step 4: Identify Principle Tensions (including stated vs practiced)",
|
|
50
|
+
"prompt": "Identify where principles conflict.\n\nLook for cases like:\n- simplicity vs extensibility\n- YAGNI vs architecture cleanliness\n- explicitness vs verbosity\n- atomicity vs implementation complexity\n- stated philosophy vs actual repo patterns (e.g., rules say immutability but module uses mutable state)\n\nFor each tension:\n- name the principles involved\n- explain the trade-off\n- say what decision still needs to be made or documented\n\nWorking notes:\n- Principle tensions\n- Why they exist\n- What decision or explicit acceptance is needed",
|
|
51
51
|
"agentRole": "You are surfacing real trade-offs instead of flattening them into fake certainty.",
|
|
52
52
|
"requireConfirmation": false
|
|
53
53
|
},
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "routine-tension-driven-design",
|
|
3
|
+
"name": "Tension-Driven Design Generation",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"description": "Generates design candidates by deeply understanding a problem, identifying real tensions and constraints (including the dev's philosophy), and producing candidates that resolve those tensions differently. Each candidate includes explicit tradeoffs, failure modes, and philosophy alignment. Replaces perspective-based generation with constraint-driven generation for higher-quality, genuinely diverse candidates.",
|
|
6
|
+
"clarificationPrompts": [
|
|
7
|
+
"What problem should this design solve?",
|
|
8
|
+
"What acceptance criteria, invariants, and constraints must it respect?",
|
|
9
|
+
"Are `philosophySources` and `philosophyConflicts` available in context? (if not, I will discover from scratch)",
|
|
10
|
+
"What artifact name should I produce?"
|
|
11
|
+
],
|
|
12
|
+
"preconditions": [
|
|
13
|
+
"Problem statement is available",
|
|
14
|
+
"Acceptance criteria and non-goals are available",
|
|
15
|
+
"Relevant files, patterns, or codebase references are available",
|
|
16
|
+
"Agent has read access to the codebase"
|
|
17
|
+
],
|
|
18
|
+
"metaGuidance": [
|
|
19
|
+
"PURPOSE: generate genuinely different design candidates grounded in real problem tensions, not abstract perspectives.",
|
|
20
|
+
"ROLE: you are a designer, not an auditor or implementer. Think deeply about the problem before proposing solutions.",
|
|
21
|
+
"PHILOSOPHY: the dev's coding philosophy is a design constraint, not an afterthought review lens. Discover it and use it.",
|
|
22
|
+
"SIMPLICITY BIAS: always consider whether the problem even needs an architectural solution. The simplest change that works is a valid candidate.",
|
|
23
|
+
"REPO PATTERNS: study how the codebase already solves similar problems. The best design often adapts an existing pattern.",
|
|
24
|
+
"HONESTY: for each candidate, state what you gain, what you give up, and how it fails. Optimize for useful comparison, not persuasion."
|
|
25
|
+
],
|
|
26
|
+
"steps": [
|
|
27
|
+
{
|
|
28
|
+
"id": "step-discover-philosophy",
|
|
29
|
+
"title": "Step 1: Discover the Dev's Philosophy",
|
|
30
|
+
"prompt": "Discover the dev's coding philosophy and preferences before designing anything.\n\nCheck `philosophySources` context variable first — if it contains pointers to rules, Memory entries, or repo files, go read those sources directly.\n\nIf `philosophySources` is empty or unavailable, discover from scratch:\n1. Memory MCP (if available): call `mcp_memory_conventions`, `mcp_memory_prefer`, `mcp_memory_recall` to retrieve learned preferences\n2. Active session rules / Firebender rules: read any rules or philosophy documents in context\n3. Repo patterns: infer preferences from how the codebase works — error handling, mutability, test style, architecture\n\nNote any `philosophyConflicts` (stated rules vs actual repo patterns).\n\nWorking notes:\n- Philosophy sources consulted\n- Key principles discovered\n- Conflicts between stated and practiced philosophy\n- Which principles are likely to constrain this design",
|
|
31
|
+
"agentRole": "You are discovering what the dev actually cares about before designing solutions.",
|
|
32
|
+
"requireConfirmation": false
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"id": "step-understand-deeply",
|
|
36
|
+
"title": "Step 2: Understand the Problem Deeply",
|
|
37
|
+
"prompt": "Understand the problem before proposing anything.\n\nReason through:\n- What are the core tensions in this problem? (e.g., performance vs simplicity, flexibility vs type safety, backward compatibility vs clean design)\n- How does the codebase already solve similar problems? Study the most relevant existing patterns — analyze the architectural decisions and constraints they protect, not just list files.\n- What's the simplest naive solution? Why is it insufficient? (If it IS sufficient, note that — it may be the best candidate.)\n- What makes this problem hard? What would a junior developer miss?\n- Which of the dev's philosophy principles are under pressure from this problem's constraints?\n\nWorking notes:\n- Core tensions (2-4 real tradeoffs, not generic labels)\n- Existing patterns analysis (decisions, invariants they protect)\n- Naive solution and why it's insufficient (or sufficient)\n- What makes this hard\n- Philosophy principles under pressure",
|
|
38
|
+
"agentRole": "You are reasoning deeply about the problem space before generating any solutions.",
|
|
39
|
+
"requireConfirmation": false
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"id": "step-generate-candidates",
|
|
43
|
+
"title": "Step 3: Generate Candidates from Tensions",
|
|
44
|
+
"prompt": "Generate design candidates that resolve the identified tensions differently.\n\nMANDATORY candidates:\n1. The simplest possible change that satisfies acceptance criteria. If the problem doesn't need an architectural solution, say so.\n2. Follow the existing repo pattern — adapt what the codebase already does for similar problems. Don't invent when you can adapt.\n\nAdditional candidates (1-2 more):\n- Each must resolve the identified tensions DIFFERENTLY, not just vary surface details\n- Each must be grounded in a real constraint or tradeoff, not an abstract perspective label\n- Consider philosophy conflicts: if the stated philosophy disagrees with repo patterns, one candidate could follow the stated philosophy and another could follow the established pattern\n\nFor each candidate, produce:\n- One-sentence summary of the approach\n- Which tensions it resolves and which it accepts\n- The specific failure mode you'd watch for\n- How it relates to existing repo patterns (follows / adapts / departs)\n- What you gain and what you give up\n- Which philosophy principles it honors and which it conflicts with (by name)\n\nRules:\n- candidates must be genuinely different in shape, not just wording\n- if all candidates converge on the same approach, that's signal — note it honestly rather than manufacturing fake diversity\n- cite specific files or patterns when they materially shape a candidate",
|
|
45
|
+
"agentRole": "You are generating genuinely diverse design candidates grounded in real tensions.",
|
|
46
|
+
"requireConfirmation": false
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"id": "step-compare-and-recommend",
|
|
50
|
+
"title": "Step 4: Compare via Tradeoffs and Recommend",
|
|
51
|
+
"prompt": "Compare candidates through tradeoff analysis, not checklists.\n\nFor the set of candidates, assess:\n- Which tensions does each resolve best?\n- Which has the most manageable failure mode?\n- Which best fits the dev's philosophy? Where are the philosophy conflicts?\n- Which is most consistent with existing repo patterns?\n- Which would be easiest to evolve or reverse if assumptions are wrong?\n\nProduce a clear recommendation with rationale tied back to tensions and philosophy. If two candidates are close, say so and explain what would tip the decision.\n\nSelf-critique your recommendation:\n- What's the strongest argument against your pick?\n- What would make you switch to a different candidate?\n- What assumption, if wrong, would invalidate this design?\n\nWorking notes:\n- Comparison matrix (tensions x candidates)\n- Recommendation and rationale\n- Strongest counter-argument\n- Pivot conditions",
|
|
52
|
+
"agentRole": "You are comparing candidates honestly and recommending based on tradeoffs, not advocacy.",
|
|
53
|
+
"requireConfirmation": false
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"id": "step-deliver",
|
|
57
|
+
"title": "Step 5: Deliver the Design Candidates",
|
|
58
|
+
"prompt": "Create `{deliverableName}`.\n\nRequired structure:\n- Problem Understanding (tensions, what makes it hard)\n- Philosophy Constraints (which principles matter, any conflicts)\n- Candidates (each with: summary, tensions resolved/accepted, failure mode, repo-pattern relationship, gains/losses, philosophy fit)\n- Comparison and Recommendation\n- Self-Critique (strongest counter-argument, pivot conditions)\n- Open Questions for the Main Agent\n\nThe main agent will interrogate this output — it is raw investigative material, not a final decision. Optimize for honest, useful analysis over polished presentation.",
|
|
59
|
+
"agentRole": "You are delivering design analysis for the main agent to interrogate and build on.",
|
|
60
|
+
"requireConfirmation": false
|
|
61
|
+
}
|
|
62
|
+
]
|
|
63
|
+
}
|