@exaudeus/workrail 3.12.0 → 3.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/console/assets/{index-CRgjJiMS.js → index-EsSXrC_a.js} +11 -11
- package/dist/console/index.html +1 -1
- package/dist/di/container.js +8 -0
- package/dist/di/tokens.d.ts +1 -0
- package/dist/di/tokens.js +1 -0
- package/dist/infrastructure/session/HttpServer.js +2 -14
- package/dist/manifest.json +93 -53
- package/dist/mcp/boundary-coercion.d.ts +2 -0
- package/dist/mcp/boundary-coercion.js +73 -0
- package/dist/mcp/handler-factory.d.ts +1 -1
- package/dist/mcp/handler-factory.js +13 -6
- package/dist/mcp/handlers/v2-manage-workflow-source.d.ts +7 -0
- package/dist/mcp/handlers/v2-manage-workflow-source.js +50 -0
- package/dist/mcp/handlers/v2-workflow.d.ts +3 -0
- package/dist/mcp/handlers/v2-workflow.js +58 -0
- package/dist/mcp/output-schemas.d.ts +93 -0
- package/dist/mcp/output-schemas.js +8 -1
- package/dist/mcp/server.js +2 -0
- package/dist/mcp/tool-descriptions.js +20 -0
- package/dist/mcp/tools.js +6 -0
- package/dist/mcp/types/tool-description-types.d.ts +1 -1
- package/dist/mcp/types/tool-description-types.js +1 -0
- package/dist/mcp/types/workflow-tool-edition.d.ts +1 -1
- package/dist/mcp/types.d.ts +2 -0
- package/dist/mcp/v2/tool-registry.js +8 -0
- package/dist/mcp/v2/tools.d.ts +12 -0
- package/dist/mcp/v2/tools.js +7 -1
- package/dist/types/workflow-definition.d.ts +1 -0
- package/dist/v2/infra/in-memory/managed-source-store/index.d.ts +8 -0
- package/dist/v2/infra/in-memory/managed-source-store/index.js +33 -0
- package/dist/v2/infra/local/data-dir/index.d.ts +2 -0
- package/dist/v2/infra/local/data-dir/index.js +6 -0
- package/dist/v2/infra/local/managed-source-store/index.d.ts +15 -0
- package/dist/v2/infra/local/managed-source-store/index.js +164 -0
- package/dist/v2/ports/data-dir.port.d.ts +2 -0
- package/dist/v2/ports/managed-source-store.port.d.ts +25 -0
- package/dist/v2/ports/managed-source-store.port.js +2 -0
- package/package.json +2 -1
- package/spec/authoring-spec.json +9 -2
- package/spec/workflow.schema.json +418 -96
- package/workflows/adaptive-ticket-creation.json +276 -282
- package/workflows/document-creation-workflow.json +70 -191
- package/workflows/documentation-update-workflow.json +59 -309
- package/workflows/intelligent-test-case-generation.json +37 -212
- package/workflows/personal-learning-materials-creation-branched.json +1 -21
- package/workflows/presentation-creation.json +143 -308
- package/workflows/relocation-workflow-us.json +161 -535
- package/workflows/scoped-documentation-workflow.json +110 -181
- package/workflows/workflow-for-workflows.v2.json +72 -16
- package/workflows/CHANGELOG-bug-investigation.md +0 -298
- package/workflows/bug-investigation.agentic.json +0 -212
- package/workflows/bug-investigation.json +0 -112
- package/workflows/mr-review-workflow.agentic.json +0 -538
- package/workflows/mr-review-workflow.json +0 -277
|
@@ -0,0 +1,164 @@
|
|
|
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.LocalManagedSourceStoreV2 = void 0;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const zod_1 = require("zod");
|
|
9
|
+
const neverthrow_1 = require("neverthrow");
|
|
10
|
+
const MANAGED_SOURCE_LOCK_RETRY_MS = 250;
|
|
11
|
+
const jcs_js_1 = require("../../../durable-core/canonical/jcs.js");
|
|
12
|
+
const ManagedSourceRecordSchema = zod_1.z.object({
|
|
13
|
+
path: zod_1.z.string(),
|
|
14
|
+
addedAtMs: zod_1.z.number().int().nonnegative(),
|
|
15
|
+
});
|
|
16
|
+
const ManagedSourcesFileSchema = zod_1.z.object({
|
|
17
|
+
v: zod_1.z.literal(1),
|
|
18
|
+
sources: zod_1.z.array(ManagedSourceRecordSchema),
|
|
19
|
+
});
|
|
20
|
+
function mapFsToManagedSourceError(e) {
|
|
21
|
+
if (e.code === 'FS_ALREADY_EXISTS') {
|
|
22
|
+
return {
|
|
23
|
+
code: 'MANAGED_SOURCE_BUSY',
|
|
24
|
+
message: 'Managed sources are being updated by another WorkRail process.',
|
|
25
|
+
retry: { kind: 'retryable_after_ms', afterMs: MANAGED_SOURCE_LOCK_RETRY_MS },
|
|
26
|
+
lockPath: 'managed-sources.lock',
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
return { code: 'MANAGED_SOURCE_IO_ERROR', message: e.message };
|
|
30
|
+
}
|
|
31
|
+
function normalizeRecords(sources) {
|
|
32
|
+
const seen = new Set();
|
|
33
|
+
const normalized = [];
|
|
34
|
+
for (const source of sources) {
|
|
35
|
+
const normalizedPath = path_1.default.resolve(source.path);
|
|
36
|
+
if (seen.has(normalizedPath))
|
|
37
|
+
continue;
|
|
38
|
+
seen.add(normalizedPath);
|
|
39
|
+
normalized.push({ path: normalizedPath, addedAtMs: source.addedAtMs });
|
|
40
|
+
}
|
|
41
|
+
return normalized;
|
|
42
|
+
}
|
|
43
|
+
class LocalManagedSourceStoreV2 {
|
|
44
|
+
constructor(dataDir, fs) {
|
|
45
|
+
this.dataDir = dataDir;
|
|
46
|
+
this.fs = fs;
|
|
47
|
+
}
|
|
48
|
+
list() {
|
|
49
|
+
return this.readSources();
|
|
50
|
+
}
|
|
51
|
+
attach(sourcePath) {
|
|
52
|
+
const normalizedPath = path_1.default.resolve(sourcePath);
|
|
53
|
+
const nowMs = Date.now();
|
|
54
|
+
return this.withLock(() => this.readSources().andThen((sources) => {
|
|
55
|
+
const alreadyPresent = sources.some((s) => s.path === normalizedPath);
|
|
56
|
+
if (alreadyPresent)
|
|
57
|
+
return (0, neverthrow_1.okAsync)(undefined);
|
|
58
|
+
const next = [...sources, { path: normalizedPath, addedAtMs: nowMs }];
|
|
59
|
+
return this.persist(next);
|
|
60
|
+
}));
|
|
61
|
+
}
|
|
62
|
+
detach(sourcePath) {
|
|
63
|
+
const normalizedPath = path_1.default.resolve(sourcePath);
|
|
64
|
+
return this.withLock(() => this.readSources().andThen((sources) => {
|
|
65
|
+
const next = sources.filter((s) => s.path !== normalizedPath);
|
|
66
|
+
if (next.length === sources.length)
|
|
67
|
+
return (0, neverthrow_1.okAsync)(undefined);
|
|
68
|
+
return this.persist(next);
|
|
69
|
+
}));
|
|
70
|
+
}
|
|
71
|
+
readSources() {
|
|
72
|
+
const filePath = this.dataDir.managedSourcesPath();
|
|
73
|
+
return this.fs.readFileUtf8(filePath)
|
|
74
|
+
.orElse((e) => {
|
|
75
|
+
if (e.code === 'FS_NOT_FOUND')
|
|
76
|
+
return (0, neverthrow_1.okAsync)('');
|
|
77
|
+
return (0, neverthrow_1.errAsync)(mapFsToManagedSourceError(e));
|
|
78
|
+
})
|
|
79
|
+
.andThen((raw) => {
|
|
80
|
+
if (raw === '')
|
|
81
|
+
return (0, neverthrow_1.okAsync)([]);
|
|
82
|
+
let parsed;
|
|
83
|
+
try {
|
|
84
|
+
parsed = JSON.parse(raw);
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
return (0, neverthrow_1.errAsync)({
|
|
88
|
+
code: 'MANAGED_SOURCE_CORRUPTION',
|
|
89
|
+
message: `Invalid JSON in managed sources file: ${filePath}`,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
const validated = ManagedSourcesFileSchema.safeParse(parsed);
|
|
93
|
+
if (!validated.success) {
|
|
94
|
+
return (0, neverthrow_1.errAsync)({
|
|
95
|
+
code: 'MANAGED_SOURCE_CORRUPTION',
|
|
96
|
+
message: `Managed sources file has invalid shape: ${filePath}`,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
return (0, neverthrow_1.okAsync)(normalizeRecords(validated.data.sources));
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
persist(sources) {
|
|
103
|
+
const filePath = this.dataDir.managedSourcesPath();
|
|
104
|
+
const dir = path_1.default.dirname(filePath);
|
|
105
|
+
const tmpPath = `${filePath}.tmp`;
|
|
106
|
+
const fileValue = {
|
|
107
|
+
v: 1,
|
|
108
|
+
sources: [...normalizeRecords(sources)],
|
|
109
|
+
};
|
|
110
|
+
const canonical = (0, jcs_js_1.toCanonicalBytes)(fileValue).mapErr((e) => ({
|
|
111
|
+
code: 'MANAGED_SOURCE_IO_ERROR',
|
|
112
|
+
message: `Failed to canonicalize managed sources state: ${e.message}`,
|
|
113
|
+
}));
|
|
114
|
+
if (canonical.isErr())
|
|
115
|
+
return (0, neverthrow_1.errAsync)(canonical.error);
|
|
116
|
+
const bytes = canonical.value;
|
|
117
|
+
return this.fs.mkdirp(dir)
|
|
118
|
+
.mapErr(mapFsToManagedSourceError)
|
|
119
|
+
.andThen(() => this.fs.openWriteTruncate(tmpPath).mapErr(mapFsToManagedSourceError))
|
|
120
|
+
.andThen(({ fd }) => this.fs.writeAll(fd, bytes)
|
|
121
|
+
.mapErr(mapFsToManagedSourceError)
|
|
122
|
+
.andThen(() => this.fs.fsyncFile(fd).mapErr(mapFsToManagedSourceError))
|
|
123
|
+
.andThen(() => this.fs.closeFile(fd).mapErr(mapFsToManagedSourceError))
|
|
124
|
+
.orElse((e) => this.fs.closeFile(fd)
|
|
125
|
+
.mapErr(() => e)
|
|
126
|
+
.andThen(() => (0, neverthrow_1.errAsync)(e))))
|
|
127
|
+
.andThen(() => this.fs.rename(tmpPath, filePath).mapErr(mapFsToManagedSourceError))
|
|
128
|
+
.andThen(() => this.fs.fsyncDir(dir).mapErr(mapFsToManagedSourceError));
|
|
129
|
+
}
|
|
130
|
+
withLock(run) {
|
|
131
|
+
const lockPath = this.dataDir.managedSourcesLockPath();
|
|
132
|
+
const dir = path_1.default.dirname(lockPath);
|
|
133
|
+
const lockBytes = new TextEncoder().encode(JSON.stringify({ v: 1, pid: process.pid }));
|
|
134
|
+
return this.fs.mkdirp(dir)
|
|
135
|
+
.mapErr(mapFsToManagedSourceError)
|
|
136
|
+
.andThen(() => this.fs.openExclusive(lockPath, lockBytes)
|
|
137
|
+
.mapErr((e) => {
|
|
138
|
+
const mapped = mapFsToManagedSourceError(e);
|
|
139
|
+
if (mapped.code === 'MANAGED_SOURCE_BUSY') {
|
|
140
|
+
return { ...mapped, lockPath };
|
|
141
|
+
}
|
|
142
|
+
return mapped;
|
|
143
|
+
}))
|
|
144
|
+
.andThen(({ fd }) => this.fs.fsyncFile(fd)
|
|
145
|
+
.mapErr(mapFsToManagedSourceError)
|
|
146
|
+
.andThen(() => this.fs.closeFile(fd).mapErr(mapFsToManagedSourceError))
|
|
147
|
+
.andThen(() => run())
|
|
148
|
+
.andThen((value) => this.fs.unlink(lockPath)
|
|
149
|
+
.orElse((e) => {
|
|
150
|
+
if (e.code === 'FS_NOT_FOUND')
|
|
151
|
+
return (0, neverthrow_1.okAsync)(undefined);
|
|
152
|
+
return (0, neverthrow_1.errAsync)(mapFsToManagedSourceError(e));
|
|
153
|
+
})
|
|
154
|
+
.map(() => value))
|
|
155
|
+
.orElse((error) => this.fs.unlink(lockPath)
|
|
156
|
+
.orElse((e) => {
|
|
157
|
+
if (e.code === 'FS_NOT_FOUND')
|
|
158
|
+
return (0, neverthrow_1.okAsync)(undefined);
|
|
159
|
+
return (0, neverthrow_1.errAsync)(mapFsToManagedSourceError(e));
|
|
160
|
+
})
|
|
161
|
+
.andThen(() => (0, neverthrow_1.errAsync)(error))));
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
exports.LocalManagedSourceStoreV2 = LocalManagedSourceStoreV2;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ResultAsync } from 'neverthrow';
|
|
2
|
+
export type ManagedSourceStoreError = {
|
|
3
|
+
readonly code: 'MANAGED_SOURCE_BUSY';
|
|
4
|
+
readonly message: string;
|
|
5
|
+
readonly retry: {
|
|
6
|
+
readonly kind: 'retryable_after_ms';
|
|
7
|
+
readonly afterMs: number;
|
|
8
|
+
};
|
|
9
|
+
readonly lockPath: string;
|
|
10
|
+
} | {
|
|
11
|
+
readonly code: 'MANAGED_SOURCE_IO_ERROR';
|
|
12
|
+
readonly message: string;
|
|
13
|
+
} | {
|
|
14
|
+
readonly code: 'MANAGED_SOURCE_CORRUPTION';
|
|
15
|
+
readonly message: string;
|
|
16
|
+
};
|
|
17
|
+
export interface ManagedSourceRecordV2 {
|
|
18
|
+
readonly path: string;
|
|
19
|
+
readonly addedAtMs: number;
|
|
20
|
+
}
|
|
21
|
+
export interface ManagedSourceStorePortV2 {
|
|
22
|
+
list(): ResultAsync<readonly ManagedSourceRecordV2[], ManagedSourceStoreError>;
|
|
23
|
+
attach(path: string): ResultAsync<void, ManagedSourceStoreError>;
|
|
24
|
+
detach(path: string): ResultAsync<void, ManagedSourceStoreError>;
|
|
25
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exaudeus/workrail",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.14.0",
|
|
4
4
|
"description": "Step-by-step workflow enforcement for AI agents via MCP",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
"watch": "tsc --watch",
|
|
41
41
|
"validate:workflows": "bash scripts/validate-workflows.sh",
|
|
42
42
|
"validate:registry": "node scripts/validate-workflows-registry.ts",
|
|
43
|
+
"stamp-workflow": "node scripts/stamp-workflow.ts",
|
|
43
44
|
"validate:authoring-spec": "node scripts/validate-authoring-spec.js",
|
|
44
45
|
"validate:authoring-docs": "node scripts/generate-authoring-docs.js --check",
|
|
45
46
|
"validate:workflow-discovery": "node scripts/validate-workflow-discovery.js",
|
package/spec/authoring-spec.json
CHANGED
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
"When a workflow feature lands or changes, update the schema and runtime first.",
|
|
21
21
|
"Then update this authoring spec so guidance matches the shipped behavior.",
|
|
22
22
|
"Then regenerate or update human-facing docs and examples derived from this spec.",
|
|
23
|
-
"Do not leave authoring guidance behind the runtime."
|
|
23
|
+
"Do not leave authoring guidance behind the runtime.",
|
|
24
|
+
"Increment `version` when any required-level rule is added, removed, or materially changed. Add a `changelog` entry for the new version."
|
|
24
25
|
],
|
|
25
26
|
"ruleModel": {
|
|
26
27
|
"levels": [
|
|
@@ -1402,6 +1403,12 @@
|
|
|
1402
1403
|
]
|
|
1403
1404
|
}
|
|
1404
1405
|
],
|
|
1405
|
-
"plannedRules": [
|
|
1406
|
+
"plannedRules": [],
|
|
1407
|
+
"changelog": [
|
|
1408
|
+
{
|
|
1409
|
+
"version": 3,
|
|
1410
|
+
"date": "2026-03-21",
|
|
1411
|
+
"summary": "Baseline version at staleness feature introduction."
|
|
1412
|
+
}
|
|
1406
1413
|
]
|
|
1407
1414
|
}
|