@exaudeus/workrail 3.32.0 → 3.34.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/cli/commands/index.d.ts +1 -0
- package/dist/cli/commands/index.js +3 -1
- package/dist/cli/commands/worktrain-await.js +11 -9
- package/dist/cli/commands/worktrain-daemon-install.d.ts +35 -0
- package/dist/cli/commands/worktrain-daemon-install.js +291 -0
- package/dist/cli/commands/worktrain-daemon.d.ts +31 -0
- package/dist/cli/commands/worktrain-daemon.js +272 -0
- package/dist/cli/commands/worktrain-spawn.js +11 -9
- package/dist/cli-worktrain.js +488 -0
- package/dist/cli.js +1 -22
- package/dist/console/standalone-console.d.ts +28 -0
- package/dist/console/standalone-console.js +142 -0
- package/dist/{console/assets/index-Cb_LO718.js → console-ui/assets/index-C1JXnwZS.js} +1 -1
- package/dist/{console → console-ui}/index.html +1 -1
- package/dist/daemon/agent-loop.d.ts +27 -0
- package/dist/daemon/agent-loop.js +39 -1
- package/dist/daemon/daemon-events.d.ts +63 -1
- package/dist/daemon/workflow-runner.d.ts +3 -2
- package/dist/daemon/workflow-runner.js +285 -46
- package/dist/infrastructure/session/HttpServer.js +133 -34
- package/dist/manifest.json +136 -104
- package/dist/mcp/handlers/v2-error-mapping.d.ts +3 -0
- package/dist/mcp/handlers/v2-error-mapping.js +2 -0
- package/dist/mcp/handlers/v2-execution/advance.js +25 -0
- package/dist/mcp/handlers/v2-execution/continue-advance.js +7 -0
- package/dist/mcp/output-schemas.d.ts +30 -30
- package/dist/mcp/transports/fatal-exit.js +4 -0
- package/dist/mcp/transports/http-entry.js +0 -5
- package/dist/mcp/transports/stdio-entry.js +24 -12
- package/dist/mcp/v2/tools.d.ts +4 -4
- package/dist/mcp-server.d.ts +0 -2
- package/dist/mcp-server.js +1 -42
- package/dist/trigger/adapters/github-poller.d.ts +44 -0
- package/dist/trigger/adapters/github-poller.js +190 -0
- package/dist/trigger/adapters/gitlab-poller.d.ts +27 -0
- package/dist/trigger/adapters/gitlab-poller.js +81 -0
- package/dist/trigger/index.d.ts +4 -1
- package/dist/trigger/index.js +5 -1
- package/dist/trigger/polled-event-store.d.ts +22 -0
- package/dist/trigger/polled-event-store.js +173 -0
- package/dist/trigger/polling-scheduler.d.ts +20 -0
- package/dist/trigger/polling-scheduler.js +249 -0
- package/dist/trigger/trigger-listener.d.ts +3 -0
- package/dist/trigger/trigger-listener.js +47 -3
- package/dist/trigger/trigger-store.js +114 -33
- package/dist/trigger/types.d.ts +17 -1
- package/dist/v2/durable-core/domain/observation-builder.d.ts +3 -0
- package/dist/v2/durable-core/domain/observation-builder.js +2 -2
- package/dist/v2/durable-core/domain/prompt-renderer.d.ts +2 -1
- package/dist/v2/durable-core/domain/prompt-renderer.js +10 -0
- package/dist/v2/durable-core/schemas/export-bundle/index.d.ts +224 -224
- package/dist/v2/durable-core/schemas/session/events.d.ts +42 -42
- package/dist/v2/durable-core/schemas/session/manifest.d.ts +6 -6
- package/dist/v2/durable-core/schemas/session/validation-event.d.ts +2 -2
- package/dist/v2/durable-core/tokens/payloads.d.ts +52 -52
- package/dist/v2/usecases/console-routes.js +3 -3
- package/dist/v2/usecases/console-service.js +185 -10
- package/dist/v2/usecases/console-types.d.ts +8 -0
- package/docs/design/bridge-removal-pr-a-candidates.md +115 -0
- package/docs/design/bridge-removal-pr-a-design-review.md +79 -0
- package/docs/design/bridge-removal-pr-a-implementation-plan.md +203 -0
- package/docs/design/daemon-conversation-logging-plan.md +98 -0
- package/docs/design/daemon-conversation-logging-review.md +55 -0
- package/docs/design/daemon-conversation-logging.md +129 -0
- package/docs/design/github-polling-adapter-design-candidates.md +226 -0
- package/docs/design/github-polling-adapter-design-review-findings.md +131 -0
- package/docs/design/github-polling-adapter-implementation-plan.md +284 -0
- package/docs/design/implementation_plan.md +192 -0
- package/docs/design/workflow-id-validation-at-startup.md +146 -0
- package/docs/design/workflow-id-validation-design-review.md +87 -0
- package/docs/design/workflow-id-validation-implementation-plan.md +185 -0
- package/docs/design/worktrain-system-prompt-report-issue-candidates.md +135 -0
- package/docs/design/worktrain-system-prompt-report-issue-design-review.md +73 -0
- package/docs/discovery/design-candidates.md +180 -0
- package/docs/discovery/design-review-findings.md +110 -0
- package/docs/discovery/wr-discovery-goal-reframing.md +303 -0
- package/docs/ideas/backlog.md +627 -0
- package/package.json +1 -1
- package/workflows/architecture-scalability-audit.json +1 -1
- package/workflows/bug-investigation.agentic.v2.json +3 -3
- package/workflows/coding-task-workflow-agentic.json +32 -32
- package/workflows/coding-task-workflow-agentic.lean.v2.json +1 -1
- package/workflows/coding-task-workflow-agentic.v2.json +7 -7
- package/workflows/mr-review-workflow.agentic.v2.json +21 -12
- package/workflows/personal-learning-materials-creation-branched.json +2 -2
- package/workflows/production-readiness-audit.json +1 -1
- package/workflows/relocation-workflow-us.json +2 -2
- package/workflows/ui-ux-design-workflow.json +14 -14
- package/workflows/workflow-for-workflows.json +3 -3
- package/workflows/workflow-for-workflows.v2.json +2 -2
- package/workflows/wr.discovery.json +59 -8
- package/dist/mcp/transports/bridge-entry.d.ts +0 -102
- package/dist/mcp/transports/bridge-entry.js +0 -454
- package/dist/mcp/transports/bridge-events.d.ts +0 -51
- package/dist/mcp/transports/bridge-events.js +0 -24
- package/dist/mcp/transports/primary-tombstone.d.ts +0 -21
- package/dist/mcp/transports/primary-tombstone.js +0 -51
- /package/dist/{console → console-ui}/assets/index-8dh0Psu-.css +0 -0
|
@@ -41,7 +41,7 @@ const path = __importStar(require("node:path"));
|
|
|
41
41
|
const fs = __importStar(require("node:fs/promises"));
|
|
42
42
|
const result_js_1 = require("../runtime/result.js");
|
|
43
43
|
const types_js_1 = require("./types.js");
|
|
44
|
-
const SUPPORTED_PROVIDERS = new Set(['generic', 'gitlab_poll']);
|
|
44
|
+
const SUPPORTED_PROVIDERS = new Set(['generic', 'gitlab_poll', 'github_issues_poll', 'github_prs_poll']);
|
|
45
45
|
function unquoteYamlScalar(raw) {
|
|
46
46
|
const s = raw.trim();
|
|
47
47
|
if ((s.startsWith('"') && s.endsWith('"')) ||
|
|
@@ -304,6 +304,18 @@ function parseTriggersYaml(content) {
|
|
|
304
304
|
case 'projectId':
|
|
305
305
|
source.projectId = srcValueResult.value;
|
|
306
306
|
break;
|
|
307
|
+
case 'repo':
|
|
308
|
+
source.repo = srcValueResult.value;
|
|
309
|
+
break;
|
|
310
|
+
case 'excludeAuthors':
|
|
311
|
+
source.excludeAuthors = srcValueResult.value;
|
|
312
|
+
break;
|
|
313
|
+
case 'notLabels':
|
|
314
|
+
source.notLabels = srcValueResult.value;
|
|
315
|
+
break;
|
|
316
|
+
case 'labelFilter':
|
|
317
|
+
source.labelFilter = srcValueResult.value;
|
|
318
|
+
break;
|
|
307
319
|
case 'token':
|
|
308
320
|
source.token = srcValueResult.value;
|
|
309
321
|
break;
|
|
@@ -577,54 +589,123 @@ function validateAndResolveTrigger(raw, env, workspaces = {}) {
|
|
|
577
589
|
console.warn(`[TriggerStore] Warning: trigger "${rawId}" has autoOpenPR: true but autoCommit is not true. ` +
|
|
578
590
|
`A PR requires a commit -- delivery will be skipped unless autoCommit is also set to true.`);
|
|
579
591
|
}
|
|
592
|
+
function parsePollIntervalSeconds(raw2, triggerId2) {
|
|
593
|
+
const intervalRaw = raw2.pollIntervalSeconds?.trim();
|
|
594
|
+
if (!intervalRaw)
|
|
595
|
+
return (0, result_js_1.ok)(60);
|
|
596
|
+
const asNumber = Number(intervalRaw);
|
|
597
|
+
if (!Number.isInteger(asNumber) || asNumber <= 0) {
|
|
598
|
+
return (0, result_js_1.err)({
|
|
599
|
+
kind: 'invalid_field_value',
|
|
600
|
+
field: `source.pollIntervalSeconds (must be a positive integer, got: ${intervalRaw})`,
|
|
601
|
+
triggerId: triggerId2,
|
|
602
|
+
});
|
|
603
|
+
}
|
|
604
|
+
return (0, result_js_1.ok)(asNumber);
|
|
605
|
+
}
|
|
580
606
|
let pollingSource;
|
|
581
|
-
|
|
607
|
+
const isPollingProvider = provider === 'gitlab_poll' ||
|
|
608
|
+
provider === 'github_issues_poll' ||
|
|
609
|
+
provider === 'github_prs_poll';
|
|
610
|
+
if (isPollingProvider) {
|
|
582
611
|
if (!raw.source) {
|
|
583
612
|
return (0, result_js_1.err)({ kind: 'missing_field', field: 'source', triggerId: rawId });
|
|
584
613
|
}
|
|
585
614
|
const src = raw.source;
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
];
|
|
589
|
-
for (const field of requiredSourceFields) {
|
|
590
|
-
if (!src[field]?.trim()) {
|
|
591
|
-
return (0, result_js_1.err)({ kind: 'missing_field', field: `source.${field}`, triggerId: rawId });
|
|
592
|
-
}
|
|
615
|
+
if (!src.token?.trim()) {
|
|
616
|
+
return (0, result_js_1.err)({ kind: 'missing_field', field: 'source.token', triggerId: rawId });
|
|
593
617
|
}
|
|
594
|
-
const
|
|
595
|
-
const tokenResult = resolveSecret(tokenRaw, rawId, env);
|
|
618
|
+
const tokenResult = resolveSecret(src.token.trim(), rawId, env);
|
|
596
619
|
if (tokenResult.kind === 'err')
|
|
597
620
|
return tokenResult;
|
|
598
|
-
|
|
599
|
-
|
|
621
|
+
if (!src.events?.trim()) {
|
|
622
|
+
return (0, result_js_1.err)({ kind: 'missing_field', field: 'source.events', triggerId: rawId });
|
|
623
|
+
}
|
|
624
|
+
const events = src.events.trim().split(/\s+/).filter(Boolean);
|
|
600
625
|
if (events.length === 0) {
|
|
601
626
|
return (0, result_js_1.err)({ kind: 'missing_field', field: 'source.events (empty)', triggerId: rawId });
|
|
602
627
|
}
|
|
603
|
-
const
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
});
|
|
628
|
+
const intervalResult = parsePollIntervalSeconds(src, rawId);
|
|
629
|
+
if (intervalResult.kind === 'err')
|
|
630
|
+
return intervalResult;
|
|
631
|
+
const pollIntervalSeconds = intervalResult.value;
|
|
632
|
+
if (provider === 'gitlab_poll') {
|
|
633
|
+
if (!src.baseUrl?.trim()) {
|
|
634
|
+
return (0, result_js_1.err)({ kind: 'missing_field', field: 'source.baseUrl', triggerId: rawId });
|
|
635
|
+
}
|
|
636
|
+
if (!src.projectId?.trim()) {
|
|
637
|
+
return (0, result_js_1.err)({ kind: 'missing_field', field: 'source.projectId', triggerId: rawId });
|
|
638
|
+
}
|
|
639
|
+
const KNOWN_MR_EVENT_TYPES = new Set([
|
|
640
|
+
'merge_request.opened',
|
|
641
|
+
'merge_request.updated',
|
|
642
|
+
'merge_request.merged',
|
|
643
|
+
'merge_request.closed',
|
|
644
|
+
]);
|
|
645
|
+
for (const event of events) {
|
|
646
|
+
if (!KNOWN_MR_EVENT_TYPES.has(event)) {
|
|
647
|
+
console.warn(`[TriggerStore] Unknown polling event type '${event}' for trigger '${rawId}' -- ` +
|
|
648
|
+
`will match all open MRs as fallback`);
|
|
649
|
+
}
|
|
650
|
+
else if (event === 'merge_request.merged' || event === 'merge_request.closed') {
|
|
651
|
+
console.warn(`[TriggerStore] Event type '${event}' for trigger '${rawId}' cannot be observed ` +
|
|
652
|
+
`with state=opened polling (GitLab only returns open MRs). ` +
|
|
653
|
+
`Use a webhook trigger for merge/close events.`);
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
pollingSource = {
|
|
657
|
+
provider: 'gitlab_poll',
|
|
658
|
+
baseUrl: src.baseUrl.trim(),
|
|
659
|
+
projectId: src.projectId.trim(),
|
|
660
|
+
token: tokenResult.value,
|
|
661
|
+
events,
|
|
662
|
+
pollIntervalSeconds,
|
|
663
|
+
};
|
|
664
|
+
}
|
|
665
|
+
else {
|
|
666
|
+
if (!src.repo?.trim()) {
|
|
667
|
+
return (0, result_js_1.err)({ kind: 'missing_field', field: 'source.repo', triggerId: rawId });
|
|
668
|
+
}
|
|
669
|
+
const KNOWN_GITHUB_ISSUE_EVENTS = new Set(['issues.opened', 'issues.updated']);
|
|
670
|
+
const KNOWN_GITHUB_PR_EVENTS = new Set(['pull_request.opened', 'pull_request.updated']);
|
|
671
|
+
const knownEvents = provider === 'github_issues_poll' ? KNOWN_GITHUB_ISSUE_EVENTS : KNOWN_GITHUB_PR_EVENTS;
|
|
672
|
+
for (const event of events) {
|
|
673
|
+
if (!knownEvents.has(event)) {
|
|
674
|
+
console.warn(`[TriggerStore] Unknown GitHub polling event type '${event}' for trigger '${rawId}' -- ` +
|
|
675
|
+
`will match all items as fallback`);
|
|
676
|
+
}
|
|
613
677
|
}
|
|
614
|
-
|
|
678
|
+
const excludeAuthors = src.excludeAuthors?.trim()
|
|
679
|
+
? src.excludeAuthors.trim().split(/\s+/).filter(Boolean)
|
|
680
|
+
: [];
|
|
681
|
+
const notLabels = src.notLabels?.trim()
|
|
682
|
+
? src.notLabels.trim().split(/\s+/).filter(Boolean)
|
|
683
|
+
: [];
|
|
684
|
+
const labelFilter = src.labelFilter?.trim()
|
|
685
|
+
? src.labelFilter.trim().split(/\s+/).filter(Boolean)
|
|
686
|
+
: [];
|
|
687
|
+
if (excludeAuthors.length === 0) {
|
|
688
|
+
console.warn(`[TriggerStore] WARNING: trigger '${rawId}' has provider='${provider}' but ` +
|
|
689
|
+
`excludeAuthors is not set. If WorkTrain creates issues/PRs under a bot account, ` +
|
|
690
|
+
`omitting excludeAuthors will cause infinite self-review loops. ` +
|
|
691
|
+
`Set excludeAuthors to your WorkTrain bot account login (e.g. "worktrain-bot").`);
|
|
692
|
+
}
|
|
693
|
+
pollingSource = {
|
|
694
|
+
provider: provider,
|
|
695
|
+
repo: src.repo.trim(),
|
|
696
|
+
token: tokenResult.value,
|
|
697
|
+
events,
|
|
698
|
+
pollIntervalSeconds,
|
|
699
|
+
excludeAuthors,
|
|
700
|
+
notLabels,
|
|
701
|
+
labelFilter,
|
|
702
|
+
};
|
|
615
703
|
}
|
|
616
|
-
pollingSource = {
|
|
617
|
-
baseUrl: src.baseUrl.trim(),
|
|
618
|
-
projectId: src.projectId.trim(),
|
|
619
|
-
token: tokenResult.value,
|
|
620
|
-
events,
|
|
621
|
-
pollIntervalSeconds,
|
|
622
|
-
};
|
|
623
704
|
}
|
|
624
705
|
else if (raw.source) {
|
|
625
706
|
console.warn(`[TriggerStore] WARNING: trigger '${rawId}' has provider='${provider}' but also ` +
|
|
626
|
-
`defines a source: block. The source: block is only used for
|
|
627
|
-
`It will be ignored for this trigger.`);
|
|
707
|
+
`defines a source: block. The source: block is only used for polling providers ` +
|
|
708
|
+
`(gitlab_poll, github_issues_poll, github_prs_poll). It will be ignored for this trigger.`);
|
|
628
709
|
}
|
|
629
710
|
const trigger = {
|
|
630
711
|
id: (0, types_js_1.asTriggerId)(rawId),
|
package/dist/trigger/types.d.ts
CHANGED
|
@@ -25,6 +25,22 @@ export interface GitLabPollingSource {
|
|
|
25
25
|
readonly events: readonly string[];
|
|
26
26
|
readonly pollIntervalSeconds: number;
|
|
27
27
|
}
|
|
28
|
+
export interface GitHubPollingSource {
|
|
29
|
+
readonly repo: string;
|
|
30
|
+
readonly token: string;
|
|
31
|
+
readonly events: readonly string[];
|
|
32
|
+
readonly pollIntervalSeconds: number;
|
|
33
|
+
readonly excludeAuthors: readonly string[];
|
|
34
|
+
readonly notLabels: readonly string[];
|
|
35
|
+
readonly labelFilter: readonly string[];
|
|
36
|
+
}
|
|
37
|
+
export type PollingSource = (GitLabPollingSource & {
|
|
38
|
+
readonly provider: 'gitlab_poll';
|
|
39
|
+
}) | (GitHubPollingSource & {
|
|
40
|
+
readonly provider: 'github_issues_poll';
|
|
41
|
+
}) | (GitHubPollingSource & {
|
|
42
|
+
readonly provider: 'github_prs_poll';
|
|
43
|
+
});
|
|
28
44
|
export interface TriggerDefinition {
|
|
29
45
|
readonly id: TriggerId;
|
|
30
46
|
readonly provider: string;
|
|
@@ -49,7 +65,7 @@ export interface TriggerDefinition {
|
|
|
49
65
|
readonly workflowId?: string;
|
|
50
66
|
readonly goal?: string;
|
|
51
67
|
};
|
|
52
|
-
readonly pollingSource?:
|
|
68
|
+
readonly pollingSource?: PollingSource;
|
|
53
69
|
readonly workspaceName?: WorkspaceName;
|
|
54
70
|
readonly soulFile?: string;
|
|
55
71
|
}
|
|
@@ -34,11 +34,11 @@ function anchorsToObservations(anchors) {
|
|
|
34
34
|
});
|
|
35
35
|
break;
|
|
36
36
|
case 'repo_root':
|
|
37
|
-
if (anchor.value.length > constants_js_1.
|
|
37
|
+
if (anchor.value.length > constants_js_1.MAX_OBSERVATION_PATH_LENGTH)
|
|
38
38
|
break;
|
|
39
39
|
observations.push({
|
|
40
40
|
key: 'repo_root',
|
|
41
|
-
value: { type: '
|
|
41
|
+
value: { type: 'path', value: anchor.value },
|
|
42
42
|
confidence: 'high',
|
|
43
43
|
});
|
|
44
44
|
break;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Result } from 'neverthrow';
|
|
2
2
|
import type { Workflow } from '../../../types/workflow.js';
|
|
3
|
-
import type { PromptFragment } from '../../../types/workflow-definition.js';
|
|
3
|
+
import type { AssessmentDefinition, PromptFragment } from '../../../types/workflow-definition.js';
|
|
4
4
|
import type { LoadedSessionTruthV2 } from '../../ports/session-event-log-store.port.js';
|
|
5
5
|
import type { LoopPathFrameV1 } from '../schemas/execution-snapshot/index.js';
|
|
6
6
|
import type { NodeId, RunId } from '../ids/index.js';
|
|
@@ -8,6 +8,7 @@ export type PromptRenderError = {
|
|
|
8
8
|
readonly code: 'RENDER_FAILED';
|
|
9
9
|
readonly message: string;
|
|
10
10
|
};
|
|
11
|
+
export declare function formatAssessmentRequirementsForTest(assessments: readonly Pick<AssessmentDefinition, 'id' | 'purpose' | 'dimensions'>[]): readonly string[];
|
|
11
12
|
export declare function assembleFragmentedPrompt(fragments: readonly PromptFragment[], context: Record<string, unknown>): string;
|
|
12
13
|
export interface StepMetadata {
|
|
13
14
|
readonly stepId: string;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatAssessmentRequirementsForTest = formatAssessmentRequirementsForTest;
|
|
3
4
|
exports.assembleFragmentedPrompt = assembleFragmentedPrompt;
|
|
4
5
|
exports.renderPendingPrompt = renderPendingPrompt;
|
|
5
6
|
const neverthrow_1 = require("neverthrow");
|
|
@@ -174,6 +175,9 @@ function formatOutputContractRequirements(outputContract) {
|
|
|
174
175
|
];
|
|
175
176
|
}
|
|
176
177
|
}
|
|
178
|
+
function formatAssessmentRequirementsForTest(assessments) {
|
|
179
|
+
return formatAssessmentRequirements(assessments);
|
|
180
|
+
}
|
|
177
181
|
function formatAssessmentRequirements(assessments) {
|
|
178
182
|
if (assessments.length === 0)
|
|
179
183
|
return [];
|
|
@@ -190,6 +194,12 @@ function formatAssessmentRequirements(assessments) {
|
|
|
190
194
|
for (const dimension of assessment.dimensions) {
|
|
191
195
|
requirements.push(` ${dimension.id} (${dimension.levels.join(' | ')}): ${dimension.purpose}`);
|
|
192
196
|
}
|
|
197
|
+
const firstDimension = assessment.dimensions[0];
|
|
198
|
+
const exampleDimValue = firstDimension ? `"${firstDimension.levels[0] ?? 'high'}"` : '"high"';
|
|
199
|
+
const exampleDimKey = firstDimension ? `"${firstDimension.id}"` : '"dimensionId"';
|
|
200
|
+
requirements.push(`Canonical format:\n\`\`\`json\n` +
|
|
201
|
+
`{ "artifacts": [{ "kind": "wr.assessment", "assessmentId": "${assessment.id}", "dimensions": { ${exampleDimKey}: ${exampleDimValue} } }] }\n` +
|
|
202
|
+
`\`\`\``);
|
|
193
203
|
requirements.push('Use only canonical dimension levels. If the engine rejects the artifact, correct the submitted levels instead of inventing new ones.');
|
|
194
204
|
}
|
|
195
205
|
return requirements;
|